#ifndef BACKEND_CONTROLLERS_H #define BACKEND_CONTROLLERS_H #include #include #include #include #include #include #include #include #include "db/db.h" using req_type = const drogon::HttpRequestPtr&; using cbk_type = std::function&&; namespace api { class admin : public drogon::HttpController { public: METHOD_LIST_BEGIN METHOD_ADD(admin::users, "/users", drogon::Get, "Login", "Admin"); METHOD_ADD(admin::set_role, "/set_role", drogon::Post, "Login", "Admin"); METHOD_ADD(admin::logout, "/logout", drogon::Post, "Login", "Admin"); METHOD_ADD(admin::delete_user, "/delete", drogon::Post, "Login", "Admin"); METHOD_ADD(admin::disable_2fa, "/disable_2fa", drogon::Post, "Login", "Admin"); METHOD_ADD(admin::is_admin, "/is_admin", drogon::Get, "Login", "Admin"); METHOD_ADD(admin::get_token, "/get_token/{}", drogon::Get, "Login", "Admin"); METHOD_LIST_END void users(req_type, cbk_type); void set_role(req_type, cbk_type); void logout(req_type, cbk_type); void delete_user(req_type, cbk_type); void disable_2fa(req_type, cbk_type); void is_admin(req_type, cbk_type); void get_token(req_type, cbk_type, uint64_t user); }; class auth : public drogon::HttpController { public: METHOD_LIST_BEGIN METHOD_ADD(auth::gitlab, "/gitlab", drogon::Get); METHOD_ADD(auth::gitlab_callback, "/gitlab_callback?code={}", drogon::Get); METHOD_ADD(auth::signup, "/signup", drogon::Post); METHOD_ADD(auth::login, "/login", drogon::Post); METHOD_ADD(auth::refresh, "/refresh", drogon::Post, "Login"); METHOD_ADD(auth::tfa_setup, "/2fa/setup", drogon::Post, "Login"); METHOD_ADD(auth::tfa_complete, "/2fa/complete", drogon::Post, "Login"); METHOD_ADD(auth::tfa_disable, "/2fa/disable", drogon::Post, "Login"); METHOD_ADD(auth::change_password, "/change_password", drogon::Post, "Login"); METHOD_ADD(auth::logout_all, "/logout_all", drogon::Post, "Login"); METHOD_LIST_END struct gitlab_tokens { gitlab_tokens(std::string at, std::string rt) : at(std::move(at)), rt(std::move(rt)) {} std::string at, rt; }; struct gitlab_user { gitlab_user(std::string name, bool isAdmin) : name(std::move(name)), is_admin(isAdmin) {} std::string name; bool is_admin; }; static std::unique_ptr rng; static std::optional get_gitlab_tokens(const std::string&, bool token); static std::optional get_gitlab_user(const std::string&); static bool verify2fa(const db::User&, uint32_t totp); static void send_mail(const db::User&); static std::string get_token(const db::User&); static void generate_root(db::User&); static void revoke_all(const db::User&); static std::string get_jwt_secret(); void gitlab(req_type, cbk_type); void gitlab_callback(req_type, cbk_type, std::string code); void signup(req_type, cbk_type); void login(req_type, cbk_type); void refresh(req_type, cbk_type); void tfa_setup(req_type, cbk_type); void tfa_complete(req_type, cbk_type); void tfa_disable(req_type, cbk_type); void change_password(req_type, cbk_type); void logout_all(req_type, cbk_type); }; class fs : public drogon::HttpController { public: METHOD_LIST_BEGIN METHOD_ADD(fs::root, "/root", drogon::Get, "Login"); METHOD_ADD(fs::node, "/node/{}", drogon::Get, "Login"); METHOD_ADD(fs::path, "/path/{}", drogon::Get, "Login"); METHOD_ADD(fs::create_node_req, "/createFolder", drogon::Post, "Login"); METHOD_ADD(fs::create_node_req, "/createFile", drogon::Post, "Login"); METHOD_ADD(fs::delete_node_req, "/delete/{}", drogon::Post, "Login"); METHOD_ADD(fs::upload, "/upload/{}", drogon::Post, "Login"); METHOD_ADD(fs::create_zip, "/create_zip", drogon::Post, "Login"); METHOD_ADD(fs::download, "/download", drogon::Post, "Login"); METHOD_ADD(fs::download_multi, "/download_multi", drogon::Post, "Login"); METHOD_ADD(fs::download_preview, "/download_preview/{}", drogon::Get, "Login"); METHOD_ADD(fs::get_type, "/get_type/{}", drogon::Get, "Login"); METHOD_LIST_END enum class create_node_error { INVALID_NAME, INVALID_PARENT, FILE_PARENT }; struct mutex_stream { std::stringstream ss; std::mutex mutex; bool done = false; }; static std::optional get_node(uint64_t node); static std::optional get_node_and_validate(const db::User& user, uint64_t node); static std::vector get_children(const db::INode& parent); static std::variant> create_node(std::string name, const db::User& owner, bool file, const std::optional &parent, bool force = false); static void delete_node(db::INode node, msd::channel& chan, bool allow_root = false); static std::shared_ptr get_user_mutex(uint64_t user_id); void root(req_type, cbk_type); void node(req_type, cbk_type, uint64_t node); void path(req_type, cbk_type, uint64_t node); template void create_node_req(req_type req, cbk_type cbk); void delete_node_req(req_type, cbk_type, uint64_t node); void upload(req_type, cbk_type, uint64_t node); void create_zip(req_type, cbk_type); void download(req_type, cbk_type); void download_multi(req_type, cbk_type); void download_preview(req_type, cbk_type, uint64_t node); void get_type(req_type, cbk_type, uint64_t node); private: static trantor::EventLoop* get_zip_loop(); static trantor::EventLoop* get_delete_loop(); static void generate_path(db::INode node, std::string& str); static Json::Value generate_path(db::INode node); static uint64_t calc_total_size(const db::INode& base); static void add_to_zip(struct zip_t* zip, const std::string& key, const db::INode& node, const std::string& path); static uint64_t next_temp_id; static std::unordered_map zip_to_temp_map; static std::unordered_map> in_progress_zips; }; class user : public drogon::HttpController { public: METHOD_LIST_BEGIN METHOD_ADD(user::info, "/info", drogon::Get, "Login"); METHOD_ADD(user::delete_user, "/delete", drogon::Post, "Login"); METHOD_LIST_END void info(req_type, cbk_type); void delete_user(req_type, cbk_type); }; } #endif //BACKEND_CONTROLLERS_H