math/src/db/auth.cpp
2024-12-28 17:05:03 +08:00

190 lines
5.4 KiB
C++

#include "auth.h"
#include "hash/hash.hpp"
#include <print>
#include <leveldb/db.h>
#include <leveldb/write_batch.h>
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;
}
}