From e376a840c23ea2eef09eb0812525ebc20e6966bd Mon Sep 17 00:00:00 2001 From: shuaiplus <2327005759@qq.com> Date: Mon, 6 Jul 2026 00:59:34 +0800 Subject: [PATCH] fix: add device verification settings endpoints --- src/handlers/accounts.ts | 64 +++++++++++++++++++++++++++++++++++++ src/router-authenticated.ts | 11 +++++++ 2 files changed, 75 insertions(+) diff --git a/src/handlers/accounts.ts b/src/handlers/accounts.ts index 45a50d0..7d98b94 100644 --- a/src/handlers/accounts.ts +++ b/src/handlers/accounts.ts @@ -819,6 +819,18 @@ function yubiKeyResponse(user: User): Record { }; } +function deviceVerificationSettingsResponse(user: User): Record { + const enabled = user.verifyDevices !== false; + return { + Enabled: enabled, + enabled, + VerifyDevices: enabled, + verifyDevices: enabled, + Object: 'deviceVerificationSettings', + object: 'deviceVerificationSettings', + }; +} + async function yubiKeySettingsResponse(storage: StorageService, env: Env, user: User): Promise> { const credentials = await getStoredYubicoCredentials(storage, env); return { @@ -893,6 +905,58 @@ export async function handleGetTwoFactorYubiKey(request: Request, env: Env, user return jsonResponse(await yubiKeySettingsResponse(storage, env, user)); } +// POST /api/two-factor/get-device-verification-settings +export async function handleGetDeviceVerificationSettings(request: Request, env: Env, userId: string): Promise { + void request; + const storage = new StorageService(env.DB); + const user = await storage.getUserById(userId); + if (!user) return errorResponse('User not found', 404); + return jsonResponse(deviceVerificationSettingsResponse(user)); +} + +// PUT/POST /api/two-factor/device-verification-settings +export async function handlePutDeviceVerificationSettings(request: Request, env: Env, userId: string): Promise { + const storage = new StorageService(env.DB); + const auth = new AuthService(env); + const user = await storage.getUserById(userId); + if (!user) return errorResponse('User not found', 404); + + let body: Record; + try { + body = await readRequestBody(request); + } catch { + return errorResponse('Invalid JSON', 400); + } + + const rawEnabled = body.enabled ?? body.Enabled ?? body.verifyDevices ?? body.VerifyDevices; + if (typeof rawEnabled !== 'boolean') { + return errorResponse('enabled must be true or false', 400); + } + + const secret = readBodyString(body, ['masterPasswordHash', 'MasterPasswordHash', 'secret', 'Secret']); + const verified = await verifyUserSecret(auth, user, secret); + if (!verified) return errorResponse('User verification failed.', 400); + + user.verifyDevices = rawEnabled; + user.updatedAt = new Date().toISOString(); + await storage.saveUser(user); + await writeAuditEvent(storage, { + actorUserId: user.id, + action: 'account.verify_devices.update', + category: 'security', + level: 'security', + targetType: 'user', + targetId: user.id, + metadata: { + verifyDevices: user.verifyDevices, + source: 'two-factor.device-verification-settings', + ...auditRequestMetadata(request), + }, + }); + + return jsonResponse(deviceVerificationSettingsResponse(user)); +} + // PUT/POST /api/two-factor/authenticator export async function handlePutTwoFactorAuthenticator(request: Request, env: Env, userId: string): Promise { const storage = new StorageService(env.DB); diff --git a/src/router-authenticated.ts b/src/router-authenticated.ts index 5f062ed..ae35c19 100644 --- a/src/router-authenticated.ts +++ b/src/router-authenticated.ts @@ -19,6 +19,8 @@ import { handlePutTwoFactorYubiKey, handlePutTwoFactorYubiKeyConfig, handleBootstrapTwoFactorYubiKeyConfig, + handleGetDeviceVerificationSettings, + handlePutDeviceVerificationSettings, handleDisableTwoFactorProvider, handleGetApiKey, handleRotateApiKey, @@ -153,6 +155,15 @@ export async function handleAuthenticatedRoute( return handleGetTwoFactorYubiKey(request, env, userId); } + if (path === '/api/two-factor/get-device-verification-settings' && method === 'POST') { + return handleGetDeviceVerificationSettings(request, env, userId); + } + + if (path === '/api/two-factor/device-verification-settings') { + if (method === 'PUT' || method === 'POST') return handlePutDeviceVerificationSettings(request, env, userId); + return errorResponse('Method not allowed', 405); + } + if (path === '/api/two-factor/get-webauthn' && method === 'POST') { return handleGetTwoFactorWebAuthn(request, env, userId, currentUser); }