feat: create sharing id for each recipient

This commit is contained in:
Ephraim Atta-Duncan
2023-08-29 18:23:52 +00:00
committed by Mythie
parent 1bce169228
commit ebcd7c78e4
12 changed files with 170 additions and 102 deletions

View File

@ -0,0 +1,20 @@
import { nanoid } from 'nanoid';
import { prisma } from '@documenso/prisma';
export interface CreateSharingIdOptions {
documentId: number;
recipientId: number;
}
export const createSharingId = async ({ documentId, recipientId }: CreateSharingIdOptions) => {
const result = await prisma.share.create({
data: {
recipientId,
documentId,
link: nanoid(),
},
});
return result;
};

View File

@ -0,0 +1,20 @@
-- CreateTable
CREATE TABLE "Share" (
"id" SERIAL NOT NULL,
"userId" INTEGER NOT NULL,
"link" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
"documentId" INTEGER,
CONSTRAINT "Share_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "Share_link_key" ON "Share"("link");
-- AddForeignKey
ALTER TABLE "Share" ADD CONSTRAINT "Share_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "Share" ADD CONSTRAINT "Share_documentId_fkey" FOREIGN KEY ("documentId") REFERENCES "Document"("id") ON DELETE SET NULL ON UPDATE CASCADE;

View File

@ -0,0 +1,16 @@
/*
Warnings:
- You are about to drop the column `userId` on the `Share` table. All the data in the column will be lost.
- Added the required column `recipientId` to the `Share` table without a default value. This is not possible if the table is not empty.
*/
-- DropForeignKey
ALTER TABLE "Share" DROP CONSTRAINT "Share_userId_fkey";
-- AlterTable
ALTER TABLE "Share" DROP COLUMN "userId",
ADD COLUMN "recipientId" INTEGER NOT NULL;
-- AddForeignKey
ALTER TABLE "Share" ADD CONSTRAINT "Share_recipientId_fkey" FOREIGN KEY ("recipientId") REFERENCES "Recipient"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -101,33 +101,16 @@ enum DocumentStatus {
}
model Document {
id Int @id @default(autoincrement())
userId Int
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
title String
status DocumentStatus @default(DRAFT)
Recipient Recipient[]
Field Field[]
documentDataId String
documentData DocumentData @relation(fields: [documentDataId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @default(now()) @updatedAt
@@unique([documentDataId])
}
enum DocumentDataType {
S3_PATH
BYTES
BYTES_64
}
model DocumentData {
id String @id @default(cuid())
type DocumentDataType
data String
initialData String
Document Document?
id Int @id @default(autoincrement())
created DateTime @default(now())
userId Int
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
title String
status DocumentStatus @default(DRAFT)
document String
Recipient Recipient[]
Field Field[]
Share Share[]
}
enum ReadStatus {
@ -159,6 +142,7 @@ model Recipient {
Document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
Field Field[]
Signature Signature[]
Share Share[]
@@unique([documentId, email])
}
@ -201,11 +185,13 @@ model Signature {
Field Field @relation(fields: [fieldId], references: [id], onDelete: Restrict)
}
model PasswordResetToken {
id Int @id @default(autoincrement())
token String @unique
createdAt DateTime @default(now())
expiry DateTime
userId Int
User User @relation(fields: [userId], references: [id])
model Share {
id Int @id @default(autoincrement())
recipientId Int
recipent Recipient @relation(fields: [recipientId], references: [id])
link String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
document Document? @relation(fields: [documentId], references: [id])
documentId Int?
}

View File

@ -3,6 +3,7 @@ import { authRouter } from './auth-router/router';
import { documentRouter } from './document-router/router';
import { fieldRouter } from './field-router/router';
import { profileRouter } from './profile-router/router';
import { shareRouter } from './share-router/router';
import { procedure, router } from './trpc';
export const appRouter = router({
@ -11,7 +12,7 @@ export const appRouter = router({
profile: profileRouter,
document: documentRouter,
field: fieldRouter,
admin: adminRouter,
share: shareRouter,
});
export type AppRouter = typeof appRouter;

View File

@ -0,0 +1,23 @@
import { TRPCError } from '@trpc/server';
import { createSharingId } from '@documenso/lib/server-only/share/create-share-id';
import { procedure, router } from '../trpc';
import { ZShareLinkSchema } from './schema';
export const shareRouter = router({
create: procedure.input(ZShareLinkSchema).mutation(async ({ input }) => {
try {
const { documentId, recipientId } = input;
return await createSharingId({ documentId, recipientId });
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to create a sharing link.',
});
}
}),
});

View File

@ -0,0 +1,8 @@
import { z } from 'zod';
export const ZShareLinkSchema = z.object({
documentId: z.number(),
recipientId: z.number(),
});
export type ZShareLinkSchema = z.infer<typeof ZShareLinkSchema>;