mirror of
https://github.com/documenso/documenso.git
synced 2025-11-15 01:01:49 +10:00
feat: migrate templates and documents to envelope model
This commit is contained in:
@ -1,10 +1,12 @@
|
||||
import { DocumentDataType } from '@prisma/client';
|
||||
import { DocumentDataType, EnvelopeType } from '@prisma/client';
|
||||
|
||||
import { getServerLimits } from '@documenso/ee/server-only/limits/server';
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { createDocumentData } from '@documenso/lib/server-only/document-data/create-document-data';
|
||||
import { createDocumentV2 } from '@documenso/lib/server-only/document/create-document-v2';
|
||||
import { createEnvelope } from '@documenso/lib/server-only/envelope/create-envelope';
|
||||
import { getPresignPostUrl } from '@documenso/lib/universal/upload/server-actions';
|
||||
import { mapSecondaryIdToDocumentId } from '@documenso/lib/utils/envelope';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
import { authenticatedProcedure } from '../trpc';
|
||||
import {
|
||||
@ -55,12 +57,12 @@ export const createDocumentTemporaryRoute = authenticatedProcedure
|
||||
type: DocumentDataType.S3_PATH,
|
||||
});
|
||||
|
||||
const createdDocument = await createDocumentV2({
|
||||
const createdEnvelope = await createEnvelope({
|
||||
userId: ctx.user.id,
|
||||
teamId,
|
||||
documentDataId: documentData.id,
|
||||
normalizePdf: false, // Not normalizing because of presigned URL.
|
||||
data: {
|
||||
type: EnvelopeType.DOCUMENT,
|
||||
title,
|
||||
externalId,
|
||||
visibility,
|
||||
@ -68,14 +70,44 @@ export const createDocumentTemporaryRoute = authenticatedProcedure
|
||||
globalActionAuth,
|
||||
recipients,
|
||||
folderId,
|
||||
envelopeItems: [
|
||||
{
|
||||
documentDataId: documentData.id,
|
||||
},
|
||||
],
|
||||
},
|
||||
meta,
|
||||
requestMetadata: ctx.metadata,
|
||||
});
|
||||
|
||||
const envelopeItems = await prisma.envelopeItem.findMany({
|
||||
where: {
|
||||
envelopeId: createdEnvelope.id,
|
||||
},
|
||||
include: {
|
||||
documentData: true,
|
||||
},
|
||||
});
|
||||
|
||||
const legacyDocumentId = mapSecondaryIdToDocumentId(createdEnvelope.secondaryId);
|
||||
|
||||
const firstDocumentData = envelopeItems[0].documentData;
|
||||
|
||||
if (!firstDocumentData) {
|
||||
throw new Error('Document data not found');
|
||||
}
|
||||
|
||||
return {
|
||||
document: createdDocument,
|
||||
folder: createdDocument.folder, // Todo: Remove this prior to api-v2 release.
|
||||
document: {
|
||||
...createdEnvelope,
|
||||
documentData: firstDocumentData,
|
||||
id: legacyDocumentId,
|
||||
fields: createdEnvelope.fields.map((field) => ({
|
||||
...field,
|
||||
documentId: legacyDocumentId,
|
||||
})),
|
||||
},
|
||||
folder: createdEnvelope.folder, // Todo: Remove this prior to api-v2 release.
|
||||
uploadUrl: url,
|
||||
};
|
||||
});
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
import { EnvelopeType } from '@prisma/client';
|
||||
|
||||
import { getServerLimits } from '@documenso/ee/server-only/limits/server';
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { createDocument } from '@documenso/lib/server-only/document/create-document';
|
||||
import { createEnvelope } from '@documenso/lib/server-only/envelope/create-envelope';
|
||||
import { mapSecondaryIdToDocumentId } from '@documenso/lib/utils/envelope';
|
||||
|
||||
import { authenticatedProcedure } from '../trpc';
|
||||
import {
|
||||
@ -9,7 +12,7 @@ import {
|
||||
} from './create-document.types';
|
||||
|
||||
export const createDocumentRoute = authenticatedProcedure
|
||||
.input(ZCreateDocumentRequestSchema)
|
||||
.input(ZCreateDocumentRequestSchema) // Note: Before releasing this to public, update the response schema to be correct.
|
||||
.output(ZCreateDocumentResponseSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { user, teamId } = ctx;
|
||||
@ -30,18 +33,25 @@ export const createDocumentRoute = authenticatedProcedure
|
||||
});
|
||||
}
|
||||
|
||||
const document = await createDocument({
|
||||
const document = await createEnvelope({
|
||||
userId: user.id,
|
||||
teamId,
|
||||
title,
|
||||
documentDataId,
|
||||
data: {
|
||||
type: EnvelopeType.DOCUMENT,
|
||||
title,
|
||||
userTimezone: timezone,
|
||||
folderId,
|
||||
envelopeItems: [
|
||||
{
|
||||
documentDataId,
|
||||
},
|
||||
],
|
||||
},
|
||||
normalizePdf: true,
|
||||
userTimezone: timezone,
|
||||
requestMetadata: ctx.metadata,
|
||||
folderId,
|
||||
});
|
||||
|
||||
return {
|
||||
id: document.id,
|
||||
legacyDocumentId: mapSecondaryIdToDocumentId(document.secondaryId),
|
||||
};
|
||||
});
|
||||
|
||||
@ -20,7 +20,7 @@ export const ZCreateDocumentRequestSchema = z.object({
|
||||
});
|
||||
|
||||
export const ZCreateDocumentResponseSchema = z.object({
|
||||
id: z.number(),
|
||||
legacyDocumentId: z.number(),
|
||||
});
|
||||
|
||||
export type TCreateDocumentRequest = z.infer<typeof ZCreateDocumentRequestSchema>;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { upsertDocumentMeta } from '@documenso/lib/server-only/document-meta/upsert-document-meta';
|
||||
import { updateDocumentMeta } from '@documenso/lib/server-only/document-meta/upsert-document-meta';
|
||||
import { sendDocument } from '@documenso/lib/server-only/document/send-document';
|
||||
import { mapEnvelopeToDocumentLite } from '@documenso/lib/utils/document';
|
||||
|
||||
import { authenticatedProcedure } from '../trpc';
|
||||
import {
|
||||
@ -23,10 +24,13 @@ export const distributeDocumentRoute = authenticatedProcedure
|
||||
});
|
||||
|
||||
if (Object.values(meta).length > 0) {
|
||||
await upsertDocumentMeta({
|
||||
await updateDocumentMeta({
|
||||
userId: ctx.user.id,
|
||||
teamId,
|
||||
documentId,
|
||||
id: {
|
||||
type: 'documentId',
|
||||
id: documentId,
|
||||
},
|
||||
subject: meta.subject,
|
||||
message: meta.message,
|
||||
dateFormat: meta.dateFormat,
|
||||
@ -41,10 +45,15 @@ export const distributeDocumentRoute = authenticatedProcedure
|
||||
});
|
||||
}
|
||||
|
||||
return await sendDocument({
|
||||
const envelope = await sendDocument({
|
||||
userId: ctx.user.id,
|
||||
documentId,
|
||||
id: {
|
||||
type: 'documentId',
|
||||
id: documentId,
|
||||
},
|
||||
teamId,
|
||||
requestMetadata: ctx.metadata,
|
||||
});
|
||||
|
||||
return mapEnvelopeToDocumentLite(envelope);
|
||||
});
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { EnvelopeType } from '@prisma/client';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { encryptSecondaryData } from '@documenso/lib/server-only/crypto/encrypt';
|
||||
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id';
|
||||
import { getEnvelopeById } from '@documenso/lib/server-only/envelope/get-envelope-by-id';
|
||||
import { mapSecondaryIdToDocumentId } from '@documenso/lib/utils/envelope';
|
||||
|
||||
import { authenticatedProcedure } from '../trpc';
|
||||
import {
|
||||
@ -24,20 +26,24 @@ export const downloadDocumentAuditLogsRoute = authenticatedProcedure
|
||||
},
|
||||
});
|
||||
|
||||
const document = await getDocumentById({
|
||||
documentId,
|
||||
const envelope = await getEnvelopeById({
|
||||
id: {
|
||||
type: 'documentId',
|
||||
id: documentId,
|
||||
},
|
||||
type: EnvelopeType.DOCUMENT,
|
||||
userId: ctx.user.id,
|
||||
teamId,
|
||||
}).catch(() => null);
|
||||
|
||||
if (!document || (teamId && document.teamId !== teamId)) {
|
||||
if (!envelope) {
|
||||
throw new AppError(AppErrorCode.UNAUTHORIZED, {
|
||||
message: 'You do not have access to this document.',
|
||||
});
|
||||
}
|
||||
|
||||
const encrypted = encryptSecondaryData({
|
||||
data: document.id.toString(),
|
||||
data: mapSecondaryIdToDocumentId(envelope.secondaryId).toString(),
|
||||
expiresAt: DateTime.now().plus({ minutes: 5 }).toJSDate().valueOf(),
|
||||
});
|
||||
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import { EnvelopeType } from '@prisma/client';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
|
||||
import { AppError } from '@documenso/lib/errors/app-error';
|
||||
import { encryptSecondaryData } from '@documenso/lib/server-only/crypto/encrypt';
|
||||
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id';
|
||||
import { getEnvelopeById } from '@documenso/lib/server-only/envelope/get-envelope-by-id';
|
||||
import { isDocumentCompleted } from '@documenso/lib/utils/document';
|
||||
import { mapSecondaryIdToDocumentId } from '@documenso/lib/utils/envelope';
|
||||
|
||||
import { authenticatedProcedure } from '../trpc';
|
||||
import {
|
||||
@ -25,18 +27,22 @@ export const downloadDocumentCertificateRoute = authenticatedProcedure
|
||||
},
|
||||
});
|
||||
|
||||
const document = await getDocumentById({
|
||||
documentId,
|
||||
const envelope = await getEnvelopeById({
|
||||
id: {
|
||||
type: 'documentId',
|
||||
id: documentId,
|
||||
},
|
||||
type: EnvelopeType.DOCUMENT,
|
||||
userId: ctx.user.id,
|
||||
teamId,
|
||||
});
|
||||
|
||||
if (!isDocumentCompleted(document.status)) {
|
||||
if (!isDocumentCompleted(envelope.status)) {
|
||||
throw new AppError('DOCUMENT_NOT_COMPLETE');
|
||||
}
|
||||
|
||||
const encrypted = encryptSecondaryData({
|
||||
data: document.id.toString(),
|
||||
data: mapSecondaryIdToDocumentId(envelope.secondaryId).toString(),
|
||||
expiresAt: DateTime.now().plus({ minutes: 5 }).toJSDate().valueOf(),
|
||||
});
|
||||
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { DocumentDataType } from '@prisma/client';
|
||||
import type { DocumentData } from '@prisma/client';
|
||||
import { DocumentDataType, EnvelopeType } from '@prisma/client';
|
||||
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id';
|
||||
import { getEnvelopeById } from '@documenso/lib/server-only/envelope/get-envelope-by-id';
|
||||
import { getPresignGetUrl } from '@documenso/lib/universal/upload/server-actions';
|
||||
import { isDocumentCompleted } from '@documenso/lib/utils/document';
|
||||
|
||||
@ -27,45 +28,51 @@ export const downloadDocumentRoute = authenticatedProcedure
|
||||
},
|
||||
});
|
||||
|
||||
const envelope = await getEnvelopeById({
|
||||
id: {
|
||||
type: 'documentId',
|
||||
id: documentId,
|
||||
},
|
||||
type: EnvelopeType.DOCUMENT,
|
||||
userId: user.id,
|
||||
teamId,
|
||||
});
|
||||
|
||||
// This error is done AFTER the get envelope so we can test access controls without S3.
|
||||
if (process.env.NEXT_PUBLIC_UPLOAD_TRANSPORT !== 's3') {
|
||||
throw new AppError(AppErrorCode.INVALID_REQUEST, {
|
||||
message: 'Document downloads are only available when S3 storage is configured.',
|
||||
});
|
||||
}
|
||||
|
||||
const document = await getDocumentById({
|
||||
documentId,
|
||||
userId: user.id,
|
||||
teamId,
|
||||
});
|
||||
const documentData: DocumentData | undefined = envelope.envelopeItems[0]?.documentData;
|
||||
|
||||
if (!document.documentData) {
|
||||
throw new AppError(AppErrorCode.NOT_FOUND, {
|
||||
message: 'Document data not found',
|
||||
if (envelope.envelopeItems.length !== 1 || !documentData) {
|
||||
throw new AppError(AppErrorCode.INVALID_REQUEST, {
|
||||
message:
|
||||
'This endpoint only supports documents with a single item. Use envelopes API instead.',
|
||||
});
|
||||
}
|
||||
|
||||
if (document.documentData.type !== DocumentDataType.S3_PATH) {
|
||||
if (documentData.type !== DocumentDataType.S3_PATH) {
|
||||
throw new AppError(AppErrorCode.INVALID_REQUEST, {
|
||||
message: 'Document is not stored in S3 and cannot be downloaded via URL.',
|
||||
});
|
||||
}
|
||||
|
||||
if (version === 'signed' && !isDocumentCompleted(document.status)) {
|
||||
if (version === 'signed' && !isDocumentCompleted(envelope.status)) {
|
||||
throw new AppError(AppErrorCode.INVALID_REQUEST, {
|
||||
message: 'Document is not completed yet.',
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const documentData =
|
||||
version === 'original'
|
||||
? document.documentData.initialData || document.documentData.data
|
||||
: document.documentData.data;
|
||||
const data =
|
||||
version === 'original' ? documentData.initialData || documentData.data : documentData.data;
|
||||
|
||||
const { url } = await getPresignGetUrl(documentData);
|
||||
const { url } = await getPresignGetUrl(data);
|
||||
|
||||
const baseTitle = document.title.replace(/\.pdf$/, '');
|
||||
const baseTitle = envelope.title.replace(/\.pdf$/, '');
|
||||
const suffix = version === 'signed' ? '_signed.pdf' : '.pdf';
|
||||
const filename = `${baseTitle}${suffix}`;
|
||||
|
||||
|
||||
@ -22,8 +22,11 @@ export const duplicateDocumentRoute = authenticatedProcedure
|
||||
});
|
||||
|
||||
return await duplicateDocument({
|
||||
id: {
|
||||
type: 'documentId',
|
||||
id: documentId,
|
||||
},
|
||||
userId: user.id,
|
||||
teamId,
|
||||
documentId,
|
||||
});
|
||||
});
|
||||
|
||||
@ -2,6 +2,7 @@ import { findDocuments } from '@documenso/lib/server-only/document/find-document
|
||||
import type { GetStatsInput } from '@documenso/lib/server-only/document/get-stats';
|
||||
import { getStats } from '@documenso/lib/server-only/document/get-stats';
|
||||
import { getTeamById } from '@documenso/lib/server-only/team/get-team';
|
||||
import { mapEnvelopesToDocumentMany } from '@documenso/lib/utils/document';
|
||||
|
||||
import { authenticatedProcedure } from '../trpc';
|
||||
import {
|
||||
@ -69,6 +70,7 @@ export const findDocumentsInternalRoute = authenticatedProcedure
|
||||
|
||||
return {
|
||||
...documents,
|
||||
data: documents.data.map((envelope) => mapEnvelopesToDocumentMany(envelope)),
|
||||
stats,
|
||||
};
|
||||
});
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { findDocuments } from '@documenso/lib/server-only/document/find-documents';
|
||||
import { mapEnvelopesToDocumentMany } from '@documenso/lib/utils/document';
|
||||
|
||||
import { authenticatedProcedure } from '../trpc';
|
||||
import {
|
||||
@ -39,5 +40,8 @@ export const findDocumentsRoute = authenticatedProcedure
|
||||
orderBy: orderByColumn ? { column: orderByColumn, direction: orderByDirection } : undefined,
|
||||
});
|
||||
|
||||
return documents;
|
||||
return {
|
||||
...documents,
|
||||
data: documents.data.map((envelope) => mapEnvelopesToDocumentMany(envelope)),
|
||||
};
|
||||
});
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import type { Document, Prisma } from '@prisma/client';
|
||||
import { DocumentStatus, RecipientRole } from '@prisma/client';
|
||||
import type { Envelope, Prisma } from '@prisma/client';
|
||||
import { DocumentStatus, EnvelopeType, RecipientRole } from '@prisma/client';
|
||||
|
||||
import type { FindResultResponse } from '@documenso/lib/types/search-params';
|
||||
import { mapEnvelopesToDocumentMany } from '@documenso/lib/utils/document';
|
||||
import { maskRecipientTokensForDocument } from '@documenso/lib/utils/mask-recipient-tokens-for-document';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
@ -16,11 +17,16 @@ export const findInboxRoute = authenticatedProcedure
|
||||
|
||||
const userId = ctx.user.id;
|
||||
|
||||
return await findInbox({
|
||||
const envelopes = await findInbox({
|
||||
userId,
|
||||
page,
|
||||
perPage,
|
||||
});
|
||||
|
||||
return {
|
||||
...envelopes,
|
||||
data: envelopes.data.map(mapEnvelopesToDocumentMany),
|
||||
};
|
||||
});
|
||||
|
||||
export type FindInboxOptions = {
|
||||
@ -28,7 +34,7 @@ export type FindInboxOptions = {
|
||||
page?: number;
|
||||
perPage?: number;
|
||||
orderBy?: {
|
||||
column: keyof Omit<Document, 'document'>;
|
||||
column: keyof Omit<Envelope, 'envelope'>;
|
||||
direction: 'asc' | 'desc';
|
||||
};
|
||||
};
|
||||
@ -38,12 +44,17 @@ export const findInbox = async ({ userId, page = 1, perPage = 10, orderBy }: Fin
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
},
|
||||
});
|
||||
|
||||
const orderByColumn = orderBy?.column ?? 'createdAt';
|
||||
const orderByDirection = orderBy?.direction ?? 'desc';
|
||||
|
||||
const whereClause: Prisma.DocumentWhereInput = {
|
||||
const whereClause: Prisma.EnvelopeWhereInput = {
|
||||
type: EnvelopeType.DOCUMENT,
|
||||
status: {
|
||||
not: DocumentStatus.DRAFT,
|
||||
},
|
||||
@ -59,7 +70,7 @@ export const findInbox = async ({ userId, page = 1, perPage = 10, orderBy }: Fin
|
||||
};
|
||||
|
||||
const [data, count] = await Promise.all([
|
||||
prisma.document.findMany({
|
||||
prisma.envelope.findMany({
|
||||
where: whereClause,
|
||||
skip: Math.max(page - 1, 0) * perPage,
|
||||
take: perPage,
|
||||
@ -83,7 +94,7 @@ export const findInbox = async ({ userId, page = 1, perPage = 10, orderBy }: Fin
|
||||
},
|
||||
},
|
||||
}),
|
||||
prisma.document.count({
|
||||
prisma.envelope.count({
|
||||
where: whereClause,
|
||||
}),
|
||||
]);
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { EnvelopeType } from '@prisma/client';
|
||||
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
@ -13,8 +15,9 @@ export const getDocumentByTokenRoute = authenticatedProcedure
|
||||
.query(async ({ input, ctx }) => {
|
||||
const { token } = input;
|
||||
|
||||
const document = await prisma.document.findFirst({
|
||||
const envelope = await prisma.envelope.findFirst({
|
||||
where: {
|
||||
type: EnvelopeType.DOCUMENT,
|
||||
recipients: {
|
||||
some: {
|
||||
token,
|
||||
@ -23,21 +26,34 @@ export const getDocumentByTokenRoute = authenticatedProcedure
|
||||
},
|
||||
},
|
||||
include: {
|
||||
documentData: true,
|
||||
envelopeItems: {
|
||||
include: {
|
||||
documentData: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!document) {
|
||||
// Todo: Envelopes
|
||||
const firstDocumentData = envelope?.envelopeItems[0].documentData;
|
||||
|
||||
if (!envelope || !firstDocumentData) {
|
||||
throw new AppError(AppErrorCode.NOT_FOUND, {
|
||||
message: 'Document not found',
|
||||
});
|
||||
}
|
||||
|
||||
if (envelope.envelopeItems.length !== 1) {
|
||||
throw new AppError(AppErrorCode.INVALID_REQUEST, {
|
||||
message: 'This endpoint does not support multiple items',
|
||||
});
|
||||
}
|
||||
|
||||
ctx.logger.info({
|
||||
documentId: document.id,
|
||||
documentId: envelope.id,
|
||||
});
|
||||
|
||||
return {
|
||||
documentData: document.documentData,
|
||||
documentData: firstDocumentData,
|
||||
};
|
||||
});
|
||||
|
||||
@ -24,6 +24,9 @@ export const getDocumentRoute = authenticatedProcedure
|
||||
return await getDocumentWithDetailsById({
|
||||
userId: user.id,
|
||||
teamId,
|
||||
documentId,
|
||||
id: {
|
||||
type: 'documentId',
|
||||
id: documentId,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { DocumentStatus, RecipientRole } from '@prisma/client';
|
||||
import { DocumentStatus, EnvelopeType, RecipientRole } from '@prisma/client';
|
||||
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
@ -20,7 +20,8 @@ export const getInboxCountRoute = authenticatedProcedure
|
||||
role: {
|
||||
not: RecipientRole.CC,
|
||||
},
|
||||
document: {
|
||||
envelope: {
|
||||
type: EnvelopeType.DOCUMENT,
|
||||
status: {
|
||||
not: DocumentStatus.DRAFT,
|
||||
},
|
||||
|
||||
@ -17,6 +17,7 @@ import { getDocumentByTokenRoute } from './get-document-by-token';
|
||||
import { getInboxCountRoute } from './get-inbox-count';
|
||||
import { redistributeDocumentRoute } from './redistribute-document';
|
||||
import { searchDocumentRoute } from './search-document';
|
||||
import { shareDocumentRoute } from './share-document';
|
||||
import { updateDocumentRoute } from './update-document';
|
||||
|
||||
export const documentRouter = router({
|
||||
@ -30,6 +31,7 @@ export const documentRouter = router({
|
||||
distribute: distributeDocumentRoute,
|
||||
redistribute: redistributeDocumentRoute,
|
||||
search: searchDocumentRoute,
|
||||
share: shareDocumentRoute,
|
||||
|
||||
// Temporary v2 beta routes to be removed once V2 is fully released.
|
||||
download: downloadDocumentRoute,
|
||||
|
||||
28
packages/trpc/server/document-router/share-document.ts
Normal file
28
packages/trpc/server/document-router/share-document.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { createOrGetShareLink } from '@documenso/lib/server-only/share/create-or-get-share-link';
|
||||
|
||||
import { procedure } from '../trpc';
|
||||
import { ZShareDocumentRequestSchema, ZShareDocumentResponseSchema } from './share-document.types';
|
||||
|
||||
// Note: This is an unauthenticated route.
|
||||
export const shareDocumentRoute = procedure
|
||||
.input(ZShareDocumentRequestSchema)
|
||||
.output(ZShareDocumentResponseSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { documentId, token } = input;
|
||||
|
||||
ctx.logger.info({
|
||||
input: {
|
||||
documentId,
|
||||
},
|
||||
});
|
||||
|
||||
if (token) {
|
||||
return await createOrGetShareLink({ documentId, token });
|
||||
}
|
||||
|
||||
if (!ctx.user?.id) {
|
||||
throw new Error('You must either provide a token or be logged in to create a sharing link.');
|
||||
}
|
||||
|
||||
return await createOrGetShareLink({ documentId, userId: ctx.user.id });
|
||||
});
|
||||
16
packages/trpc/server/document-router/share-document.types.ts
Normal file
16
packages/trpc/server/document-router/share-document.types.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import DocumentShareLinkSchema from '@documenso/prisma/generated/zod/modelSchema/DocumentShareLinkSchema';
|
||||
|
||||
export const ZShareDocumentRequestSchema = z.object({
|
||||
documentId: z.number(),
|
||||
token: z.string().optional(),
|
||||
});
|
||||
|
||||
export const ZShareDocumentResponseSchema = DocumentShareLinkSchema.pick({
|
||||
slug: true,
|
||||
email: true,
|
||||
});
|
||||
|
||||
export type TShareDocumentRequest = z.infer<typeof ZShareDocumentRequestSchema>;
|
||||
export type TShareDocumentResponse = z.infer<typeof ZShareDocumentResponseSchema>;
|
||||
@ -1,18 +1,19 @@
|
||||
import { upsertDocumentMeta } from '@documenso/lib/server-only/document-meta/upsert-document-meta';
|
||||
import { updateDocumentMeta } from '@documenso/lib/server-only/document-meta/upsert-document-meta';
|
||||
import { updateDocument } from '@documenso/lib/server-only/document/update-document';
|
||||
import { mapSecondaryIdToDocumentId } from '@documenso/lib/utils/envelope';
|
||||
|
||||
import { authenticatedProcedure } from '../trpc';
|
||||
import {
|
||||
ZUpdateDocumentRequestSchema,
|
||||
ZUpdateDocumentResponseSchema,
|
||||
} from './update-document.types';
|
||||
import { updateDocumentMeta } from './update-document.types';
|
||||
import { updateDocumentMeta as updateDocumentTrpcMeta } from './update-document.types';
|
||||
|
||||
/**
|
||||
* Public route.
|
||||
*/
|
||||
export const updateDocumentRoute = authenticatedProcedure
|
||||
.meta(updateDocumentMeta)
|
||||
.meta(updateDocumentTrpcMeta)
|
||||
.input(ZUpdateDocumentRequestSchema)
|
||||
.output(ZUpdateDocumentResponseSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
@ -28,10 +29,13 @@ export const updateDocumentRoute = authenticatedProcedure
|
||||
const userId = ctx.user.id;
|
||||
|
||||
if (Object.values(meta).length > 0) {
|
||||
await upsertDocumentMeta({
|
||||
await updateDocumentMeta({
|
||||
userId: ctx.user.id,
|
||||
teamId,
|
||||
documentId,
|
||||
id: {
|
||||
type: 'documentId',
|
||||
id: documentId,
|
||||
},
|
||||
subject: meta.subject,
|
||||
message: meta.message,
|
||||
timezone: meta.timezone,
|
||||
@ -51,11 +55,18 @@ export const updateDocumentRoute = authenticatedProcedure
|
||||
});
|
||||
}
|
||||
|
||||
return await updateDocument({
|
||||
const envelope = await updateDocument({
|
||||
userId,
|
||||
teamId,
|
||||
documentId,
|
||||
data,
|
||||
requestMetadata: ctx.metadata,
|
||||
});
|
||||
|
||||
const mappedDocument = {
|
||||
...envelope,
|
||||
id: mapSecondaryIdToDocumentId(envelope.secondaryId),
|
||||
};
|
||||
|
||||
return mappedDocument;
|
||||
});
|
||||
|
||||
@ -45,6 +45,7 @@ export const ZUpdateDocumentRequestSchema = z.object({
|
||||
globalAccessAuth: z.array(ZDocumentAccessAuthTypesSchema).optional(),
|
||||
globalActionAuth: z.array(ZDocumentActionAuthTypesSchema).optional(),
|
||||
useLegacyFieldInsertion: z.boolean().optional(),
|
||||
folderId: z.string().nullish(),
|
||||
})
|
||||
.optional(),
|
||||
meta: z
|
||||
|
||||
Reference in New Issue
Block a user