162 lines
6.9 KiB
C
Raw Normal View History

2022-08-28 17:37:09 +02:00
#ifndef BACKEND_CONTROLLERS_H
#define BACKEND_CONTROLLERS_H
2022-09-03 23:32:20 +02:00
#include <variant>
2022-09-04 05:33:26 +02:00
#include <unordered_map>
#include <shared_mutex>
2022-09-03 23:32:20 +02:00
2022-08-28 17:37:09 +02:00
#include <drogon/drogon.h>
#include <botan/rng.h>
2022-09-03 23:32:20 +02:00
#include <msd/channel.hpp>
2022-09-04 05:33:26 +02:00
#include <trantor/net/EventLoopThread.h>
#include <kubazip/zip/zip.h>
2022-08-28 17:37:09 +02:00
#include "db/db.h"
using req_type = const drogon::HttpRequestPtr&;
using cbk_type = std::function<void(const drogon::HttpResponsePtr &)>&&;
namespace api {
class admin : public drogon::HttpController<admin> {
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");
2022-08-28 17:37:09 +02:00
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);
2022-08-28 17:37:09 +02:00
};
class auth : public drogon::HttpController<auth> {
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<Botan::RNG> rng;
2022-09-04 10:35:10 +02:00
static std::optional<gitlab_tokens> get_gitlab_tokens(const std::string&, bool token);
2022-08-28 17:37:09 +02:00
static std::optional<gitlab_user> 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();
2022-08-28 17:37:09 +02:00
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<fs> {
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<false>, "/createFolder", drogon::Post, "Login");
METHOD_ADD(fs::create_node_req<true>, "/createFile", drogon::Post, "Login");
METHOD_ADD(fs::delete_node_req, "/delete/{}", drogon::Post, "Login");
METHOD_ADD(fs::upload, "/upload/{}", drogon::Post, "Login");
2022-09-03 23:32:20 +02:00
METHOD_ADD(fs::create_zip, "/create_zip", drogon::Post, "Login");
2022-08-28 17:37:09 +02:00
METHOD_ADD(fs::download, "/download", drogon::Post, "Login");
2022-09-03 23:32:20 +02:00
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");
2022-08-28 17:37:09 +02:00
METHOD_LIST_END
2022-09-03 23:32:20 +02:00
enum class create_node_error {
INVALID_NAME,
INVALID_PARENT,
FILE_PARENT
};
struct mutex_stream {
std::stringstream ss;
std::mutex mutex;
bool done = false;
};
2022-08-28 17:37:09 +02:00
static std::optional<db::INode> get_node(uint64_t node);
static std::optional<db::INode> get_node_and_validate(const db::User& user, uint64_t node);
static std::vector<db::INode> get_children(const db::INode& parent);
2022-09-03 23:32:20 +02:00
static std::variant<db::INode, fs::create_node_error, std::tuple<bool, uint64_t>>
create_node(std::string name, const db::User& owner, bool file, const std::optional<uint64_t> &parent, bool force = false);
static void delete_node(db::INode node, msd::channel<std::string>& chan, bool allow_root = false);
2022-09-04 05:33:26 +02:00
static std::shared_ptr<std::shared_mutex> get_user_mutex(uint64_t user_id);
2022-08-28 17:37:09 +02:00
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<bool file> 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);
2022-09-03 23:32:20 +02:00
void create_zip(req_type, cbk_type);
2022-08-28 17:37:09 +02:00
void download(req_type, cbk_type);
2022-09-03 23:32:20 +02:00
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);
2022-09-04 05:33:26 +02:00
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<std::string, std::string> zip_to_temp_map;
static std::unordered_map<std::string, std::tuple<std::string, uint64_t, uint64_t>> in_progress_zips;
2022-08-28 17:37:09 +02:00
};
class user : public drogon::HttpController<user> {
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