From ebc2b0006757333ec0d9a37f9bb5857f02e57664 Mon Sep 17 00:00:00 2001 From: David Nguyen Date: Thu, 13 Feb 2025 20:21:23 +1100 Subject: [PATCH] fix: add sign up hook --- .../_authenticated+/documents+/$id._index.tsx | 22 +--------------- .../_authenticated+/documents+/$id.edit.tsx | 18 ------------- .../_authenticated+/documents+/$id.logs.tsx | 2 +- .../_recipient+/sign.$token+/_index.tsx | 18 ------------- apps/remix/server/api/files.ts | 5 ---- apps/remix/server/context.ts | 8 +++--- apps/remix/server/middleware.ts | 10 ++++---- apps/remix/server/trpc/hono-trpc-remix.ts | 10 -------- package-lock.json | 2 +- packages/auth/server/lib/utils/authorizer.ts | 8 ------ packages/auth/server/routes/google.ts | 6 +++++ packages/lib/server-only/user/create-user.ts | 17 +++++++++++++ packages/lib/utils/debugger.ts | 25 +++++++++++++++---- 13 files changed, 55 insertions(+), 96 deletions(-) diff --git a/apps/remix/app/routes/_authenticated+/documents+/$id._index.tsx b/apps/remix/app/routes/_authenticated+/documents+/$id._index.tsx index d472bb9ee..9bbb0306e 100644 --- a/apps/remix/app/routes/_authenticated+/documents+/$id._index.tsx +++ b/apps/remix/app/routes/_authenticated+/documents+/$id._index.tsx @@ -81,27 +81,7 @@ export async function loader({ params }: Route.LoaderArgs) { throw redirect(documentRootPath); } - const { documentMeta } = document; - - // 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??? + // Todo: Get full document instead? const [recipients, fields] = await Promise.all([ getRecipientsForDocument({ documentId, diff --git a/apps/remix/app/routes/_authenticated+/documents+/$id.edit.tsx b/apps/remix/app/routes/_authenticated+/documents+/$id.edit.tsx index e3f250aba..9970c676c 100644 --- a/apps/remix/app/routes/_authenticated+/documents+/$id.edit.tsx +++ b/apps/remix/app/routes/_authenticated+/documents+/$id.edit.tsx @@ -68,24 +68,6 @@ export async function loader({ params }: Route.LoaderArgs) { 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({ userId: user.id, teamId: team?.id, diff --git a/apps/remix/app/routes/_authenticated+/documents+/$id.logs.tsx b/apps/remix/app/routes/_authenticated+/documents+/$id.logs.tsx index 17144b080..f4c54e384 100644 --- a/apps/remix/app/routes/_authenticated+/documents+/$id.logs.tsx +++ b/apps/remix/app/routes/_authenticated+/documents+/$id.logs.tsx @@ -36,7 +36,7 @@ export async function loader({ params }: Route.LoaderArgs) { throw redirect(documentRootPath); } - // Todo: Get detailed? + // Todo: Get full document instead? const [document, recipients] = await Promise.all([ getDocumentById({ documentId, diff --git a/apps/remix/app/routes/_recipient+/sign.$token+/_index.tsx b/apps/remix/app/routes/_recipient+/sign.$token+/_index.tsx index c9f3a227c..5ee620913 100644 --- a/apps/remix/app/routes/_recipient+/sign.$token+/_index.tsx +++ b/apps/remix/app/routes/_recipient+/sign.$token+/_index.tsx @@ -118,24 +118,6 @@ export async function loader({ params }: Route.LoaderArgs) { 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 }); return superLoaderJson({ diff --git a/apps/remix/server/api/files.ts b/apps/remix/server/api/files.ts index 8a54f6f33..41d47fea6 100644 --- a/apps/remix/server/api/files.ts +++ b/apps/remix/server/api/files.ts @@ -33,11 +33,6 @@ export const filesRoute = new Hono() 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. // Add file size validation. // Convert MB to bytes (1 MB = 1024 * 1024 bytes) diff --git a/apps/remix/server/context.ts b/apps/remix/server/context.ts index f5bd8f9a2..01799a409 100644 --- a/apps/remix/server/context.ts +++ b/apps/remix/server/context.ts @@ -9,9 +9,9 @@ import { type RequestMetadata, extractRequestMetadata, } 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 = { requestMetadata: RequestMetadata; @@ -27,7 +27,7 @@ export const appContext = async (c: Context, next: Next) => { const noSessionCookie = extractSessionCookieFromHeaders(request.headers) === null; if (!isPageRequest(request) || noSessionCookie || blacklistedPathsRegex.test(url.pathname)) { - // logger.log('Pathname ignored', url.pathname); + // debug.log('Pathname ignored', url.pathname); setAppContext(c, { requestMetadata: extractRequestMetadata(request), @@ -61,7 +61,7 @@ export const appContext = async (c: Context, next: Next) => { } 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, { requestMetadata: extractRequestMetadata(request), diff --git a/apps/remix/server/middleware.ts b/apps/remix/server/middleware.ts index 5d94b6eae..0a1e5e168 100644 --- a/apps/remix/server/middleware.ts +++ b/apps/remix/server/middleware.ts @@ -1,9 +1,9 @@ import type { Context, Next } from 'hono'; 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. @@ -23,7 +23,7 @@ export const appMiddleware = async (c: Context, next: Next) => { return next(); } - logger.log('Path', path); + debug.log('Path', path); 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`. // if (path === '/') { - // logger.log('Redirecting from root to documents'); + // debug.log('Redirecting from root to documents'); // const redirectUrlPath = formatDocumentsPath( // 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. // if (resetPreferredTeamUrl || path === '/documents') { - // logger.log('Resetting preferred team url'); + // debug.log('Resetting preferred team url'); // deleteCookie(c, 'preferred-team-url'); // return next(); diff --git a/apps/remix/server/trpc/hono-trpc-remix.ts b/apps/remix/server/trpc/hono-trpc-remix.ts index 524b215bc..affa957f6 100644 --- a/apps/remix/server/trpc/hono-trpc-remix.ts +++ b/apps/remix/server/trpc/hono-trpc-remix.ts @@ -4,16 +4,6 @@ import { createTrpcContext } from '@documenso/trpc/server/context'; import { appRouter } from '@documenso/trpc/server/router'; 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/* */ diff --git a/package-lock.json b/package-lock.json index 689b2b9d3..c8cf7ba9e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42439,4 +42439,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/auth/server/lib/utils/authorizer.ts b/packages/auth/server/lib/utils/authorizer.ts index d982bda7c..f88ad7ffb 100644 --- a/packages/auth/server/lib/utils/authorizer.ts +++ b/packages/auth/server/lib/utils/authorizer.ts @@ -19,12 +19,4 @@ export const onAuthorize = async (user: AuthorizeUser, c: Context { - // console.error(err); - // }); - // } }; diff --git a/packages/auth/server/routes/google.ts b/packages/auth/server/routes/google.ts index 94d650863..49f447262 100644 --- a/packages/auth/server/routes/google.ts +++ b/packages/auth/server/routes/google.ts @@ -6,6 +6,7 @@ import { z } from 'zod'; import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app'; 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 { prisma } from '@documenso/prisma'; import { UserSecurityAuditLogType } from '@documenso/prisma/client'; @@ -232,6 +233,11 @@ export const googleRoute = new Hono() return user; }); + await onCreateUserHook(createdUser).catch((err) => { + // Todo: Add logging. + console.error(err); + }); + await onAuthorize({ userId: createdUser.id }, c); return c.redirect(redirectPath, 302); diff --git a/packages/lib/server-only/user/create-user.ts b/packages/lib/server-only/user/create-user.ts index c0a9999cd..c6b9576c5 100644 --- a/packages/lib/server-only/user/create-user.ts +++ b/packages/lib/server-only/user/create-user.ts @@ -1,4 +1,5 @@ import { hash } from '@node-rs/bcrypt'; +import type { User } from '@prisma/client'; import { TeamMemberInviteStatus } from '@prisma/client'; 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; }); + 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({ where: { status: TeamMemberInviteStatus.ACCEPTED, diff --git a/packages/lib/utils/debugger.ts b/packages/lib/utils/debugger.ts index 0ce9d6e1c..67534c629 100644 --- a/packages/lib/utils/debugger.ts +++ b/packages/lib/utils/debugger.ts @@ -1,10 +1,25 @@ -export const appLog = (context: string, ...args: Parameters) => { - // if (env('NEXT_DEBUG') === 'true') { - console.log(`[${context}]: ${args[0]}`, ...args.slice(1)); - // } +import { env } from './env'; + +/** + * Which areas to debug, keyed by context. + */ +const debugging: Record = { + 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) => { + 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; constructor(context: string) {