diff --git a/src/auth/resources.cpp b/src/auth/resources.cpp index 202e09d..50dede1 100644 --- a/src/auth/resources.cpp +++ b/src/auth/resources.cpp @@ -1,6 +1,7 @@ #include "resources.h" #include #include +#include #include "jwt.h" #include "utils.h" @@ -8,6 +9,9 @@ http::auth::User::User(const std::string &username, const std::string &passwordHash): username(username), passwordHash(passwordHash.empty() ? utils::sha256(username) : passwordHash) {} +http::auth::User::User(const std::string &username, const std::string &passwordHash, uint32_t perms): perms(perms), + username(username), passwordHash(passwordHash.empty() ? utils::sha256(username) : passwordHash) {} + bool http::auth::User::checkPassword(const std::string &pass) const { return utils::sha256(pass) == passwordHash; } @@ -19,9 +23,8 @@ void http::auth::User::setPassword(const std::string &pass) { bool http::auth::User::checkPremisions(uint32_t p) const { if (this->perms & SUPERUSER) { return true; - } else { - return (this->perms & p) == p; } + return (this->perms & p) == p; } void http::auth::User::setPremisions(uint32_t p) { @@ -73,3 +76,23 @@ std::shared_ptr http::auth::AuthProvider::getSession(const ser } http::auth::AuthProvider::~AuthProvider() = default; + +http::auth::AuthRequiredResource::AuthRequiredResource(const std::string &path, AuthProvider& provider, resource::respGenerator generator): + BasicResource(path), provider_(provider), generator_(std::move(generator)), perms(User::SUPERUSER) {} + +http::auth::AuthRequiredResource::AuthRequiredResource(const std::string &path, AuthProvider& provider, uint32_t perms, resource::respGenerator generator): + BasicResource(path), provider_(provider), generator_(std::move(generator)), perms(perms) {} + +void http::auth::AuthRequiredResource::handle(const server::Request &req, server::Reply &rep) { + if (auto user = this->provider_.getSession(req)) { + if (user->checkPremisions(this->perms)) { + this->generator_(req, rep); + return; + } + stockReply(server::forbidden, rep); + } else { + stockReply(server::unauthorized, rep); + } +} + +http::auth::AuthRequiredResource::~AuthRequiredResource() = default; diff --git a/src/auth/resources.h b/src/auth/resources.h index 4d623ec..53817f6 100644 --- a/src/auth/resources.h +++ b/src/auth/resources.h @@ -16,12 +16,20 @@ namespace http::auth { std::string passwordHash; /** - * Конструктор пользователя. + * Конструктор пользователя. По-умолчанию пользователь создается без прав, их нужно задать отдельной функцией. * @param username Имя пользователя, он же - логин. * @param passwordHash Хеш sha256 пароля пользователя. Если передать пустой, то пароль будет сгенерирован такой же, как и имя пользователя. */ explicit User(const std::string& username, const std::string& passwordHash = ""); + /** + * Конструктор пользователя с указанными правами. Аналогично первому конструктору. + * @param username Имя пользователя, он же - логин. + * @param passwordHash Хеш sha256 пароля пользователя. Если передать пустой, то пароль будет сгенерирован такой же, как и имя пользователя. + * @param perms Права пользователя + */ + explicit User(const std::string& username, const std::string& passwordHash, uint32_t perms); + /** * Проверить пароль на соответствие хешу * @param pass @@ -42,6 +50,7 @@ namespace http::auth { static constexpr uint32_t WATCH_SETTINGS = 0x0008; // просмотр настроек , если недоступно, то вкладки с настройками не будет static constexpr uint32_t EDIT_SETTINGS = 0x0010; // редактирование настроек, установка параметров модулятора/демодулятора/dma/cinc static constexpr uint32_t UPDATE_FIRMWARE = 0x0020; // обновление прошивки + static constexpr uint32_t SETUP_QOS = 0x0040; // управление профилем QoS /** * Проверить, что у пользователя есть нужное право. Если это суперпользователь, то у него по умолчанию все права есть. @@ -79,17 +88,19 @@ namespace http::auth { ~AuthProvider(); }; - class AuentificationRequiredResource final: public resource::BasicResource { + class AuthRequiredResource final: public resource::BasicResource { public: - explicit AuentificationRequiredResource(const std::string& path, std::shared_ptr provider, resource::respGenerator generator); + explicit AuthRequiredResource(const std::string& path, AuthProvider& provider, resource::respGenerator generator); + explicit AuthRequiredResource(const std::string& path, AuthProvider& provider, uint32_t perms, resource::respGenerator generator); void handle(const server::Request &req, server::Reply &rep) override; - ~AuentificationRequiredResource() override; + ~AuthRequiredResource() override; private: + uint32_t perms; resource::respGenerator generator_; - std::shared_ptr provider_; + AuthProvider& provider_; }; } diff --git a/src/main.cpp b/src/main.cpp index f3888bb..555a794 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -98,7 +98,7 @@ public: ServerResources(): sf(std::make_unique()), api(std::make_unique()) { api->startDaemon(); - auth.users.emplace_back(std::make_shared("admin")); + auth.users.emplace_back(std::make_shared("admin", "", http::auth::User::SUPERUSER)); sf->registerFile(FAVICON_ICO, mime_types::image_png, true); sf->registerFile(KROKODIL_GIF, mime_types::image_gif, true); @@ -176,7 +176,7 @@ public: s.resources.emplace_back(std::make_unique("/js/vue.js", [this](const auto& req, auto& rep) { boost::ignore_unused(req); sf->serve(VUE_JS, rep); })); s.resources.emplace_back(std::make_unique("/vid/video_2024-11-06_15-49-35.mp4", [this](const auto& req, auto& rep) { boost::ignore_unused(req); sf->serve(KB_MP4, rep); })); - s.resources.emplace_back(std::make_unique("/api/get/statistics", [this](const auto& req, auto& rep) { + s.resources.emplace_back(std::make_unique("/api/get/statistics", this->auth, http::auth::User::WATCH_STATISTICS, [this](const auto& req, auto& rep) { if (req.method != "GET") { http::server::stockReply(http::server::bad_request, rep); } @@ -190,7 +190,7 @@ public: rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size()); })); - s.resources.emplace_back(std::make_unique("/api/get/settings", [this](const auto& req, auto& rep) { + s.resources.emplace_back(std::make_unique("/api/get/settings", this->auth, http::auth::User::WATCH_SETTINGS, [this](const auto& req, auto& rep) { if (req.method != "GET") { http::server::stockReply(http::server::bad_request, rep); } @@ -204,7 +204,7 @@ public: rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size()); })); - s.resources.emplace_back(std::make_unique("/api/resetPacketStatistics", [this](const auto& req, auto& rep) { + s.resources.emplace_back(std::make_unique("/api/resetPacketStatistics", this->auth, http::auth::User::RESET_PACKET_STATISTICS, [this](const auto& req, auto& rep) { if (req.method != "POST") { http::server::stockReply(http::server::bad_request, rep); } @@ -217,7 +217,7 @@ public: rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size()); })); - s.resources.emplace_back(std::make_unique("/api/set/qos", [this](const auto& req, auto& rep) { + s.resources.emplace_back(std::make_unique("/api/set/qos", this->auth, http::auth::User::SETUP_QOS, [this](const auto& req, auto& rep) { if (req.method != "POST") { http::server::stockReply(http::server::bad_request, rep); } @@ -245,7 +245,7 @@ public: } })); - s.resources.emplace_back(std::make_unique("/api/set/bucLnb", [this](const auto& req, auto& rep) { + s.resources.emplace_back(std::make_unique("/api/set/bucLnb", this->auth, http::auth::User::SUPERUSER, [this](const auto& req, auto& rep) { if (req.method != "POST") { http::server::stockReply(http::server::bad_request, rep); }