mirror of
https://github.com/documenso/documenso.git
synced 2025-11-17 18:21:32 +10:00
fix: wip
This commit is contained in:
@ -1,5 +1,8 @@
|
||||
import { env } from '@documenso/lib/utils/env';
|
||||
|
||||
// Todo: Delete
|
||||
export const authDebugger = (message: string) => {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
if (env('NODE_ENV') === 'development') {
|
||||
console.log(`[DEBUG]: ${message}`);
|
||||
}
|
||||
};
|
||||
|
||||
@ -4,6 +4,7 @@ import { Hono } from 'hono';
|
||||
import { DateTime } from 'luxon';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app';
|
||||
import { AppError } from '@documenso/lib/errors/app-error';
|
||||
import { jobsClient } from '@documenso/lib/jobs/client';
|
||||
import { disableTwoFactorAuthentication } from '@documenso/lib/server-only/2fa/disable-2fa';
|
||||
@ -16,19 +17,25 @@ import { createUser } from '@documenso/lib/server-only/user/create-user';
|
||||
import { forgotPassword } from '@documenso/lib/server-only/user/forgot-password';
|
||||
import { getMostRecentVerificationTokenByUserId } from '@documenso/lib/server-only/user/get-most-recent-verification-token-by-user-id';
|
||||
import { resetPassword } from '@documenso/lib/server-only/user/reset-password';
|
||||
import { verifyEmail } from '@documenso/lib/server-only/user/verify-email';
|
||||
import { updatePassword } from '@documenso/lib/server-only/user/update-password';
|
||||
import {
|
||||
EMAIL_VERIFICATION_STATE,
|
||||
verifyEmail,
|
||||
} from '@documenso/lib/server-only/user/verify-email';
|
||||
import { env } from '@documenso/lib/utils/env';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
import { UserSecurityAuditLogType } from '@documenso/prisma/client';
|
||||
|
||||
import { AuthenticationErrorCode } from '../lib/errors/error-codes';
|
||||
import { onAuthorize } from '../lib/utils/authorizer';
|
||||
import { getRequiredSession } from '../lib/utils/get-session';
|
||||
import { getRequiredSession, getSession } from '../lib/utils/get-session';
|
||||
import type { HonoAuthContext } from '../types/context';
|
||||
import {
|
||||
ZForgotPasswordSchema,
|
||||
ZResetPasswordSchema,
|
||||
ZSignInFormSchema,
|
||||
ZSignUpRequestSchema,
|
||||
ZSignInSchema,
|
||||
ZSignUpSchema,
|
||||
ZUpdatePasswordSchema,
|
||||
ZVerifyEmailSchema,
|
||||
} from '../types/email-password';
|
||||
|
||||
@ -36,7 +43,7 @@ export const emailPasswordRoute = new Hono<HonoAuthContext>()
|
||||
/**
|
||||
* Authorize endpoint.
|
||||
*/
|
||||
.post('/authorize', zValidator('json', ZSignInFormSchema), async (c) => {
|
||||
.post('/authorize', zValidator('json', ZSignInSchema), async (c) => {
|
||||
const requestMetadata = c.get('requestMetadata');
|
||||
|
||||
const { email, password, totpCode, backupCode } = c.req.valid('json');
|
||||
@ -48,8 +55,8 @@ export const emailPasswordRoute = new Hono<HonoAuthContext>()
|
||||
});
|
||||
|
||||
if (!user || !user.password) {
|
||||
throw new AppError(AuthenticationErrorCode.NotFound, {
|
||||
message: 'User not found',
|
||||
throw new AppError(AuthenticationErrorCode.InvalidCredentials, {
|
||||
message: 'Invalid email or password',
|
||||
});
|
||||
}
|
||||
|
||||
@ -85,7 +92,7 @@ export const emailPasswordRoute = new Hono<HonoAuthContext>()
|
||||
},
|
||||
});
|
||||
|
||||
throw new AppError(AuthenticationErrorCode.IncorrectTwoFactorCode);
|
||||
throw new AppError(AuthenticationErrorCode.InvalidTwoFactorCode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,20 +132,20 @@ export const emailPasswordRoute = new Hono<HonoAuthContext>()
|
||||
/**
|
||||
* Signup endpoint.
|
||||
*/
|
||||
.post('/signup', zValidator('json', ZSignUpRequestSchema), async (c) => {
|
||||
// if (NEXT_PUBLIC_DISABLE_SIGNUP() === 'true') {
|
||||
// throw new AppError('SIGNUP_DISABLED', {
|
||||
// message: 'Signups are disabled.',
|
||||
// });
|
||||
// }
|
||||
.post('/signup', zValidator('json', ZSignUpSchema), async (c) => {
|
||||
if (env('NEXT_PUBLIC_DISABLE_SIGNUP') === 'true') {
|
||||
throw new AppError('SIGNUP_DISABLED', {
|
||||
message: 'Signups are disabled.',
|
||||
});
|
||||
}
|
||||
|
||||
const { name, email, password, signature, url } = c.req.valid('json');
|
||||
|
||||
// if (IS_BILLING_ENABLED() && url && url.length < 6) {
|
||||
// throw new AppError(AppErrorCode.PREMIUM_PROFILE_URL, {
|
||||
// message: 'Only subscribers can have a username shorter than 6 characters',
|
||||
// });
|
||||
// }
|
||||
if (IS_BILLING_ENABLED() && url && url.length < 6) {
|
||||
throw new AppError('PREMIUM_PROFILE_URL', {
|
||||
message: 'Only subscribers can have a username shorter than 6 characters',
|
||||
});
|
||||
}
|
||||
|
||||
const user = await createUser({ name, email, password, signature, url });
|
||||
|
||||
@ -149,18 +156,59 @@ export const emailPasswordRoute = new Hono<HonoAuthContext>()
|
||||
},
|
||||
});
|
||||
|
||||
// Todo: Check this.
|
||||
return c.json({
|
||||
user,
|
||||
return c.text('OK', 201);
|
||||
})
|
||||
/**
|
||||
* Update password endpoint.
|
||||
*/
|
||||
.post('/update-password', zValidator('json', ZUpdatePasswordSchema), async (c) => {
|
||||
const { password, currentPassword } = c.req.valid('json');
|
||||
const requestMetadata = c.get('requestMetadata');
|
||||
|
||||
const session = await getSession(c);
|
||||
|
||||
if (!session.isAuthenticated) {
|
||||
throw new AppError(AuthenticationErrorCode.Unauthorized);
|
||||
}
|
||||
|
||||
await updatePassword({
|
||||
userId: session.user.id,
|
||||
password,
|
||||
currentPassword,
|
||||
requestMetadata,
|
||||
});
|
||||
|
||||
return c.text('OK', 201);
|
||||
})
|
||||
/**
|
||||
* Verify email endpoint.
|
||||
*/
|
||||
.post('/verify-email', zValidator('json', ZVerifyEmailSchema), async (c) => {
|
||||
await verifyEmail({ token: c.req.valid('json').token });
|
||||
const { state, userId } = await verifyEmail({ token: c.req.valid('json').token });
|
||||
|
||||
return c.text('OK', 201);
|
||||
// If email is verified, automatically authenticate user.
|
||||
if (state === EMAIL_VERIFICATION_STATE.VERIFIED && userId !== null) {
|
||||
await onAuthorize({ userId }, c);
|
||||
}
|
||||
|
||||
return c.json({
|
||||
state,
|
||||
});
|
||||
})
|
||||
/**
|
||||
* Resend verification email endpoint.
|
||||
*/
|
||||
.post('/resend-email', zValidator('json', ZVerifyEmailSchema), async (c) => {
|
||||
const { state, userId } = await verifyEmail({ token: c.req.valid('json').token });
|
||||
|
||||
// If email is verified, automatically authenticate user.
|
||||
if (state === EMAIL_VERIFICATION_STATE.VERIFIED && userId !== null) {
|
||||
await onAuthorize({ userId }, c);
|
||||
}
|
||||
|
||||
return c.json({
|
||||
state,
|
||||
});
|
||||
})
|
||||
/**
|
||||
* Forgot password endpoint.
|
||||
@ -180,9 +228,12 @@ export const emailPasswordRoute = new Hono<HonoAuthContext>()
|
||||
.post('/reset-password', zValidator('json', ZResetPasswordSchema), async (c) => {
|
||||
const { token, password } = c.req.valid('json');
|
||||
|
||||
const requestMetadata = c.get('requestMetadata');
|
||||
|
||||
await resetPassword({
|
||||
token,
|
||||
password,
|
||||
requestMetadata,
|
||||
});
|
||||
|
||||
return c.text('OK', 201);
|
||||
@ -291,9 +342,7 @@ export const emailPasswordRoute = new Hono<HonoAuthContext>()
|
||||
requestMetadata,
|
||||
});
|
||||
|
||||
return c.json({
|
||||
success: true,
|
||||
});
|
||||
return c.text('OK', 201);
|
||||
},
|
||||
)
|
||||
/**
|
||||
|
||||
@ -4,6 +4,7 @@ import { getCookie, setCookie } from 'hono/cookie';
|
||||
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { setupTwoFactorAuthentication } from '@documenso/lib/server-only/2fa/setup-2fa';
|
||||
import { env } from '@documenso/lib/utils/env';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
import { AuthenticationErrorCode } from '../lib/errors/error-codes';
|
||||
@ -12,8 +13,8 @@ import { getRequiredSession } from '../lib/utils/get-session';
|
||||
import type { HonoAuthContext } from '../types/context';
|
||||
|
||||
const options = {
|
||||
clientId: import.meta.env.NEXT_PRIVATE_GOOGLE_CLIENT_ID,
|
||||
clientSecret: import.meta.env.NEXT_PRIVATE_GOOGLE_CLIENT_SECRET,
|
||||
clientId: env('NEXT_PRIVATE_GOOGLE_CLIENT_ID'),
|
||||
clientSecret: env('NEXT_PRIVATE_GOOGLE_CLIENT_SECRET'),
|
||||
redirectUri: 'http://localhost:3000/api/auth/google/callback',
|
||||
scope: ['openid', 'email', 'profile'],
|
||||
id: 'google',
|
||||
@ -36,7 +37,7 @@ export const googleRoute = new Hono<HonoAuthContext>()
|
||||
setCookie(c, 'google_oauth_state', state, {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
secure: env('NODE_ENV') === 'production',
|
||||
maxAge: 60 * 10, // 10 minutes
|
||||
sameSite: 'lax',
|
||||
});
|
||||
@ -44,7 +45,8 @@ export const googleRoute = new Hono<HonoAuthContext>()
|
||||
setCookie(c, 'google_code_verifier', codeVerifier, {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
// Todo: Might not be node_env but something vite specific?
|
||||
secure: env('NODE_ENV') === 'production',
|
||||
maxAge: 60 * 10, // 10 minutes
|
||||
sameSite: 'lax',
|
||||
});
|
||||
|
||||
@ -5,14 +5,14 @@ export const ZCurrentPasswordSchema = z
|
||||
.min(6, { message: 'Must be at least 6 characters in length' })
|
||||
.max(72);
|
||||
|
||||
export const ZSignInFormSchema = z.object({
|
||||
export const ZSignInSchema = z.object({
|
||||
email: z.string().email().min(1),
|
||||
password: ZCurrentPasswordSchema,
|
||||
totpCode: z.string().trim().optional(),
|
||||
backupCode: z.string().trim().optional(),
|
||||
});
|
||||
|
||||
export type TSignInFormSchema = z.infer<typeof ZSignInFormSchema>;
|
||||
export type TSignInSchema = z.infer<typeof ZSignInSchema>;
|
||||
|
||||
export const ZPasswordSchema = z
|
||||
.string()
|
||||
@ -31,7 +31,7 @@ export const ZPasswordSchema = z
|
||||
message: 'One special character is required',
|
||||
});
|
||||
|
||||
export const ZSignUpRequestSchema = z.object({
|
||||
export const ZSignUpSchema = z.object({
|
||||
name: z.string().min(1),
|
||||
email: z.string().email(),
|
||||
password: ZPasswordSchema,
|
||||
@ -47,7 +47,7 @@ export const ZSignUpRequestSchema = z.object({
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export type TSignUpRequestSchema = z.infer<typeof ZSignUpRequestSchema>;
|
||||
export type TSignUpSchema = z.infer<typeof ZSignUpSchema>;
|
||||
|
||||
export const ZForgotPasswordSchema = z.object({
|
||||
email: z.string().email().min(1),
|
||||
@ -67,3 +67,10 @@ export const ZVerifyEmailSchema = z.object({
|
||||
});
|
||||
|
||||
export type TVerifyEmailSchema = z.infer<typeof ZVerifyEmailSchema>;
|
||||
|
||||
export const ZUpdatePasswordSchema = z.object({
|
||||
currentPassword: ZCurrentPasswordSchema,
|
||||
password: ZPasswordSchema,
|
||||
});
|
||||
|
||||
export type TUpdatePasswordSchema = z.infer<typeof ZUpdatePasswordSchema>;
|
||||
|
||||
Reference in New Issue
Block a user