webui: real multi-user accounts (SQLite + PBKDF2)
Replace the single env/generated password with a proper account system, owned entirely by the webui plugin: - auth_store: SQLite users table, PBKDF2-HMAC-SHA256 password hashing (per-user salt, 210k iterations) via OpenSSL. DB at NAUT_WEBUI_DB or an XDG default. Thread-safe (serialized connection). - Login verifies against the DB; sessions now carry the username + role. First run bootstraps an admin from NAUT_AUTH_USER/PASSWORD or a generated password (logged once). - Admin-only user management: GET/POST /api/users, /api/users/delete, /api/users/password, /api/users/role. Self-service POST /api/account/password. Guards the last admin and invalidates a user's sessions on delete or password reset. - /api/auth/status and /api/login now return the role. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ab733cb573
commit
a4ec585aed
4 changed files with 604 additions and 51 deletions
46
plugins/webui/auth_store.h
Normal file
46
plugins/webui/auth_store.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/* auth_store.h — SQLite-backed user account store for the web UI.
|
||||
*
|
||||
* Owned entirely by the webui plugin. Passwords are stored as PBKDF2-HMAC-
|
||||
* SHA256 hashes with a per-user random salt. All calls are thread-safe (the
|
||||
* store serializes access to its single SQLite connection internally). */
|
||||
#ifndef NAUT_WEBUI_AUTH_STORE_H
|
||||
#define NAUT_WEBUI_AUTH_STORE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <jansson.h>
|
||||
|
||||
typedef struct auth_store auth_store;
|
||||
|
||||
/* Open (creating if needed) the account database at `path`. Returns NULL on
|
||||
* failure. The schema is created/migrated on open. */
|
||||
auth_store *auth_store_open(const char *path);
|
||||
void auth_store_close(auth_store *s);
|
||||
|
||||
/* Number of accounts, or -1 on error. */
|
||||
int auth_store_user_count(auth_store *s);
|
||||
/* Number of admin accounts, or -1 on error. */
|
||||
int auth_store_admin_count(auth_store *s);
|
||||
bool auth_store_user_exists(auth_store *s, const char *username);
|
||||
|
||||
/* Verify a username/password pair (constant-time). On success, copies the
|
||||
* account's role ("admin"/"user") into role_out. */
|
||||
bool auth_store_verify(auth_store *s, const char *username,
|
||||
const char *password, char *role_out, size_t role_sz);
|
||||
|
||||
/* Create an account. `role` must be "admin" or "user" (defaults to "user" if
|
||||
* NULL/invalid). Returns false if the username already exists or on error. */
|
||||
bool auth_store_create_user(auth_store *s, const char *username,
|
||||
const char *password, const char *role);
|
||||
|
||||
bool auth_store_set_password(auth_store *s, const char *username,
|
||||
const char *password);
|
||||
/* Change an account's role ("admin"/"user"). */
|
||||
bool auth_store_set_role(auth_store *s, const char *username, const char *role);
|
||||
bool auth_store_delete_user(auth_store *s, const char *username);
|
||||
|
||||
/* Append {username, role, createdAt} objects (sorted by username) to the
|
||||
* json array `out`. Returns false on error. */
|
||||
bool auth_store_list_users(auth_store *s, json_t *out);
|
||||
|
||||
#endif /* NAUT_WEBUI_AUTH_STORE_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue