feat(web/m7-user-mgmt): /admin/users CRUD actions (U2)
Extends the U1 /admin/users page with the four U2 admin endpoints. - "New user" button opens a modal: username, optional display name, password + confirm, optional admin checkbox. Validates password match client-side; surface server-side errors (username_taken, username_invalid, password_too_short). - Per-row "Delete" opens a confirm modal explaining the cascade (plays, likes, sessions). Last-admin guard surfaces as a clear toast if the server refuses. - Per-row "Reset password" opens a small modal: new password + confirm. Toast confirms success. - Per-row "Enable / Disable auto-approve" toggles the per-user flag (the #355 sub-feature surface). Inline button state reflects the current value. AdminUser type extended with auto_approve_requests; the badge appears next to the admin badge when enabled. Tests cover create-user submit, delete confirm flow, last-admin toast on delete, reset-password submit, auto-approve toggle. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -385,6 +385,7 @@ export type AdminUser = {
|
||||
username: string;
|
||||
display_name: string | null;
|
||||
is_admin: boolean;
|
||||
auto_approve_requests: boolean;
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
@@ -420,6 +421,31 @@ export async function deleteInvite(token: string): Promise<void> {
|
||||
await api.del(`/api/admin/invites/${token}`);
|
||||
}
|
||||
|
||||
// U2 user-management actions -----------------------------------------------
|
||||
|
||||
export type CreateUserInput = {
|
||||
username: string;
|
||||
password: string;
|
||||
display_name?: string;
|
||||
is_admin?: boolean;
|
||||
};
|
||||
|
||||
export async function createUser(input: CreateUserInput): Promise<AdminUser> {
|
||||
return api.post<AdminUser>('/api/admin/users', input);
|
||||
}
|
||||
|
||||
export async function deleteUser(id: string): Promise<void> {
|
||||
await api.del(`/api/admin/users/${id}`);
|
||||
}
|
||||
|
||||
export async function resetUserPassword(id: string, password: string): Promise<void> {
|
||||
await api.post(`/api/admin/users/${id}/reset-password`, { password });
|
||||
}
|
||||
|
||||
export async function updateUserAutoApprove(id: string, autoApprove: boolean): Promise<AdminUser> {
|
||||
return api.put<AdminUser>(`/api/admin/users/${id}/auto-approve`, { auto_approve: autoApprove });
|
||||
}
|
||||
|
||||
export function createAdminUsersQuery() {
|
||||
return createQuery({
|
||||
queryKey: qk.adminUsers(),
|
||||
|
||||
Reference in New Issue
Block a user