diff --git a/CMakeLists.txt b/CMakeLists.txt index c0f05eb..062756e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,11 +4,14 @@ project(auth_service LANGUAGES C) set(CMAKE_C_STANDARD 23) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_C_FLAGS "-ffunction-sections -fdata-sections") -set(CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections") +if (APPLE) +elseif (UNIX) + set(CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections") +endif() -include_directories(./src/lib/ ${SQLite3_INCLUDE_DIRS}) +include_directories(./src/lib/ ./src ${SQLite3_INCLUDE_DIRS}) -FILE(GLOB_RECURSE SOURCES src/*.c) +FILE(GLOB SOURCES src/*.c src/lib/*.c src/file_db/*.c src/config/*.c src/api/*.c src/database/*.c src/security/*.c src/utils/*.c) option(USE_SQLITE3 "Enable SQLite3 support" OFF) option(USE_WERROR "Enable SQLite3 support" OFF) @@ -16,6 +19,7 @@ option(USE_WERROR "Enable SQLite3 support" OFF) if(USE_SQLITE3) find_package(SQLite3 REQUIRED) add_definitions(-DUSE_SQLITE3) + FILE(GLOB SOURCES src/*.c src/lib/*.c src/sqlite_db/*.c src/file_db/*.c src/config/*.c src/api/*.c src/database/*.c src/security/*.c src/utils/*.c) endif() if(USE_WERROR) diff --git a/Makefile b/Makefile index 3bbe610..e3b98a8 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ CC = gcc CFLAGS = -Wall -g -std=gnu2x -DMG_TLS=MG_TLS_OPENSSL -ffunction-sections -fdata-sections -LDFLAGS = -Wl,--gc-sections +LDFLAGS = INCLUDES = -I./src/lib -I./src -SRCS = $(wildcard src/*/*.c src/*.c) +SRCS = $(wildcard src/lib/*.c src/file_db/*.c src/*.c src/config/*.c src/database/*.c src/api/*.c src/security/*.c src/utils/*.c) OBJS = $(SRCS:.c=.o) TARGET = auth_service BUILD_DIR=./build @@ -11,9 +11,14 @@ LIBS = -lpthread -lcrypto -lssl USE_SQLITE3 ?= 0 WERROR ?= 0 +ifeq ($(shell uname), Linux) + LDFLAGS += -Wl,--gc-sections +endif + ifeq ($(USE_SQLITE3), 1) CFLAGS += -DUSE_SQLITE3 LIBS += -lsqlite3 + SRCS = $(wildcard src/lib/*.c src/sqlite_db/*.c src/file_db/*.c src/*.c src/config/*.c src/database/*.c src/api/*.c src/security/*.c src/utils/*.c) endif ifeq ($(WERROR), 1) diff --git a/meson.build b/meson.build index b51d336..028b0d6 100644 --- a/meson.build +++ b/meson.build @@ -2,17 +2,80 @@ project('auth_service', 'c', default_options: ['c_std=gnu2x']) include_dirs = include_directories('src', 'src/lib') deps = [dependency('openssl')] extra_c_args = ['-ffunction-sections', '-fdata-sections'] -extra_c_link_args = ['-Wl,--gc-sections'] +extra_c_link_args = [] +system = host_machine.system() +if system == 'linux' + extra_c_link_args += ['-Wl,--gc-sections'] +endif sqlite3_dep = dependency('sqlite3', required: false) use_sqlite3 = get_option('use_sqlite3') use_werror = get_option('use_werror') +sources = [ + 'src/main.c', + 'src/api/user.c', + 'src/api/add_user.c', + 'src/api/change_password.c', + 'src/api/change_user.c', + 'src/api/delete_user.c', + 'src/api/get_all_users.c', + 'src/api/get_token.c', + 'src/api/get_user.c', + 'src/api/register_user.c', + 'src/api/verify_token.c', + 'src/utils/utils.c', + 'src/security/jwt.c', + 'src/lib/mongoose.c', + 'src/lib/cJSON.c', + 'src/database/database.c', + 'src/database/db_get_all_users.c', + 'src/database/db_get_user_by_username.c', + 'src/database/db_get_users_from_file.c', + 'src/utils/file.c', + 'src/database/db_insert_user.c', + 'src/database/db_update_user.c', + 'src/database/db_delete_user.c', + 'src/database/db_get_user_by_id.c', + 'src/config/ConfigManager.c', + 'src/config/config.c', + 'src/api/static.c', + 'src/security/cors.c', + 'src/database/db_get_user_field_by_id.c', + 'src/database/db_update_user_field.c', +] + +with_filedb_sources = [ + 'src/file_db/filedb.c', + 'src/file_db/filedb_delete_user.c', + 'src/file_db/filedb_get_all_users.c', + 'src/file_db/filedb_get_user_by_id.c', + 'src/file_db/filedb_get_user_by_username.c', + 'src/file_db/filedb_get_user_field_by_id.c', + 'src/file_db/filedb_insert_user.c', + 'src/file_db/filedb_update_user.c', + 'src/file_db/filedb_update_user_field.c', +] + +with_sqlite3_sources = [ + 'src/sqlite_db/sqlite.c', + 'src/sqlite_db/sqlite_delete_user.c', + 'src/sqlite_db/sqlite_get_all_users.c', + 'src/sqlite_db/sqlite_get_user_by_id.c', + 'src/sqlite_db/sqlite_get_user_by_username.c', + 'src/sqlite_db/sqlite_get_user_field_by_id.c', + 'src/sqlite_db/sqlite_init_db.c', + 'src/sqlite_db/sqlite_insert_user.c', + 'src/sqlite_db/sqlite_migrate_db.c', + 'src/sqlite_db/sqlite_update_user.c', + 'src/sqlite_db/sqlite_update_user_field.c', +] if use_sqlite3 if not sqlite3_dep.found() error('SQLite3 requested but not found') endif deps += sqlite3_dep + sources += with_sqlite3_sources add_project_arguments('-DUSE_SQLITE3', language: 'c') endif @@ -22,36 +85,7 @@ endif executable( 'auth_service', - 'src/main.c', - 'src/user.c', - 'src/add_user.c', - 'src/change_password.c', - 'src/change_user.c', - 'src/delete_user.c', - 'src/get_all_users.c', - 'src/get_token.c', - 'src/get_user.c', - 'src/register_user.c', - 'src/verify_token.c', - 'src/utils.c', - 'src/jwt.c', - 'src/lib/mongoose.c', - 'src/lib/cJSON.c', - 'src/database.c', - 'src/db_get_all_users.c', - 'src/db_get_user_by_username.c', - 'src/db_get_users_from_file.c', - 'src/file.c', - 'src/db_insert_user.c', - 'src/db_update_user.c', - 'src/db_delete_user.c', - 'src/db_get_user_by_id.c', - 'src/ConfigManager.c', - 'src/config.c', - 'src/static.c', - 'src/cors.c', - 'src/db_get_user_field_by_id.c', - 'src/db_update_user_field.c', + sources + with_filedb_sources, include_directories: include_dirs, dependencies: deps, c_args: extra_c_args, diff --git a/src/add_user.c b/src/api/add_user.c similarity index 97% rename from src/add_user.c rename to src/api/add_user.c index e8c8c2b..8a740cd 100644 --- a/src/add_user.c +++ b/src/api/add_user.c @@ -1,6 +1,6 @@ -#include "jwt.h" +#include "security/jwt.h" #include "user.h" -#include "utils.h" +#include "utils/utils.h" void add_user(struct mg_connection *c, struct mg_http_message *hm) { request_with_token *requestdata = check_body(hm); diff --git a/src/change_password.c b/src/api/change_password.c similarity index 98% rename from src/change_password.c rename to src/api/change_password.c index a73d117..e373fef 100644 --- a/src/change_password.c +++ b/src/api/change_password.c @@ -1,7 +1,7 @@ #include "cJSON.h" -#include "jwt.h" +#include "security/jwt.h" #include "user.h" -#include "utils.h" +#include "utils/utils.h" void change_password(struct mg_connection *c, struct mg_http_message *hm) { if (hm->body.len == 0) { diff --git a/src/change_user.c b/src/api/change_user.c similarity index 98% rename from src/change_user.c rename to src/api/change_user.c index 7d260be..8fc57b4 100644 --- a/src/change_user.c +++ b/src/api/change_user.c @@ -1,6 +1,6 @@ -#include "jwt.h" +#include "security/jwt.h" #include "user.h" -#include "utils.h" +#include "utils/utils.h" void change_user(struct mg_connection *c, struct mg_http_message *hm) { if (hm->body.len == 0) { diff --git a/src/delete_user.c b/src/api/delete_user.c similarity index 97% rename from src/delete_user.c rename to src/api/delete_user.c index cedb534..811ff38 100644 --- a/src/delete_user.c +++ b/src/api/delete_user.c @@ -1,6 +1,6 @@ -#include "jwt.h" +#include "security/jwt.h" #include "user.h" -#include "utils.h" +#include "utils/utils.h" void delete_user(struct mg_connection *c, struct mg_http_message *hm) { if (hm->body.len == 0) { diff --git a/src/get_all_users.c b/src/api/get_all_users.c similarity index 94% rename from src/get_all_users.c rename to src/api/get_all_users.c index 1cad438..f48c733 100644 --- a/src/get_all_users.c +++ b/src/api/get_all_users.c @@ -1,6 +1,6 @@ -#include "jwt.h" +#include "security/jwt.h" #include "user.h" -#include "utils.h" +#include "utils/utils.h" void get_all_users(struct mg_connection *c, struct mg_http_message *hm) { request_with_token *data = check_body(hm); diff --git a/src/get_token.c b/src/api/get_token.c similarity index 98% rename from src/get_token.c rename to src/api/get_token.c index 40f5efa..8a2a7b9 100644 --- a/src/get_token.c +++ b/src/api/get_token.c @@ -1,4 +1,4 @@ -#include "jwt.h" +#include "security/jwt.h" #include "user.h" void get_token(struct mg_connection *c, struct mg_http_message *hm) { diff --git a/src/get_user.c b/src/api/get_user.c similarity index 96% rename from src/get_user.c rename to src/api/get_user.c index f3c7626..d2b3e18 100644 --- a/src/get_user.c +++ b/src/api/get_user.c @@ -1,6 +1,6 @@ -#include "jwt.h" +#include "security/jwt.h" #include "user.h" -#include "utils.h" +#include "utils/utils.h" void get_user(struct mg_connection *c, struct mg_http_message *hm) { if (hm->body.len == 0) { diff --git a/src/register_user.c b/src/api/register_user.c similarity index 100% rename from src/register_user.c rename to src/api/register_user.c diff --git a/src/route.h b/src/api/route.h similarity index 100% rename from src/route.h rename to src/api/route.h diff --git a/src/static.c b/src/api/static.c similarity index 88% rename from src/static.c rename to src/api/static.c index 69c5d2a..ac4454a 100644 --- a/src/static.c +++ b/src/api/static.c @@ -1,9 +1,9 @@ #include "static.h" -#include "config.h" +#include "config/config.h" void root_handler(struct mg_connection *c, struct mg_http_message *hm) { struct mg_http_serve_opts opts = { .root_dir = cm_get_parameter_as_string(config, "web")}; mg_http_serve_dir(c, hm, &opts); -} \ No newline at end of file +} diff --git a/src/static.h b/src/api/static.h similarity index 100% rename from src/static.h rename to src/api/static.h diff --git a/src/user.c b/src/api/user.c similarity index 100% rename from src/user.c rename to src/api/user.c diff --git a/src/user.h b/src/api/user.h similarity index 100% rename from src/user.h rename to src/api/user.h diff --git a/src/verify_token.c b/src/api/verify_token.c similarity index 95% rename from src/verify_token.c rename to src/api/verify_token.c index 5ed6237..e3920e4 100644 --- a/src/verify_token.c +++ b/src/api/verify_token.c @@ -1,6 +1,6 @@ -#include "jwt.h" +#include "security/jwt.h" #include "user.h" -#include "utils.h" +#include "utils/utils.h" void verify_token(struct mg_connection *c, struct mg_http_message *hm) { request_with_token *data = check_body(hm); diff --git a/src/ConfigManager.c b/src/config/ConfigManager.c similarity index 99% rename from src/ConfigManager.c rename to src/config/ConfigManager.c index 28b247c..9cb070e 100644 --- a/src/ConfigManager.c +++ b/src/config/ConfigManager.c @@ -6,7 +6,7 @@ #include #include -#include "file.h" +#include "utils/file.h" typedef struct ConfigManager { cJSON *config; diff --git a/src/ConfigManager.h b/src/config/ConfigManager.h similarity index 100% rename from src/ConfigManager.h rename to src/config/ConfigManager.h diff --git a/src/config.c b/src/config/config.c similarity index 100% rename from src/config.c rename to src/config/config.c diff --git a/src/config.h b/src/config/config.h similarity index 100% rename from src/config.h rename to src/config/config.h diff --git a/src/database.h b/src/database.h deleted file mode 100644 index da62dda..0000000 --- a/src/database.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -#ifdef USE_SQLITE3 -#include -extern sqlite3 *db; -extern pthread_mutex_t db_mutex; -#else -extern pthread_mutex_t users_file_mutex; -#endif - -void init_db(); -void migrate_db(); -char *json_escape(const char *str); diff --git a/src/database.c b/src/database/database.c similarity index 67% rename from src/database.c rename to src/database/database.c index 7639e04..cbd371b 100644 --- a/src/database.c +++ b/src/database/database.c @@ -5,25 +5,12 @@ #include #ifdef USE_SQLITE3 -#include "config.h" -#include "sql.h" -#endif - -#ifdef USE_SQLITE3 -sqlite3 *db = nullptr; -pthread_mutex_t db_mutex = PTHREAD_MUTEX_INITIALIZER; -#else -pthread_mutex_t users_file_mutex = PTHREAD_MUTEX_INITIALIZER; +#include "sqlite_db/sqlite.h" #endif void init_db() { #ifdef USE_SQLITE3 - if (sqlite3_open(cm_get_parameter_as_string(config, "database"), &db) != - SQLITE_OK) { - fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db)); - sqlite3_close(db); - exit(1); - } + sqlite_init_db(); #else return; #endif @@ -31,16 +18,7 @@ void init_db() { void migrate_db() { #ifdef USE_SQLITE3 - char *err_msg = 0; - pthread_mutex_lock(&db_mutex); - if (sqlite3_exec(db, CREATE_TABLE_USERS, nullptr, nullptr, &err_msg) != - SQLITE_OK) { - fprintf(stderr, "SQL error: %s\n", err_msg); - sqlite3_free(err_msg); - sqlite3_close(db); - exit(1); - } - pthread_mutex_unlock(&db_mutex); + sqlite_migrate_db(); #else return; #endif diff --git a/src/database/database.h b/src/database/database.h new file mode 100644 index 0000000..0587742 --- /dev/null +++ b/src/database/database.h @@ -0,0 +1,5 @@ +#pragma once + +void init_db(); +void migrate_db(); +char *json_escape(const char *str); diff --git a/src/database/db_delete_user.c b/src/database/db_delete_user.c new file mode 100644 index 0000000..b3e405a --- /dev/null +++ b/src/database/db_delete_user.c @@ -0,0 +1,15 @@ +#include "api/user.h" + +#ifdef USE_SQLITE3 +#include "sqlite_db/sqlite.h" +#else +#include "file_db/filedb.h" +#endif + +bool db_delete_user(const int id) { +#ifdef USE_SQLITE3 + return sqlite_delete_user(id); +#else + return filedb_delete_user(id); +#endif +} diff --git a/src/database/db_get_all_users.c b/src/database/db_get_all_users.c new file mode 100644 index 0000000..e489643 --- /dev/null +++ b/src/database/db_get_all_users.c @@ -0,0 +1,15 @@ +#include "api/user.h" + +#ifdef USE_SQLITE3 +#include "sqlite_db/sqlite.h" +#else +#include "file_db/filedb.h" +#endif + +char *db_get_all_users() { +#ifdef USE_SQLITE3 + return sqlite_get_all_users(); +#else + return filedb_get_all_users(); +#endif +} diff --git a/src/database/db_get_user_by_id.c b/src/database/db_get_user_by_id.c new file mode 100644 index 0000000..d0d1203 --- /dev/null +++ b/src/database/db_get_user_by_id.c @@ -0,0 +1,15 @@ +#include "api/user.h" + +#ifdef USE_SQLITE3 +#include "sqlite_db/sqlite.h" +#else +#include "file_db/filedb.h" +#endif + +User *db_get_user_by_id(const int id) { +#ifdef USE_SQLITE3 + return sqlite_get_user_by_id(id); +#else + return filedb_get_user_by_id(id); +#endif +} diff --git a/src/database/db_get_user_by_username.c b/src/database/db_get_user_by_username.c new file mode 100644 index 0000000..275f725 --- /dev/null +++ b/src/database/db_get_user_by_username.c @@ -0,0 +1,15 @@ +#include "api/user.h" + +#ifdef USE_SQLITE3 +#include "sqlite_db/sqlite.h" +#else +#include "file_db/filedb.h" +#endif + +User *db_get_user_by_username(const char *username) { +#ifdef USE_SQLITE3 + return sqlite_get_user_by_username(username); +#else + return filedb_get_user_by_username(username); +#endif +} diff --git a/src/database/db_get_user_field_by_id.c b/src/database/db_get_user_field_by_id.c new file mode 100644 index 0000000..9885584 --- /dev/null +++ b/src/database/db_get_user_field_by_id.c @@ -0,0 +1,15 @@ +#include "api/user.h" + +#ifdef USE_SQLITE3 +#include "sqlite_db/sqlite.h" +#else +#include "file_db/filedb.h" +#endif + +char *db_get_user_field_by_id(const int id, const char *field) { +#ifdef USE_SQLITE3 + return sqlite_get_user_field_by_id(id, field); +#else + return filedb_get_user_field_by_id(id, field); +#endif +} diff --git a/src/db_get_users_from_file.c b/src/database/db_get_users_from_file.c similarity index 95% rename from src/db_get_users_from_file.c rename to src/database/db_get_users_from_file.c index 1730021..b0aa112 100644 --- a/src/db_get_users_from_file.c +++ b/src/database/db_get_users_from_file.c @@ -1,6 +1,6 @@ #include -#include "file.h" -#include "user.h" +#include "utils/file.h" +#include "api/user.h" void db_get_users_from_file(const char *path) { char *users_string = read_file(path); diff --git a/src/database/db_insert_user.c b/src/database/db_insert_user.c new file mode 100644 index 0000000..51dbc62 --- /dev/null +++ b/src/database/db_insert_user.c @@ -0,0 +1,17 @@ +#include "api/user.h" + +#ifdef USE_SQLITE3 +#include "sqlite_db/sqlite.h" +#else +#include "file_db/filedb.h" +#endif + +User *db_insert_user(const char *username, const char *email, + const char *password, const char *group, + const bool *is_superuser) { +#ifdef USE_SQLITE3 + return sqlite_insert_user(username, email, password, group, is_superuser); +#else + return filedb_insert_user(username, email, password, group, is_superuser); +#endif +} diff --git a/src/database/db_update_user.c b/src/database/db_update_user.c new file mode 100644 index 0000000..c0eddfa --- /dev/null +++ b/src/database/db_update_user.c @@ -0,0 +1,19 @@ +#include "api/user.h" + +#ifdef USE_SQLITE3 +#include "sqlite_db/sqlite.h" +#else +#include "file_db/filedb.h" +#endif + +User *db_update_user(const int userid, const char *username, const char *email, + const char *password, const char *group, + const bool *is_superuser) { +#ifdef USE_SQLITE3 + return sqlite_update_user(userid, username, email, password, group, + is_superuser); +#else + return filedb_update_user(userid, username, email, password, group, + is_superuser); +#endif +} diff --git a/src/database/db_update_user_field.c b/src/database/db_update_user_field.c new file mode 100644 index 0000000..46bd030 --- /dev/null +++ b/src/database/db_update_user_field.c @@ -0,0 +1,15 @@ +#include "api/user.h" + +#ifdef USE_SQLITE3 +#include "sqlite_db/sqlite.h" +#else +#include "file_db/filedb.h" +#endif + +bool db_update_user_field(const int id, const char *field, const char *value) { +#ifdef USE_SQLITE3 + return sqlite_update_user_field(id, field, value); +#else + return filedb_update_user_field(id, field, value); +#endif +} diff --git a/src/db_delete_user.c b/src/db_delete_user.c deleted file mode 100644 index 039f997..0000000 --- a/src/db_delete_user.c +++ /dev/null @@ -1,79 +0,0 @@ -#include "database.h" -#include "user.h" - -#ifdef USE_SQLITE3 -#include "sql.h" -#else -#include "file.h" -#endif - -bool db_delete_user(const int id) { -#ifdef USE_SQLITE3 - pthread_mutex_lock(&db_mutex); - if (!db) { - fprintf(stderr, "Database not initialized\n"); - pthread_mutex_unlock(&db_mutex); - return false; - } - sqlite3_stmt *stmt; - int rc; - - rc = sqlite3_prepare_v2(db, DELETE_USER_SQL, -1, &stmt, 0); - if (rc != SQLITE_OK) { - fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db)); - pthread_mutex_unlock(&db_mutex); - return false; - } - - sqlite3_bind_int(stmt, 1, id); - - rc = sqlite3_step(stmt); - if (rc != SQLITE_DONE) { - fprintf(stderr, "Execution failed: %s\n", sqlite3_errmsg(db)); - sqlite3_finalize(stmt); - pthread_mutex_unlock(&db_mutex); - return false; - } - - int changes = sqlite3_changes(db); - sqlite3_finalize(stmt); - - if (changes > 0) { - printf("User deleted successfully. ID: %d\n", id); - } else { - printf("No user found with ID: %d\n", id); - pthread_mutex_unlock(&db_mutex); - return false; - } - - pthread_mutex_unlock(&db_mutex); - return true; -#else - pthread_mutex_lock(&users_file_mutex); - char *data = read_file("users_db.json"); - cJSON *users = cJSON_Parse(data); - cJSON *user = nullptr; - int index = 0; - bool found = false; - cJSON_ArrayForEach(user, users) { - cJSON *user_id = cJSON_GetObjectItem(user, "id"); - if (user_id->valueint == id) { - cJSON_DeleteItemFromArray(users, index); - found = true; - break; - } - index++; - } - if (!found) { - pthread_mutex_unlock(&users_file_mutex); - return false; - } - char *new_data = cJSON_Print(users); - write_file("users_db.json", new_data); - free(new_data); - free(data); - cJSON_Delete(users); - pthread_mutex_unlock(&users_file_mutex); - return true; -#endif -} diff --git a/src/db_get_user_by_id.c b/src/db_get_user_by_id.c deleted file mode 100644 index c25a67e..0000000 --- a/src/db_get_user_by_id.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "database.h" -#include "user.h" - -#ifdef USE_SQLITE3 -#include "sql.h" -#else -#include "cJSON.h" -#include "file.h" -#endif - -User *db_get_user_by_id(const int id) { -#ifdef USE_SQLITE3 - User *user = nullptr; - pthread_mutex_lock(&db_mutex); - if (!db) { - fprintf(stderr, "Database not initialized\n"); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - sqlite3_stmt *stmt; - int rc = sqlite3_prepare_v2(db, SELECT_USER_BY_ID_SQL, -1, &stmt, nullptr); - if (rc != SQLITE_OK) { - fprintf(stderr, "Cannot prepare statement: %s\n", sqlite3_errmsg(db)); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - - sqlite3_bind_int(stmt, 1, id); - - while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { - int id = sqlite3_column_int(stmt, 0); - const unsigned char *db_username = sqlite3_column_text(stmt, 1); - const unsigned char *db_email = sqlite3_column_text(stmt, 2); - const unsigned char *db_password = sqlite3_column_text(stmt, 3); - const unsigned char *db_group = sqlite3_column_text(stmt, 4); - int db_is_superuser = sqlite3_column_int(stmt, 5); - user = new_user(id, (char *) db_username, (char *) db_password, - (char *) db_email, (char *) db_group, db_is_superuser); - } - - if (rc != SQLITE_DONE) { - fprintf(stderr, "Error reading data: %s\n", sqlite3_errmsg(db)); - free_user(user); - sqlite3_finalize(stmt); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - - pthread_mutex_unlock(&db_mutex); - return user; -#else - pthread_mutex_lock(&users_file_mutex); - char *data = read_file("users_db.json"); - cJSON *users = cJSON_Parse(data); - cJSON *user = nullptr; - User *found = nullptr; - cJSON_ArrayForEach(user, users) { - cJSON *user_id = cJSON_GetObjectItem(user, "id"); - cJSON *user_username = cJSON_GetObjectItem(user, "username"); - cJSON *user_password = cJSON_GetObjectItem(user, "password"); - cJSON *user_email = cJSON_GetObjectItem(user, "email"); - cJSON *user_group = cJSON_GetObjectItem(user, "group"); - cJSON *user_is_superuser = cJSON_GetObjectItem(user, "is_superuser"); - if (user_id->valueint == id) { - found = new_user(user_id->valueint, user_username->valuestring, - user_password->valuestring, user_email->valuestring, - user_group->valuestring, user_is_superuser->valueint); - break; - } - } - if (found == nullptr) { - pthread_mutex_unlock(&users_file_mutex); - // if (user != nullptr) cJSON_Delete(user); - cJSON_Delete(users); - free(data); - return nullptr; - } - pthread_mutex_unlock(&users_file_mutex); - // if (user != nullptr) cJSON_Delete(user); - cJSON_Delete(users); - free(data); - return found; -#endif -} diff --git a/src/db_get_user_by_username.c b/src/db_get_user_by_username.c deleted file mode 100644 index 5dc30a5..0000000 --- a/src/db_get_user_by_username.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "database.h" -#include "user.h" - -#ifdef USE_SQLITE3 -#include "sql.h" -#else -#include "cJSON.h" -#include "file.h" -#endif - -User *db_get_user_by_username(const char *username) { -#ifdef USE_SQLITE3 - User *user = nullptr; - pthread_mutex_lock(&db_mutex); - if (!db) { - fprintf(stderr, "Database not initialized\n"); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - sqlite3_stmt *stmt; - int rc = - sqlite3_prepare_v2(db, SELECT_USER_BY_USERNAME_SQL, -1, &stmt, nullptr); - if (rc != SQLITE_OK) { - fprintf(stderr, "Cannot prepare statement: %s\n", sqlite3_errmsg(db)); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - - sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC); - - while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { - int id = sqlite3_column_int(stmt, 0); - const unsigned char *db_username = sqlite3_column_text(stmt, 1); - const unsigned char *db_email = sqlite3_column_text(stmt, 2); - const unsigned char *db_password = sqlite3_column_text(stmt, 3); - const unsigned char *db_group = sqlite3_column_text(stmt, 4); - int db_is_superuser = sqlite3_column_int(stmt, 5); - user = new_user(id, (char *) db_username, (char *) db_password, - (char *) db_email, (char *) db_group, db_is_superuser); - } - - if (rc != SQLITE_DONE) { - fprintf(stderr, "Error reading data: %s\n", sqlite3_errmsg(db)); - free_user(user); - sqlite3_finalize(stmt); - return nullptr; - } - - pthread_mutex_unlock(&db_mutex); - return user; -#else - pthread_mutex_lock(&users_file_mutex); - char *data = read_file("users_db.json"); - cJSON *users = cJSON_Parse(data); - cJSON *user = nullptr; - User *found = nullptr; - cJSON_ArrayForEach(user, users) { - cJSON *user_id = cJSON_GetObjectItem(user, "id"); - cJSON *user_username = cJSON_GetObjectItem(user, "username"); - cJSON *user_password = cJSON_GetObjectItem(user, "password"); - cJSON *user_email = cJSON_GetObjectItem(user, "email"); - cJSON *user_group = cJSON_GetObjectItem(user, "group"); - cJSON *user_is_superuser = cJSON_GetObjectItem(user, "is_superuser"); - if (!strcmp(user_username->valuestring, username)) { - found = new_user(user_id->valueint, user_username->valuestring, - user_password->valuestring, user_email->valuestring, - user_group->valuestring, user_is_superuser->valueint); - break; - } - } - if (found == nullptr) { - pthread_mutex_unlock(&users_file_mutex); - // if (user != nullptr) cJSON_Delete(user); - cJSON_Delete(users); - free(data); - return nullptr; - } - pthread_mutex_unlock(&users_file_mutex); - // if (user != nullptr) cJSON_Delete(user); - cJSON_Delete(users); - free(data); - return found; -#endif -} diff --git a/src/db_get_user_field_by_id.c b/src/db_get_user_field_by_id.c deleted file mode 100644 index bb74908..0000000 --- a/src/db_get_user_field_by_id.c +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include "database.h" -#include "user.h" - -#ifdef USE_SQLITE3 -#include "sql.h" -#else -#include "file.h" -#endif - -char *db_get_user_field_by_id(const int id, const char *field) { -#ifdef USE_SQLITE3 - char *password = nullptr; - pthread_mutex_lock(&db_mutex); - if (!db) { - fprintf(stderr, "Database not initialized\n"); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - char sql[256]; - snprintf(sql, sizeof(sql), SELECT_USER_FIELD_SQL, field); - sqlite3_stmt *stmt; - int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr); - if (rc != SQLITE_OK) { - fprintf(stderr, "Cannot prepare statement: %s\n", sqlite3_errmsg(db)); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - sqlite3_bind_int(stmt, 1, id); - rc = sqlite3_step(stmt); - if (rc == SQLITE_ROW) { - const unsigned char *db_password = sqlite3_column_text(stmt, 0); - password = malloc(strlen((const char *) db_password) + 1); - if (password) { - strcpy(password, (const char *) db_password); - } - sqlite3_finalize(stmt); - } else if (rc == SQLITE_DONE) { - fprintf(stderr, "Can't find user"); - sqlite3_finalize(stmt); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } else { - fprintf(stderr, "Error executing query: %s\n", sqlite3_errmsg(db)); - sqlite3_finalize(stmt); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - pthread_mutex_unlock(&db_mutex); - return password; -#else - pthread_mutex_lock(&users_file_mutex); - char *data = read_file("users_db.json"); - cJSON *users = cJSON_Parse(data); - cJSON *user = nullptr; - User *found = nullptr; - cJSON_ArrayForEach(user, users) { - cJSON *user_id = cJSON_GetObjectItem(user, "id"); - cJSON *user_username = cJSON_GetObjectItem(user, "username"); - cJSON *user_password = cJSON_GetObjectItem(user, "password"); - cJSON *user_email = cJSON_GetObjectItem(user, "email"); - cJSON *user_group = cJSON_GetObjectItem(user, "group"); - cJSON *user_is_superuser = cJSON_GetObjectItem(user, "is_superuser"); - if (user_id->valueint == id) { - found = new_user(user_id->valueint, user_username->valuestring, - user_password->valuestring, user_email->valuestring, - user_group->valuestring, user_is_superuser->valueint); - break; - } - } - if (found == nullptr) { - pthread_mutex_unlock(&users_file_mutex); - // if (user != nullptr) cJSON_Delete(user); - cJSON_Delete(users); - free(data); - return nullptr; - } - pthread_mutex_unlock(&users_file_mutex); - // if (user != nullptr) cJSON_Delete(user); - cJSON_Delete(users); - free(data); - return found->password; -#endif -} diff --git a/src/db_insert_user.c b/src/db_insert_user.c deleted file mode 100644 index b32f0c2..0000000 --- a/src/db_insert_user.c +++ /dev/null @@ -1,119 +0,0 @@ -#include "database.h" -#include "user.h" - -#ifdef USE_SQLITE3 -#include "sql.h" -#else -#include "cJSON.h" -#include "file.h" -#endif - -User *db_insert_user(const char *username, const char *email, - const char *password, const char *group, - const bool *is_superuser) { -#ifdef USE_SQLITE3 - pthread_mutex_lock(&db_mutex); - if (!db) { - fprintf(stderr, "Databse not initialized\n"); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - if (!username || !email || !password) { - fprintf(stderr, "username, email, password connot be empty\n"); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - const char *sql = nullptr; - sqlite3_stmt *stmt; - int rc; - if (!group || !is_superuser) { - sql = INSERT_USER_USERNAME_EMAIL_PASSWORD_SQL; - } else if (!group) { - sql = INSERT_USER_USERNAME_EMAIL_PASSWORD_GROUP_SQL; - } else { - sql = INSERT_USER_FULL_SQL; - } - rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - fprintf(stderr, "Cannot prepare statement: %s\n", sqlite3_errmsg(db)); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - - sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC); - sqlite3_bind_text(stmt, 2, email, -1, SQLITE_STATIC); - sqlite3_bind_text(stmt, 3, password, -1, SQLITE_STATIC); - - if (group) { - sqlite3_bind_text(stmt, 4, group, -1, SQLITE_STATIC); - } - if (is_superuser) { - sqlite3_bind_int(stmt, 5, *is_superuser); - } - - rc = sqlite3_step(stmt); - if (rc != SQLITE_DONE) { - fprintf(stderr, "Execution failed: %s\n", sqlite3_errmsg(db)); - sqlite3_finalize(stmt); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - - int inserted_id = sqlite3_last_insert_rowid(db); - - sqlite3_finalize(stmt); - printf("User inserted successfully. ID: %d\n", inserted_id); - pthread_mutex_unlock(&db_mutex); - User *new_db_user = - new_user(inserted_id, username, email, password, group, is_superuser); - return new_db_user; -#else - pthread_mutex_lock(&users_file_mutex); - char *data = read_file("users_db.json"); - cJSON *users = cJSON_Parse(data); - cJSON *user = nullptr; - int users_size = 0; - bool found = false; - cJSON_ArrayForEach(user, users) { - cJSON *user_username = cJSON_GetObjectItem(user, "username"); - cJSON *user_password = cJSON_GetObjectItem(user, "password"); - cJSON *user_email = cJSON_GetObjectItem(user, "email"); - cJSON *user_group = cJSON_GetObjectItem(user, "group"); - if (!strcmp(user_username->valuestring, username) && - !strcmp(user_password->valuestring, password) && - !strcmp(user_email->valuestring, email) && - !strcmp(user_group->valuestring, group)) { - found = true; - } - users_size++; - } - if (found == true) { - pthread_mutex_unlock(&users_file_mutex); - return nullptr; - } - cJSON *new_user_data = cJSON_CreateObject(); - cJSON_AddNumberToObject(new_user_data, "id", users_size); - cJSON_AddStringToObject(new_user_data, "username", username); - cJSON_AddStringToObject(new_user_data, "password", password); - cJSON_AddStringToObject(new_user_data, "email", email); - cJSON_AddStringToObject(new_user_data, "group", group); - cJSON_AddBoolToObject(new_user_data, "is_superuser", *is_superuser); - char *new_user_data_string = cJSON_Print(new_user_data); - if (users_size == 0) { - users = cJSON_CreateArray(); - } - cJSON_AddItemToArray(users, new_user_data); - char *new_data = cJSON_Print(users); - write_file("users_db.json", new_data); - pthread_mutex_unlock(&users_file_mutex); - User *return_user = - new_user(users_size, username, email, password, group, is_superuser); - free(new_data); - free(data); - free(new_user_data_string); - // cJSON_Delete(new_user_data); - cJSON_Delete(users); - if (user != nullptr) cJSON_Delete(user); - return return_user; -#endif -} diff --git a/src/db_update_user.c b/src/db_update_user.c deleted file mode 100644 index 2707dda..0000000 --- a/src/db_update_user.c +++ /dev/null @@ -1,97 +0,0 @@ -#include -#include "database.h" -#include "user.h" - -#ifdef USE_SQLITE3 -#include "sql.h" -#else -#include "cJSON.h" -#include "file.h" -#endif - -User *db_update_user(const int userid, const char *username, const char *email, - const char *password, const char *group, - const bool *is_superuser) { -#ifdef USE_SQLITE3 - pthread_mutex_lock(&db_mutex); - if (!db) { - fprintf(stderr, "Databse not initialized\n"); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - if (!username || !email || !password || !group || !is_superuser) { - fprintf(stderr, - "username, email, password, group, is_superuser connot be empty\n"); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - sqlite3_stmt *stmt; - int rc; - - rc = sqlite3_prepare_v2(db, UPDATE_USER_FULL_SQL, -1, &stmt, 0); - if (rc != SQLITE_OK) { - fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db)); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC); - sqlite3_bind_text(stmt, 2, email, -1, SQLITE_STATIC); - sqlite3_bind_text(stmt, 3, password, -1, SQLITE_STATIC); - sqlite3_bind_text(stmt, 4, group, -1, SQLITE_STATIC); - sqlite3_bind_int(stmt, 5, *is_superuser); - sqlite3_bind_int(stmt, 6, userid); - - rc = sqlite3_step(stmt); - if (rc != SQLITE_DONE) { - fprintf(stderr, "Execution failed: %s\n", sqlite3_errmsg(db)); - sqlite3_finalize(stmt); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - - int changes = sqlite3_changes(db); - sqlite3_finalize(stmt); - - if (changes > 0) { - printf("User updated successfully. ID: %d\n", userid); - } else { - printf("No user found with ID: %d\n", userid); - return nullptr; - } - pthread_mutex_unlock(&db_mutex); - return new_user(userid, username, email, password, group, is_superuser); -#else - pthread_mutex_lock(&users_file_mutex); - char *data = read_file("users_db.json"); - cJSON *users = cJSON_Parse(data); - cJSON *user = nullptr; - cJSON_ArrayForEach(user, users) { - cJSON *user_id = cJSON_GetObjectItem(user, "id"); - if (user_id->valueint == userid) { - cJSON *user_username = cJSON_GetObjectItem(user, "username"); - cJSON *user_password = cJSON_GetObjectItem(user, "password"); - cJSON *user_email = cJSON_GetObjectItem(user, "email"); - cJSON *user_group = cJSON_GetObjectItem(user, "group"); - cJSON_SetValuestring(user_username, username); - cJSON_SetValuestring(user_password, password); - cJSON_SetValuestring(user_email, email); - cJSON_SetValuestring(user_group, group); - cJSON_DeleteItemFromObject(user, "is_superuser"); - cJSON_AddBoolToObject(user, "is_superuser", *is_superuser); - char *new_data = cJSON_Print(users); - write_file("users_db.json", new_data); - free(new_data); - free(data); - cJSON_Delete(users); - User *ret = - new_user(userid, username, password, email, group, is_superuser); - pthread_mutex_unlock(&users_file_mutex); - return ret; - } - } - free(data); - cJSON_Delete(users); - pthread_mutex_unlock(&users_file_mutex); - return nullptr; -#endif -} diff --git a/src/db_update_user_field.c b/src/db_update_user_field.c deleted file mode 100644 index 7351093..0000000 --- a/src/db_update_user_field.c +++ /dev/null @@ -1,75 +0,0 @@ -#include "database.h" -#include "user.h" - -#ifdef USE_SQLITE3 -#include "sql.h" -#else -#include "cJSON.h" -#include "file.h" -#endif - -bool db_update_user_field(const int id, const char *field, const char *value) { -#ifdef USE_SQLITE3 - pthread_mutex_lock(&db_mutex); - if (!db || !field || !value) { - fprintf(stderr, "invalid parameters\n"); - pthread_mutex_unlock(&db_mutex); - return false; - } - char sql[256]; - snprintf(sql, sizeof(sql), UPDATE_USER_FIELD_SQL, field); - - sqlite3_stmt *stmt; - int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0); - if (rc != SQLITE_OK) { - fprintf(stderr, "failed to prepare statement: %s\n", sqlite3_errmsg(db)); - pthread_mutex_unlock(&db_mutex); - return false; - } - sqlite3_bind_text(stmt, 1, value, -1, SQLITE_STATIC); - sqlite3_bind_int(stmt, 2, id); - - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - - if (rc != SQLITE_DONE) { - fprintf(stderr, "execution failed: %s\n", sqlite3_errmsg(db)); - pthread_mutex_unlock(&db_mutex); - return false; - } - pthread_mutex_unlock(&db_mutex); - return sqlite3_changes(db) > 0; -#else - pthread_mutex_lock(&users_file_mutex); - char *data = read_file("users_db.json"); - cJSON *users = cJSON_Parse(data); - cJSON *user = nullptr; - cJSON_ArrayForEach(user, users) { - cJSON *user_id = cJSON_GetObjectItem(user, "id"); - if (user_id->valueint == id) { - cJSON *user_field = cJSON_GetObjectItem(user, field); - if (cJSON_IsNumber(user_field)) { - // cJSON_SetNumberValue(user_field, value); - return false; - } else if (cJSON_IsBool(user_field)) { - // cJSON_DeleteItemFromObject(user, field); - // cJSON_AddBoolToObject(user, field, value); - return false; - } else if (cJSON_IsString(user_field)) { - cJSON_SetValuestring(user_field, value); - } - char *new_data = cJSON_Print(users); - write_file("users_db.json", new_data); - free(new_data); - free(data); - cJSON_Delete(users); - pthread_mutex_unlock(&users_file_mutex); - return true; - } - } - free(data); - cJSON_Delete(users); - pthread_mutex_unlock(&users_file_mutex); - return false; -#endif -} diff --git a/src/file_db/filedb.c b/src/file_db/filedb.c new file mode 100644 index 0000000..3c9fab1 --- /dev/null +++ b/src/file_db/filedb.c @@ -0,0 +1,4 @@ +#include "filedb.h" +#include + +pthread_mutex_t users_file_mutex = PTHREAD_MUTEX_INITIALIZER; diff --git a/src/file_db/filedb.h b/src/file_db/filedb.h new file mode 100644 index 0000000..e923e5c --- /dev/null +++ b/src/file_db/filedb.h @@ -0,0 +1,19 @@ +#pragma once + +#include "api/user.h" + +extern pthread_mutex_t users_file_mutex; + +bool filedb_delete_user(const int id); +char *filedb_get_all_users(); +User *filedb_get_user_by_id(const int id); +User *filedb_get_user_by_username(const char *username); +char *filedb_get_user_field_by_id(const int id, const char *field); +User *filedb_insert_user(const char *username, const char *email, + const char *password, const char *group, + const bool *is_superuser); +User *filedb_update_user(const int userid, const char *username, + const char *email, const char *password, + const char *group, const bool *is_superuser); +bool filedb_update_user_field(const int id, const char *field, + const char *value); diff --git a/src/file_db/filedb_delete_user.c b/src/file_db/filedb_delete_user.c new file mode 100644 index 0000000..da99b05 --- /dev/null +++ b/src/file_db/filedb_delete_user.c @@ -0,0 +1,34 @@ +#include +#include +#include "utils/file.h" +#include "cJSON.h" +#include "filedb.h" + +bool filedb_delete_user(const int id) { + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + cJSON *users = cJSON_Parse(data); + cJSON *user = nullptr; + int index = 0; + bool found = false; + cJSON_ArrayForEach(user, users) { + cJSON *user_id = cJSON_GetObjectItem(user, "id"); + if (user_id->valueint == id) { + cJSON_DeleteItemFromArray(users, index); + found = true; + break; + } + index++; + } + if (!found) { + pthread_mutex_unlock(&users_file_mutex); + return false; + } + char *new_data = cJSON_Print(users); + write_file("users_db.json", new_data); + free(new_data); + free(data); + cJSON_Delete(users); + pthread_mutex_unlock(&users_file_mutex); + return true; +} diff --git a/src/file_db/filedb_get_all_users.c b/src/file_db/filedb_get_all_users.c new file mode 100644 index 0000000..42ab6af --- /dev/null +++ b/src/file_db/filedb_get_all_users.c @@ -0,0 +1,10 @@ +#include +#include "utils/file.h" +#include "filedb.h" + +char *filedb_get_all_users() { + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + pthread_mutex_unlock(&users_file_mutex); + return data; +} diff --git a/src/file_db/filedb_get_user_by_id.c b/src/file_db/filedb_get_user_by_id.c new file mode 100644 index 0000000..3bae35c --- /dev/null +++ b/src/file_db/filedb_get_user_by_id.c @@ -0,0 +1,37 @@ +#include +#include "utils/file.h" +#include "filedb.h" + +User *filedb_get_user_by_id(const int id) { + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + cJSON *users = cJSON_Parse(data); + cJSON *user = nullptr; + User *found = nullptr; + cJSON_ArrayForEach(user, users) { + cJSON *user_id = cJSON_GetObjectItem(user, "id"); + cJSON *user_username = cJSON_GetObjectItem(user, "username"); + cJSON *user_password = cJSON_GetObjectItem(user, "password"); + cJSON *user_email = cJSON_GetObjectItem(user, "email"); + cJSON *user_group = cJSON_GetObjectItem(user, "group"); + cJSON *user_is_superuser = cJSON_GetObjectItem(user, "is_superuser"); + if (user_id->valueint == id) { + found = new_user(user_id->valueint, user_username->valuestring, + user_password->valuestring, user_email->valuestring, + user_group->valuestring, user_is_superuser->valueint); + break; + } + } + if (found == nullptr) { + pthread_mutex_unlock(&users_file_mutex); + // if (user != nullptr) cJSON_Delete(user); + cJSON_Delete(users); + free(data); + return nullptr; + } + pthread_mutex_unlock(&users_file_mutex); + // if (user != nullptr) cJSON_Delete(user); + cJSON_Delete(users); + free(data); + return found; +} diff --git a/src/file_db/filedb_get_user_by_username.c b/src/file_db/filedb_get_user_by_username.c new file mode 100644 index 0000000..587df8a --- /dev/null +++ b/src/file_db/filedb_get_user_by_username.c @@ -0,0 +1,37 @@ +#include +#include "utils/file.h" +#include "filedb.h" + +User *filedb_get_user_by_username(const char *username) { + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + cJSON *users = cJSON_Parse(data); + cJSON *user = nullptr; + User *found = nullptr; + cJSON_ArrayForEach(user, users) { + cJSON *user_id = cJSON_GetObjectItem(user, "id"); + cJSON *user_username = cJSON_GetObjectItem(user, "username"); + cJSON *user_password = cJSON_GetObjectItem(user, "password"); + cJSON *user_email = cJSON_GetObjectItem(user, "email"); + cJSON *user_group = cJSON_GetObjectItem(user, "group"); + cJSON *user_is_superuser = cJSON_GetObjectItem(user, "is_superuser"); + if (!strcmp(user_username->valuestring, username)) { + found = new_user(user_id->valueint, user_username->valuestring, + user_password->valuestring, user_email->valuestring, + user_group->valuestring, user_is_superuser->valueint); + break; + } + } + if (found == nullptr) { + pthread_mutex_unlock(&users_file_mutex); + // if (user != nullptr) cJSON_Delete(user); + cJSON_Delete(users); + free(data); + return nullptr; + } + pthread_mutex_unlock(&users_file_mutex); + // if (user != nullptr) cJSON_Delete(user); + cJSON_Delete(users); + free(data); + return found; +} diff --git a/src/file_db/filedb_get_user_field_by_id.c b/src/file_db/filedb_get_user_field_by_id.c new file mode 100644 index 0000000..ee45cf6 --- /dev/null +++ b/src/file_db/filedb_get_user_field_by_id.c @@ -0,0 +1,37 @@ +#include +#include "utils/file.h" +#include "filedb.h" + +char *filedb_get_user_field_by_id(const int id, const char *field) { + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + cJSON *users = cJSON_Parse(data); + cJSON *user = nullptr; + User *found = nullptr; + cJSON_ArrayForEach(user, users) { + cJSON *user_id = cJSON_GetObjectItem(user, "id"); + cJSON *user_username = cJSON_GetObjectItem(user, "username"); + cJSON *user_password = cJSON_GetObjectItem(user, "password"); + cJSON *user_email = cJSON_GetObjectItem(user, "email"); + cJSON *user_group = cJSON_GetObjectItem(user, "group"); + cJSON *user_is_superuser = cJSON_GetObjectItem(user, "is_superuser"); + if (user_id->valueint == id) { + found = new_user(user_id->valueint, user_username->valuestring, + user_password->valuestring, user_email->valuestring, + user_group->valuestring, user_is_superuser->valueint); + break; + } + } + if (found == nullptr) { + pthread_mutex_unlock(&users_file_mutex); + // if (user != nullptr) cJSON_Delete(user); + cJSON_Delete(users); + free(data); + return nullptr; + } + pthread_mutex_unlock(&users_file_mutex); + // if (user != nullptr) cJSON_Delete(user); + cJSON_Delete(users); + free(data); + return found->password; +} diff --git a/src/file_db/filedb_insert_user.c b/src/file_db/filedb_insert_user.c new file mode 100644 index 0000000..8b84370 --- /dev/null +++ b/src/file_db/filedb_insert_user.c @@ -0,0 +1,55 @@ +#include +#include "utils/file.h" +#include "filedb.h" + +User *filedb_insert_user(const char *username, const char *email, + const char *password, const char *group, + const bool *is_superuser) { + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + cJSON *users = cJSON_Parse(data); + cJSON *user = nullptr; + int users_size = 0; + bool found = false; + cJSON_ArrayForEach(user, users) { + cJSON *user_username = cJSON_GetObjectItem(user, "username"); + cJSON *user_password = cJSON_GetObjectItem(user, "password"); + cJSON *user_email = cJSON_GetObjectItem(user, "email"); + cJSON *user_group = cJSON_GetObjectItem(user, "group"); + if (!strcmp(user_username->valuestring, username) && + !strcmp(user_password->valuestring, password) && + !strcmp(user_email->valuestring, email) && + !strcmp(user_group->valuestring, group)) { + found = true; + } + users_size++; + } + if (found == true) { + pthread_mutex_unlock(&users_file_mutex); + return nullptr; + } + cJSON *new_user_data = cJSON_CreateObject(); + cJSON_AddNumberToObject(new_user_data, "id", users_size); + cJSON_AddStringToObject(new_user_data, "username", username); + cJSON_AddStringToObject(new_user_data, "password", password); + cJSON_AddStringToObject(new_user_data, "email", email); + cJSON_AddStringToObject(new_user_data, "group", group); + cJSON_AddBoolToObject(new_user_data, "is_superuser", *is_superuser); + char *new_user_data_string = cJSON_Print(new_user_data); + if (users_size == 0) { + users = cJSON_CreateArray(); + } + cJSON_AddItemToArray(users, new_user_data); + char *new_data = cJSON_Print(users); + write_file("users_db.json", new_data); + pthread_mutex_unlock(&users_file_mutex); + User *return_user = + new_user(users_size, username, email, password, group, is_superuser); + free(new_data); + free(data); + free(new_user_data_string); + // cJSON_Delete(new_user_data); + cJSON_Delete(users); + if (user != nullptr) cJSON_Delete(user); + return return_user; +} diff --git a/src/file_db/filedb_update_user.c b/src/file_db/filedb_update_user.c new file mode 100644 index 0000000..279bca7 --- /dev/null +++ b/src/file_db/filedb_update_user.c @@ -0,0 +1,40 @@ +#include +#include "utils/file.h" +#include "filedb.h" + +User *filedb_update_user(const int userid, const char *username, + const char *email, const char *password, + const char *group, const bool *is_superuser) { + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + cJSON *users = cJSON_Parse(data); + cJSON *user = nullptr; + cJSON_ArrayForEach(user, users) { + cJSON *user_id = cJSON_GetObjectItem(user, "id"); + if (user_id->valueint == userid) { + cJSON *user_username = cJSON_GetObjectItem(user, "username"); + cJSON *user_password = cJSON_GetObjectItem(user, "password"); + cJSON *user_email = cJSON_GetObjectItem(user, "email"); + cJSON *user_group = cJSON_GetObjectItem(user, "group"); + cJSON_SetValuestring(user_username, username); + cJSON_SetValuestring(user_password, password); + cJSON_SetValuestring(user_email, email); + cJSON_SetValuestring(user_group, group); + cJSON_DeleteItemFromObject(user, "is_superuser"); + cJSON_AddBoolToObject(user, "is_superuser", *is_superuser); + char *new_data = cJSON_Print(users); + write_file("users_db.json", new_data); + free(new_data); + free(data); + cJSON_Delete(users); + User *ret = + new_user(userid, username, password, email, group, is_superuser); + pthread_mutex_unlock(&users_file_mutex); + return ret; + } + } + free(data); + cJSON_Delete(users); + pthread_mutex_unlock(&users_file_mutex); + return nullptr; +} diff --git a/src/file_db/filedb_update_user_field.c b/src/file_db/filedb_update_user_field.c new file mode 100644 index 0000000..7f587b8 --- /dev/null +++ b/src/file_db/filedb_update_user_field.c @@ -0,0 +1,38 @@ +#include +#include "utils/file.h" +#include "filedb.h" + +bool filedb_update_user_field(const int id, const char *field, + const char *value) { + pthread_mutex_lock(&users_file_mutex); + char *data = read_file("users_db.json"); + cJSON *users = cJSON_Parse(data); + cJSON *user = nullptr; + cJSON_ArrayForEach(user, users) { + cJSON *user_id = cJSON_GetObjectItem(user, "id"); + if (user_id->valueint == id) { + cJSON *user_field = cJSON_GetObjectItem(user, field); + if (cJSON_IsNumber(user_field)) { + // cJSON_SetNumberValue(user_field, value); + return false; + } else if (cJSON_IsBool(user_field)) { + // cJSON_DeleteItemFromObject(user, field); + // cJSON_AddBoolToObject(user, field, value); + return false; + } else if (cJSON_IsString(user_field)) { + cJSON_SetValuestring(user_field, value); + } + char *new_data = cJSON_Print(users); + write_file("users_db.json", new_data); + free(new_data); + free(data); + cJSON_Delete(users); + pthread_mutex_unlock(&users_file_mutex); + return true; + } + } + free(data); + cJSON_Delete(users); + pthread_mutex_unlock(&users_file_mutex); + return false; +} diff --git a/src/main.c b/src/main.c index a0e3754..51a31e8 100644 --- a/src/main.c +++ b/src/main.c @@ -5,13 +5,13 @@ #include #endif -#include "config.h" -#include "cors.h" -#include "database.h" -#include "file.h" -#include "route.h" -#include "static.h" -#include "user.h" +#include "config/config.h" +#include "security/cors.h" +#include "database/database.h" +#include "utils/file.h" +#include "api/route.h" +#include "api/static.h" +#include "api/user.h" static const struct route routes[] = { {"GET", "/#", root_handler}, diff --git a/src/cors.c b/src/security/cors.c similarity index 100% rename from src/cors.c rename to src/security/cors.c diff --git a/src/cors.h b/src/security/cors.h similarity index 100% rename from src/cors.h rename to src/security/cors.h diff --git a/src/jwt.c b/src/security/jwt.c similarity index 100% rename from src/jwt.c rename to src/security/jwt.c diff --git a/src/jwt.h b/src/security/jwt.h similarity index 100% rename from src/jwt.h rename to src/security/jwt.h diff --git a/src/sql.h b/src/sqlite_db/sql.h similarity index 100% rename from src/sql.h rename to src/sqlite_db/sql.h diff --git a/src/sqlite_db/sqlite.c b/src/sqlite_db/sqlite.c new file mode 100644 index 0000000..0d4f27b --- /dev/null +++ b/src/sqlite_db/sqlite.c @@ -0,0 +1,5 @@ +#include "sqlite.h" +#include "pthread.h" + +sqlite3 *db = nullptr; +pthread_mutex_t db_mutex = PTHREAD_MUTEX_INITIALIZER; diff --git a/src/sqlite_db/sqlite.h b/src/sqlite_db/sqlite.h new file mode 100644 index 0000000..3e1a171 --- /dev/null +++ b/src/sqlite_db/sqlite.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include "api/user.h" + +extern sqlite3 *db; +extern pthread_mutex_t db_mutex; + +void sqlite_init_db(); +void sqlite_migrate_db(); +bool sqlite_delete_user(const int id); +char *sqlite_get_all_users(); +User *sqlite_get_user_by_id(const int id); +User *sqlite_get_user_by_username(const char *username); +char *sqlite_get_user_field_by_id(const int id, const char *field); +User *sqlite_insert_user(const char *username, const char *email, + const char *password, const char *group, + const bool *is_superuser); +User *sqlite_update_user(const int userid, const char *username, + const char *email, const char *password, + const char *group, const bool *is_superuser); +bool sqlite_update_user_field(const int id, const char *field, + const char *value); diff --git a/src/sqlite_db/sqlite_delete_user.c b/src/sqlite_db/sqlite_delete_user.c new file mode 100644 index 0000000..7c8f54a --- /dev/null +++ b/src/sqlite_db/sqlite_delete_user.c @@ -0,0 +1,46 @@ +#include "sqlite.h" +#include "sql.h" +#include +#include "pthread.h" + +bool sqlite_delete_user(const int id) { + pthread_mutex_lock(&db_mutex); + if (!db) { + fprintf(stderr, "Database not initialized\n"); + pthread_mutex_unlock(&db_mutex); + return false; + } + sqlite3_stmt *stmt; + int rc; + + rc = sqlite3_prepare_v2(db, DELETE_USER_SQL, -1, &stmt, 0); + if (rc != SQLITE_OK) { + fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db)); + pthread_mutex_unlock(&db_mutex); + return false; + } + + sqlite3_bind_int(stmt, 1, id); + + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + fprintf(stderr, "Execution failed: %s\n", sqlite3_errmsg(db)); + sqlite3_finalize(stmt); + pthread_mutex_unlock(&db_mutex); + return false; + } + + int changes = sqlite3_changes(db); + sqlite3_finalize(stmt); + + if (changes > 0) { + printf("User deleted successfully. ID: %d\n", id); + } else { + printf("No user found with ID: %d\n", id); + pthread_mutex_unlock(&db_mutex); + return false; + } + + pthread_mutex_unlock(&db_mutex); + return true; +} diff --git a/src/db_get_all_users.c b/src/sqlite_db/sqlite_get_all_users.c similarity index 90% rename from src/db_get_all_users.c rename to src/sqlite_db/sqlite_get_all_users.c index 2471c96..9c57c3d 100644 --- a/src/db_get_all_users.c +++ b/src/sqlite_db/sqlite_get_all_users.c @@ -1,14 +1,12 @@ -#include "database.h" -#include "user.h" - -#ifdef USE_SQLITE3 +#include +#include +#include +#include +#include "database/database.h" #include "sql.h" -#else -#include "file.h" -#endif +#include "sqlite.h" -char *db_get_all_users() { -#ifdef USE_SQLITE3 +char *sqlite_get_all_users() { pthread_mutex_lock(&db_mutex); if (!db) { fprintf(stderr, "Database not initialized\n"); @@ -101,10 +99,4 @@ char *db_get_all_users() { sqlite3_finalize(stmt); pthread_mutex_unlock(&db_mutex); return result; -#else - pthread_mutex_lock(&users_file_mutex); - char *data = read_file("users_db.json"); - pthread_mutex_unlock(&users_file_mutex); - return data; -#endif } diff --git a/src/sqlite_db/sqlite_get_user_by_id.c b/src/sqlite_db/sqlite_get_user_by_id.c new file mode 100644 index 0000000..7058297 --- /dev/null +++ b/src/sqlite_db/sqlite_get_user_by_id.c @@ -0,0 +1,44 @@ +#include "sql.h" +#include "sqlite.h" +#include "pthread.h" + +User *sqlite_get_user_by_id(const int id) { + User *user = nullptr; + pthread_mutex_lock(&db_mutex); + if (!db) { + fprintf(stderr, "Database not initialized\n"); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + sqlite3_stmt *stmt; + int rc = sqlite3_prepare_v2(db, SELECT_USER_BY_ID_SQL, -1, &stmt, nullptr); + if (rc != SQLITE_OK) { + fprintf(stderr, "Cannot prepare statement: %s\n", sqlite3_errmsg(db)); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + + sqlite3_bind_int(stmt, 1, id); + + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + int id = sqlite3_column_int(stmt, 0); + const unsigned char *db_username = sqlite3_column_text(stmt, 1); + const unsigned char *db_email = sqlite3_column_text(stmt, 2); + const unsigned char *db_password = sqlite3_column_text(stmt, 3); + const unsigned char *db_group = sqlite3_column_text(stmt, 4); + int db_is_superuser = sqlite3_column_int(stmt, 5); + user = new_user(id, (char *) db_username, (char *) db_password, + (char *) db_email, (char *) db_group, db_is_superuser); + } + + if (rc != SQLITE_DONE) { + fprintf(stderr, "Error reading data: %s\n", sqlite3_errmsg(db)); + free_user(user); + sqlite3_finalize(stmt); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + + pthread_mutex_unlock(&db_mutex); + return user; +} diff --git a/src/sqlite_db/sqlite_get_user_by_username.c b/src/sqlite_db/sqlite_get_user_by_username.c new file mode 100644 index 0000000..1c5bf21 --- /dev/null +++ b/src/sqlite_db/sqlite_get_user_by_username.c @@ -0,0 +1,44 @@ +#include "sql.h" +#include "sqlite.h" +#include "pthread.h" + +User *sqlite_get_user_by_username(const char *username) { + User *user = nullptr; + pthread_mutex_lock(&db_mutex); + if (!db) { + fprintf(stderr, "Database not initialized\n"); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + sqlite3_stmt *stmt; + int rc = + sqlite3_prepare_v2(db, SELECT_USER_BY_USERNAME_SQL, -1, &stmt, nullptr); + if (rc != SQLITE_OK) { + fprintf(stderr, "Cannot prepare statement: %s\n", sqlite3_errmsg(db)); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + + sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC); + + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + int id = sqlite3_column_int(stmt, 0); + const unsigned char *db_username = sqlite3_column_text(stmt, 1); + const unsigned char *db_email = sqlite3_column_text(stmt, 2); + const unsigned char *db_password = sqlite3_column_text(stmt, 3); + const unsigned char *db_group = sqlite3_column_text(stmt, 4); + int db_is_superuser = sqlite3_column_int(stmt, 5); + user = new_user(id, (char *) db_username, (char *) db_password, + (char *) db_email, (char *) db_group, db_is_superuser); + } + + if (rc != SQLITE_DONE) { + fprintf(stderr, "Error reading data: %s\n", sqlite3_errmsg(db)); + free_user(user); + sqlite3_finalize(stmt); + return nullptr; + } + + pthread_mutex_unlock(&db_mutex); + return user; +} diff --git a/src/sqlite_db/sqlite_get_user_field_by_id.c b/src/sqlite_db/sqlite_get_user_field_by_id.c new file mode 100644 index 0000000..a58f823 --- /dev/null +++ b/src/sqlite_db/sqlite_get_user_field_by_id.c @@ -0,0 +1,44 @@ +#include "pthread.h" +#include "sql.h" +#include "sqlite.h" + +char *sqlite_get_user_field_by_id(const int id, const char *field) { + char *password = nullptr; + pthread_mutex_lock(&db_mutex); + if (!db) { + fprintf(stderr, "Database not initialized\n"); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + char sql[256]; + snprintf(sql, sizeof(sql), SELECT_USER_FIELD_SQL, field); + sqlite3_stmt *stmt; + int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr); + if (rc != SQLITE_OK) { + fprintf(stderr, "Cannot prepare statement: %s\n", sqlite3_errmsg(db)); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + sqlite3_bind_int(stmt, 1, id); + rc = sqlite3_step(stmt); + if (rc == SQLITE_ROW) { + const unsigned char *db_password = sqlite3_column_text(stmt, 0); + password = malloc(strlen((const char *) db_password) + 1); + if (password) { + strcpy(password, (const char *) db_password); + } + sqlite3_finalize(stmt); + } else if (rc == SQLITE_DONE) { + fprintf(stderr, "Can't find user"); + sqlite3_finalize(stmt); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } else { + fprintf(stderr, "Error executing query: %s\n", sqlite3_errmsg(db)); + sqlite3_finalize(stmt); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + pthread_mutex_unlock(&db_mutex); + return password; +} diff --git a/src/sqlite_db/sqlite_init_db.c b/src/sqlite_db/sqlite_init_db.c new file mode 100644 index 0000000..5b275fc --- /dev/null +++ b/src/sqlite_db/sqlite_init_db.c @@ -0,0 +1,11 @@ +#include "../config/config.h" +#include "sqlite.h" + +void sqlite_init_db() { + if (sqlite3_open(cm_get_parameter_as_string(config, "database"), &db) != + SQLITE_OK) { + fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db)); + sqlite3_close(db); + exit(1); + } +} diff --git a/src/sqlite_db/sqlite_insert_user.c b/src/sqlite_db/sqlite_insert_user.c new file mode 100644 index 0000000..37e1a39 --- /dev/null +++ b/src/sqlite_db/sqlite_insert_user.c @@ -0,0 +1,63 @@ +#include "pthread.h" +#include "sql.h" +#include "sqlite.h" + +User *sqlite_insert_user(const char *username, const char *email, + const char *password, const char *group, + const bool *is_superuser) { + pthread_mutex_lock(&db_mutex); + if (!db) { + fprintf(stderr, "Databse not initialized\n"); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + if (!username || !email || !password) { + fprintf(stderr, "username, email, password connot be empty\n"); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + const char *sql = nullptr; + sqlite3_stmt *stmt; + int rc; + if (!group || !is_superuser) { + sql = INSERT_USER_USERNAME_EMAIL_PASSWORD_SQL; + } else if (!group) { + sql = INSERT_USER_USERNAME_EMAIL_PASSWORD_GROUP_SQL; + } else { + sql = INSERT_USER_FULL_SQL; + } + rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + fprintf(stderr, "Cannot prepare statement: %s\n", sqlite3_errmsg(db)); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + + sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 2, email, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 3, password, -1, SQLITE_STATIC); + + if (group) { + sqlite3_bind_text(stmt, 4, group, -1, SQLITE_STATIC); + } + if (is_superuser) { + sqlite3_bind_int(stmt, 5, *is_superuser); + } + + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + fprintf(stderr, "Execution failed: %s\n", sqlite3_errmsg(db)); + sqlite3_finalize(stmt); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + + int inserted_id = sqlite3_last_insert_rowid(db); + + sqlite3_finalize(stmt); + printf("User inserted successfully. ID: %d\n", inserted_id); + pthread_mutex_unlock(&db_mutex); + User *new_db_user = + new_user(inserted_id, username, email, password, group, is_superuser); + return new_db_user; +} diff --git a/src/sqlite_db/sqlite_migrate_db.c b/src/sqlite_db/sqlite_migrate_db.c new file mode 100644 index 0000000..d145803 --- /dev/null +++ b/src/sqlite_db/sqlite_migrate_db.c @@ -0,0 +1,16 @@ +#include "pthread.h" +#include "sql.h" +#include "sqlite.h" + +void sqlite_migrate_db() { + char *err_msg = 0; + pthread_mutex_lock(&db_mutex); + if (sqlite3_exec(db, CREATE_TABLE_USERS, nullptr, nullptr, &err_msg) != + SQLITE_OK) { + fprintf(stderr, "SQL error: %s\n", err_msg); + sqlite3_free(err_msg); + sqlite3_close(db); + exit(1); + } + pthread_mutex_unlock(&db_mutex); +} diff --git a/src/sqlite_db/sqlite_update_user.c b/src/sqlite_db/sqlite_update_user.c new file mode 100644 index 0000000..457265c --- /dev/null +++ b/src/sqlite_db/sqlite_update_user.c @@ -0,0 +1,55 @@ +#include "pthread.h" +#include "sql.h" +#include "sqlite.h" + +User *sqlite_update_user(const int userid, const char *username, + const char *email, const char *password, + const char *group, const bool *is_superuser) { + pthread_mutex_lock(&db_mutex); + if (!db) { + fprintf(stderr, "Databse not initialized\n"); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + if (!username || !email || !password || !group || !is_superuser) { + fprintf(stderr, + "username, email, password, group, is_superuser connot be empty\n"); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + sqlite3_stmt *stmt; + int rc; + + rc = sqlite3_prepare_v2(db, UPDATE_USER_FULL_SQL, -1, &stmt, 0); + if (rc != SQLITE_OK) { + fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db)); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 2, email, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 3, password, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 4, group, -1, SQLITE_STATIC); + sqlite3_bind_int(stmt, 5, *is_superuser); + sqlite3_bind_int(stmt, 6, userid); + + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + fprintf(stderr, "Execution failed: %s\n", sqlite3_errmsg(db)); + sqlite3_finalize(stmt); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + + int changes = sqlite3_changes(db); + sqlite3_finalize(stmt); + + if (changes > 0) { + printf("User updated successfully. ID: %d\n", userid); + } else { + printf("No user found with ID: %d\n", userid); + return nullptr; + } + pthread_mutex_unlock(&db_mutex); + return new_user(userid, username, email, password, group, is_superuser); +} diff --git a/src/sqlite_db/sqlite_update_user_field.c b/src/sqlite_db/sqlite_update_user_field.c new file mode 100644 index 0000000..93c202d --- /dev/null +++ b/src/sqlite_db/sqlite_update_user_field.c @@ -0,0 +1,36 @@ +#include "pthread.h" +#include "sql.h" +#include "sqlite.h" + +bool sqlite_update_user_field(const int id, const char *field, + const char *value) { + pthread_mutex_lock(&db_mutex); + if (!db || !field || !value) { + fprintf(stderr, "invalid parameters\n"); + pthread_mutex_unlock(&db_mutex); + return false; + } + char sql[256]; + snprintf(sql, sizeof(sql), UPDATE_USER_FIELD_SQL, field); + + sqlite3_stmt *stmt; + int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0); + if (rc != SQLITE_OK) { + fprintf(stderr, "failed to prepare statement: %s\n", sqlite3_errmsg(db)); + pthread_mutex_unlock(&db_mutex); + return false; + } + sqlite3_bind_text(stmt, 1, value, -1, SQLITE_STATIC); + sqlite3_bind_int(stmt, 2, id); + + rc = sqlite3_step(stmt); + sqlite3_finalize(stmt); + + if (rc != SQLITE_DONE) { + fprintf(stderr, "execution failed: %s\n", sqlite3_errmsg(db)); + pthread_mutex_unlock(&db_mutex); + return false; + } + pthread_mutex_unlock(&db_mutex); + return sqlite3_changes(db) > 0; +} diff --git a/src/file.c b/src/utils/file.c similarity index 100% rename from src/file.c rename to src/utils/file.c diff --git a/src/file.h b/src/utils/file.h similarity index 100% rename from src/file.h rename to src/utils/file.h diff --git a/src/utils.c b/src/utils/utils.c similarity index 96% rename from src/utils.c rename to src/utils/utils.c index 2c1a018..6fb49d9 100644 --- a/src/utils.c +++ b/src/utils/utils.c @@ -3,7 +3,7 @@ #include #include -#include "user.h" +#include "api/user.h" request_with_token *check_body(const struct mg_http_message *hm) { if (hm->body.len == 0) { diff --git a/src/utils.h b/src/utils/utils.h similarity index 78% rename from src/utils.h rename to src/utils/utils.h index e8bf573..6ad8c75 100644 --- a/src/utils.h +++ b/src/utils/utils.h @@ -1,5 +1,5 @@ #pragma once -#include "user.h" +#include "api/user.h" request_with_token *check_body(const struct mg_http_message *hm);