Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: remove jwt from esign token #492

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions prisma/migrations/20240820093558_add_esign_token/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
Warnings:

- The values [Signature token] on the enum `AccessTokenType` will be removed. If these variants are still used in the database, this will fail.

*/
-- AlterEnum
BEGIN;
CREATE TYPE "AccessTokenType_new" AS ENUM ('Data room token', 'API access token', 'Investor update token');
ALTER TABLE "AccessToken" ALTER COLUMN "typeEnum" DROP DEFAULT;
ALTER TABLE "AccessToken" ALTER COLUMN "typeEnum" TYPE "AccessTokenType_new" USING ("typeEnum"::text::"AccessTokenType_new");
ALTER TYPE "AccessTokenType" RENAME TO "AccessTokenType_old";
ALTER TYPE "AccessTokenType_new" RENAME TO "AccessTokenType";
DROP TYPE "AccessTokenType_old";
ALTER TABLE "AccessToken" ALTER COLUMN "typeEnum" SET DEFAULT 'API access token';
COMMIT;

-- CreateTable
CREATE TABLE "ESignToken" (
"id" TEXT NOT NULL,
"token" TEXT NOT NULL,
"templateId" TEXT NOT NULL,
"recipientId" TEXT NOT NULL,
"expiresAt" TIMESTAMP(3),
"lastUsed" TIMESTAMP(3),
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,

CONSTRAINT "ESignToken_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE INDEX "ESignToken_templateId_idx" ON "ESignToken"("templateId");

-- CreateIndex
CREATE INDEX "ESignToken_recipientId_idx" ON "ESignToken"("recipientId");
21 changes: 20 additions & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,7 @@ model Template {

completedOn DateTime?
eSignAudits EsignAudit[]
eSignTokens ESignToken[]

@@index([bucketId])
@@index([uploaderId])
Expand Down Expand Up @@ -661,6 +662,7 @@ model EsignRecipient {
updatedAt DateTime @updatedAt
templateFields TemplateField[]
eSignAudits EsignAudit[]
eSignTokens ESignToken[]

@@index([memberId])
@@index([templateId])
Expand Down Expand Up @@ -1120,7 +1122,6 @@ model BillingCustomer {
}

enum AccessTokenType {
sig @map("Signature token")
doc @map("Data room token")
api @map("API access token")
upd @map("Investor update token")
Expand All @@ -1144,3 +1145,21 @@ model AccessToken {
@@index([userId])
@@index([typeEnum, clientId])
}

model ESignToken {
id String @id @default(cuid())
token String
templateId String
template Template @relation(fields: [templateId], references: [id])

recipientId String
recipient EsignRecipient @relation(fields: [recipientId], references: [id])

expiresAt DateTime?
lastUsed DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

@@index([templateId])
@@index([recipientId])
}
51 changes: 29 additions & 22 deletions src/trpc/routers/template-field-router/procedures/add-fields.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,49 @@
/* eslint-disable @typescript-eslint/prefer-for-of */
import { customId } from "@/common/id";
import {
EsignNotificationEmailJob,
type ExtendedEsignPayloadType,
} from "@/jobs/esign-email";
import { decode, encode } from "@/lib/jwt";
import { Audit } from "@/server/audit";
import { checkMembership } from "@/server/auth";
import type { TPrismaOrTransaction } from "@/server/db";
import { withAuth } from "@/trpc/api/trpc";
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { ZodAddFieldMutationSchema } from "../schema";

const emailTokenPayloadSchema = z.object({
id: z.string(),
rec: z.string(),
});

type TEmailTokenPayloadSchema = z.infer<typeof emailTokenPayloadSchema>;

interface EncodeEmailTokenOption {
interface TEncodeSignatureTokenOption {
db: TPrismaOrTransaction;
templateId: string;
recipientId: string;
}

export function EncodeEmailToken({
export async function encodeSignatureToken({
recipientId,
templateId,
}: EncodeEmailTokenOption) {
const encodeToken: TEmailTokenPayloadSchema = {
rec: recipientId,
id: templateId,
};
db,
}: TEncodeSignatureTokenOption) {
const token = customId();

await db.eSignToken.create({
data: {
templateId,
recipientId,
token,
},
});

return encode(encodeToken);
return token;
}

export async function DecodeEmailToken(jwt: string) {
const { payload } = await decode(jwt);
return emailTokenPayloadSchema.parse(payload);
export function decodeSignatureToken(token: string, db: TPrismaOrTransaction) {
return db.eSignToken.findFirstOrThrow({
where: {
token,
},
select: {
recipientId: true,
templateId: true,
},
});
}

export const addFieldProcedure = withAuth
Expand Down Expand Up @@ -165,9 +171,10 @@ export const addFieldProcedure = withAuth
throw new Error("not found");
}

const token = await EncodeEmailToken({
const token = await encodeSignatureToken({
recipientId: recipient.id,
templateId: template.id,
db: tx,
});

const email = recipient.email;
Expand Down
110 changes: 56 additions & 54 deletions src/trpc/routers/template-router/procedures/get-signing-fields.tsx
Original file line number Diff line number Diff line change
@@ -1,70 +1,72 @@
import { getPresignedGetUrl } from "@/server/file-uploads";
import { withoutAuth } from "@/trpc/api/trpc";
import { DecodeEmailToken } from "../../template-field-router/procedures/add-fields";
import { decodeSignatureToken } from "../../template-field-router/procedures/add-fields";
import { ZodGetSigningFieldsSchema } from "../schema";

export const getSigningFieldsProcedure = withoutAuth
.input(ZodGetSigningFieldsSchema)
.query(async ({ ctx, input }) => {
const { id: templateId, rec: recipientId } = await DecodeEmailToken(
input.token,
);
const { bucket, fields, status, recipientId, templateId } =
await ctx.db.$transaction(async (tx) => {
const { recipientId, templateId } = await decodeSignatureToken(
input.token,
tx,
);

const { bucket, fields, status } = await ctx.db.$transaction(async (tx) => {
const recipient = await tx.esignRecipient.findFirstOrThrow({
where: {
id: recipientId,
templateId,
status: "SENT",
},
select: {
templateId: true,
},
});
const recipient = await tx.esignRecipient.findFirstOrThrow({
where: {
id: recipientId,
templateId,
status: "SENT",
},
select: {
templateId: true,
},
});

const { bucket, status } = await tx.template.findFirstOrThrow({
where: {
id: recipient.templateId,
},
select: {
bucket: {
select: {
key: true,
const { bucket, status } = await tx.template.findFirstOrThrow({
where: {
id: recipient.templateId,
},
select: {
bucket: {
select: {
key: true,
},
},
status: true,
},
status: true,
},
});
});

const fields = await tx.templateField.findMany({
where: {
templateId: recipient.templateId,
},
select: {
id: true,
name: true,
width: true,
height: true,
top: true,
left: true,
required: true,
defaultValue: true,
readOnly: true,
type: true,
viewportHeight: true,
viewportWidth: true,
page: true,
recipientId: true,
prefilledValue: true,
meta: true,
},
orderBy: {
top: "asc",
},
});
const fields = await tx.templateField.findMany({
where: {
templateId: recipient.templateId,
},
select: {
id: true,
name: true,
width: true,
height: true,
top: true,
left: true,
required: true,
defaultValue: true,
readOnly: true,
type: true,
viewportHeight: true,
viewportWidth: true,
page: true,
recipientId: true,
prefilledValue: true,
meta: true,
},
orderBy: {
top: "asc",
},
});

return { bucket, fields, status };
});
return { bucket, fields, status, templateId, recipientId };
});

const { key, url } = await getPresignedGetUrl(bucket.key);

Expand Down
5 changes: 3 additions & 2 deletions src/trpc/routers/template-router/procedures/sign-template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
type uploadEsignDocumentsOptions,
} from "@/server/esign";
import { withoutAuth } from "@/trpc/api/trpc";
import { EncodeEmailToken } from "../../template-field-router/procedures/add-fields";
import { encodeSignatureToken } from "../../template-field-router/procedures/add-fields";
import { SignTemplateMutationSchema } from "../schema";

export const signTemplateProcedure = withoutAuth
Expand Down Expand Up @@ -218,9 +218,10 @@ export const signTemplateProcedure = withoutAuth
},
});
if (nextDelivery) {
const token = await EncodeEmailToken({
const token = await encodeSignatureToken({
recipientId: nextDelivery.id,
templateId: template.id,
db: tx,
});
const email = nextDelivery.email;

Expand Down