mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-13 07:40:59 +00:00
f2ac12ca4f
- The SSO unlink answers with a response contract (adminSsoUnlinkResponseSchema). - It reuses linkOidcIdentity with nulls instead of a new repository method, so UsersRepository keeps its method count and size. - The client calls the route through apiClient, so api/client.ts does not grow, and its confirm dialog takes no async callback. - The pager's preview step and pagesFor keep their complexity.
72 lines
2.4 KiB
TypeScript
72 lines
2.4 KiB
TypeScript
import { adminApi, apiClient } from '../../api/client';
|
|
import type { TranslationFn } from '../../types';
|
|
|
|
interface UserActionsHost {
|
|
toast: { success: (message: string) => void; error: (message: string) => void };
|
|
setRotatingJwt: (value: boolean) => void;
|
|
setShowRotateJwtModal: (value: boolean) => void;
|
|
logout: () => void;
|
|
navigate: (to: string, options?: { state?: unknown }) => void;
|
|
}
|
|
|
|
/**
|
|
* The irreversible user actions behind the admin dialogs and their phone sheets:
|
|
* rotating the JWT secret, which signs everyone out including the admin, removing a
|
|
* user's passkeys, switching off a user's two-factor login and removing a user's SSO
|
|
* link. Each shell keeps its own confirm step and busy state around them.
|
|
*/
|
|
export function useAdminUserActions(admin: UserActionsHost, t: TranslationFn) {
|
|
const { toast, setRotatingJwt, setShowRotateJwtModal, logout, navigate } = admin;
|
|
|
|
const rotateJwt = async () => {
|
|
setRotatingJwt(true);
|
|
try {
|
|
await adminApi.rotateJwtSecret();
|
|
setShowRotateJwtModal(false);
|
|
logout();
|
|
navigate('/login', { state: { noRedirect: true } });
|
|
} catch {
|
|
toast.error(t('common.error'));
|
|
setRotatingJwt(false);
|
|
}
|
|
};
|
|
|
|
/** Removes the user's passkeys and toasts how many went; true when it worked. */
|
|
const resetPasskeys = async (user: { id: number }): Promise<boolean> => {
|
|
try {
|
|
const r = await adminApi.resetUserPasskeys(user.id);
|
|
toast.success(t('admin.passkey.resetDone', { count: r.deleted ?? 0 }));
|
|
return true;
|
|
} catch {
|
|
toast.error(t('common.error'));
|
|
return false;
|
|
}
|
|
};
|
|
|
|
/** Switches off the user's 2FA (their sessions end with it) and toasts; true when it worked. */
|
|
const resetMfa = async (user: { id: number }): Promise<boolean> => {
|
|
try {
|
|
await adminApi.resetUserMfa(user.id);
|
|
toast.success(t('admin.mfa.resetDone'));
|
|
return true;
|
|
} catch {
|
|
toast.error(t('common.error'));
|
|
return false;
|
|
}
|
|
};
|
|
|
|
/** Forgets the user's SSO identity so the next SSO sign-in links again (#3065); true when it worked. */
|
|
const unlinkSso = async (user: { id: number }): Promise<boolean> => {
|
|
try {
|
|
await apiClient.delete(`/admin/users/${user.id}/sso`);
|
|
toast.success(t('admin.sso.unlinkDone'));
|
|
return true;
|
|
} catch {
|
|
toast.error(t('common.error'));
|
|
return false;
|
|
}
|
|
};
|
|
|
|
return { rotateJwt, resetPasskeys, resetMfa, unlinkSso };
|
|
}
|