Fix QA review #2: backup code flow, audit filters, schema hardening
C-01: verifyTotp now sends backup_code field when in backup mode C-02: Backup code input filter allows alphanumeric chars (not digits only) W-01: Audit log ACTION_TYPES aligned with actual backend action strings W-02: Added extra="forbid" to SetupRequest and LoginRequest schemas Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
72ac1d53fb
commit
72e00f3a69
@ -32,6 +32,8 @@ def _validate_username(v: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
class SetupRequest(BaseModel):
|
class SetupRequest(BaseModel):
|
||||||
|
model_config = ConfigDict(extra="forbid")
|
||||||
|
|
||||||
username: str
|
username: str
|
||||||
password: str
|
password: str
|
||||||
|
|
||||||
@ -69,6 +71,8 @@ class RegisterRequest(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class LoginRequest(BaseModel):
|
class LoginRequest(BaseModel):
|
||||||
|
model_config = ConfigDict(extra="forbid")
|
||||||
|
|
||||||
username: str
|
username: str
|
||||||
password: str
|
password: str
|
||||||
|
|
||||||
|
|||||||
@ -16,21 +16,20 @@ import { cn } from '@/lib/utils';
|
|||||||
import { actionColor } from './shared';
|
import { actionColor } from './shared';
|
||||||
|
|
||||||
const ACTION_TYPES = [
|
const ACTION_TYPES = [
|
||||||
'user.create',
|
'admin.user_created',
|
||||||
'user.login',
|
'admin.role_changed',
|
||||||
'user.logout',
|
'admin.password_reset',
|
||||||
'user.login_failed',
|
'admin.mfa_disabled',
|
||||||
'user.locked',
|
'admin.mfa_enforce_toggled',
|
||||||
'user.unlocked',
|
'admin.user_deactivated',
|
||||||
'user.role_changed',
|
'admin.user_activated',
|
||||||
'user.disabled',
|
'admin.sessions_revoked',
|
||||||
'user.enabled',
|
'admin.config_updated',
|
||||||
'user.password_reset',
|
'auth.login_success',
|
||||||
'user.totp_disabled',
|
'auth.login_failed',
|
||||||
'user.mfa_enforced',
|
'auth.setup_complete',
|
||||||
'user.mfa_enforcement_removed',
|
'auth.registration',
|
||||||
'user.sessions_revoked',
|
'auth.mfa_enforce_prompted',
|
||||||
'config.updated',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
function actionLabel(action: string): string {
|
function actionLabel(action: string): string {
|
||||||
|
|||||||
@ -145,7 +145,7 @@ export default function LockScreen() {
|
|||||||
const handleTotpSubmit = async (e: FormEvent) => {
|
const handleTotpSubmit = async (e: FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
try {
|
try {
|
||||||
await verifyTotp(totpCode);
|
await verifyTotp({ code: totpCode, isBackup: useBackupCode });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast.error(getErrorMessage(error, 'Invalid verification code'));
|
toast.error(getErrorMessage(error, 'Invalid verification code'));
|
||||||
setTotpCode('');
|
setTotpCode('');
|
||||||
@ -257,7 +257,7 @@ export default function LockScreen() {
|
|||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setTotpCode(
|
setTotpCode(
|
||||||
useBackupCode
|
useBackupCode
|
||||||
? e.target.value.replace(/[^0-9-]/g, '')
|
? e.target.value.replace(/[^A-Za-z0-9-]/g, '').toUpperCase()
|
||||||
: e.target.value.replace(/\D/g, '')
|
: e.target.value.replace(/\D/g, '')
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,11 +57,14 @@ export function useAuth() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const totpVerifyMutation = useMutation({
|
const totpVerifyMutation = useMutation({
|
||||||
mutationFn: async (code: string) => {
|
mutationFn: async ({ code, isBackup }: { code: string; isBackup: boolean }) => {
|
||||||
const { data } = await api.post('/auth/totp-verify', {
|
const payload: Record<string, string> = { mfa_token: mfaToken! };
|
||||||
mfa_token: mfaToken,
|
if (isBackup) {
|
||||||
code,
|
payload.backup_code = code;
|
||||||
});
|
} else {
|
||||||
|
payload.code = code;
|
||||||
|
}
|
||||||
|
const { data } = await api.post('/auth/totp-verify', payload);
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user