diff --git a/INSTALL.md b/INSTALL.md index a47882a..a30a738 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -18,22 +18,22 @@ As root, trust the following debian package provider and add it in your list of wget https://debian.poupon.dev/apt/debian/epoupon.gpg -P /usr/share/keyrings echo "deb [signed-by=/usr/share/keyrings/epoupon.gpg] https://debian.poupon.dev/apt/debian bookworm main" > /etc/apt/sources.list.d/epoupon.list ``` -To install or upgrade _fileshelter_: +To install or upgrade _Fileshelter_: ```sh apt update apt install fileshelter ``` -The _fileshelter_ service is started just after the package installation, run by a dedicated _fileshelter_ system user.
+The `fileshelter` service is started just after the package installation, run by a dedicated `fileshelter` system user.
Please refer to [Deployment](#deployment) for further configuration options. ## From source __Note__: this installation process and the default values of the configuration files have been written for _Debian Bookworm_. Therefore, you may have to adapt commands and/or paths in order to fit to your distribution. ### Debian/Ubuntu dependencies -__Note__: a C++17 compiler is needed to compile _fileshelter_ +__Note__: a C++17 compiler is needed to compile _Fileshelter_ ```sh -apt-get install build-essential cmake libboost-dev libconfig++-dev +apt-get install build-essential cmake libboost-dev libconfig++-dev libarchive-dev ``` -You also need _Wt4_, that is not packaged yet on _Debian_. See [installation instructions](https://www.webtoolkit.eu/wt/doc/reference/html/InstallationUnix.html). +You also need _Wt4_, that is not packaged on _Debian_. See [installation instructions](https://www.webtoolkit.eu/wt/doc/reference/html/InstallationUnix.html). ### Build ```sh @@ -71,7 +71,7 @@ cp /usr/share/fileshelter/fileshelter.conf /etc/fileshelter.conf cp /usr/share/fileshelter/fileshelter.service /lib/systemd/system/fileshelter.service ``` -Create the working directory and give it access to the _fileshelter_ user: +Create the working directory and give it access to the `fileshelter` user: ```sh mkdir /var/fileshelter chown -R fileshelter:fileshelter /var/fileshelter @@ -103,13 +103,16 @@ systemctl restart fileshelter ## Configuration _Fileshelter_ uses a configuration file, installed by default in `/etc/fileshelter.conf`. It is recommended to edit this file and change relevant settings (listen address, listen port, working directory, ...). -A basic _Terms of Services_ is provided. The configuration file contains the definition of the fields needed by the default tos. -You may also specify an alternate tos file to fit your needs. +A basic _Terms of Service_ is provided. The configuration file contains the definition of the fields needed by the default ToS. +You may also specify an alternate ToS file to fit your needs. If a setting is not present in the configuration file, a hardcoded default value is used (the same as in the [default.conf](conf/fileshelter.conf) file) ## Reverse proxy settings -_Fileshelter_ is shipped with an embedded web server, but it is recommended to deploy behind a reverse proxy. You have to set the _behind-reverse-proxy_ option to _true_ in the `fileshelter.conf` configuration file. +_Fileshelter_ is shipped with an embedded web server, but it is recommended to deploy behind a reverse proxy. +You have to set the `behind-reverse-proxy` option to `true` in the `fileshelter.conf` configuration file and to adjust the trusted proxy list in `trusted-proxies`. + +__Note__: when running in a docker environment, you have to trust the docker gateway IP (which is `172.17.0.1` by default) Here is an example to make _Fileshelter_ properly work on _myserver.org_ using _nginx_: ``` @@ -143,7 +146,7 @@ server { systemctl start fileshelter ``` -Log traces can be accessed using journactl: +Logs can be accessed using `journalctl`: ```sh journalctl -u fileshelter.service ``` diff --git a/conf/fileshelter.conf b/conf/fileshelter.conf index 7e4b7b3..5ba9d81 100644 --- a/conf/fileshelter.conf +++ b/conf/fileshelter.conf @@ -60,6 +60,9 @@ tos-org = "**[ORG]**"; tos-url = "**[DEPLOY URL]**/tos"; tos-support-email = "**[SUPPORT EMAIL ADDRESS]**"; +# Set to false if you want to hide links to other Create application pages on the download page +show-create-links-on-download = true; + # Location for deployment deploy-path = "/"; diff --git a/src/fileshelter/main/main.cpp b/src/fileshelter/main/main.cpp index 2fb5e50..b4dead2 100644 --- a/src/fileshelter/main/main.cpp +++ b/src/fileshelter/main/main.cpp @@ -57,7 +57,7 @@ std::vector generateWtConfig(std::string execPath) if (Service::get()->getBool("tls-enable", false)) { - args.push_back("--https-port=" + std::to_string( Service::get()->getULong("listen-port", 5081))); + args.push_back("--https-port=" + std::to_string( Service::get()->getULong("listen-port", 5091))); args.push_back("--https-address=" + std::string {Service::get()->getString("listen-addr", "0.0.0.0")}); args.push_back("--ssl-certificate=" + std::string {Service::get()->getString("tls-cert")}); args.push_back("--ssl-private-key=" + std::string {Service::get()->getString("tls-key")}); @@ -65,7 +65,7 @@ std::vector generateWtConfig(std::string execPath) } else { - args.push_back("--http-port=" + std::to_string( Service::get()->getULong("listen-port", 5081))); + args.push_back("--http-port=" + std::to_string( Service::get()->getULong("listen-port", 5091))); args.push_back("--http-address=" + std::string {Service::get()->getString("listen-addr", "0.0.0.0")}); } diff --git a/src/fileshelter/ui/FileShelterApplication.cpp b/src/fileshelter/ui/FileShelterApplication.cpp index 2743796..a331a75 100644 --- a/src/fileshelter/ui/FileShelterApplication.cpp +++ b/src/fileshelter/ui/FileShelterApplication.cpp @@ -82,7 +82,10 @@ handlePathChange(Wt::WStackedWidget* stack) { if (wApp->internalPathMatches(index.first)) { + FsApp->updateMenuVisibility(); + stack->setCurrentIndex(index.second); + return; } } @@ -139,19 +142,20 @@ FileShelterApplication::initialize() Wt::WTemplate* main {root()->addNew(Wt::WString::tr("template-main"))}; Wt::WNavigationBar* navbar {main->bindNew("navbar-top")}; - navbar->setTitle(" " + Wt::WString::tr("msg-app-name"), Wt::WLink {Wt::LinkType::InternalPath, defaultPath}); + + navbar->setTitle(Wt::WString::tr("msg-app-name")); Wt::WMenu* menu {navbar->addMenu(std::make_unique())}; { - auto menuItem = menu->addItem(Wt::WString::tr("msg-share-create")); - menuItem->setLink(Wt::WLink {Wt::LinkType::InternalPath, "/share-create"}); - menuItem->setSelectable(true); + _menuItemShareCreate = menu->addItem(Wt::WString::tr("msg-share-create")); + _menuItemShareCreate->setLink(Wt::WLink {Wt::LinkType::InternalPath, "/share-create"}); + _menuItemShareCreate->setSelectable(true); } { - auto menuItem = menu->addItem(Wt::WString::tr("msg-tos")); - menuItem->setLink(Wt::WLink {Wt::LinkType::InternalPath, "/tos"}); - menuItem->setSelectable(true); - } + Wt::WMenuItem* menuItemTos = menu->addItem(Wt::WString::tr("msg-tos")); + menuItemTos->setLink(Wt::WLink {Wt::LinkType::InternalPath, "/tos"}); + menuItemTos->setSelectable(true); + } Wt::WContainerWidget* container {main->bindNew("contents")}; // Same order as Idx enum @@ -170,6 +174,22 @@ FileShelterApplication::initialize() handlePathChange(mainStack); } +void +FileShelterApplication::updateMenuVisibility() +{ + if (!Service::get()->getBool("show-create-links-on-download", true)) + { + if (wApp->internalPathMatches("/share-download")) + { + _menuItemShareCreate->hide(); + } + else + { + _menuItemShareCreate->show(); + } + } +} + void FileShelterApplication::displayError(std::string_view error) { diff --git a/src/fileshelter/ui/FileShelterApplication.hpp b/src/fileshelter/ui/FileShelterApplication.hpp index a996d62..cddbf1b 100644 --- a/src/fileshelter/ui/FileShelterApplication.hpp +++ b/src/fileshelter/ui/FileShelterApplication.hpp @@ -36,7 +36,7 @@ namespace UserInterface { public: FileShelterApplication(const Wt::WEnvironment& env); - + void updateMenuVisibility(); static std::filesystem::path prepareUploadDirectory(); static FileShelterApplication* instance(); const std::filesystem::path& getWorkingDirectory() const { return _workingDirectory; } @@ -47,6 +47,8 @@ namespace UserInterface void displayError(std::string_view error); + Wt::WMenuItem* _menuItemShareCreate; + static inline std::filesystem::path _workingDirectory; }; diff --git a/src/fileshelter/ui/ShareCreatePassword.cpp b/src/fileshelter/ui/ShareCreatePassword.cpp index a215431..3a8a457 100644 --- a/src/fileshelter/ui/ShareCreatePassword.cpp +++ b/src/fileshelter/ui/ShareCreatePassword.cpp @@ -69,20 +69,9 @@ namespace UserInterface ShareCreatePassword::ShareCreatePassword() { - auto model = std::make_shared(); + auto model {std::make_shared()}; - setTemplateText(tr("template-share-create-password")); - addFunction("id", &WTemplate::Functions::id); - addFunction("block", &WTemplate::Functions::block); - - // Password - auto password = std::make_unique(); - password->setEchoMode(Wt::EchoMode::Password); - setFormWidget(ShareCreatePasswordFormModel::PasswordField, std::move(password)); - - // Buttons - Wt::WPushButton* unlockBtn {bindNew("unlock-btn", tr("msg-unlock"))}; - unlockBtn->clicked().connect([=] + auto validateForm {[this, model] { updateModel(model.get()); @@ -100,7 +89,21 @@ namespace UserInterface std::this_thread::sleep_for(std::chrono::seconds {1}); updateView(model.get()); - }); + }}; + + setTemplateText(tr("template-share-create-password")); + addFunction("id", &WTemplate::Functions::id); + addFunction("block", &WTemplate::Functions::block); + + // Password + auto password = std::make_unique(); + password->setEchoMode(Wt::EchoMode::Password); + password->enterPressed().connect([=]{ validateForm(); }); + setFormWidget(ShareCreatePasswordFormModel::PasswordField, std::move(password)); + + // Buttons + Wt::WPushButton* unlockBtn {bindNew("unlock-btn", tr("msg-unlock"))}; + unlockBtn->clicked().connect([=] { validateForm(); }); updateView(model.get()); } diff --git a/src/fileshelter/ui/ShareCreated.cpp b/src/fileshelter/ui/ShareCreated.cpp index 403602a..331daf5 100644 --- a/src/fileshelter/ui/ShareCreated.cpp +++ b/src/fileshelter/ui/ShareCreated.cpp @@ -29,7 +29,6 @@ #include "ShareUtils.hpp" - namespace UserInterface { ShareCreated::ShareCreated() diff --git a/src/fileshelter/ui/ShareDownloadPassword.cpp b/src/fileshelter/ui/ShareDownloadPassword.cpp index 93aa3b7..a340737 100644 --- a/src/fileshelter/ui/ShareDownloadPassword.cpp +++ b/src/fileshelter/ui/ShareDownloadPassword.cpp @@ -91,18 +91,7 @@ namespace UserInterface { auto model {std::make_shared(shareUUID)}; - setTemplateText(tr("template-share-download-password")); - addFunction("id", &WTemplate::Functions::id); - addFunction("block", &WTemplate::Functions::block); - - // Password - auto password = std::make_unique(); - password->setEchoMode(Wt::EchoMode::Password); - setFormWidget(ShareDownloadPasswordFormModel::PasswordField, std::move(password)); - - // Buttons - Wt::WPushButton *unlockBtn = bindNew("unlock-btn", tr("msg-unlock")); - unlockBtn->clicked().connect([=] + auto validateForm {[this, model] { updateModel(model.get()); @@ -117,7 +106,21 @@ namespace UserInterface FS_LOG(UI, DEBUG) << "Download password validation failed"; updateView(model.get()); - }); + }}; + + setTemplateText(tr("template-share-download-password")); + addFunction("id", &WTemplate::Functions::id); + addFunction("block", &WTemplate::Functions::block); + + // Password + auto password = std::make_unique(); + password->setEchoMode(Wt::EchoMode::Password); + password->enterPressed().connect([=]{ validateForm(); }); + setFormWidget(ShareDownloadPasswordFormModel::PasswordField, std::move(password)); + + // Buttons + Wt::WPushButton *unlockBtn = bindNew("unlock-btn", tr("msg-unlock")); + unlockBtn->clicked().connect([=] { validateForm(); }); updateView(model.get()); }