添加检查用户是否有访问权限的功能,优化配置读取返回值

This commit is contained in:
keqingmoe 2025-01-04 20:51:34 +08:00
parent 4625978ab1
commit 035448ca00
11 changed files with 188 additions and 193 deletions

View File

@ -26,6 +26,8 @@ extern "C"
int records_count();
int have_ac(const char* user_id, int problem_id);
#ifdef __cplusplus
}
#endif

View File

@ -1,8 +1,6 @@
#ifndef SERVER_CONFIG_H
#define SERVER_CONFIG_H
#include <stdbool.h>
typedef struct
{
int server_port;
@ -12,7 +10,7 @@ typedef struct
void config_ctor(config_t* this);
void config_dtor(config_t* this);
bool config_read(config_t* this, const char* filename);
int config_read(config_t* this, const char* filename);
int print_config();

View File

@ -58,6 +58,7 @@ void res_all_records(mg_connection* conn, const char* records);
void res_all_records_by(mg_connection* conn, const char* records);
void res_all_records_of(mg_connection* conn, const char* records);
void res_records_count(mg_connection* conn, int count);
void res_have_ac(mg_connection* conn, int status);
void res_add_set(mg_connection* conn, int id);
void res_get_set(mg_connection* conn, const char* set);

View File

@ -5,6 +5,7 @@
int problems_handler(mg_connection* conn, void* cbdata);
int records_handler(mg_connection* conn, void* cbdata);
int sets_handler(mg_connection* conn, void* cbdata);
extern char* secret;

View File

@ -2,18 +2,20 @@
#include <chrono>
#include <print>
#include <unordered_map>
#include <unordered_set>
#include <leveldb/db.h>
#include <nlohmann/json.hpp>
using leveldb_ptr = leveldb::DB*;
auto records_db = leveldb_ptr{nullptr};
auto records_count_ = 0;
auto records = std::unordered_map<std::string, std::unordered_set<int>>{};
extern "C"
{
int open_records_db()
@ -29,8 +31,21 @@ extern "C"
return 0;
}
auto user_id_buf = std::string{};
auto problem_id_buf = 0;
auto status_buf = std::string{};
auto it = records_db->NewIterator(leveldb::ReadOptions());
for (it->SeekToFirst(); it->Valid(); it->Next()) {
auto json = nlohmann::json::parse(it->value().ToString());
// std::println(stderr, "{}", json.dump());
json["data"]["status"].get_to(status_buf);
if (status_buf == "ac") {
// std::println(stderr, "{}", json.dump());
json["user_id"].get_to(user_id_buf);
json["problem"].get_to(problem_id_buf);
records[user_id_buf].emplace(problem_id_buf);
}
records_count_++;
}
@ -163,4 +178,9 @@ extern "C"
{
return records_count_;
}
int have_ac(const char* user_id, int problem_id)
{
return records[user_id].contains(problem_id);
}
}

View File

