添加检查用户是否有访问权限的功能,优化配置读取返回值
This commit is contained in:
parent
4625978ab1
commit
035448ca00
@ -26,6 +26,8 @@ extern "C"
|
||||
|
||||
int records_count();
|
||||
|
||||
int have_ac(const char* user_id, int problem_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
221
src/main.c
221
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 <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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user