Implement deleting a user
This commit is contained in:
@@ -5,7 +5,7 @@ static Noh_String build_path_(bool url, Noh_String_View *first, ...) {
|
||||
va_start(args, first);
|
||||
bool start = true;
|
||||
Noh_String result = {0};
|
||||
if (url) noh_string_append_cstr(&result, "/");
|
||||
if (url || noh_sv_starts_with(*first, noh_sv_from_cstr("/"))) noh_string_append_cstr(&result, "/");
|
||||
|
||||
while (elem_ != NULL) {
|
||||
Noh_String_View elem = *elem_;
|
||||
|
||||
102
src/userctl.c
102
src/userctl.c
@@ -1,5 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <sha256.h>
|
||||
#include <dirent.h>
|
||||
#define NOH_IMPLEMENTATION
|
||||
#include "noh.h"
|
||||
|
||||
@@ -70,6 +71,38 @@ typedef struct {
|
||||
size_t capacity;
|
||||
} Users;
|
||||
|
||||
bool remove_directory(char *path) {
|
||||
noh_arena_save(&temp);
|
||||
bool result = true;
|
||||
|
||||
DIR *dir = opendir(path);
|
||||
if (!dir) return false;
|
||||
|
||||
struct dirent *p;
|
||||
while ((p = readdir(dir))) {
|
||||
// Ignore . and .. file entries.
|
||||
if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) continue;
|
||||
|
||||
char *sub_path = noh_arena_sprintf(&temp, "%s/%s", path, p->d_name);
|
||||
|
||||
// Delete files and recurse subfolders.
|
||||
struct stat statbuf;
|
||||
if (!stat(sub_path, &statbuf)) {
|
||||
if (S_ISDIR(statbuf.st_mode))
|
||||
result &= remove_directory(sub_path);
|
||||
else
|
||||
result &= unlink(sub_path) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
if (result) result = rmdir(path);
|
||||
|
||||
noh_arena_reset(&temp);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool read_users_file(char *file_path, Users *users) {
|
||||
Noh_String users_file = {0};
|
||||
|
||||
@@ -99,11 +132,13 @@ bool read_users_file(char *file_path, Users *users) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool write_users_file(char *file_path, Users *users) {
|
||||
bool write_users_file(char *file_path, Users *users, User *user_to_skip) {
|
||||
Noh_String users_file = {0};
|
||||
|
||||
for (size_t i = 0; i < users->count; i++) {
|
||||
User *u = &users->elems[i];
|
||||
if (u == user_to_skip) continue;
|
||||
|
||||
noh_string_append_sv(&users_file, u->username);
|
||||
noh_string_append_cstr(&users_file, ":");
|
||||
noh_string_append_sv(&users_file, u->hash);
|
||||
@@ -149,14 +184,14 @@ bool register_user(Noh_String_View library_path, Noh_String_View username, Noh_S
|
||||
if (!noh_sv_eq_ci(user->username, username)) continue;
|
||||
|
||||
// The user exists. Update password after confirmation.
|
||||
if (!prompt_user("User already exists. Update password? [yn]")) {
|
||||
if (!prompt_user("User already exists. Update password?")) {
|
||||
noh_log(NOH_INFO, "Ok, not changing anything.");
|
||||
noh_return_defer(true);
|
||||
}
|
||||
|
||||
noh_log(NOH_INFO, "Updating user password.");
|
||||
user->hash = noh_sv_from_string(hashed);
|
||||
if (!write_users_file(users_file_path.elems, &users)) noh_return_defer(false);
|
||||
if (!write_users_file(users_file_path.elems, &users, NULL)) noh_return_defer(false);
|
||||
|
||||
noh_return_defer(true);
|
||||
}
|
||||
@@ -164,7 +199,58 @@ bool register_user(Noh_String_View library_path, Noh_String_View username, Noh_S
|
||||
// User was not found, add it to the list.
|
||||
noh_log(NOH_INFO, "Adding a new user.");
|
||||
noh_da_append(&users, ((User){ .username = username, .hash = noh_sv_from_string(hashed) }));
|
||||
if (!write_users_file(users_file_path.elems, &users)) noh_return_defer(false);
|
||||
if (!write_users_file(users_file_path.elems, &users, NULL)) noh_return_defer(false);
|
||||
|
||||
defer:
|
||||
noh_da_free(&users);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool delete_user(Noh_String_View library_path, Noh_String_View username) {
|
||||
// Read the file.
|
||||
Noh_String_View file_name = noh_sv_from_cstr("users.conf");
|
||||
Noh_String users_file_path = build_path(false, &library_path, &file_name);
|
||||
noh_string_append_null(&users_file_path);
|
||||
|
||||
// Build users map.
|
||||
Users users = {0};
|
||||
if (!read_users_file(users_file_path.elems, &users)) return false;
|
||||
bool result = true;
|
||||
|
||||
// Check if the user exists.
|
||||
User *user_to_delete = NULL;
|
||||
for (size_t i = 0; i < users.count; i++) {
|
||||
User *user = &users.elems[i];
|
||||
if (!noh_sv_eq_ci(user->username, username)) continue;
|
||||
|
||||
user_to_delete = user;
|
||||
break;
|
||||
}
|
||||
|
||||
// User does not exist, don't change anything.
|
||||
if (!user_to_delete) {
|
||||
noh_log(NOH_INFO, "User does not exist.");
|
||||
noh_return_defer(true);
|
||||
}
|
||||
|
||||
// The user exists. Prompt to confirm deletion.
|
||||
if (!prompt_user("User found, delete the user?")) {
|
||||
noh_log(NOH_INFO, "Ok, not changing anything.");
|
||||
noh_return_defer(true);
|
||||
}
|
||||
|
||||
noh_log(NOH_INFO, "Deleting user.");
|
||||
if (!write_users_file(users_file_path.elems, &users, user_to_delete)) noh_return_defer(false);
|
||||
|
||||
// Prompt to delete the user's library folder.
|
||||
Noh_String user_folder_path = build_path(false, &library_path, &username);
|
||||
noh_string_append_null(&user_folder_path);
|
||||
if (!noh_file_exists(user_folder_path.elems)) noh_return_defer(true);
|
||||
|
||||
if (prompt_user("Library folder exists. Delete it?")) {
|
||||
noh_log(NOH_INFO, "Deleting library folder.");
|
||||
return remove_directory(user_folder_path.elems);
|
||||
}
|
||||
|
||||
defer:
|
||||
noh_da_free(&users);
|
||||
@@ -218,22 +304,22 @@ int main(int argc, char **argv) {
|
||||
if (argc < 1) show_usage(program_name, "Password not provided.");
|
||||
Noh_String_View password = noh_sv_from_cstr(noh_shift_args(&argc, &argv));
|
||||
|
||||
return register_user(library_path, username, password);
|
||||
return register_user(library_path, username, password) ? 0 : 1;
|
||||
|
||||
} else if (noh_sv_eq_ci(command, sv("delete"))) {
|
||||
if (argc < 1) show_usage(program_name, "Username not provided.");
|
||||
Noh_String_View username = noh_sv_from_cstr(noh_shift_args(&argc, &argv));
|
||||
(void)username;
|
||||
|
||||
noh_assert(false);
|
||||
return delete_user(library_path, username) ? 0 : 1;
|
||||
|
||||
} else if (noh_sv_eq_ci(command, sv("list"))) {
|
||||
return list_users(library_path);
|
||||
return list_users(library_path) ? 0 : 1;
|
||||
|
||||
} else {
|
||||
noh_arena_save(&temp);
|
||||
show_usage(program_name, noh_arena_sprintf(&temp, "Unknown command: "Nsv_Fmt, Nsv_Arg(command)));
|
||||
noh_arena_reset(&temp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user