feat(admin): wire Admin Users management (A9)

User list with create dialog, role toggle, (de)activate, and reset-password;
self-lockout guard. Adds getUser/resetPassword endpoints, an isActive field on
the User type, and en/ru strings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Цвылев Александр Вадимович
2026-07-28 20:40:36 +03:00
parent 57044dabba
commit 28d9e59e34
6 changed files with 557 additions and 8 deletions
+18 -2
View File
@@ -14,6 +14,11 @@ export const adminApi = api.injectEndpoints({
transformResponse: (raw: RawUser[]) => raw.map(toUser),
providesTags: ['User'],
}),
getUser: build.query<User, string>({
query: (id) => `/admin/users/${id}`,
transformResponse: (raw: RawUser) => toUser(raw),
providesTags: (_res, _err, id) => [{ type: 'User', id }],
}),
createUser: build.mutation<
User,
{ username: string; password: string; role: 'admin' | 'user' }
@@ -39,11 +44,20 @@ export const adminApi = api.injectEndpoints({
},
}),
transformResponse: (raw: RawUser) => toUser(raw),
invalidatesTags: ['User'],
invalidatesTags: (_res, _err, { id }) => ['User', { type: 'User', id }],
}),
// Soft delete on the backend: deactivates the account and revokes its
// sessions (see admin.py::deactivate_user), so it also refreshes the row.
deleteUser: build.mutation<void, string>({
query: (id) => ({ url: `/admin/users/${id}`, method: 'DELETE' }),
invalidatesTags: ['User'],
invalidatesTags: (_res, _err, id) => ['User', { type: 'User', id }],
}),
resetPassword: build.mutation<void, { id: string; newPassword: string }>({
query: ({ id, newPassword }) => ({
url: `/admin/users/${id}/reset-password`,
method: 'POST',
body: { new_password: newPassword },
}),
}),
}),
overrideExisting: false,
@@ -51,7 +65,9 @@ export const adminApi = api.injectEndpoints({
export const {
useGetUsersQuery,
useGetUserQuery,
useCreateUserMutation,
useUpdateUserMutation,
useDeleteUserMutation,
useResetPasswordMutation,
} = adminApi;