@ -1,12 +1,14 @@
#include "db/problems.h"
#include "db/records.h"
#include "db/sets.h"
#include "server/auth.h"
#include "server/config.h"
#include "server/study.h"
#include "server/types.h"
#include "jwt/jwt.h"
#include "hash/hash.h"
#include "db/auth.h"
#include "db/db.h"
#include <civetweb.h>
@ -15,127 +17,162 @@
#include <stdlib.h>
#include <string.h>
leveldb_t* db = NULL;
void signal_handler(int signal)
{
fprintf(stderr, "Signal %d received, cleaning up...\n", signal);
close_db(db);
exit(1);
printf("Recieved signal %d.\n", signal);
exit(0);
}
void cleanup(void)
{
if (admin_session) free(admin_session);
if (secret) free(secret);
close_sets_db();
close_records_db();
close_problems_db();
close_user_db();
printf("Cleanup.\n");
}
int reset_admin_password()
{
char* random_password = kqm_random_password(16);
printf("Admin password is `%s`, "
"this password will not be showed again, "
"please save it well by yourself.\n",
random_password);
int flag = set_admin_password(random_password);
if (!flag) {
printf("cannot set admin password hash\n");
}
free(random_password);
return flag;
}
int init_admin_password()
{
int result;
int flag = has_admin_password(&result);
if (flag) {
if (!result) {
flag = reset_admin_password();
}
} else {
printf("cannot check admin password hash\n");
}
return flag;
}
int init_db()
{
if (!open_user_db()) {
fprintf(stderr, "cannot open user database\n");
return 1;
}
if (!open_problems_db()) {
fprintf(stderr, "cannot open problems database");
return 1;
}
if (!open_records_db()) {
fprintf(stderr, "cannot open records database\n");
return 1;
}
if (!open_sets_db()) {
fprintf(stderr, "cannot open problems set database\n");
return 1;
}
}
int main(int argc, char** argv)
{
open_user_db();
/*
4.1.1
*/
if (atexit(cleanup)) {
printf("cannot register cleanup function\n");
return 1;
}
// while (1) {
// printf("> ");
// char op[16];
// scanf("%15s", op);
// if (strcmp(op, "exit") == 0) break;
// if (strcmp(op, "login") == 0) {
// char user_id[64];
// char password[64];
// scanf("%63s %63s", user_id, password);
// int result;
// int flag = login(user_id, password, &result);
// if (!flag) {
// printf("Failed to login\n");
// } else {
// printf("Result: %s\n", result ? "login success" : "login failed");
// }
// }else if(strcmp(op, "logout") == 0){
// char user_id[64];
// scanf("%63s", user_id);
// int flag = logout(user_id);
// if (!flag) {
// printf("Failed to logout\n");
// } else {
// printf("Logout success\n");
// }
// } else if (strcmp(op, "register") == 0) {
// char user_id[64];
// char password[64];
// scanf("%63s %63s", user_id, password);
// int result;
// int flag = check_user_exists(user_id, &result);
// if(!flag){
// printf("Failed to check user existence\n");
// continue;
// }else if (result) {
// printf("User already exists\n");
// continue;
// }
// flag = set_user_password(user_id, password);
// if (!flag) {
// printf("Failed to register\n");
// } else {
// printf("Registration success\n");
// }
// } else if (strcmp(op, "check") == 0) {
// char user_id[64];
// scanf("%63s", user_id);
// int result;
// int flag = check_user_exists(user_id, &result);
// if (!flag) {
// printf("Failed to check user existence\n");
// } else {
// printf("Result: %s\n", result ? "user exists" : "user does not exist");
// }
// }
// }
int flag = 0;
// getchar();
flag |= SIG_ERR == signal(SIGINT, signal_handler);
flag |= SIG_ERR == signal(SIGTERM, signal_handler);
flag |= SIG_ERR == signal(SIGABRT, signal_handler);
flag |= SIG_ERR == signal(SIGSEGV, signal_handler);
// char* jwt = create_token("Hello", "world");
// printf("JWT: %s\n", jwt);
// int flag = verify_token(jwt, "world");
// printf("Flag: %d\n", flag);
// char* id = get_payload(jwt);
// printf("ID: %s\n", id);
// free(id);
// free(jwt);
if (flag) {
printf("cannot register signal handler\n");
return 1;
}
// if (!(db = open_db("db/main"))) return 1;
if (!init_db()) {
return 1;
}
// signal(SIGINT, signal_handler);
// signal(SIGTERM, signal_handler);
// signal(SIGSEGV, signal_handler);
if (!init_admin_password()) {
fprintf(stderr, "cannot init admin password hash\n");
return 1;
}
if (argc > 1) {
if (!strcmp(argv[1], "repasswd")) {
int flag = reset_admin_password();
if (!flag) {
fprintf(stderr, "cannot reset admin password\n");
}
return !flag;
}
}
config_t config;
int stat = config_read(&config, "configs/config.json");
if (!stat) {
printf("config_read() returned %d\n", stat);
flag = config_read(&config, "configs/config.json");
if (!flag) {
fprintf(stderr, "cannot read config file\n");
config_dtor(&config);
return 1;
}
if (config.server_port > 65535 || config.server_port <= 0) {
printf("Invalid server_port: %d\n", config.server_port);
printf("invalid server_port: %d\n", config.server_port);
config_dtor(&config);
return 1;
}
secret = config.secret;
secret = config.secret;
config.secret = NULL;
config_dtor(&config);
char server_port_str[6];
snprintf(server_port_str, sizeof(server_port_str), "%d", config.server_port);
const char* options[] =
{"document_root", "./www", "listening_ports", server_port_str, "error_log_file", "logs/civetweb.log", NULL};
const char* options[] = {"document_root",
"./www",
"listening_ports",
server_port_str,
"error_log_file",
"logs/civetweb.log",
NULL};
mg_callbacks callbacks;
mg_context* ctx;
memset(&callbacks, 0, sizeof(callbacks));
ctx = mg_start(&callbacks, NULL, options);
mg_set_request_handler(ctx, "/api/auth/login", login_handler, NULL);
mg_set_request_handler(ctx, "/api/auth/register", register_handler, NULL);
mg_set_request_handler(ctx, "/api/auth/delete", delete_handler, NULL);
mg_set_request_handler(ctx, "/api/auth/login", user_login_handler, NULL);
mg_set_request_handler(ctx, "/api/auth/register", user_register_handler, NULL);
mg_set_request_handler(ctx, "/api/auth/delete", user_delete_handler, NULL);
mg_set_request_handler(ctx, "/api/auth/repasswd", user_repasswd_handler, NULL);
mg_set_request_handler(ctx, "/api/auth/logout", user_logout_handler, NULL);
mg_set_request_handler(ctx, "/api/auth/permission", user_permission_handler, NULL);
mg_set_request_handler(ctx, "/api/auth/admin", admin_handler, NULL);
mg_set_request_handler(ctx, "/api/study/problems", problems_handler, NULL);
mg_set_request_handler(ctx, "/api/study/records", records_handler, NULL);
mg_set_request_handler(ctx, "/api/study/sets", sets_handler, NULL);
printf("Server started on port(s) %s\n", mg_get_option(ctx, "listening_ports"));
getchar();
mg_stop(ctx);
close_user_db();
// close_db(db);
return 0;
}

View File

@ -14,36 +14,6 @@
#include <stdlib.h>
#include <string.h>
// typedef struct
// {
// char* token;
// char* user_id;
// } logout_form_t;
// static void logout_form_dtor(logout_form_t* form)
// {
// if (form->token) free(form->token);
// if (form->user_id) free(form->user_id);
// }
// static int field_found(const char* key, const char* filename, char* path, size_t pathlen, void* user_data)
// {
// return MG_FORM_FIELD_HANDLE_GET;
// }
// static int field_get(const char* key, const char* value, size_t valuelen, void* user_data)
// {
// logout_form_t* form = (logout_form_t*)user_data;
// if (strcmp(key, "token") == 0) {
// form->token = kqm_strndup(value, valuelen);
// } else if (strcmp(key, "user_id") == 0) {
// form->user_id = kqm_strndup(value, valuelen);
// }
// if (form->token && form->user_id) {
// return MG_FORM_FIELD_HANDLE_ABORT;
// }
// return MG_FORM_FIELD_HANDLE_GET;
// }
int user_logout_handler(mg_connection* conn, void* cbdata)
{
@ -61,62 +31,5 @@ int user_logout_handler(mg_connection* conn, void* cbdata)
res_logout(conn);
// logout_form_t form = {NULL, NULL};
// mg_form_data_handler logout_callback = {
// .field_found = field_found,
// .field_get = field_get,
// .field_store = NULL,
// .user_data = &form,
// };
// mg_handle_form_request(conn, &logout_callback);
// if (!form.token) {
// res_need_token(conn);
// logout_form_dtor(&form);
// return 1;
// }
// if (!verify_token(form.token, secret)) {
// res_auth_fail(conn);
// logout_form_dtor(&form);
// return 1;
// }
// char* user_id = get_payload(form.token);
// if (form.user_id && strcmp(user_id, form.user_id)) {
// int perm1;
// int flag = get_user_permission(user_id, &perm1);
// if (!flag) {
// res_check_permission_fail(conn);
// }
// int perm2;
// flag = get_user_permission(form.user_id, &perm2);
// if (!flag) {
// res_check_permission_fail(conn);
// }
// if (perm1 < perm2) {
// int flag = logout_user(form.user_id);
// if (!flag) {
// res_logout_fail(conn);
// } else {
// res_logout(conn);
// }
// } else {
// res_permission_denied(conn);
// }
// } else {
// int flag = logout_user(user_id);
// if (!flag) {
// res_logout_account_fail(conn);
// } else {
// res_logout_account(conn);
// }
// }
// free(user_id);
// logout_form_dtor(&form);
return 1;
}

View File

@ -43,17 +43,17 @@ void config_dtor(config_t* this)
if (this->secret) free(this->secret);
}
bool config_read(config_t* this, const char* filename)
int config_read(config_t* this, const char* filename)
{
char* json_data = read_file(filename);
if (json_data == NULL) {
return false;
return 0;
}
cJSON* root = cJSON_Parse(json_data);
if (root == NULL) {
free(json_data);
return false;
return 0;
}
cJSON* server_port = cJSON_GetObjectItem(root, "server_port");
@ -73,5 +73,5 @@ bool config_read(config_t* this, const char* filename)
cJSON_Delete(root);
free(json_data);
return true;
return 1;
}

