mirror of
https://github.com/documenso/documenso.git
synced 2025-11-10 04:22:32 +10:00
119 lines
3.4 KiB
TypeScript
119 lines
3.4 KiB
TypeScript
import { TRPCError } from '@trpc/server';
|
|
|
|
import { ErrorCode } from '@documenso/lib/next-auth/error-codes';
|
|
import { disableTwoFactorAuthentication } from '@documenso/lib/server-only/2fa/disable-2fa';
|
|
import { enableTwoFactorAuthentication } from '@documenso/lib/server-only/2fa/enable-2fa';
|
|
import { getBackupCodes } from '@documenso/lib/server-only/2fa/get-backup-code';
|
|
import { setupTwoFactorAuthentication } from '@documenso/lib/server-only/2fa/setup-2fa';
|
|
import { compareSync } from '@documenso/lib/server-only/auth/hash';
|
|
import { extractNextApiRequestMetadata } from '@documenso/lib/universal/extract-request-metadata';
|
|
|
|
import { authenticatedProcedure, router } from '../trpc';
|
|
import {
|
|
ZDisableTwoFactorAuthenticationMutationSchema,
|
|
ZEnableTwoFactorAuthenticationMutationSchema,
|
|
ZSetupTwoFactorAuthenticationMutationSchema,
|
|
ZViewRecoveryCodesMutationSchema,
|
|
} from './schema';
|
|
|
|
export const twoFactorAuthenticationRouter = router({
|
|
setup: authenticatedProcedure
|
|
.input(ZSetupTwoFactorAuthenticationMutationSchema)
|
|
.mutation(async ({ ctx, input }) => {
|
|
const user = ctx.user;
|
|
|
|
const { password } = input;
|
|
|
|
return await setupTwoFactorAuthentication({
|
|
user,
|
|
password,
|
|
});
|
|
}),
|
|
|
|
enable: authenticatedProcedure
|
|
.input(ZEnableTwoFactorAuthenticationMutationSchema)
|
|
.mutation(async ({ ctx, input }) => {
|
|
try {
|
|
const user = ctx.user;
|
|
|
|
const { code } = input;
|
|
|
|
return await enableTwoFactorAuthentication({
|
|
user,
|
|
code,
|
|
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
|
|
throw new TRPCError({
|
|
code: 'BAD_REQUEST',
|
|
message: 'We were unable to enable two-factor authentication. Please try again later.',
|
|
});
|
|
}
|
|
}),
|
|
|
|
disable: authenticatedProcedure
|
|
.input(ZDisableTwoFactorAuthenticationMutationSchema)
|
|
.mutation(async ({ ctx, input }) => {
|
|
try {
|
|
const user = ctx.user;
|
|
|
|
const { password, backupCode } = input;
|
|
|
|
return await disableTwoFactorAuthentication({
|
|
user,
|
|
password,
|
|
backupCode,
|
|
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
|
|
throw new TRPCError({
|
|
code: 'BAD_REQUEST',
|
|
message: 'We were unable to disable two-factor authentication. Please try again later.',
|
|
});
|
|
}
|
|
}),
|
|
|
|
viewRecoveryCodes: authenticatedProcedure
|
|
.input(ZViewRecoveryCodesMutationSchema)
|
|
.mutation(async ({ ctx, input }) => {
|
|
try {
|
|
const user = ctx.user;
|
|
|
|
const { password } = input;
|
|
|
|
if (!user.twoFactorEnabled) {
|
|
throw new TRPCError({
|
|
code: 'BAD_REQUEST',
|
|
message: ErrorCode.TWO_FACTOR_SETUP_REQUIRED,
|
|
});
|
|
}
|
|
|
|
if (!user.password || !compareSync(password, user.password)) {
|
|
throw new TRPCError({
|
|
code: 'UNAUTHORIZED',
|
|
message: ErrorCode.INCORRECT_PASSWORD,
|
|
});
|
|
}
|
|
|
|
const recoveryCodes = await getBackupCodes({ user });
|
|
|
|
return { recoveryCodes };
|
|
} catch (err) {
|
|
console.error(err);
|
|
|
|
if (err instanceof TRPCError) {
|
|
throw err;
|
|
}
|
|
|
|
throw new TRPCError({
|
|
code: 'BAD_REQUEST',
|
|
message: 'We were unable to view your recovery codes. Please try again later.',
|
|
});
|
|
}
|
|
}),
|
|
});
|