fix(auth): clean up MFA routes — remove redundant imports, use userRepo.update()

- Remove redundant dynamic import('node:crypto'), use top-level nodeCrypto
- Remove getCollection import, use userRepo.update() for mfaEnabled/mfaMethods
- Expand update() Pick type to include mfaEnabled, mfaMethods, emailVerified
- Remove unused _reply param from MFA policy PUT handler
This commit is contained in:
saravanakumardb1 2026-03-12 11:12:33 -07:00
parent 362b915ea9
commit bdb3e95e00
2 changed files with 17 additions and 17 deletions

View File

@ -16,7 +16,6 @@
import type { FastifyInstance } from 'fastify';
import { BadRequestError, UnauthorizedError, ForbiddenError } from '../../../lib/errors.js';
import * as nodeCrypto from 'node:crypto';
import { getCollection } from '../../../lib/datastore.js';
import * as userRepo from '../repository.js';
import * as mfaRepo from './repository.js';
import * as jwt from '../jwt.js';
@ -27,7 +26,6 @@ import {
MfaDisableSchema,
MfaPolicySchema,
} from './types.js';
import type { UserDoc } from '../types.js';
import type { MfaPolicyDoc } from './types.js';
export async function mfaRoutes(app: FastifyInstance) {
@ -44,8 +42,7 @@ export async function mfaRoutes(app: FastifyInstance) {
}
// Generate TOTP secret (base32)
const { randomBytes } = await import('node:crypto');
const secretBuffer = randomBytes(20);
const secretBuffer = nodeCrypto.randomBytes(20);
const secret = base32Encode(secretBuffer);
// Encrypt the secret
@ -113,11 +110,7 @@ export async function mfaRoutes(app: FastifyInstance) {
// Update user doc
try {
await getCollection<UserDoc>('users', '/id').update(payload.sub, payload.sub, {
mfaEnabled: true,
mfaMethods: ['totp'],
updatedAt: now,
} as Partial<UserDoc>);
await userRepo.update(payload.sub, { mfaEnabled: true, mfaMethods: ['totp'] });
} catch {
// best-effort
}
@ -205,12 +198,7 @@ export async function mfaRoutes(app: FastifyInstance) {
// Update user doc
try {
const now = new Date().toISOString();
await getCollection<UserDoc>('users', '/id').update(payload.sub, payload.sub, {
mfaEnabled: false,
mfaMethods: [],
updatedAt: now,
} as Partial<UserDoc>);
await userRepo.update(payload.sub, { mfaEnabled: false, mfaMethods: [] });
} catch {
// best-effort
}
@ -265,7 +253,7 @@ export async function mfaRoutes(app: FastifyInstance) {
return { policy: policy ?? null };
});
app.put('/auth/mfa/policies/:productId', async (req, _reply) => {
app.put('/auth/mfa/policies/:productId', async req => {
const role = req.jwtPayload?.role;
if (!role || !['super_admin', 'admin'].includes(role)) {
throw new ForbiddenError('Admin access required');

View File

@ -88,7 +88,19 @@ export async function countByPlan(productId: string): Promise<Record<string, num
export async function update(
id: string,
updates: Partial<
Pick<UserDoc, 'displayName' | 'role' | 'plan' | 'status' | 'phone' | 'bio' | 'avatarUrl'>
Pick<
UserDoc,
| 'displayName'
| 'role'
| 'plan'
| 'status'
| 'phone'
| 'bio'
| 'avatarUrl'
| 'mfaEnabled'
| 'mfaMethods'
| 'emailVerified'
>
>
): Promise<UserDoc | null> {
try {