#include "auth.h" #include "hash/hash.hpp" #include #include #include using leveldb_ptr = leveldb::DB*; auto user_db = leveldb_ptr{nullptr}; auto iter_round = 10000; auto filter(const std::string_view id) -> bool { return id.contains(':'); } auto mangle_user_id(const std::string_view id) -> std::string { return std::format("{}:user_id", id); } auto mangle_permission(const std::string_view id) -> std::string { return std::format("{}:permission", id); } extern "C" { auto open_user_db() -> int { auto opts = leveldb::Options{}; opts.create_if_missing = true; auto status = leveldb::DB::Open(opts, "db/user", &user_db); if (!status.ok()) { std::println(stderr, "Failed to open user database: {}", status.ToString()); return 0; } return 1; } auto close_user_db() -> void { delete user_db; } auto check_user_exists(const char* user_id, int* result) -> int { if (filter(user_id)) return 0; auto value = std::string{}; auto status = user_db->Get(leveldb::ReadOptions{}, mangle_user_id(user_id), &value); if (status.ok()) { *result = 1; } else if (status.IsNotFound()) { *result = 0; } else { std::println(stderr, "Failed to check user existence: {}", status.ToString()); return 0; } return 1; } auto set_user_password(const char* user_id, const char* password) -> int { if (filter(user_id)) return 0; auto hash = generate_hash(password, iter_round); auto status = user_db->Put(leveldb::WriteOptions{}, mangle_user_id(user_id), hash); if (!status.ok()) { std::println(stderr, "Failed to set user password: {}", status.ToString()); return 0; } return 1; } auto login(const char* user_id, const char* password, int* result) -> int { if (filter(user_id)) return 0; auto value = std::string{}; auto status = user_db->Get(leveldb::ReadOptions{}, mangle_user_id(user_id), &value); if (!status.ok()) { std::println(stderr, "Failed to login: {}", status.ToString()); return 0; } *result = validate_password(password, value.data()); return 1; } int registe(const char* user_id, const char* password) { if (filter(user_id)) return 0; auto batch = leveldb::WriteBatch{}; batch.Put(mangle_user_id(user_id), generate_hash(password, iter_round)); batch.Put(mangle_permission(user_id), "2"); auto status = user_db->Write(leveldb::WriteOptions{}, &batch); if (!status.ok()) { std::println(stderr, "Failed to register: {}", status.ToString()); return 0; } return 1; } auto delete_user(const char* user_id) -> int { if (filter(user_id)) return 0; auto batch = leveldb::WriteBatch{}; batch.Delete(mangle_user_id(user_id)); batch.Delete(mangle_permission(user_id)); auto status = user_db->Write(leveldb::WriteOptions{}, &batch); if (!status.ok()) { std::println(stderr, "Failed to delete: {}", status.ToString()); return 0; } return 1; } int get_user_permission(const char* user_id, int* result) { if (filter(user_id)) return 0; auto value = std::string{}; auto status = user_db->Get(leveldb::ReadOptions{}, mangle_permission(user_id), &value); if (status.ok()) { *result = std::stoi(value); } else { std::println(stderr, "Failed to get user permission: {}", status.ToString()); return 0; } return 1; } int set_user_permission(const char* user_id, int permission) { if (filter(user_id)) return 0; auto status = user_db->Put(leveldb::WriteOptions{}, mangle_permission(user_id), std::to_string(permission)); if (!status.ok()) { std::println(stderr, "Failed to set user permission: {}", status.ToString()); return 0; } return 1; } int set_admin_password(const char* password) { auto hash = generate_hash(password, iter_round); auto status = user_db->Put(leveldb::WriteOptions{}, "admin_password_hash", hash); if (!status.ok()) { std::println(stderr, "Failed to set admin password: {}", status.ToString()); return 0; } return 1; } int admin_login(const char* password, int* result) { auto value = std::string{}; auto status = user_db->Get(leveldb::ReadOptions{}, "admin_password_hash", &value); if (!status.ok()) { std::println(stderr, "Failed to login admin: {}", status.ToString()); return 0; } *result = validate_password(password, value.data()); return 1; } int has_admin_password(int* result) { auto value = std::string{}; auto status = user_db->Get(leveldb::ReadOptions{}, "admin_password_hash", &value); if (status.ok()) { *result = 1; } else if (status.IsNotFound()) { *result = 0; } else { std::println(stderr, "Failed to check admin password existence: {}", status.ToString()); return 0; } return 1; } }