87 lines
3.2 KiB
TypeScript
87 lines
3.2 KiB
TypeScript
import { db } from '@/db/knex'
|
|
import { deleteExistingAuthTokensFactory } from '@/modules/auth/repositories'
|
|
import { getServerInfoFactory } from '@/modules/core/repositories/server'
|
|
import {
|
|
getUserByEmailFactory,
|
|
getUserFactory,
|
|
updateUserFactory
|
|
} from '@/modules/core/repositories/users'
|
|
import { changePasswordFactory } from '@/modules/core/services/users/management'
|
|
import { renderEmail } from '@/modules/emails/services/emailRendering'
|
|
import { sendEmail } from '@/modules/emails/services/sending'
|
|
import {
|
|
createTokenFactory,
|
|
deleteTokensFactory,
|
|
getPendingTokenFactory
|
|
} from '@/modules/pwdreset/repositories'
|
|
import { finalizePasswordResetFactory } from '@/modules/pwdreset/services/finalize'
|
|
import { requestPasswordRecoveryFactory } from '@/modules/pwdreset/services/request'
|
|
import { BadRequestError } from '@/modules/shared/errors'
|
|
import { withOperationLogging } from '@/observability/domain/businessLogging'
|
|
import { ensureError } from '@speckle/shared'
|
|
import { Express } from 'express'
|
|
|
|
export default function (app: Express) {
|
|
const getUserByEmail = getUserByEmailFactory({ db })
|
|
|
|
// sends a password recovery email.
|
|
app.post('/auth/pwdreset/request', async (req, res) => {
|
|
try {
|
|
const email = req.body.email
|
|
const logger = req.log.child({ email })
|
|
const requestPasswordRecovery = requestPasswordRecoveryFactory({
|
|
getUserByEmail,
|
|
getPendingToken: getPendingTokenFactory({ db }),
|
|
createToken: createTokenFactory({ db }),
|
|
getServerInfo: getServerInfoFactory({ db }),
|
|
renderEmail,
|
|
sendEmail
|
|
})
|
|
|
|
await withOperationLogging(async () => await requestPasswordRecovery(email), {
|
|
logger,
|
|
operationName: 'requestPasswordRecovery',
|
|
operationDescription: `Requesting password recovery`
|
|
})
|
|
|
|
return res.status(200).send('Password reset email sent.')
|
|
} catch (e: unknown) {
|
|
req.log.info({ err: e }, 'Error while requesting password recovery.')
|
|
res.status(400).send(ensureError(e).message)
|
|
}
|
|
})
|
|
|
|
// Finalizes password recovery.
|
|
app.post('/auth/pwdreset/finalize', async (req, res) => {
|
|
const logger = req.log
|
|
try {
|
|
const finalizePasswordReset = finalizePasswordResetFactory({
|
|
getUserByEmail,
|
|
getPendingToken: getPendingTokenFactory({ db }),
|
|
deleteTokens: deleteTokensFactory({ db }),
|
|
updateUserPassword: changePasswordFactory({
|
|
getUser: getUserFactory({ db }),
|
|
updateUser: updateUserFactory({ db })
|
|
}),
|
|
deleteExistingAuthTokens: deleteExistingAuthTokensFactory({ db })
|
|
})
|
|
|
|
if (!req.body.tokenId || !req.body.password)
|
|
throw new BadRequestError('Invalid request.')
|
|
await withOperationLogging(
|
|
async () => await finalizePasswordReset(req.body.tokenId, req.body.password),
|
|
{
|
|
logger,
|
|
operationName: 'finalizePasswordReset',
|
|
operationDescription: `Finalizing password reset`
|
|
}
|
|
)
|
|
|
|
return res.status(200).send('Password reset. Please log in.')
|
|
} catch (e: unknown) {
|
|
req.log.info({ err: e }, 'Error while finalizing password recovery.')
|
|
res.status(400).send(ensureError(e).message)
|
|
}
|
|
})
|
|
}
|