diff --git a/include/db/records.h b/include/db/records.h index 49cf682..99060ed 100644 --- a/include/db/records.h +++ b/include/db/records.h @@ -25,6 +25,8 @@ extern "C" int all_records_of(int problems_id, char** result); int records_count(); + + int have_ac(const char* user_id, int problem_id); #ifdef __cplusplus } diff --git a/include/server/config.h b/include/server/config.h index 94d2151..b89f7c1 100644 --- a/include/server/config.h +++ b/include/server/config.h @@ -1,8 +1,6 @@ #ifndef SERVER_CONFIG_H #define SERVER_CONFIG_H -#include - 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(); diff --git a/include/server/response.h b/include/server/response.h index 2428e89..b20ba9e 100644 --- a/include/server/response.h +++ b/include/server/response.h @@ -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); diff --git a/include/server/study.h b/include/server/study.h index d2547db..e7bc2b6 100644 --- a/include/server/study.h +++ b/include/server/study.h @@ -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; diff --git a/src/db/records.cpp b/src/db/records.cpp index 257766c..afb0201 100644 --- a/src/db/records.cpp +++ b/src/db/records.cpp @@ -2,18 +2,20 @@ #include #include - +#include +#include #include #include - using leveldb_ptr = leveldb::DB*; auto records_db = leveldb_ptr{nullptr}; auto records_count_ = 0; +auto records = std::unordered_map>{}; + 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); + } } \ No newline at end of file diff --git a/src/main.c b/src/main.c index e101db6..626bc2f 100644 --- a/src/main.c +++ b/src/main.c @@ -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 @@ -15,127 +17,162 @@ #include #include -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; } diff --git a/src/server/auth/logout.c b/src/server/auth/logout.c index bb5345e..8531c80 100644 --- a/src/server/auth/logout.c +++ b/src/server/auth/logout.c @@ -14,36 +14,6 @@ #include #include -// 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; } diff --git a/src/server/config.c b/src/server/config.c index e806af4..75839f9 100644 --- a/src/server/config.c +++ b/src/server/config.c @@ -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; } diff --git a/src/server/response.c b/src/server/response.c index b0120af..3289665 100644 --- a/src/server/response.c +++ b/src/server/response.c @@ -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, diff --git a/src/server/study/records.c b/src/server/study/records.c index 4a90e37..5b0431e 100644 --- a/src/server/study/records.c +++ b/src/server/study/records.c @@ -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); } diff --git a/src/server/study/sets.c b/src/server/study/sets.c index fbb2ae5..557a04a 100644 --- a/src/server/study/sets.c +++ b/src/server/study/sets.c @@ -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);