From e47ab838c5934c925b0845a6550943a9c267ac17 Mon Sep 17 00:00:00 2001 From: Ephraim Atta-Duncan Date: Wed, 6 Sep 2023 07:37:03 +0000 Subject: [PATCH 1/9] chore: remove undefined check --- apps/web/src/app/(signing)/sign/[token]/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/app/(signing)/sign/[token]/page.tsx b/apps/web/src/app/(signing)/sign/[token]/page.tsx index a55687196..45a2cbbad 100644 --- a/apps/web/src/app/(signing)/sign/[token]/page.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/page.tsx @@ -44,7 +44,7 @@ export default async function SigningPage({ params: { token } }: SigningPageProp return notFound(); } - if (document?.status === 'COMPLETED') { + if (document.status === 'COMPLETED') { redirect(`/sign/${token}/complete`); } From 02424596db492ea2c2e811312334fcc6f1fbfae6 Mon Sep 17 00:00:00 2001 From: Ephraim Atta-Duncan Date: Sun, 17 Sep 2023 14:45:22 +0000 Subject: [PATCH 2/9] fix: update for code review --- apps/web/src/app/(signing)/sign/[token]/page.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/web/src/app/(signing)/sign/[token]/page.tsx b/apps/web/src/app/(signing)/sign/[token]/page.tsx index 45a2cbbad..9b77649cc 100644 --- a/apps/web/src/app/(signing)/sign/[token]/page.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/page.tsx @@ -8,7 +8,7 @@ import { getDocumentAndSenderByToken } from '@documenso/lib/server-only/document import { viewedDocument } from '@documenso/lib/server-only/document/viewed-document'; import { getFieldsForToken } from '@documenso/lib/server-only/field/get-fields-for-token'; import { getRecipientByToken } from '@documenso/lib/server-only/recipient/get-recipient-by-token'; -import { FieldType } from '@documenso/prisma/client'; +import { DocumentStatus, FieldType, SigningStatus } from '@documenso/prisma/client'; import { Card, CardContent } from '@documenso/ui/primitives/card'; import { ElementVisible } from '@documenso/ui/primitives/element-visible'; import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer'; @@ -44,7 +44,10 @@ export default async function SigningPage({ params: { token } }: SigningPageProp return notFound(); } - if (document.status === 'COMPLETED') { + if ( + document.status === DocumentStatus.COMPLETED || + recipient.signingStatus === SigningStatus.SIGNED + ) { redirect(`/sign/${token}/complete`); } From e8205c1390b0a8346db7779580a1e4c0d4bf4235 Mon Sep 17 00:00:00 2001 From: Mythie Date: Wed, 27 Sep 2023 07:52:24 +1000 Subject: [PATCH 3/9] fix: better share links --- .../route.tsx} | 6 ++-- .../web/src/app/(share)/share/[slug]/page.tsx | 29 +++++++++++++++---- .../src/app/(share)/share/[slug]/redirect.tsx | 11 ------- .../(signing)/sign/[token]/complete/page.tsx | 4 +-- 4 files changed, 29 insertions(+), 21 deletions(-) rename apps/web/src/app/(share)/share/[slug]/{opengraph-image.tsx => opengraph/route.tsx} (94%) delete mode 100644 apps/web/src/app/(share)/share/[slug]/redirect.tsx diff --git a/apps/web/src/app/(share)/share/[slug]/opengraph-image.tsx b/apps/web/src/app/(share)/share/[slug]/opengraph/route.tsx similarity index 94% rename from apps/web/src/app/(share)/share/[slug]/opengraph-image.tsx rename to apps/web/src/app/(share)/share/[slug]/opengraph/route.tsx index 8751f407e..d6a2c6397 100644 --- a/apps/web/src/app/(share)/share/[slug]/opengraph-image.tsx +++ b/apps/web/src/app/(share)/share/[slug]/opengraph/route.tsx @@ -1,4 +1,4 @@ -import { ImageResponse } from 'next/server'; +import { ImageResponse, NextResponse } from 'next/server'; import { P, match } from 'ts-pattern'; @@ -21,7 +21,7 @@ type SharePageOpenGraphImageProps = { params: { slug: string }; }; -export default async function Image({ params: { slug } }: SharePageOpenGraphImageProps) { +export async function GET(_request: Request, { params: { slug } }: SharePageOpenGraphImageProps) { const [interSemiBold, interRegular, caveatRegular, shareFrameImage] = await Promise.all([ getAssetBuffer('/fonts/inter-semibold.ttf'), getAssetBuffer('/fonts/inter-regular.ttf'), @@ -32,7 +32,7 @@ export default async function Image({ params: { slug } }: SharePageOpenGraphImag const recipientOrSender = await getRecipientOrSenderByShareLinkSlug({ slug }).catch(() => null); if (!recipientOrSender) { - return null; + return NextResponse.json({ error: 'Not found' }, { status: 404 }); } const isRecipient = 'Signature' in recipientOrSender; diff --git a/apps/web/src/app/(share)/share/[slug]/page.tsx b/apps/web/src/app/(share)/share/[slug]/page.tsx index 63449f29f..2f9369f60 100644 --- a/apps/web/src/app/(share)/share/[slug]/page.tsx +++ b/apps/web/src/app/(share)/share/[slug]/page.tsx @@ -1,11 +1,30 @@ import { Metadata } from 'next'; +import { headers } from 'next/headers'; +import { redirect } from 'next/navigation'; -import { Redirect } from './redirect'; +import { APP_BASE_URL } from '@documenso/lib/constants/app'; -export const metadata: Metadata = { - title: 'Documenso - Share', +type SharePageProps = { + params: { slug: string }; }; -export default function SharePage() { - return ; +export function generateMetadata({ params: { slug } }: SharePageProps) { + return { + title: 'Documenso - Share', + description: 'I just signed a document with Documenso!', + openGraph: { + images: [`${APP_BASE_URL}/share/${slug}/opengraph`], + }, + } satisfies Metadata; +} + +export default function SharePage() { + const userAgent = headers().get('User-Agent') ?? ''; + + // https://stackoverflow.com/questions/47026171/how-to-detect-bots-for-open-graph-with-user-agent + if (/bot|facebookexternalhit|WhatsApp|google|bing|duckduckbot|MetaInspector/i.test(userAgent)) { + return null; + } + + redirect(process.env.NEXT_PUBLIC_MARKETING_URL ?? 'http://localhost:3001'); } diff --git a/apps/web/src/app/(share)/share/[slug]/redirect.tsx b/apps/web/src/app/(share)/share/[slug]/redirect.tsx deleted file mode 100644 index 5b3af0771..000000000 --- a/apps/web/src/app/(share)/share/[slug]/redirect.tsx +++ /dev/null @@ -1,11 +0,0 @@ -'use client'; - -import { useEffect } from 'react'; - -export const Redirect = () => { - useEffect(() => { - window.location.href = process.env.NEXT_PUBLIC_MARKETING_URL ?? 'http://localhost:3001'; - }, []); - - return null; -}; diff --git a/apps/web/src/app/(signing)/sign/[token]/complete/page.tsx b/apps/web/src/app/(signing)/sign/[token]/complete/page.tsx index a89f1bb3f..cf9625071 100644 --- a/apps/web/src/app/(signing)/sign/[token]/complete/page.tsx +++ b/apps/web/src/app/(signing)/sign/[token]/complete/page.tsx @@ -9,7 +9,7 @@ import { getFieldsForToken } from '@documenso/lib/server-only/field/get-fields-f import { getRecipientByToken } from '@documenso/lib/server-only/recipient/get-recipient-by-token'; import { DocumentStatus, FieldType } from '@documenso/prisma/client'; import { DocumentDownloadButton } from '@documenso/ui/components/document/document-download-button'; -import { SigningCard } from '@documenso/ui/components/signing-card'; +import { SigningCard3D } from '@documenso/ui/components/signing-card'; import signingCelebration from '~/assets/signing-celebration.png'; @@ -55,7 +55,7 @@ export default async function CompletedSigningPage({ return (
{/* Card with recipient */} - +
{match(document.status) From ddbeb9e3dbf3058b13a113f07b80c119ef8095e2 Mon Sep 17 00:00:00 2001 From: Mythie Date: Wed, 27 Sep 2023 08:02:51 +1000 Subject: [PATCH 4/9] fix: twitter images --- apps/web/src/app/(share)/share/[slug]/page.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/web/src/app/(share)/share/[slug]/page.tsx b/apps/web/src/app/(share)/share/[slug]/page.tsx index 2f9369f60..a80020657 100644 --- a/apps/web/src/app/(share)/share/[slug]/page.tsx +++ b/apps/web/src/app/(share)/share/[slug]/page.tsx @@ -15,6 +15,9 @@ export function generateMetadata({ params: { slug } }: SharePageProps) { openGraph: { images: [`${APP_BASE_URL}/share/${slug}/opengraph`], }, + twitter: { + images: [`${APP_BASE_URL}/share/${slug}/opengraph`], + }, } satisfies Metadata; } From a0c327cfcf742b231e7fef3b01122b037908b942 Mon Sep 17 00:00:00 2001 From: Mythie Date: Wed, 27 Sep 2023 09:03:53 +1000 Subject: [PATCH 5/9] fix: share og updates --- apps/web/src/app/(share)/share/[slug]/page.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/web/src/app/(share)/share/[slug]/page.tsx b/apps/web/src/app/(share)/share/[slug]/page.tsx index a80020657..b9ca4baea 100644 --- a/apps/web/src/app/(share)/share/[slug]/page.tsx +++ b/apps/web/src/app/(share)/share/[slug]/page.tsx @@ -13,10 +13,16 @@ export function generateMetadata({ params: { slug } }: SharePageProps) { title: 'Documenso - Share', description: 'I just signed a document with Documenso!', openGraph: { - images: [`${APP_BASE_URL}/share/${slug}/opengraph`], + title: 'Documenso - Join the open source signing revolution', + description: 'I just signed with Documenso!', + type: 'website', + images: [`${process.env.NEXT_PUBLIC_WEBAPP_URL}/share/${slug}/opengraph`], }, twitter: { - images: [`${APP_BASE_URL}/share/${slug}/opengraph`], + site: '@documenso', + card: 'summary_large_image', + images: [`${process.env.NEXT_PUBLIC_WEBAPP_URL}/share/${slug}/opengraph`], + description: 'I just signed with Documenso!', }, } satisfies Metadata; } From 2348221b031104e7a7c5eeebe93d9a6492fe6546 Mon Sep 17 00:00:00 2001 From: Mythie Date: Wed, 27 Sep 2023 09:09:53 +1000 Subject: [PATCH 6/9] fix: faster tooltips --- .../(dashboard)/avatar/stack-avatars-with-tooltip.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx b/apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx index 9ef2cd105..8d611c2d1 100644 --- a/apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx +++ b/apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx @@ -40,7 +40,7 @@ export const StackAvatarsWithTooltip = ({ return ( - + {children || } From e49c102e8c97281b712b84a09ecd68aab7f8bfab Mon Sep 17 00:00:00 2001 From: Mythie Date: Wed, 27 Sep 2023 09:11:56 +1000 Subject: [PATCH 7/9] fix: lint errors --- apps/web/src/app/(share)/share/[slug]/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/src/app/(share)/share/[slug]/page.tsx b/apps/web/src/app/(share)/share/[slug]/page.tsx index b9ca4baea..51684d384 100644 --- a/apps/web/src/app/(share)/share/[slug]/page.tsx +++ b/apps/web/src/app/(share)/share/[slug]/page.tsx @@ -16,12 +16,12 @@ export function generateMetadata({ params: { slug } }: SharePageProps) { title: 'Documenso - Join the open source signing revolution', description: 'I just signed with Documenso!', type: 'website', - images: [`${process.env.NEXT_PUBLIC_WEBAPP_URL}/share/${slug}/opengraph`], + images: [`${APP_BASE_URL}/share/${slug}/opengraph`], }, twitter: { site: '@documenso', card: 'summary_large_image', - images: [`${process.env.NEXT_PUBLIC_WEBAPP_URL}/share/${slug}/opengraph`], + images: [`${APP_BASE_URL}/share/${slug}/opengraph`], description: 'I just signed with Documenso!', }, } satisfies Metadata; From 572f9d5ad63f6b10eb0066c67da18d555fc85f2a Mon Sep 17 00:00:00 2001 From: Mythie Date: Wed, 27 Sep 2023 14:58:10 +1000 Subject: [PATCH 8/9] chore: styling updates --- .../single-player-mode-success.tsx | 8 +- .../(signing)/sign/[token]/complete/page.tsx | 75 ++++++++++--------- packages/ui/components/signing-card.tsx | 10 +-- 3 files changed, 48 insertions(+), 45 deletions(-) diff --git a/apps/marketing/src/components/(marketing)/single-player-mode/single-player-mode-success.tsx b/apps/marketing/src/components/(marketing)/single-player-mode/single-player-mode-success.tsx index 70bf58926..0c85fc65c 100644 --- a/apps/marketing/src/components/(marketing)/single-player-mode/single-player-mode-success.tsx +++ b/apps/marketing/src/components/(marketing)/single-player-mode/single-player-mode-success.tsx @@ -73,7 +73,7 @@ export const SinglePlayerModeSuccess = ({ className, document }: SinglePlayerMod )} -

+

You have signed {document.title}

@@ -84,17 +84,17 @@ export const SinglePlayerModeSuccess = ({ className, document }: SinglePlayerMod signingCelebrationImage={signingCelebration} /> -
+
{/* TODO: Hook this up */} - +
{/* Card with recipient */} -
+
{match(document.status) .with(DocumentStatus.COMPLETED, () => (
@@ -71,41 +71,44 @@ export default async function CompletedSigningPage({ Waiting for others to sign
))} + +

+ You have signed "{document.title}" +

+ + {match(document.status) + .with(DocumentStatus.COMPLETED, () => ( +

+ Everyone has signed! You will receive an Email copy of the signed document. +

+ )) + .otherwise(() => ( +

+ You will receive an Email copy of the signed document once everyone has signed. +

+ ))} + +
+ + + +
+ +

+ Want to send slick signing links like this one?{' '} + + Check out Documenso. + +

- -

- You have signed "{document.title}" -

- - {match(document.status) - .with(DocumentStatus.COMPLETED, () => ( -

- Everyone has signed! You will receive an Email copy of the signed document. -

- )) - .otherwise(() => ( -

- You will receive an Email copy of the signed document once everyone has signed. -

- ))} - -
- - - -
- -

- Want to send slick signing links like this one?{' '} - - Check out Documenso. - -

); } diff --git a/packages/ui/components/signing-card.tsx b/packages/ui/components/signing-card.tsx index 496e451d0..a2dd66bae 100644 --- a/packages/ui/components/signing-card.tsx +++ b/packages/ui/components/signing-card.tsx @@ -148,7 +148,7 @@ const SigningCardContent = ({ className, name }: SigningCardContentProps) => { return ( { return ( background pattern Date: Wed, 27 Sep 2023 16:53:22 +1000 Subject: [PATCH 9/9] chore: add missing migrations --- .../20230605122017_password_reset/migration.sql | 15 +++++++++++++++ .../migration.sql | 8 ++++++++ .../migration.sql | 2 ++ 3 files changed, 25 insertions(+) create mode 100644 packages/prisma/migrations/20230605122017_password_reset/migration.sql create mode 100644 packages/prisma/migrations/20230605164015_expire_password_reset_token/migration.sql diff --git a/packages/prisma/migrations/20230605122017_password_reset/migration.sql b/packages/prisma/migrations/20230605122017_password_reset/migration.sql new file mode 100644 index 000000000..782a60880 --- /dev/null +++ b/packages/prisma/migrations/20230605122017_password_reset/migration.sql @@ -0,0 +1,15 @@ +-- CreateTable +CREATE TABLE "PasswordResetToken" ( + "id" SERIAL NOT NULL, + "token" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "userId" INTEGER NOT NULL, + + CONSTRAINT "PasswordResetToken_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "PasswordResetToken_token_key" ON "PasswordResetToken"("token"); + +-- AddForeignKey +ALTER TABLE "PasswordResetToken" ADD CONSTRAINT "PasswordResetToken_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/packages/prisma/migrations/20230605164015_expire_password_reset_token/migration.sql b/packages/prisma/migrations/20230605164015_expire_password_reset_token/migration.sql new file mode 100644 index 000000000..a3a70e575 --- /dev/null +++ b/packages/prisma/migrations/20230605164015_expire_password_reset_token/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - Added the required column `expiry` to the `PasswordResetToken` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "PasswordResetToken" ADD COLUMN "expiry" TIMESTAMP(3) NOT NULL; diff --git a/packages/prisma/migrations/20230917190854_password_reset_token/migration.sql b/packages/prisma/migrations/20230917190854_password_reset_token/migration.sql index d22107691..2d127d917 100644 --- a/packages/prisma/migrations/20230917190854_password_reset_token/migration.sql +++ b/packages/prisma/migrations/20230917190854_password_reset_token/migration.sql @@ -1,3 +1,5 @@ +DROP TABLE IF EXISTS "PasswordResetToken" CASCADE; + -- CreateTable CREATE TABLE "PasswordResetToken" ( "id" SERIAL NOT NULL,