added update user change user and change password

This commit is contained in:
wt committed 2025-08-23 00:30:45 +07:00
1 parent 33e8bed178
commit 9c3a8d796a
14 files changed
+278 -45

No files matched your search

+3
View File
@@ -23,6 +23,9 @@ executable(
'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',
include_directories: include_dirs,
dependencies: deps,
)
+40 -1
View File
@@ -10,8 +10,47 @@ void add_user(struct mg_connection *c, struct mg_http_message *hm) {
MG_ESC("invalid token"));
return;
}
cJSON *jsonbody = cJSON_Parse(hm->body.buf);
cJSON *username = cJSON_GetObjectItem(jsonbody, "username");
cJSON *password = cJSON_GetObjectItem(jsonbody, "password");
cJSON *email = cJSON_GetObjectItem(jsonbody, "email");
cJSON *group = cJSON_GetObjectItem(jsonbody, "group");
cJSON *is_superuser = cJSON_GetObjectItem(jsonbody, "is_superuser");
if (username == nullptr || password == nullptr || email == nullptr ||
is_superuser == nullptr || group == nullptr) {
mg_http_reply(c, 400, "", "{%m:%m}", MG_ESC("error"),
MG_ESC("must have <username>, <password>, <email>, <group, "
"optional>, <is_superuser, optional>"));
return;
}
cJSON *payload = jwt_get_payload(requestdata->token);
bool jwt_is_superuser =
cJSON_GetObjectItem(payload, "is_superuser")->valueint;
if (!jwt_is_superuser) {
mg_http_reply(c, 403, "", "{%m:%m}", MG_ESC("error"),
MG_ESC("not authorized"));
cJSON_Delete(payload);
return;
}
const bool user_is_superuser = is_superuser->valueint ? true : false;
User *new_db_user = db_insert_user(
username->valuestring, email->valuestring, password->valuestring,
group->valuestring,
&user_is_superuser);
if (!new_db_user) {
mg_http_reply(c, 500, "", "{%m:%m}", MG_ESC("error"),
MG_ESC("failed to create user"));
cJSON_Delete(payload);
return;
}
char responsedata[2048] = {0};
snprintf(responsedata, sizeof(responsedata), "{\"success\": true}");
snprintf(responsedata, sizeof(responsedata),
"{\"username\":\"%s\",\"email\":\"%s\",\"group\":\"%s\",\"is_"
"superuser\":%s}",
username->valuestring, email->valuestring, group->valuestring,
is_superuser->valueint ? "true" : "false");
mg_http_reply(c, 200, "Content-Type: application/json\r\n", responsedata);
cJSON_Delete(payload);
}
+31
View File
@@ -10,8 +10,39 @@ void change_password(struct mg_connection *c, struct mg_http_message *hm) {
MG_ESC("invalid token"));
return;
}
cJSON *jsonbody = cJSON_Parse(hm->body.buf);
cJSON *old_password = cJSON_GetObjectItem(jsonbody, "old_password");
cJSON *new_password = cJSON_GetObjectItem(jsonbody, "new_password");
if (old_password == nullptr || new_password == nullptr) {
mg_http_reply(c, 400, "", "{%m:%m}", MG_ESC("error"),
MG_ESC("must have <old_password>, <new_password>"));
return;
}
cJSON *payload = jwt_get_payload(requestdata->token);
char *username = cJSON_GetObjectItem(payload, "username")->valuestring;
User *old_user_data = db_get_user_by_username(username);
char *password = old_user_data->password;
if (strcmp(password, old_password->valuestring)) {
mg_http_reply(c, 400, "", "{%m:%m}", MG_ESC("error"),
MG_ESC("invalid old password"));
return;
}
const bool old_is_superuser = old_user_data->is_superuser;
User *new_user_data = db_update_user(
old_user_data->id, old_user_data->username, old_user_data->email,
new_password->valuestring, old_user_data->group, &old_is_superuser);
if (!new_user_data) {
mg_http_reply(c, 500, "", "{%m:%m}", MG_ESC("error"),
MG_ESC("failed to update user"));
return;
}
char responsedata[64] = {0};
snprintf(responsedata, sizeof(responsedata), "{\"success\": true}");
mg_http_reply(c, 200, "Content-Type: application/json\r\n", responsedata);
// free(username);
free_user(old_user_data);
cJSON_Delete(payload);
}
+51 -1
View File
@@ -10,8 +10,58 @@ void change_user(struct mg_connection *c, struct mg_http_message *hm) {
MG_ESC("invalid token"));
return;
}
cJSON *jsonbody = cJSON_Parse(hm->body.buf);
cJSON *username = cJSON_GetObjectItem(jsonbody, "username");
cJSON *email = cJSON_GetObjectItem(jsonbody, "email");
cJSON *group = cJSON_GetObjectItem(jsonbody, "group");
cJSON *is_superuser = cJSON_GetObjectItem(jsonbody, "is_superuser");
User *old_user_data = db_get_user_by_username(username->valuestring);
if (!old_user_data) {
mg_http_reply(c, 404, "", "{%m:%m}", MG_ESC("error"),
MG_ESC("user not found"));
return;
}
char *password = old_user_data->password;
if (!password) {
mg_http_reply(c, 400, "", "{%m:%m}", MG_ESC("error"),
MG_ESC("password is required"));
return;
}
if (username == nullptr || email == nullptr ||
is_superuser == nullptr || group == nullptr) {
mg_http_reply(c, 400, "", "{%m:%m}", MG_ESC("error"),
MG_ESC("must have <username>, <email>, <group, "
"optional>, <is_superuser, optional>"));
free_user(old_user_data);
free(password);
return;
}
cJSON *payload = jwt_get_payload(requestdata->token);
int id = cJSON_GetObjectItem(payload, "id")->valueint;
const bool user_is_superuser = is_superuser->valueint ? true : false;
User *updated_user_data = db_update_user(
id, username->valuestring, email->valuestring, password,
group->valuestring, &user_is_superuser);
if (!updated_user_data) {
mg_http_reply(c, 500, "", "{%m:%m}", MG_ESC("error"),
MG_ESC("failed to update user"));
cJSON_Delete(payload);
free_user(old_user_data);
free(password);
return;
}
char responsedata[2048] = {0};
snprintf(responsedata, sizeof(responsedata), "{\"success\": true}");
snprintf(responsedata, sizeof(responsedata),
"{\"username\":\"%s\",\"email\":\"%s\",\"group\":\"%s\",\"is_"
"superuser\":%s}",
username->valuestring, email->valuestring, group->valuestring,
is_superuser->valueint ? "true" : "false");
mg_http_reply(c, 200, "Content-Type: application/json\r\n", responsedata);
free_user(updated_user_data);
free_user(old_user_data);
cJSON_Delete(payload);
free(password);
}
+44
View File
@@ -0,0 +1,44 @@
#include "database.h"
#include "sql.h"
#include "user.h"
bool db_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);
return false;
}
pthread_mutex_unlock(&db_mutex);
return true;
}
+6 -27
View File
@@ -1,14 +1,11 @@
#include <cJSON.h>
#include <sqlite3.h>
#include "sql.h"
#include "user.h"
#include "file.h"
#include "database.h"
#include "user.h"
void db_get_users_from_file(const char *path) {
char *users_string = read_file(path);
cJSON *json_array = cJSON_Parse(users_string);
pthread_mutex_lock(&db_mutex);
for (int i = 0; i < cJSON_GetArraySize(json_array); i++) {
cJSON *json_object = cJSON_GetArrayItem(json_array, i);
const char *username =
@@ -19,32 +16,14 @@ void db_get_users_from_file(const char *path) {
const char *group = cJSON_GetObjectItem(json_object, "group")->valuestring;
const bool is_superuser =
cJSON_GetObjectItem(json_object, "is_superuser")->valueint;
sqlite3_stmt *stmt;
int rc = sqlite3_prepare_v2(db, INSERT_USER_SQL, -1, &stmt, nullptr);
if (rc != SQLITE_OK) {
fprintf(stderr, "Cannot prepare statement: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
User *new_db_user =
db_insert_user(username, email, password, group, &is_superuser);
if (!new_db_user) {
fprintf(stderr, "Cannot insert user: %s\n", username);
}
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);
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) {
fprintf(stderr, "Cannot insert data: %s\n", sqlite3_errmsg(db));
} else {
printf("Record inserted successfully. Row ID: %lld\n",
sqlite3_last_insert_rowid(db));
}
sqlite3_finalize(stmt);
free_user(new_db_user);
}
cJSON_Delete(json_array);
free(users_string);
pthread_mutex_unlock(&db_mutex);
}
+10 -3
View File
@@ -4,14 +4,16 @@
User *db_insert_user(const char *username, const char *email,
const char *password, const char *group,
bool *is_superuser) {
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;
@@ -27,6 +29,7 @@ User *db_insert_user(const char *username, const char *email,
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;
}
@@ -38,13 +41,14 @@ User *db_insert_user(const char *username, const char *email,
sqlite3_bind_text(stmt, 4, group, -1, SQLITE_STATIC);
}
if (is_superuser) {
sqlite3_bind_int(stmt, 5, 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;
}
@@ -53,4 +57,7 @@ User *db_insert_user(const char *username, const char *email,
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;
}
+55
View File
@@ -0,0 +1,55 @@
#include "database.h"
#include "sql.h"
#include "user.h"
User *db_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);
}
+5 -1
View File
@@ -10,8 +10,12 @@ void delete_user(struct mg_connection *c, struct mg_http_message *hm) {
MG_ESC("invalid token"));
return;
}
cJSON *payload = jwt_get_payload(requestdata->token);
int id = cJSON_GetObjectItem(payload, "id")->valueint;
bool user_deleted = db_delete_user(id);
char responsedata[2048] = {0};
snprintf(responsedata, sizeof(responsedata), "{\"success\": true}");
snprintf(responsedata, sizeof(responsedata), "{\"success\": %s}",
user_deleted ? "true" : "false");
mg_http_reply(c, 200, "Content-Type: application/json\r\n", responsedata);
}
+1 -2
View File
@@ -2,7 +2,6 @@
#include <sqlite3.h>
#include "database.h"
#include "route.h"
#include "sql.h"
#include "user.h"
static void root_handler(struct mg_connection *c, struct mg_http_message *hm) {
@@ -18,7 +17,7 @@ static const struct route routes[] = {
{"POST", "/api/users/user", get_user},
{"POST", "/api/users/delete", delete_user},
{"POST", "/api/users/password", change_password},
{"POST", "/api/users/change", change_password},
{"POST", "/api/users/change", change_user},
{"POST", "/api/users/add", add_user},
{"POST", "/api/register", register_user},
{nullptr, nullptr, nullptr}};
+5 -3
View File
@@ -25,9 +25,10 @@ void register_user(struct mg_connection *c, struct mg_http_message *hm) {
if (is_superuser == nullptr) {
is_superuser = cJSON_CreateBool(false);
}
const User *new_user_data =
new_user(0, username->valuestring, password->valuestring, email->valuestring,
group->valuestring, is_superuser->valueint);
const bool is_superuser_value = is_superuser->valueint ? true : false;
User *new_user_data = db_insert_user(
username->valuestring, email->valuestring, password->valuestring,
group->valuestring, (const bool*)is_superuser_value);
if (new_user_data == nullptr) {
mg_http_reply(c, 500, "", "{%m:%m}", MG_ESC("error"),
MG_ESC("failed to create user"));
@@ -41,4 +42,5 @@ void register_user(struct mg_connection *c, struct mg_http_message *hm) {
new_user_data->group, new_user_data->is_superuser);
mg_http_reply(c, 200, "Content-Type: application/json\r\n", responsedata);
free_user(new_user_data);
}
+5
View File
@@ -24,3 +24,8 @@
#define INSERT_USER_FULL_SQL \
"insert into users (username, email, password, user_group, is_superuser) " \
"values (?, ?, ?, ?, ?)"
#define UPDATE_USER_FULL_SQL \
"update users set username = ?, email = ?, password = ?, user_group = ?, " \
"is_superuser = ? where id = ?"
#define DELETE_USER_SQL "delete from users where id = ?"
#define UPDATE_USER_PASSWORD_SQL "update users set password = ? where id = ?"
+17 -6
View File
@@ -24,8 +24,8 @@ void free_request_with_token(request_with_token *data) {
free(data);
}
User *new_user(int id, const char *username, const char *password, const char *email,
const char *group, bool is_superuser) {
User *new_user(int id, const char *username, const char *password,
const char *email, const char *group, bool is_superuser) {
User *user = malloc(sizeof(User));
if (user == NULL) {
return NULL;
@@ -40,9 +40,20 @@ User *new_user(int id, const char *username, const char *password, const char *e
}
void free_user(User *user) {
free(user->username);
free(user->password);
free(user->email);
free(user->group);
if (!user) {
return;
}
if (user->username != nullptr) {
free(user->username);
}
if (user->password != nullptr) {
free(user->password);
}
if (user->email != nullptr) {
free(user->email);
}
if (user->group != nullptr) {
free(user->group);
}
free(user);
}
+5 -1
View File
@@ -57,4 +57,8 @@ char *db_get_all_users();
User *db_get_user_by_username(const char *username);
User *db_insert_user(const char *username, const char *email,
const char *password, const char *group,
bool *is_superuser);
const bool *is_superuser);
User *db_update_user(const int userid, const char *username, const char *email,
const char *password, const char *group,
const bool *is_superuser);
bool db_delete_user(const int id);