This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { prisma } from '../../lib/prisma'
|
||||
import { hashPublicAccessToken } from '../../security/publicAccessTokens'
|
||||
|
||||
const companyListInclude = {
|
||||
brand: { select: { displayName: true, logoUrl: true, subdomain: true } },
|
||||
@@ -80,17 +81,18 @@ export function markAdminRecoveryCodeUsed(id: string) {
|
||||
return prisma.adminRecoveryCode.update({ where: { id }, data: { usedAt: new Date() } })
|
||||
}
|
||||
|
||||
export function setAdminPasswordReset(id: string, token: string, expiresAt: Date) {
|
||||
export function setAdminPasswordReset(id: string, tokenHash: string, expiresAt: Date) {
|
||||
return prisma.adminUser.update({
|
||||
where: { id },
|
||||
data: { passwordResetToken: token, passwordResetExpiresAt: expiresAt },
|
||||
data: { passwordResetToken: tokenHash, passwordResetExpiresAt: expiresAt },
|
||||
})
|
||||
}
|
||||
|
||||
export function findAdminByResetToken(token: string) {
|
||||
const tokenHash = hashPublicAccessToken(token)
|
||||
return prisma.adminUser.findFirst({
|
||||
where: {
|
||||
passwordResetToken: token,
|
||||
OR: [{ passwordResetToken: tokenHash }, { passwordResetToken: token }],
|
||||
passwordResetExpiresAt: { gt: new Date() },
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Router } from 'express'
|
||||
import { requireAdminAuth, requireAdminRole, requireFreshAdmin2FA } from '../../middleware/requireAdminAuth'
|
||||
import { requireAdminAuth, requireAdminRole, requireFreshAdmin2FA, requireFreshAdmin2FAWhenEnabled } from '../../middleware/requireAdminAuth'
|
||||
import { parseBody, parseQuery, parseParams } from '../../http/validate'
|
||||
import { ok, created } from '../../http/respond'
|
||||
import { setSessionCookie, clearSessionCookie } from '../../security/sessionCookies'
|
||||
@@ -80,7 +80,7 @@ router.get('/auth/me', requireAdminAuth, (req, res) => {
|
||||
ok(res, presentAdminUser(req.admin as any))
|
||||
})
|
||||
|
||||
router.post('/auth/2fa/setup', requireAdminAuth, async (req, res, next) => {
|
||||
router.post('/auth/2fa/setup', requireAdminAuth, requireFreshAdmin2FAWhenEnabled, async (req, res, next) => {
|
||||
try {
|
||||
ok(res, await service.setupTotp(req.admin.id, req.admin.email))
|
||||
} catch (err) { next(err) }
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import bcrypt from 'bcryptjs'
|
||||
import crypto from 'crypto'
|
||||
import { hashPublicAccessToken } from '../../security/publicAccessTokens'
|
||||
import { authenticator } from 'otplib'
|
||||
import { signActorToken } from '../../security/tokens'
|
||||
import qrcode from 'qrcode'
|
||||
@@ -144,7 +145,7 @@ export async function forgotPassword(email: string) {
|
||||
|
||||
const rawToken = crypto.randomBytes(32).toString('hex')
|
||||
const expiresAt = new Date(Date.now() + ADMIN_RESET_TTL_MINUTES * 60 * 1000)
|
||||
await repo.setAdminPasswordReset(admin.id, rawToken, expiresAt)
|
||||
await repo.setAdminPasswordReset(admin.id, hashPublicAccessToken(rawToken), expiresAt)
|
||||
|
||||
const adminUrl = ensureAdminBasePath(
|
||||
process.env.ADMIN_URL ?? process.env.NEXT_PUBLIC_ADMIN_URL ?? 'http://localhost:3000/admin',
|
||||
|
||||
Reference in New Issue
Block a user