fix: add sign up hook

This commit is contained in:
David Nguyen
2025-02-13 20:21:23 +11:00
parent 87dcdd44cd
commit ebc2b00067
13 changed files with 55 additions and 96 deletions

View File

@@ -81,27 +81,7 @@ export async function loader({ params }: Route.LoaderArgs) {
throw redirect(documentRootPath); throw redirect(documentRootPath);
} }
const { documentMeta } = document; // Todo: Get full document instead?
// Todo: We don't handle encrypted files right.
// if (documentMeta?.password) {
// const key = DOCUMENSO_ENCRYPTION_KEY;
// if (!key) {
// throw new Error('Missing DOCUMENSO_ENCRYPTION_KEY');
// }
// const securePassword = Buffer.from(
// symmetricDecrypt({
// key,
// data: documentMeta.password,
// }),
// ).toString('utf-8');
// documentMeta.password = securePassword;
// }
// Todo: Get full document instead???
const [recipients, fields] = await Promise.all([ const [recipients, fields] = await Promise.all([
getRecipientsForDocument({ getRecipientsForDocument({
documentId, documentId,

View File

@@ -68,24 +68,6 @@ export async function loader({ params }: Route.LoaderArgs) {
throw redirect(`${documentRootPath}/${documentId}`); throw redirect(`${documentRootPath}/${documentId}`);
} }
// Todo: We don't handle encrypted files right.
// if (documentMeta?.password) {
// const key = DOCUMENSO_ENCRYPTION_KEY;
// if (!key) {
// throw new Error('Missing DOCUMENSO_ENCRYPTION_KEY');
// }
// const securePassword = Buffer.from(
// symmetricDecrypt({
// key,
// data: documentMeta.password,
// }),
// ).toString('utf-8');
// documentMeta.password = securePassword;
// }
const isDocumentEnterprise = await isUserEnterprise({ const isDocumentEnterprise = await isUserEnterprise({
userId: user.id, userId: user.id,
teamId: team?.id, teamId: team?.id,

View File

@@ -36,7 +36,7 @@ export async function loader({ params }: Route.LoaderArgs) {
throw redirect(documentRootPath); throw redirect(documentRootPath);
} }
// Todo: Get detailed? // Todo: Get full document instead?
const [document, recipients] = await Promise.all([ const [document, recipients] = await Promise.all([
getDocumentById({ getDocumentById({
documentId, documentId,

View File

@@ -118,24 +118,6 @@ export async function loader({ params }: Route.LoaderArgs) {
throw redirect(documentMeta?.redirectUrl || `/sign/${token}/complete`); throw redirect(documentMeta?.redirectUrl || `/sign/${token}/complete`);
} }
// Todo: We don't handle encrypted files right.
// if (documentMeta?.password) {
// const key = DOCUMENSO_ENCRYPTION_KEY;
// if (!key) {
// throw new Error('Missing DOCUMENSO_ENCRYPTION_KEY');
// }
// const securePassword = Buffer.from(
// symmetricDecrypt({
// key,
// data: documentMeta.password,
// }),
// ).toString('utf-8');
// documentMeta.password = securePassword;
// }
const [recipientSignature] = await getRecipientSignatures({ recipientId: recipient.id }); const [recipientSignature] = await getRecipientSignatures({ recipientId: recipient.id });
return superLoaderJson({ return superLoaderJson({

View File

@@ -33,11 +33,6 @@ export const filesRoute = new Hono<HonoEnv>()
return c.json({ error: 'No file provided' }, 400); return c.json({ error: 'No file provided' }, 400);
} }
// Todo: Do we want to validate the file type?
// if (file.type !== 'application/pdf') {
// return c.json({ error: 'File must be a PDF' }, 400);
// }
// Todo: This is new. // Todo: This is new.
// Add file size validation. // Add file size validation.
// Convert MB to bytes (1 MB = 1024 * 1024 bytes) // Convert MB to bytes (1 MB = 1024 * 1024 bytes)

View File

@@ -9,9 +9,9 @@ import {
type RequestMetadata, type RequestMetadata,
extractRequestMetadata, extractRequestMetadata,
} from '@documenso/lib/universal/extract-request-metadata'; } from '@documenso/lib/universal/extract-request-metadata';
import { AppLogger } from '@documenso/lib/utils/debugger'; import { AppDebugger } from '@documenso/lib/utils/debugger';
const logger = new AppLogger('Middleware'); const debug = new AppDebugger('Middleware');
export type AppContext = { export type AppContext = {
requestMetadata: RequestMetadata; requestMetadata: RequestMetadata;
@@ -27,7 +27,7 @@ export const appContext = async (c: Context, next: Next) => {
const noSessionCookie = extractSessionCookieFromHeaders(request.headers) === null; const noSessionCookie = extractSessionCookieFromHeaders(request.headers) === null;
if (!isPageRequest(request) || noSessionCookie || blacklistedPathsRegex.test(url.pathname)) { if (!isPageRequest(request) || noSessionCookie || blacklistedPathsRegex.test(url.pathname)) {
// logger.log('Pathname ignored', url.pathname); // debug.log('Pathname ignored', url.pathname);
setAppContext(c, { setAppContext(c, {
requestMetadata: extractRequestMetadata(request), requestMetadata: extractRequestMetadata(request),
@@ -61,7 +61,7 @@ export const appContext = async (c: Context, next: Next) => {
} }
const endTime = Date.now(); const endTime = Date.now();
logger.log(`Pathname accepted in ${endTime - initTime}ms`, url.pathname); debug.log(`Pathname accepted in ${endTime - initTime}ms`, url.pathname);
setAppContext(c, { setAppContext(c, {
requestMetadata: extractRequestMetadata(request), requestMetadata: extractRequestMetadata(request),

View File

@@ -1,9 +1,9 @@
import type { Context, Next } from 'hono'; import type { Context, Next } from 'hono';
import { getCookie } from 'hono/cookie'; import { getCookie } from 'hono/cookie';
import { AppLogger } from '@documenso/lib/utils/debugger'; import { AppDebugger } from '@documenso/lib/utils/debugger';
const logger = new AppLogger('Middleware'); const debug = new AppDebugger('Middleware');
/** /**
* Middleware for initial page loads. * Middleware for initial page loads.
@@ -23,7 +23,7 @@ export const appMiddleware = async (c: Context, next: Next) => {
return next(); return next();
} }
logger.log('Path', path); debug.log('Path', path);
const preferredTeamUrl = getCookie(c, 'preferred-team-url'); const preferredTeamUrl = getCookie(c, 'preferred-team-url');
@@ -39,7 +39,7 @@ export const appMiddleware = async (c: Context, next: Next) => {
// // Redirect root page to `/documents` or `/t/{preferredTeamUrl}/documents`. // // Redirect root page to `/documents` or `/t/{preferredTeamUrl}/documents`.
// if (path === '/') { // if (path === '/') {
// logger.log('Redirecting from root to documents'); // debug.log('Redirecting from root to documents');
// const redirectUrlPath = formatDocumentsPath( // const redirectUrlPath = formatDocumentsPath(
// resetPreferredTeamUrl ? undefined : preferredTeamUrl, // resetPreferredTeamUrl ? undefined : preferredTeamUrl,
@@ -58,7 +58,7 @@ export const appMiddleware = async (c: Context, next: Next) => {
// // Clear preferred team url cookie if user accesses a non team page from a team page. // // Clear preferred team url cookie if user accesses a non team page from a team page.
// if (resetPreferredTeamUrl || path === '/documents') { // if (resetPreferredTeamUrl || path === '/documents') {
// logger.log('Resetting preferred team url'); // debug.log('Resetting preferred team url');
// deleteCookie(c, 'preferred-team-url'); // deleteCookie(c, 'preferred-team-url');
// return next(); // return next();

View File

@@ -4,16 +4,6 @@ import { createTrpcContext } from '@documenso/trpc/server/context';
import { appRouter } from '@documenso/trpc/server/router'; import { appRouter } from '@documenso/trpc/server/router';
import { handleTrpcRouterError } from '@documenso/trpc/utils/trpc-error-handler'; import { handleTrpcRouterError } from '@documenso/trpc/utils/trpc-error-handler';
// Todo
// export const config = {
// maxDuration: 120,
// api: {
// bodyParser: {
// sizeLimit: '50mb',
// },
// },
// };
/** /**
* Trpc server for internal routes like /api/trpc/* * Trpc server for internal routes like /api/trpc/*
*/ */

View File

@@ -19,12 +19,4 @@ export const onAuthorize = async (user: AuthorizeUser, c: Context<HonoAuthContex
await createSession(sessionToken, user.userId, metadata); await createSession(sessionToken, user.userId, metadata);
await setSessionCookie(c, sessionToken); await setSessionCookie(c, sessionToken);
// Todo.
// Create the Stripe customer and attach it to the user if it doesn't exist.
// if (user.customerId === null && IS_BILLING_ENABLED()) {
// await getStripeCustomerByUser(user).catch((err) => {
// console.error(err);
// });
// }
}; };

View File

@@ -6,6 +6,7 @@ import { z } from 'zod';
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app'; import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
import { onCreateUserHook } from '@documenso/lib/server-only/user/create-user';
import { env } from '@documenso/lib/utils/env'; import { env } from '@documenso/lib/utils/env';
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import { UserSecurityAuditLogType } from '@documenso/prisma/client'; import { UserSecurityAuditLogType } from '@documenso/prisma/client';
@@ -232,6 +233,11 @@ export const googleRoute = new Hono<HonoAuthContext>()
return user; return user;
}); });
await onCreateUserHook(createdUser).catch((err) => {
// Todo: Add logging.
console.error(err);
});
await onAuthorize({ userId: createdUser.id }, c); await onAuthorize({ userId: createdUser.id }, c);
return c.redirect(redirectPath, 302); return c.redirect(redirectPath, 302);

View File

@@ -1,4 +1,5 @@
import { hash } from '@node-rs/bcrypt'; import { hash } from '@node-rs/bcrypt';
import type { User } from '@prisma/client';
import { TeamMemberInviteStatus } from '@prisma/client'; import { TeamMemberInviteStatus } from '@prisma/client';
import { getStripeCustomerByUser } from '@documenso/ee/server-only/stripe/get-customer'; import { getStripeCustomerByUser } from '@documenso/ee/server-only/stripe/get-customer';
@@ -70,6 +71,22 @@ export const createUser = async ({ name, email, password, signature, url }: Crea
return user; return user;
}); });
await onCreateUserHook(user).catch((err) => {
// Todo: Add logging.
console.error(err);
});
return user;
};
/**
* Should be run after a user is created.
*
* @returns User
*/
export const onCreateUserHook = async (user: User) => {
const { email } = user;
const acceptedTeamInvites = await prisma.teamMemberInvite.findMany({ const acceptedTeamInvites = await prisma.teamMemberInvite.findMany({
where: { where: {
status: TeamMemberInviteStatus.ACCEPTED, status: TeamMemberInviteStatus.ACCEPTED,

View File

@@ -1,10 +1,25 @@
export const appLog = (context: string, ...args: Parameters<typeof console.log>) => { import { env } from './env';
// if (env('NEXT_DEBUG') === 'true') {
console.log(`[${context}]: ${args[0]}`, ...args.slice(1)); /**
// } * Which areas to debug, keyed by context.
*/
const debugging: Record<string, boolean> = {
auth: env('NEXT_DEBUG_AUTH') === 'true',
job: env('NEXT_DEBUG_JOB') === 'true',
middleware: env('NEXT_DEBUG_MIDDLEWARE') === 'true',
}; };
export class AppLogger { export const appLog = (context: string, ...args: Parameters<typeof console.log>) => {
if (debugging[context.toLowerCase()] === false) {
return;
}
if (env('NEXT_DEBUG') === 'true') {
console.log(`[${context}]: ${args[0]}`, ...args.slice(1));
}
};
export class AppDebugger {
public context: string; public context: string;
constructor(context: string) { constructor(context: string) {