1.0
This commit is contained in:
227
include/dps/app.hpp
Normal file
227
include/dps/app.hpp
Normal file
@@ -0,0 +1,227 @@
|
||||
#pragma once
|
||||
|
||||
#include "dps/config.hpp"
|
||||
#include "dps/http.hpp"
|
||||
#include "dps/json.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace dps {
|
||||
|
||||
struct User {
|
||||
int id = 0;
|
||||
std::string username;
|
||||
std::string password;
|
||||
int gold = 0;
|
||||
int level = 1;
|
||||
std::string qq;
|
||||
std::string name;
|
||||
std::string img;
|
||||
std::string client_key;
|
||||
std::string server_key;
|
||||
};
|
||||
|
||||
struct UserAndServer {
|
||||
std::string user_name;
|
||||
std::string server_ip;
|
||||
std::string account;
|
||||
std::string password;
|
||||
std::string port;
|
||||
};
|
||||
|
||||
struct UserServerProject {
|
||||
std::string server_ip;
|
||||
std::string project_name;
|
||||
std::string user_name;
|
||||
std::string expiration_date;
|
||||
int open = 1;
|
||||
};
|
||||
|
||||
struct ProjectDefinition {
|
||||
std::string name;
|
||||
std::vector<std::string> script_paths;
|
||||
std::map<std::string, Json> info;
|
||||
int price = 0;
|
||||
bool is_private = false;
|
||||
std::string img_path;
|
||||
};
|
||||
|
||||
class LegacyCrypto {
|
||||
public:
|
||||
explicit LegacyCrypto(std::string jwt_secret);
|
||||
|
||||
std::string issue_jwt(const std::string &username, long long expiration_seconds) const;
|
||||
std::optional<std::string> validate_jwt(const std::string &token) const;
|
||||
|
||||
std::string hash_password(const std::string &password) const;
|
||||
bool verify_password(const std::string &password, const std::string &encoded) const;
|
||||
|
||||
std::string rsa_private_encrypt_tool(const std::string &plain) const;
|
||||
std::string rsa_private_encrypt_script(const std::string &plain) const;
|
||||
std::string gzip_base64(const std::string &plain) const;
|
||||
std::vector<unsigned char> makecode(std::vector<unsigned char> bytes, const std::vector<int> &key) const;
|
||||
std::string xor_encrypt(const std::string &plain, const std::string &key) const;
|
||||
|
||||
private:
|
||||
std::string base64_url_encode(const std::string &input) const;
|
||||
std::string base64_url_decode(const std::string &input) const;
|
||||
std::string hmac_sha256(const std::string &message) const;
|
||||
std::string sha256_hex(const std::string &message) const;
|
||||
std::string bcrypt_hash(const std::string &password) const;
|
||||
std::string rsa_private_encrypt_der_b64(const std::string &der_b64, const std::string &plain) const;
|
||||
|
||||
std::string jwt_secret_;
|
||||
};
|
||||
|
||||
class Database {
|
||||
public:
|
||||
explicit Database(const DatabaseConfig &config);
|
||||
~Database();
|
||||
|
||||
bool connect();
|
||||
bool is_connected() const;
|
||||
std::string last_error() const;
|
||||
std::string escape(const std::string &value) const;
|
||||
bool execute(const std::string &sql);
|
||||
std::vector<std::map<std::string, std::string>> query(const std::string &sql);
|
||||
long long last_insert_id() const;
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
|
||||
class ProjectCatalog {
|
||||
public:
|
||||
explicit ProjectCatalog(const PathConfig &paths);
|
||||
|
||||
void reload();
|
||||
std::optional<ProjectDefinition> get_project(const std::string &name, const std::string &version = "") const;
|
||||
Json public_project_info() const;
|
||||
Json all_project_info() const;
|
||||
int project_price(const std::string &name) const;
|
||||
std::string project_img_path(const std::string &name) const;
|
||||
std::vector<std::string> base_script_contents(const std::string &version, bool cs_mode) const;
|
||||
std::vector<std::string> project_script_contents(const std::string &project_name, const std::string &version) const;
|
||||
std::vector<std::string> custom_client_scripts(const std::string &ip, const std::string &version) const;
|
||||
std::vector<std::pair<std::string, std::string>> dps_service_scripts(const std::string &ip) const;
|
||||
std::vector<std::pair<std::string, std::string>> dps_service_scripts_new(const std::string &ip, const std::string &version) const;
|
||||
std::string newest_version() const;
|
||||
long long base_update_time(const std::string &version) const;
|
||||
|
||||
private:
|
||||
struct VersionData {
|
||||
std::string name;
|
||||
std::map<std::string, ProjectDefinition> projects;
|
||||
std::vector<std::string> base_scripts;
|
||||
std::vector<std::string> cs_base_scripts;
|
||||
std::map<std::string, std::vector<std::string>> project_scripts;
|
||||
std::map<std::string, std::vector<std::string>> custom_client_scripts;
|
||||
Json dps_manifest;
|
||||
};
|
||||
|
||||
const VersionData *find_version(const std::string &requested) const;
|
||||
std::vector<std::string> read_script_list(const std::string &root, const std::vector<std::string> &items) const;
|
||||
std::vector<std::pair<std::string, std::string>> read_named_scripts(const std::string &root, const std::vector<std::string> &items) const;
|
||||
void load_client_versions();
|
||||
void load_custom_client_scripts(VersionData &data);
|
||||
Json parse_json_file(const std::string &path) const;
|
||||
|
||||
PathConfig paths_;
|
||||
std::map<std::string, VersionData> versions_;
|
||||
std::string newest_version_;
|
||||
};
|
||||
|
||||
class Application {
|
||||
public:
|
||||
explicit Application(AppConfig config);
|
||||
int run();
|
||||
|
||||
private:
|
||||
using Row = std::map<std::string, std::string>;
|
||||
|
||||
void register_routes();
|
||||
Response handle_login(const Request &request);
|
||||
Response handle_register(const Request &request);
|
||||
Response handle_change_password(const Request &request);
|
||||
Response handle_get_info(const Request &request);
|
||||
Response handle_add_server(const Request &request);
|
||||
Response handle_delete_server(const Request &request);
|
||||
Response handle_get_server_list(const Request &request);
|
||||
Response handle_get_server(const Request &request);
|
||||
Response handle_get_project_info_list(const Request &request);
|
||||
Response handle_get_user_project_list(const Request &request);
|
||||
Response handle_get_server_project_list(const Request &request);
|
||||
Response handle_buy(const Request &request);
|
||||
Response handle_add_gold(const Request &request);
|
||||
Response handle_transfer(const Request &request);
|
||||
Response handle_set_key(const Request &request);
|
||||
Response handle_set_project_open(const Request &request);
|
||||
|
||||
Response handle_rindro_download(const Request &request);
|
||||
Response handle_static_download(const std::string &disk_path, const std::string &download_name) const;
|
||||
Response handle_get_image(const Request &request, bool thumbnail);
|
||||
Response handle_get_mp42(const Request &request);
|
||||
Response handle_get_version(const Request &request);
|
||||
|
||||
Response handle_dps_version(const std::string &relative_file) const;
|
||||
Response handle_dps_list(const std::string &relative_dir, const std::string &metadata_file) const;
|
||||
Response handle_dps_download(const Request &request, const std::string &base_dir) const;
|
||||
|
||||
Response handle_script_client(const Request &request);
|
||||
Response handle_script_client2(const Request &request);
|
||||
Response handle_script_getzdy(const Request &request);
|
||||
Response handle_script_getpro(const Request &request);
|
||||
Response handle_script_getservice(const Request &request);
|
||||
Response handle_script_base_update_time(const Request &request);
|
||||
Response handle_script_base_sut(const Request &request);
|
||||
Response handle_script_getservice_new(const Request &request);
|
||||
|
||||
Response handle_video_placeholder(const Request &request);
|
||||
Response handle_payment_placeholder(const Request &request);
|
||||
|
||||
std::optional<User> find_user_by_username(const std::string &username);
|
||||
bool username_exists(const std::string &username);
|
||||
bool create_user(const std::string &username, const std::string &password, const std::string &qq);
|
||||
bool update_password(const std::string &username, const std::string &qq, const std::string &password);
|
||||
bool update_user_row(const User &user);
|
||||
std::vector<UserAndServer> servers_for_user(const std::string &username);
|
||||
std::optional<UserAndServer> find_server(const std::string &username, const std::string &ip);
|
||||
bool upsert_server(const UserAndServer &server);
|
||||
bool delete_server(const std::string &username, const std::string &ip);
|
||||
std::vector<UserServerProject> projects_for_ip(const std::string &ip, bool require_open = false);
|
||||
std::vector<UserServerProject> projects_for_user(const std::string &username);
|
||||
std::optional<UserServerProject> find_project_binding(const std::string &ip, const std::string &project_name);
|
||||
bool add_or_extend_project(const std::string &ip, const std::string &project_name, int days, const std::string &username);
|
||||
bool update_project_open(const std::string &ip, const std::string &project_name, int open_value);
|
||||
bool insert_log(const std::string &username, int type, const std::string &content);
|
||||
|
||||
Response json_response(int status, const Json &body) const;
|
||||
Response common_success(const Json &data, const std::string &message = "操作成功", int status = 200) const;
|
||||
Response common_failed(int code, const std::string &message, int http_status = 200) const;
|
||||
Response file_response(const std::filesystem::path &path, const std::string &download_name = "") const;
|
||||
std::string request_ip(const Request &request) const;
|
||||
std::vector<int> random_key() const;
|
||||
std::string format_date_now() const;
|
||||
std::string add_days(const std::string &iso_date, int days) const;
|
||||
std::string make_random_name() const;
|
||||
Json parse_body_or_empty(const Request &request) const;
|
||||
std::optional<std::string> current_user(const Request &request) const;
|
||||
|
||||
AppConfig config_;
|
||||
Router router_;
|
||||
LegacyCrypto crypto_;
|
||||
Database database_;
|
||||
ProjectCatalog catalog_;
|
||||
mutable std::mutex transfer_mutex_;
|
||||
mutable std::mutex script_mutex_;
|
||||
std::map<std::string, std::string> ip_and_mac_;
|
||||
};
|
||||
|
||||
} // namespace dps
|
||||
62
include/dps/config.hpp
Normal file
62
include/dps/config.hpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace dps {
|
||||
|
||||
struct ServerConfig {
|
||||
std::string host = "0.0.0.0";
|
||||
int port = 8651;
|
||||
bool trust_proxy = false;
|
||||
std::string proxy_header = "x-forwarded-for";
|
||||
};
|
||||
|
||||
struct JwtConfig {
|
||||
std::string secret = "change-me";
|
||||
long long expiration_seconds = 7200;
|
||||
};
|
||||
|
||||
struct LoggingConfig {
|
||||
std::string level = "info";
|
||||
bool http_summary = true;
|
||||
bool http_dump = false;
|
||||
int http_max_body = 2048;
|
||||
};
|
||||
|
||||
struct FeatureConfig {
|
||||
bool video_enabled = false;
|
||||
bool payment_enabled = false;
|
||||
};
|
||||
|
||||
struct DatabaseConfig {
|
||||
std::string host = "127.0.0.1";
|
||||
int port = 3306;
|
||||
std::string name = "rindro";
|
||||
std::string user = "root";
|
||||
std::string password;
|
||||
std::string ssl_mode = "preferred";
|
||||
std::string ssl_ca;
|
||||
std::string plugin_dir;
|
||||
};
|
||||
|
||||
struct PathConfig {
|
||||
std::string configfile = "/root/rindro/Script/FileConfig.json";
|
||||
std::string file_root = "/root/rindro/";
|
||||
std::string file_map = "/root/rindro/file.json";
|
||||
std::string script_root = "/root/rindro/ClentScript/";
|
||||
std::string dps_root = "/home/DP_S/";
|
||||
std::string client_user_script_root = "/root/rindro/ClentUserScript/";
|
||||
};
|
||||
|
||||
struct AppConfig {
|
||||
ServerConfig server;
|
||||
JwtConfig jwt;
|
||||
LoggingConfig logging;
|
||||
FeatureConfig features;
|
||||
DatabaseConfig database;
|
||||
PathConfig paths;
|
||||
};
|
||||
|
||||
AppConfig load_config(const std::string &path);
|
||||
|
||||
} // namespace dps
|
||||
14
include/dps/fs_utils.hpp
Normal file
14
include/dps/fs_utils.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace dps {
|
||||
|
||||
std::filesystem::path path_from_utf8(const std::string &value);
|
||||
std::string path_to_utf8_string(const std::filesystem::path &path);
|
||||
std::string read_text_file(const std::filesystem::path &path);
|
||||
std::vector<unsigned char> read_binary_file(const std::filesystem::path &path);
|
||||
|
||||
} // namespace dps
|
||||
73
include/dps/http.hpp
Normal file
73
include/dps/http.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
#include "dps/config.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace dps {
|
||||
|
||||
struct Request {
|
||||
std::string method;
|
||||
std::string raw_target;
|
||||
std::string path;
|
||||
std::string body;
|
||||
std::string remote_addr;
|
||||
std::map<std::string, std::string> headers;
|
||||
std::map<std::string, std::string> query;
|
||||
std::map<std::string, std::string> path_params;
|
||||
std::optional<std::string> current_user;
|
||||
|
||||
std::string header(const std::string &name) const;
|
||||
std::string query_value(const std::string &name) const;
|
||||
std::string path_param(const std::string &name) const;
|
||||
};
|
||||
|
||||
struct Response {
|
||||
int status = 200;
|
||||
std::string content_type = "application/json; charset=utf-8";
|
||||
std::string body;
|
||||
std::vector<unsigned char> binary_body;
|
||||
std::map<std::string, std::string> headers;
|
||||
|
||||
bool has_binary() const;
|
||||
};
|
||||
|
||||
using Handler = std::function<Response(const Request &)>;
|
||||
|
||||
class Router {
|
||||
public:
|
||||
void add(const std::string &method, const std::string &pattern, bool requires_auth, Handler handler);
|
||||
Response dispatch(Request request) const;
|
||||
|
||||
private:
|
||||
struct Route {
|
||||
std::string method;
|
||||
std::string pattern;
|
||||
bool requires_auth = false;
|
||||
Handler handler;
|
||||
};
|
||||
|
||||
std::vector<Route> routes_;
|
||||
};
|
||||
|
||||
class HttpServer {
|
||||
public:
|
||||
HttpServer(std::string host, int port, LoggingConfig logging, const Router &router);
|
||||
int run() const;
|
||||
|
||||
private:
|
||||
std::string host_;
|
||||
int port_;
|
||||
LoggingConfig logging_;
|
||||
const Router &router_;
|
||||
};
|
||||
|
||||
std::string url_decode(const std::string &value);
|
||||
std::map<std::string, std::string> parse_query_string(const std::string &query);
|
||||
std::string guess_content_type(const std::string &path);
|
||||
|
||||
} // namespace dps
|
||||
72
include/dps/json.hpp
Normal file
72
include/dps/json.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace dps {
|
||||
|
||||
class Json {
|
||||
public:
|
||||
using array_t = std::vector<Json>;
|
||||
using object_t = std::map<std::string, Json>;
|
||||
using value_t = std::variant<std::nullptr_t, bool, double, std::string, array_t, object_t>;
|
||||
|
||||
Json();
|
||||
Json(std::nullptr_t);
|
||||
Json(bool value);
|
||||
Json(int value);
|
||||
Json(long long value);
|
||||
Json(double value);
|
||||
Json(const char *value);
|
||||
Json(const std::string &value);
|
||||
Json(std::string &&value);
|
||||
Json(const array_t &value);
|
||||
Json(array_t &&value);
|
||||
Json(const object_t &value);
|
||||
Json(object_t &&value);
|
||||
|
||||
static Json parse(const std::string &text);
|
||||
static Json object();
|
||||
static Json array();
|
||||
|
||||
bool is_null() const;
|
||||
bool is_bool() const;
|
||||
bool is_number() const;
|
||||
bool is_string() const;
|
||||
bool is_array() const;
|
||||
bool is_object() const;
|
||||
|
||||
bool as_bool() const;
|
||||
double as_number() const;
|
||||
int as_int() const;
|
||||
long long as_int64() const;
|
||||
const std::string &as_string() const;
|
||||
const array_t &as_array() const;
|
||||
const object_t &as_object() const;
|
||||
array_t &as_array();
|
||||
object_t &as_object();
|
||||
|
||||
bool contains(const std::string &key) const;
|
||||
const Json &at(const std::string &key) const;
|
||||
Json &operator[](const std::string &key);
|
||||
const Json &operator[](const std::string &key) const;
|
||||
|
||||
const Json &at(std::size_t index) const;
|
||||
Json &at(std::size_t index);
|
||||
void push_back(const Json &value);
|
||||
std::size_t size() const;
|
||||
|
||||
std::string dump() const;
|
||||
std::string to_string_or(const std::string &fallback) const;
|
||||
int to_int_or(int fallback) const;
|
||||
bool to_bool_or(bool fallback) const;
|
||||
|
||||
private:
|
||||
value_t value_;
|
||||
};
|
||||
|
||||
} // namespace dps
|
||||
9
include/dps/labels.hpp
Normal file
9
include/dps/labels.hpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace dps {
|
||||
|
||||
std::string membership_label(int level);
|
||||
|
||||
} // namespace dps
|
||||
Reference in New Issue
Block a user