diff --git a/Makefile b/Makefile index 3bbe610..74b7b36 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CC = gcc CFLAGS = -Wall -g -std=gnu2x -DMG_TLS=MG_TLS_OPENSSL -ffunction-sections -fdata-sections LDFLAGS = -Wl,--gc-sections INCLUDES = -I./src/lib -I./src -SRCS = $(wildcard src/*/*.c src/*.c) +SRCS = $(wildcard src/lib/*.c src/file_db/*.c src/*.c) OBJS = $(SRCS:.c=.o) TARGET = auth_service BUILD_DIR=./build @@ -14,6 +14,7 @@ WERROR ?= 0 ifeq ($(USE_SQLITE3), 1) CFLAGS += -DUSE_SQLITE3 LIBS += -lsqlite3 + SRCS = $(wildcard src/lib/*.c src/sqlite_db/*.c src/file_db/*.c src/*.c) endif ifeq ($(WERROR), 1) diff --git a/meson.build b/meson.build index b51d336..277563b 100644 --- a/meson.build +++ b/meson.build @@ -7,21 +7,7 @@ extra_c_link_args = ['-Wl,--gc-sections'] sqlite3_dep = dependency('sqlite3', required: false) use_sqlite3 = get_option('use_sqlite3') use_werror = get_option('use_werror') - -if use_sqlite3 - if not sqlite3_dep.found() - error('SQLite3 requested but not found') - endif - deps += sqlite3_dep - add_project_arguments('-DUSE_SQLITE3', language: 'c') -endif - -if use_werror - add_project_arguments('-Werror', language: 'c') -endif - -executable( - 'auth_service', +sources = [ 'src/main.c', 'src/user.c', 'src/add_user.c', @@ -52,6 +38,50 @@ executable( 'src/cors.c', 'src/db_get_user_field_by_id.c', 'src/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 + +if use_werror + add_project_arguments('-Werror', language: 'c') +endif + +executable( + 'auth_service', + sources + with_filedb_sources, include_directories: include_dirs, dependencies: deps, c_args: extra_c_args, diff --git a/src/database.c b/src/database.c index 7639e04..cbd371b 100644 --- a/src/database.c +++ b/src/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.h b/src/database.h index da62dda..0587742 100644 --- a/src/database.h +++ b/src/database.h @@ -1,15 +1,5 @@ #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/db_delete_user.c b/src/db_delete_user.c index 039f997..e0c1820 100644 --- a/src/db_delete_user.c +++ b/src/db_delete_user.c @@ -1,79 +1,15 @@ -#include "database.h" #include "user.h" #ifdef USE_SQLITE3 -#include "sql.h" +#include "sqlite_db/sqlite.h" #else -#include "file.h" +#include "file_db/filedb.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; + return sqlite_delete_user(id); #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; + return filedb_delete_user(id); #endif } diff --git a/src/db_get_all_users.c b/src/db_get_all_users.c index 2471c96..66763de 100644 --- a/src/db_get_all_users.c +++ b/src/db_get_all_users.c @@ -1,110 +1,15 @@ -#include "database.h" #include "user.h" #ifdef USE_SQLITE3 -#include "sql.h" +#include "sqlite_db/sqlite.h" #else -#include "file.h" +#include "file_db/filedb.h" #endif char *db_get_all_users() { #ifdef USE_SQLITE3 - 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; - - rc = sqlite3_prepare_v2(db, SELECT_ALL_USERS_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; - } - - char *result = malloc(1024); - if (!result) { - sqlite3_finalize(stmt); - pthread_mutex_unlock(&db_mutex); - return nullptr; - } - - strcpy(result, "["); - size_t result_size = strlen(result); - size_t result_capacity = 1024; - - int first_record = 1; - - while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { - int id = sqlite3_column_int(stmt, 0); - const unsigned char *username = sqlite3_column_text(stmt, 1); - const unsigned char *email = sqlite3_column_text(stmt, 2); - const unsigned char *group = sqlite3_column_text(stmt, 4); - int is_superuser = sqlite3_column_int(stmt, 5); - - char *escaped_username = json_escape((const char *) username); - char *escaped_email = json_escape((const char *) email); - char *escaped_group = json_escape((const char *) group); - if (!escaped_username || !escaped_email || !escaped_group) { - free(escaped_username); - free(escaped_email); - free(escaped_group); - sqlite3_finalize(stmt); - return NULL; - } - - char record[512]; - if (sqlite3_column_type(stmt, 2) == SQLITE_NULL) { - snprintf(record, sizeof(record), - "%s{\"id\":%d,\"username\":\"%s\",\"email\":\"%s\",\"group\":" - "\"%s\",\"is_superuser\":%s}", - first_record ? "" : ",", id, escaped_username, escaped_email, - escaped_group, is_superuser ? "true" : "false"); - } else { - snprintf(record, sizeof(record), - "%s{\"id\":%d,\"username\":\"%s\",\"email\":\"%s\",\"group\":" - "\"%s\",\"is_superuser\":%s}", - first_record ? "" : ",", id, escaped_username, escaped_email, - escaped_group, is_superuser ? "true" : "false"); - } - - free(escaped_username); - free(escaped_email); - free(escaped_group); - - size_t record_len = strlen(record); - if (result_size + record_len + 10 > result_capacity) { - result_capacity *= 2; - char *new_result = realloc(result, result_capacity); - if (!new_result) { - free(result); - sqlite3_finalize(stmt); - return nullptr; - } - result = new_result; - } - strcat(result, record); - result_size += record_len; - first_record = 0; - } - - if (rc != SQLITE_DONE) { - fprintf(stderr, "Error reading data: %s\n", sqlite3_errmsg(db)); - free(result); - sqlite3_finalize(stmt); - return NULL; - } - strcat(result, "]"); - sqlite3_finalize(stmt); - pthread_mutex_unlock(&db_mutex); - return result; + return sqlite_get_all_users(); #else - pthread_mutex_lock(&users_file_mutex); - char *data = read_file("users_db.json"); - pthread_mutex_unlock(&users_file_mutex); - return data; + return filedb_get_all_users(); #endif } diff --git a/src/db_get_user_by_id.c b/src/db_get_user_by_id.c index c25a67e..cff7836 100644 --- a/src/db_get_user_by_id.c +++ b/src/db_get_user_by_id.c @@ -1,84 +1,15 @@ -#include "database.h" #include "user.h" #ifdef USE_SQLITE3 -#include "sql.h" +#include "sqlite_db/sqlite.h" #else -#include "cJSON.h" -#include "file.h" +#include "file_db/filedb.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; + return sqlite_get_user_by_id(id); #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; + return filedb_get_user_by_id(id); #endif } diff --git a/src/db_get_user_by_username.c b/src/db_get_user_by_username.c index 5dc30a5..8766fa6 100644 --- a/src/db_get_user_by_username.c +++ b/src/db_get_user_by_username.c @@ -1,84 +1,15 @@ -#include "database.h" #include "user.h" #ifdef USE_SQLITE3 -#include "sql.h" +#include "sqlite_db/sqlite.h" #else -#include "cJSON.h" -#include "file.h" +#include "file_db/filedb.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; + return sqlite_get_user_by_username(username); #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; + return filedb_get_user_by_username(username); #endif } diff --git a/src/db_get_user_field_by_id.c b/src/db_get_user_field_by_id.c index bb74908..40c6cb3 100644 --- a/src/db_get_user_field_by_id.c +++ b/src/db_get_user_field_by_id.c @@ -1,84 +1,15 @@ -#include -#include "database.h" #include "user.h" #ifdef USE_SQLITE3 -#include "sql.h" +#include "sqlite_db/sqlite.h" #else -#include "file.h" +#include "file_db/filedb.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; + return sqlite_get_user_field_by_id(id, field); #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; + return filedb_get_user_field_by_id(id, field); #endif } diff --git a/src/db_insert_user.c b/src/db_insert_user.c index b32f0c2..107d02f 100644 --- a/src/db_insert_user.c +++ b/src/db_insert_user.c @@ -1,119 +1,17 @@ -#include "database.h" #include "user.h" #ifdef USE_SQLITE3 -#include "sql.h" +#include "sqlite_db/sqlite.h" #else -#include "cJSON.h" -#include "file.h" +#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 - 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; + return sqlite_insert_user(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; - 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; + return filedb_insert_user(username, email, password, group, is_superuser); #endif } diff --git a/src/db_update_user.c b/src/db_update_user.c index 2707dda..0109069 100644 --- a/src/db_update_user.c +++ b/src/db_update_user.c @@ -1,97 +1,19 @@ -#include -#include "database.h" #include "user.h" #ifdef USE_SQLITE3 -#include "sql.h" +#include "sqlite_db/sqlite.h" #else -#include "cJSON.h" -#include "file.h" +#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 - 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); + return sqlite_update_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; + return filedb_update_user(userid, username, email, password, group, + is_superuser); #endif } diff --git a/src/db_update_user_field.c b/src/db_update_user_field.c index 7351093..a4f52f3 100644 --- a/src/db_update_user_field.c +++ b/src/db_update_user_field.c @@ -1,75 +1,15 @@ -#include "database.h" #include "user.h" #ifdef USE_SQLITE3 -#include "sql.h" +#include "sqlite_db/sqlite.h" #else -#include "cJSON.h" -#include "file.h" +#include "file_db/filedb.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; + return sqlite_update_user_field(id, field, value); #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; + return filedb_update_user_field(id, field, value); #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..d861fff --- /dev/null +++ b/src/file_db/filedb.h @@ -0,0 +1,19 @@ +#pragma once + +#include "../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..257430b --- /dev/null +++ b/src/file_db/filedb_delete_user.c @@ -0,0 +1,34 @@ +#include +#include +#include "../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..d20c3b4 --- /dev/null +++ b/src/file_db/filedb_get_all_users.c @@ -0,0 +1,10 @@ +#include +#include "../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..88be3b2 --- /dev/null +++ b/src/file_db/filedb_get_user_by_id.c @@ -0,0 +1,37 @@ +#include +#include "../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..65ef941 --- /dev/null +++ b/src/file_db/filedb_get_user_by_username.c @@ -0,0 +1,37 @@ +#include +#include "../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..82859de --- /dev/null +++ b/src/file_db/filedb_get_user_field_by_id.c @@ -0,0 +1,37 @@ +#include +#include "../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..89da731 --- /dev/null +++ b/src/file_db/filedb_insert_user.c @@ -0,0 +1,55 @@ +#include +#include "../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..06593d8 --- /dev/null +++ b/src/file_db/filedb_update_user.c @@ -0,0 +1,40 @@ +#include +#include "../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..fd386ff --- /dev/null +++ b/src/file_db/filedb_update_user_field.c @@ -0,0 +1,38 @@ +#include +#include "../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/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..926a09f --- /dev/null +++ b/src/sqlite_db/sqlite.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include "../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/sqlite_db/sqlite_get_all_users.c b/src/sqlite_db/sqlite_get_all_users.c new file mode 100644 index 0000000..556ae62 --- /dev/null +++ b/src/sqlite_db/sqlite_get_all_users.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include "../database.h" +#include "sql.h" +#include "sqlite.h" + +char *sqlite_get_all_users() { + 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; + + rc = sqlite3_prepare_v2(db, SELECT_ALL_USERS_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; + } + + char *result = malloc(1024); + if (!result) { + sqlite3_finalize(stmt); + pthread_mutex_unlock(&db_mutex); + return nullptr; + } + + strcpy(result, "["); + size_t result_size = strlen(result); + size_t result_capacity = 1024; + + int first_record = 1; + + while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) { + int id = sqlite3_column_int(stmt, 0); + const unsigned char *username = sqlite3_column_text(stmt, 1); + const unsigned char *email = sqlite3_column_text(stmt, 2); + const unsigned char *group = sqlite3_column_text(stmt, 4); + int is_superuser = sqlite3_column_int(stmt, 5); + + char *escaped_username = json_escape((const char *) username); + char *escaped_email = json_escape((const char *) email); + char *escaped_group = json_escape((const char *) group); + if (!escaped_username || !escaped_email || !escaped_group) { + free(escaped_username); + free(escaped_email); + free(escaped_group); + sqlite3_finalize(stmt); + return NULL; + } + + char record[512]; + if (sqlite3_column_type(stmt, 2) == SQLITE_NULL) { + snprintf(record, sizeof(record), + "%s{\"id\":%d,\"username\":\"%s\",\"email\":\"%s\",\"group\":" + "\"%s\",\"is_superuser\":%s}", + first_record ? "" : ",", id, escaped_username, escaped_email, + escaped_group, is_superuser ? "true" : "false"); + } else { + snprintf(record, sizeof(record), + "%s{\"id\":%d,\"username\":\"%s\",\"email\":\"%s\",\"group\":" + "\"%s\",\"is_superuser\":%s}", + first_record ? "" : ",", id, escaped_username, escaped_email, + escaped_group, is_superuser ? "true" : "false"); + } + + free(escaped_username); + free(escaped_email); + free(escaped_group); + + size_t record_len = strlen(record); + if (result_size + record_len + 10 > result_capacity) { + result_capacity *= 2; + char *new_result = realloc(result, result_capacity); + if (!new_result) { + free(result); + sqlite3_finalize(stmt); + return nullptr; + } + result = new_result; + } + strcat(result, record); + result_size += record_len; + first_record = 0; + } + + if (rc != SQLITE_DONE) { + fprintf(stderr, "Error reading data: %s\n", sqlite3_errmsg(db)); + free(result); + sqlite3_finalize(stmt); + return NULL; + } + strcat(result, "]"); + sqlite3_finalize(stmt); + pthread_mutex_unlock(&db_mutex); + return result; +} 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..8af19c9 --- /dev/null +++ b/src/sqlite_db/sqlite_init_db.c @@ -0,0 +1,11 @@ +#include "../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; +}