Remove public sign-up; accounts are created by an administrator
This is a private instance, so anyone able to reach the login page could previously give themselves an account. The registration route is gone rather than hidden, and the login screen no longer hints that accounts can be made. Accounts now come from an admin under Account → Administration: create, delete, and reset a password. Appointing further admins is deliberately not offered — with one admin it is not needed, and it is the one power that turns a compromised account into a lost instance. The first admin comes from INKNOTE_ADMIN_USER / INKNOTE_ADMIN_PASSWORD, used only when the database has no users, or to choose whom to promote when an older database has users but no admin. Once an admin exists both are ignored, so leaving them in .env cannot reset anything. Two things that would otherwise have been quietly wrong: - a deleted user's token stayed valid until it expired, because tokens are signed rather than stored and there was no session to revoke. authMiddleware now checks the account still exists, so an open tab stops working the moment the account is deleted. - deleting an account takes its notes, notebooks, drawings and version history with it via ON DELETE CASCADE. Verified: no orphaned rows in notes, notebooks, sync_log, attachments or note_versions. Deletion asks for the username to be typed back, since it destroys data that version history cannot bring back. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
55a6b3caab
commit
68e184163e
12 files changed
+859
-123
No files matched your search
@@ -8,6 +8,7 @@
|
||||
import * as db from "./offlineStore";
|
||||
import type {
|
||||
Backlink,
|
||||
ManagedUser,
|
||||
NoteContent,
|
||||
NoteMeta,
|
||||
NoteVersion,
|
||||
@@ -254,9 +255,8 @@ export async function login(username: string, password: string): Promise<User> {
|
||||
return acceptAuth(await api.post<AuthResponse>("/auth/login", { username, password }));
|
||||
}
|
||||
|
||||
export async function register(username: string, password: string, displayName?: string): Promise<User> {
|
||||
return acceptAuth(await api.post<AuthResponse>("/auth/register", { username, password, displayName }));
|
||||
}
|
||||
/* There is no register(): this instance has no public sign-up. Accounts are
|
||||
* created by an administrator through the functions under "Administration". */
|
||||
|
||||
/**
|
||||
* Restores a session from storage.
|
||||
@@ -1041,6 +1041,31 @@ export async function getAllLinks(): Promise<
|
||||
}
|
||||
}
|
||||
|
||||
/* ─── Administration ───
|
||||
* Only reachable for accounts flagged isAdmin; the server refuses the rest.
|
||||
* These talk to the server directly and are never queued: creating or deleting
|
||||
* an account offline would be a promise the client cannot keep. */
|
||||
|
||||
export async function listUsers(): Promise<ManagedUser[]> {
|
||||
return api.get<ManagedUser[]>("/admin/users");
|
||||
}
|
||||
|
||||
export async function createUser(fields: {
|
||||
username: string;
|
||||
password: string;
|
||||
displayName?: string;
|
||||
}): Promise<User> {
|
||||
return api.post<User>("/admin/users", fields);
|
||||
}
|
||||
|
||||
export async function resetUserPassword(id: string, newPassword: string): Promise<void> {
|
||||
await api.put(`/admin/users/${id}/password`, { newPassword });
|
||||
}
|
||||
|
||||
export async function deleteUser(id: string): Promise<void> {
|
||||
await api.del(`/admin/users/${id}`);
|
||||
}
|
||||
|
||||
export { DEVICE_ID };
|
||||
|
||||
/* ─── Test seam ───
|
||||
|
||||
Reference in new issue
Block a user