View File

@ -396,6 +396,16 @@ void res_records_count(mg_connection* conn, int count)
count);
}
void res_have_ac(mg_connection* conn, int status)
{
mg_printf(conn,
"HTTP/1.1 200 OK\r\n"
"Content-Type: application/json\r\n"
"Access-Control-Allow-Origin: *\r\n\r\n"
"{\"success\":\"success to check if have ac\", \"result\":%s}",
status ? "true" : "false");
}
void res_add_set(mg_connection* conn, int id)
{
mg_printf(conn,

View File

@ -139,6 +139,21 @@ static void impl_count(mg_connection* conn)
res_records_count(conn, count);
}
static void impl_have(mg_connection* conn, record_form_t* form)
{
if (!form->user_id) {
res_need_xxx(conn, "user id");
return;
}
if (!form->has_problem_id) {
res_need_xxx(conn, "problem id");
return;
}
int status = have_ac(form->user_id, form->problem_id);
res_have_ac(conn, status);
}
int records_handler(mg_connection* conn, void* cbdata)
{
const mg_request_info* post_body = mg_get_request_info(conn);
@ -176,6 +191,8 @@ int records_handler(mg_connection* conn, void* cbdata)
impl_of(conn, &form);
} else if (!strcmp(form.action, "count")) {
impl_count(conn);
} else if (!strcmp(form.action, "have")) {
impl_have(conn, &form);
} else {
res_bad_action(conn);
}

View File

@ -229,11 +229,7 @@ int sets_handler(mg_connection* conn, void* cbdata)
impl_delete(conn, &form);
}
} else if (!strcmp(form.action, "query")) {
if (result == 2) {
res_permission_denied(conn);
} else {
impl_query(conn, &form);
}
impl_query(conn, &form);
} else if (!strcmp(form.action, "modify")) {
if (result == 2) {
res_permission_denied(conn);