Implement listing users
This commit is contained in:
104
src/userctl.c
104
src/userctl.c
@@ -8,6 +8,8 @@
|
||||
|
||||
#include "path.c"
|
||||
|
||||
Noh_Arena temp;
|
||||
|
||||
static void show_usage(char *program_name, char *error) {
|
||||
noh_log(NOH_INFO, "Usage:");
|
||||
noh_log(NOH_INFO, "%s command [args]", program_name);
|
||||
@@ -24,11 +26,15 @@ static void show_usage(char *program_name, char *error) {
|
||||
noh_log(NOH_INFO, " username: The username of the user to delete.");
|
||||
noh_log(NOH_INFO, "Deletes a user, optionally also deleting their library folder.");
|
||||
noh_log(NOH_INFO, "");
|
||||
noh_log(NOH_INFO, "%s list library_path", program_name);
|
||||
noh_log(NOH_INFO, " library_path: The path to the library where the users file and user subfolders are located.");
|
||||
noh_log(NOH_INFO, "Lists all users defined in the provided library path.");
|
||||
noh_log(NOH_INFO, "");
|
||||
noh_log(NOH_ERROR, "%s", error);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Noh_String hash_password(Noh_Arena *arena, Noh_String_View username, Noh_String_View password) {
|
||||
Noh_String hash_password(Noh_String_View username, Noh_String_View password) {
|
||||
// Build the sha input string.
|
||||
Noh_String input = {0};
|
||||
noh_string_append_sv(&input, username);
|
||||
@@ -43,12 +49,12 @@ Noh_String hash_password(Noh_Arena *arena, Noh_String_View username, Noh_String_
|
||||
sha256_final(&ctx, hash);
|
||||
|
||||
// Build the result string.
|
||||
noh_arena_save(arena);
|
||||
noh_arena_save(&temp);
|
||||
Noh_String result = {0};
|
||||
for (int i = 0; i < 32; i++) {
|
||||
noh_string_append_cstr(&result, noh_arena_sprintf(arena, "%02x", hash[i]));
|
||||
noh_string_append_cstr(&result, noh_arena_sprintf(&temp, "%02x", hash[i]));
|
||||
}
|
||||
noh_arena_reset(arena);
|
||||
noh_arena_reset(&temp);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -64,16 +70,21 @@ typedef struct {
|
||||
size_t capacity;
|
||||
} Users;
|
||||
|
||||
|
||||
bool read_users_file(char *file_path, Users *users) {
|
||||
Noh_String users_file = {0};
|
||||
|
||||
noh_log(NOH_INFO, "Reading users file: %s", file_path);
|
||||
if (!noh_file_exists(file_path)) return true;
|
||||
if (!noh_string_read_file(&users_file, file_path)) return false;
|
||||
Noh_String_View users_file_sv = noh_sv_from_string(users_file);
|
||||
|
||||
Noh_String_View line = {0};
|
||||
for (size_t i = 0; users_file_sv.count > 0; i++) {
|
||||
Noh_String_View line = noh_sv_chop_line(&users_file_sv);
|
||||
line = noh_sv_chop_line(&users_file_sv);
|
||||
|
||||
// Ignore empty lines.
|
||||
noh_sv_trim_space(&line);
|
||||
if (line.count == 0) continue;
|
||||
|
||||
Noh_String_View un = noh_sv_chop_by_delim(&line, ':');
|
||||
|
||||
@@ -103,9 +114,24 @@ bool write_users_file(char *file_path, Users *users) {
|
||||
}
|
||||
|
||||
|
||||
/// Prompts a user with a question and returns their response.
|
||||
bool prompt_user(char *question) {
|
||||
noh_arena_save(&temp);
|
||||
noh_log(NOH_INFO, noh_arena_sprintf(&temp, "%s [yn]", question));
|
||||
noh_arena_reset(&temp);
|
||||
|
||||
char response;
|
||||
if (!scanf(" %c", &response)) {
|
||||
noh_log(NOH_ERROR, "Error reading response from stdin.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return response == 'y' || response == 'Y';
|
||||
}
|
||||
|
||||
bool register_user(Noh_String_View library_path, Noh_String_View username, Noh_String_View password) {
|
||||
// Read the file.
|
||||
Noh_String_View file_name = noh_sv_from_cstr("users.txt");
|
||||
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);
|
||||
|
||||
@@ -115,8 +141,7 @@ bool register_user(Noh_String_View library_path, Noh_String_View username, Noh_S
|
||||
bool result = true;
|
||||
|
||||
// Hash the password.
|
||||
Noh_Arena arena = noh_arena_init(1 KB);
|
||||
Noh_String hashed = hash_password(&arena, username, password);
|
||||
Noh_String hashed = hash_password(username, password);
|
||||
|
||||
// Find the user in the map of users.
|
||||
for (size_t i = 0; i < users.count; i++) {
|
||||
@@ -124,15 +149,7 @@ 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.
|
||||
noh_log(NOH_INFO, "User already exists. Update password? [yn]");
|
||||
|
||||
char response;
|
||||
if (!scanf(" %c", &response)) {
|
||||
noh_log(NOH_ERROR, "Error reading response from stdin.");
|
||||
noh_return_defer(false);
|
||||
}
|
||||
|
||||
if (response != 'y') {
|
||||
if (!prompt_user("User already exists. Update password? [yn]")) {
|
||||
noh_log(NOH_INFO, "Ok, not changing anything.");
|
||||
noh_return_defer(true);
|
||||
}
|
||||
@@ -154,10 +171,39 @@ defer:
|
||||
return result;
|
||||
}
|
||||
|
||||
bool list_users(Noh_String_View library_path) {
|
||||
// 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;
|
||||
|
||||
if (users.count == 0) {
|
||||
noh_log(NOH_INFO, "No users registered.");
|
||||
noh_da_free(&users);
|
||||
return true;
|
||||
}
|
||||
|
||||
noh_arena_save(&temp);
|
||||
noh_log(NOH_INFO, "Users:");
|
||||
for (size_t i = 0; i < users.count; i++) {
|
||||
User *user = &users.elems[i];
|
||||
noh_log(NOH_INFO, noh_arena_sprintf(&temp, "- "Nsv_Fmt, Nsv_Arg(user->username)));
|
||||
}
|
||||
noh_arena_reset(&temp);
|
||||
|
||||
noh_da_free(&users);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
temp = noh_arena_init(64 KB);
|
||||
|
||||
// Parse input parameters.
|
||||
char *program_name = noh_shift_args(&argc, &argv);
|
||||
Noh_Arena arena = noh_arena_init(64 KB);
|
||||
|
||||
if (argc < 1) show_usage(program_name, "Command not provided");
|
||||
Noh_String_View command = noh_sv_from_cstr(noh_shift_args(&argc, &argv));
|
||||
@@ -165,21 +211,29 @@ int main(int argc, char **argv) {
|
||||
if (argc < 1) show_usage(program_name, "Library path not provided.");
|
||||
Noh_String_View library_path = noh_sv_from_cstr(noh_shift_args(&argc, &argv));
|
||||
|
||||
if (argc < 1) show_usage(program_name, "Username not provided.");
|
||||
Noh_String_View username = noh_sv_from_cstr(noh_shift_args(&argc, &argv));
|
||||
|
||||
if (noh_sv_eq_ci(command, noh_sv_from_cstr("register"))) {
|
||||
if (argc < 1) show_usage(program_name, "Username not provided.");
|
||||
Noh_String_View username = noh_sv_from_cstr(noh_shift_args(&argc, &argv));
|
||||
|
||||
if (argc < 1) show_usage(program_name, "Password not provided.");
|
||||
Noh_String_View password = noh_sv_from_cstr(noh_shift_args(&argc, &argv));
|
||||
|
||||
if (!register_user(library_path, username, password)) return 1;
|
||||
return 0;
|
||||
return register_user(library_path, username, password);
|
||||
|
||||
} 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);
|
||||
|
||||
} else if (noh_sv_eq_ci(command, sv("list"))) {
|
||||
return list_users(library_path);
|
||||
|
||||
} else {
|
||||
show_usage(program_name, noh_arena_sprintf(&arena, "Unknown command: "Nsv_Fmt, Nsv_Arg(command)));
|
||||
noh_arena_save(&temp);
|
||||
show_usage(program_name, noh_arena_sprintf(&temp, "Unknown command: "Nsv_Fmt, Nsv_Arg(command)));
|
||||
noh_arena_reset(&temp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user