Implement listing users
This commit is contained in:
12
src/noh.h
12
src/noh.h
@@ -397,13 +397,13 @@ void noh_sv_trim_right(Noh_String_View *sv, bool (*do_trim)(char));
|
|||||||
void noh_sv_trim(Noh_String_View *sv, bool (*do_trim)(char));
|
void noh_sv_trim(Noh_String_View *sv, bool (*do_trim)(char));
|
||||||
|
|
||||||
// Trims spaces from the left part of a string view.
|
// Trims spaces from the left part of a string view.
|
||||||
inline void noh_sv_trim_space_left(Noh_String_View *sv);
|
void noh_sv_trim_space_left(Noh_String_View *sv);
|
||||||
|
|
||||||
// Trims spaces from the right part of a string view.
|
// Trims spaces from the right part of a string view.
|
||||||
inline void noh_sv_trim_space_right(Noh_String_View *sv);
|
void noh_sv_trim_space_right(Noh_String_View *sv);
|
||||||
|
|
||||||
// Trims spaces from both sides of a string view.
|
// Trims spaces from both sides of a string view.
|
||||||
inline void noh_sv_trim_space(Noh_String_View *sv);
|
void noh_sv_trim_space(Noh_String_View *sv);
|
||||||
|
|
||||||
// Creates a string view from a c-string.
|
// Creates a string view from a c-string.
|
||||||
Noh_String_View noh_sv_from_cstr(const char *cstr);
|
Noh_String_View noh_sv_from_cstr(const char *cstr);
|
||||||
@@ -1000,15 +1000,15 @@ bool is_space(char c) {
|
|||||||
return isspace(c) > 0;
|
return isspace(c) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void noh_sv_trim_space_left(Noh_String_View *sv) {
|
void noh_sv_trim_space_left(Noh_String_View *sv) {
|
||||||
noh_sv_trim_left(sv, &is_space);
|
noh_sv_trim_left(sv, &is_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void noh_sv_trim_space_right(Noh_String_View *sv) {
|
void noh_sv_trim_space_right(Noh_String_View *sv) {
|
||||||
noh_sv_trim_right(sv, &is_space);
|
noh_sv_trim_right(sv, &is_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void noh_sv_trim_space(Noh_String_View *sv) {
|
void noh_sv_trim_space(Noh_String_View *sv) {
|
||||||
noh_sv_trim(sv, &is_space);
|
noh_sv_trim(sv, &is_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
104
src/userctl.c
104
src/userctl.c
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "path.c"
|
#include "path.c"
|
||||||
|
|
||||||
|
Noh_Arena temp;
|
||||||
|
|
||||||
static void show_usage(char *program_name, char *error) {
|
static void show_usage(char *program_name, char *error) {
|
||||||
noh_log(NOH_INFO, "Usage:");
|
noh_log(NOH_INFO, "Usage:");
|
||||||
noh_log(NOH_INFO, "%s command [args]", program_name);
|
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, " 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, "Deletes a user, optionally also deleting their library folder.");
|
||||||
noh_log(NOH_INFO, "");
|
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);
|
noh_log(NOH_ERROR, "%s", error);
|
||||||
exit(1);
|
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.
|
// Build the sha input string.
|
||||||
Noh_String input = {0};
|
Noh_String input = {0};
|
||||||
noh_string_append_sv(&input, username);
|
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);
|
sha256_final(&ctx, hash);
|
||||||
|
|
||||||
// Build the result string.
|
// Build the result string.
|
||||||
noh_arena_save(arena);
|
noh_arena_save(&temp);
|
||||||
Noh_String result = {0};
|
Noh_String result = {0};
|
||||||
for (int i = 0; i < 32; i++) {
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -64,16 +70,21 @@ typedef struct {
|
|||||||
size_t capacity;
|
size_t capacity;
|
||||||
} Users;
|
} Users;
|
||||||
|
|
||||||
|
|
||||||
bool read_users_file(char *file_path, Users *users) {
|
bool read_users_file(char *file_path, Users *users) {
|
||||||
Noh_String users_file = {0};
|
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_file_exists(file_path)) return true;
|
||||||
if (!noh_string_read_file(&users_file, file_path)) return false;
|
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 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++) {
|
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, ':');
|
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) {
|
bool register_user(Noh_String_View library_path, Noh_String_View username, Noh_String_View password) {
|
||||||
// Read the file.
|
// 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 users_file_path = build_path(false, &library_path, &file_name);
|
||||||
noh_string_append_null(&users_file_path);
|
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;
|
bool result = true;
|
||||||
|
|
||||||
// Hash the password.
|
// Hash the password.
|
||||||
Noh_Arena arena = noh_arena_init(1 KB);
|
Noh_String hashed = hash_password(username, password);
|
||||||
Noh_String hashed = hash_password(&arena, username, password);
|
|
||||||
|
|
||||||
// Find the user in the map of users.
|
// Find the user in the map of users.
|
||||||
for (size_t i = 0; i < users.count; i++) {
|
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;
|
if (!noh_sv_eq_ci(user->username, username)) continue;
|
||||||
|
|
||||||
// The user exists. Update password after confirmation.
|
// The user exists. Update password after confirmation.
|
||||||
noh_log(NOH_INFO, "User already exists. Update password? [yn]");
|
if (!prompt_user("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') {
|
|
||||||
noh_log(NOH_INFO, "Ok, not changing anything.");
|
noh_log(NOH_INFO, "Ok, not changing anything.");
|
||||||
noh_return_defer(true);
|
noh_return_defer(true);
|
||||||
}
|
}
|
||||||
@@ -154,10 +171,39 @@ defer:
|
|||||||
return result;
|
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) {
|
int main(int argc, char **argv) {
|
||||||
|
temp = noh_arena_init(64 KB);
|
||||||
|
|
||||||
// Parse input parameters.
|
// Parse input parameters.
|
||||||
char *program_name = noh_shift_args(&argc, &argv);
|
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");
|
if (argc < 1) show_usage(program_name, "Command not provided");
|
||||||
Noh_String_View command = noh_sv_from_cstr(noh_shift_args(&argc, &argv));
|
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.");
|
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));
|
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 (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.");
|
if (argc < 1) show_usage(program_name, "Password not provided.");
|
||||||
Noh_String_View password = noh_sv_from_cstr(noh_shift_args(&argc, &argv));
|
Noh_String_View password = noh_sv_from_cstr(noh_shift_args(&argc, &argv));
|
||||||
|
|
||||||
if (!register_user(library_path, username, password)) return 1;
|
return register_user(library_path, username, password);
|
||||||
return 0;
|
|
||||||
|
|
||||||
} else if (noh_sv_eq_ci(command, sv("delete"))) {
|
} 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);
|
noh_assert(false);
|
||||||
|
|
||||||
|
} else if (noh_sv_eq_ci(command, sv("list"))) {
|
||||||
|
return list_users(library_path);
|
||||||
|
|
||||||
} else {
|
} 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