Compare commits

...

5 Commits

Author SHA1 Message Date
7dc2ce8702 updated build system
Some checks reported errors
BlockStorage/repertory/pipeline/head Something is wrong with the build of this commit
2025-02-27 14:52:03 -06:00
ed5f1f04ad change base href 2025-02-27 14:48:41 -06:00
863e0b2165 refactor 2025-02-27 14:42:38 -06:00
122b4998d6 added signal handler 2025-02-27 14:35:37 -06:00
722357388c added signal handler 2025-02-27 14:29:21 -06:00
11 changed files with 125 additions and 112 deletions

View File

@ -19,6 +19,8 @@ PROJECT_APP_LIST=(${PROJECT_NAME})
PROJECT_PRIVATE_KEY=${DEVELOPER_PRIVATE_KEY}
PROJECT_PUBLIC_KEY=${DEVELOPER_PUBLIC_KEY}
PROJECT_FLUTTER_BASE_HREF=/ui/
PROJECT_ENABLE_WIN32_LONG_PATH_NAMES=OFF
PROJECT_ENABLE_BACKWARD_CPP=OFF

View File

@ -0,0 +1,82 @@
/*
Copyright <2018-2025> <scott.e.graves@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef REPERTORY_INCLUDE_RPC_COMMON_HPP_
#define REPERTORY_INCLUDE_RPC_COMMON_HPP_
#include "utils/base64.hpp"
#include "utils/error_utils.hpp"
#include "utils/string.hpp"
namespace repertory::rpc {
[[nodiscard]] auto check_authorization(const auto &cfg,
const httplib::Request &req) -> bool {
REPERTORY_USES_FUNCTION_NAME();
if (cfg.get_api_auth().empty() || cfg.get_api_user().empty()) {
utils::error::raise_error(function_name,
"authorization user or password is not set");
return false;
}
auto authorization = req.get_header_value("Authorization");
if (authorization.empty()) {
utils::error::raise_error(function_name,
"'Authorization' header is not set");
return false;
}
auto auth_parts = utils::string::split(authorization, ' ', true);
if (auth_parts.empty()) {
utils::error::raise_error(function_name, "'Authorization' header is empty");
return false;
}
auto auth_type = auth_parts[0U];
if (auth_type != "Basic") {
utils::error::raise_error(function_name,
"authorization type is not 'Basic'");
return false;
}
auto data = macaron::Base64::Decode(authorization.substr(6U));
auto auth_str = std::string(data.begin(), data.end());
auto auth = utils::string::split(auth_str, ':', false);
if (auth.size() < 2U) {
utils::error::raise_error(function_name, "authorization data is not valid");
return false;
}
auto user = auth.at(0U);
auth.erase(auth.begin());
auto pwd = utils::string::join(auth, ':');
if ((user != cfg.get_api_user()) || (pwd != cfg.get_api_auth())) {
utils::error::raise_error(function_name, "authorization failed");
return false;
}
return true;
}
} // namespace repertory::rpc
#endif // REPERTORY_INCLUDE_RPC_COMMON_HPP_

View File

@ -40,8 +40,6 @@ private:
std::mutex start_stop_mutex_;
private:
[[nodiscard]] auto check_authorization(const httplib::Request &req) -> bool;
void handle_get_config(const httplib::Request &req, httplib::Response &res);
void handle_get_config_value_by_name(const httplib::Request &req,

View File

@ -282,6 +282,7 @@ enum class exit_code : std::int32_t {
unpin_failed = -17,
init_failed = -18,
ui_mount_failed = -19,
exception = -20,
};
enum http_error_codes : std::int32_t {

View File

@ -28,6 +28,7 @@
#include "events/types/service_stop_begin.hpp"
#include "events/types/service_stop_end.hpp"
#include "events/types/unmount_requested.hpp"
#include "rpc/common.hpp"
#include "utils/base64.hpp"
#include "utils/error_utils.hpp"
#include "utils/string.hpp"
@ -35,54 +36,6 @@
namespace repertory {
server::server(app_config &config) : config_(config) {}
auto server::check_authorization(const httplib::Request &req) -> bool {
REPERTORY_USES_FUNCTION_NAME();
if (config_.get_api_auth().empty() || config_.get_api_user().empty()) {
utils::error::raise_error(function_name,
"authorization user or password is not set");
return false;
}
auto authorization = req.get_header_value("Authorization");
if (authorization.empty()) {
utils::error::raise_error(function_name, "Authorization header is not set");
return false;
}
auto auth_parts = utils::string::split(authorization, ' ', true);
if (auth_parts.empty()) {
utils::error::raise_error(function_name, "Authorization header is empty");
return false;
}
auto auth_type = auth_parts[0U];
if (auth_type != "Basic") {
utils::error::raise_error(function_name, "Authorization is not Basic");
return false;
}
auto data = macaron::Base64::Decode(authorization.substr(6U));
auto auth_str = std::string(data.begin(), data.end());
auto auth = utils::string::split(auth_str, ':', false);
if (auth.size() < 2U) {
utils::error::raise_error(function_name, "Authorization is not valid");
return false;
}
auto user = auth.at(0U);
auth.erase(auth.begin());
auto pwd = utils::string::join(auth, ':');
if ((user != config_.get_api_user()) || (pwd != config_.get_api_auth())) {
utils::error::raise_error(function_name, "Authorization failed");
return false;
}
return true;
}
void server::handle_get_config(const httplib::Request & /*req*/,
httplib::Response &res) {
auto data = config_.get_json();
@ -173,7 +126,7 @@ void server::start() {
server_->set_pre_routing_handler(
[this](auto &&req, auto &&res) -> httplib::Server::HandlerResponse {
if (check_authorization(req)) {
if (rpc::check_authorization(config_, req)) {
return httplib::Server::HandlerResponse::Unhandled;
}

View File

@ -47,7 +47,7 @@ ui(std::vector<const char *> args, const std::string & /*data_directory*/,
}
httplib::Server server;
if (not server.set_mount_point("/", "./web")) {
if (not server.set_mount_point("/ui", "./web")) {
return exit_code::ui_mount_failed;
}

View File

@ -56,9 +56,6 @@ private:
private:
console_consumer console{};
private:
[[nodiscard]] auto check_authorization(const httplib::Request &req) -> bool;
};
} // namespace repertory::ui

View File

@ -146,10 +146,17 @@ auto main(int argc, char **argv) -> int {
(res == exit_code::option_not_found) &&
(idx < utils::cli::options::option_list.size());
idx++) {
res = cli::actions::perform_action(
utils::cli::options::option_list[idx], args, data_directory, prov,
unique_id, user, password);
try {
res = cli::actions::perform_action(
utils::cli::options::option_list[idx], args, data_directory, prov,
unique_id, user, password);
} catch (const std::exception &ex) {
res = exit_code::exception;
} catch (...) {
res = exit_code::exception;
}
}
if (res == exit_code::option_not_found) {
res = cli::actions::mount(args, data_directory, mount_result, prov,
remote_host, remote_port, unique_id);

View File

@ -22,6 +22,7 @@
#include "ui/handlers.hpp"
#include "events/event_system.hpp"
#include "rpc/common.hpp"
#include "types/repertory.hpp"
#include "utils/base64.hpp"
#include "utils/error_utils.hpp"
@ -34,7 +35,7 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server)
server_->set_pre_routing_handler(
[this](auto &&req, auto &&res) -> httplib::Server::HandlerResponse {
if (check_authorization(req)) {
if (rpc::check_authorization(*config_, req)) {
return httplib::Server::HandlerResponse::Unhandled;
}
@ -69,58 +70,27 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server)
});
event_system::instance().start();
static std::atomic<httplib::Server *> this_server{server_};
static const auto quit_handler = [](int /* sig */) {
auto *ptr = this_server.load();
if (ptr == nullptr) {
return;
}
this_server = nullptr;
ptr->stop();
};
std::signal(SIGINT, quit_handler);
#if !defined(_WIN32)
std::signal(SIGQUIT, quit_handler);
#endif // !defined(_WIN32)
std::signal(SIGTERM, quit_handler);
server_->listen("127.0.0.1", config_->get_api_port());
this_server = nullptr;
}
handlers::~handlers() { event_system::instance().stop(); }
auto handlers::check_authorization(const httplib::Request &req) -> bool {
REPERTORY_USES_FUNCTION_NAME();
if (config_->get_api_auth().empty() || config_->get_api_user().empty()) {
utils::error::raise_error(function_name,
"authorization user or password is not set");
return false;
}
auto authorization = req.get_header_value("Authorization");
if (authorization.empty()) {
utils::error::raise_error(function_name,
"'Authorization' header is not set");
return false;
}
auto auth_parts = utils::string::split(authorization, ' ', true);
if (auth_parts.empty()) {
utils::error::raise_error(function_name, "'Authorization' header is empty");
return false;
}
auto auth_type = auth_parts[0U];
if (auth_type != "Basic") {
utils::error::raise_error(function_name,
"authorization type is not 'Basic'");
return false;
}
auto data = macaron::Base64::Decode(authorization.substr(6U));
auto auth_str = std::string(data.begin(), data.end());
auto auth = utils::string::split(auth_str, ':', false);
if (auth.size() < 2U) {
utils::error::raise_error(function_name, "authorization data is not valid");
return false;
}
auto user = auth.at(0U);
auth.erase(auth.begin());
auto pwd = utils::string::join(auth, ':');
if ((user != config_->get_api_user()) || (pwd != config_->get_api_auth())) {
utils::error::raise_error(function_name, "authorization failed");
return false;
}
return true;
}
} // namespace repertory::ui

View File

@ -7,6 +7,8 @@ PROJECT_IS_MINGW=$4
PROJECT_IS_MINGW_UNIX=$5
DISABLE_CREATE_DIRS=$6
PROJECT_FLUTTER_BASE_HREF=/
if [ "${PROJECT_IS_MINGW}" != "1" ]; then
PROJECT_IS_MINGW_UNIX=0
fi
@ -310,9 +312,10 @@ export PROJECT_COMPANY_NAME
export PROJECT_COPYRIGHT
export PROJECT_DESC
export PROJECT_DIST_DIR
export PROJECT_ENABLE_WIN32_LONG_PATH_NAMES
export PROJECT_ENABLE_V2_ERRORS
export PROJECT_ENABLE_WIN32_LONG_PATH_NAMES
export PROJECT_FILE_PART
export PROJECT_FLUTTER_BASE_HREF
export PROJECT_GIT_REV
export PROJECT_IS_ALPINE
export PROJECT_IS_ARM64

View File

@ -101,13 +101,13 @@ if [ -f "${PROJECT_SOURCE_DIR}/web/${PROJECT_NAME}/pubspec.yaml" ]; then
docker exec \
${FLUTTER_CONTAINER_NAME} \
/bin/bash -c \
"flutter build web" || exit 1
"flutter build web --base-href=${PROJECT_FLUTTER_BASE_HREF}" || exit 1
docker stop ${FLUTTER_CONTAINER_NAME}
docker rm ${FLUTTER_CONTAINER_NAME}
else
pushd "${PROJECT_SOURCE_DIR}/web/${PROJECT_NAME}"
flutter build web || exit 1
flutter build web --base-href=${PROJECT_FLUTTER_BASE_HREF} || exit 1
popd
fi