Implement userctl user registering
This commit is contained in:
143
src/userctl.c
143
src/userctl.c
@@ -3,11 +3,26 @@
|
||||
#define NOH_IMPLEMENTATION
|
||||
#include "noh.h"
|
||||
|
||||
#define SV Noh_String_View
|
||||
#define sv noh_sv_from_cstr
|
||||
|
||||
#include "path.c"
|
||||
|
||||
static void show_usage(char *program_name, char *error) {
|
||||
noh_log(NOH_INFO, "Usage:");
|
||||
noh_log(NOH_INFO, "%s username password", program_name);
|
||||
noh_log(NOH_INFO, "%s command [args]", program_name);
|
||||
noh_log(NOH_INFO, "");
|
||||
noh_log(NOH_INFO, "Commands:");
|
||||
noh_log(NOH_INFO, "%s register library_path username password", 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, " username: The username of the user to register.");
|
||||
noh_log(NOH_INFO, " password: The password of the user to register.");
|
||||
noh_log(NOH_INFO, "Registers a new user, or changes their password if they already exist.");
|
||||
noh_log(NOH_INFO, "");
|
||||
noh_log(NOH_INFO, "%s delete library_path username", 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, " 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_ERROR, "%s", error);
|
||||
exit(1);
|
||||
@@ -38,21 +53,133 @@ Noh_String hash_password(Noh_Arena *arena, Noh_String_View username, Noh_String_
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
Noh_String_View username;
|
||||
Noh_String_View hash;
|
||||
} User;
|
||||
|
||||
typedef struct {
|
||||
User *elems;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} Users;
|
||||
|
||||
|
||||
bool read_users_file(char *file_path, Users *users) {
|
||||
Noh_String users_file = {0};
|
||||
|
||||
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);
|
||||
|
||||
for (size_t i = 0; users_file_sv.count > 0; i++) {
|
||||
Noh_String_View line = noh_sv_chop_line(&users_file_sv);
|
||||
|
||||
Noh_String_View un = noh_sv_chop_by_delim(&line, ':');
|
||||
|
||||
if (line.count == 0) {
|
||||
noh_log(NOH_ERROR, "%s %zu: Line not in username:hash format.", file_path, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
noh_da_append(users, ((User){ .username = un, .hash = line }));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool write_users_file(char *file_path, Users *users) {
|
||||
Noh_String users_file = {0};
|
||||
|
||||
for (size_t i = 0; i < users->count; i++) {
|
||||
User *u = &users->elems[i];
|
||||
noh_string_append_sv(&users_file, u->username);
|
||||
noh_string_append_cstr(&users_file, ":");
|
||||
noh_string_append_sv(&users_file, u->hash);
|
||||
noh_string_append_cstr(&users_file, "\n");
|
||||
}
|
||||
|
||||
return noh_string_write_file(&users_file, file_path);
|
||||
}
|
||||
|
||||
|
||||
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 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;
|
||||
|
||||
// Hash the password.
|
||||
Noh_Arena arena = noh_arena_init(1 KB);
|
||||
Noh_String hashed = hash_password(&arena, username, password);
|
||||
|
||||
// Find the user in the map of users.
|
||||
for (size_t i = 0; i < users.count; i++) {
|
||||
User *user = &users.elems[i];
|
||||
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') {
|
||||
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);
|
||||
|
||||
noh_return_defer(true);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
defer:
|
||||
noh_da_free(&users);
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// 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));
|
||||
|
||||
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 (argc < 1) show_usage(program_name, "Password not provided.");
|
||||
Noh_String_View password = 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, "Password not provided.");
|
||||
Noh_String_View password = noh_sv_from_cstr(noh_shift_args(&argc, &argv));
|
||||
|
||||
Noh_Arena arena = noh_arena_init(64 KB);
|
||||
Noh_String result = hash_password(&arena, username, password);
|
||||
noh_string_append_null(&result);
|
||||
printf("%s\n", result.elems);
|
||||
if (!register_user(library_path, username, password)) return 1;
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
} else if (noh_sv_eq_ci(command, sv("delete"))) {
|
||||
noh_assert(false);
|
||||
|
||||
} else {
|
||||
show_usage(program_name, noh_arena_sprintf(&arena, "Unknown command: "Nsv_Fmt, Nsv_Arg(command)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user