Files
sign/packages/trpc/server/document-router/router.ts

338 lines
10 KiB
TypeScript
Raw Normal View History

import { TRPCError } from '@trpc/server';
2023-10-15 20:26:32 +11:00
import { getServerLimits } from '@documenso/ee/server-only/limits/server';
import { DOCUMENSO_ENCRYPTION_KEY } from '@documenso/lib/constants/crypto';
2023-12-02 09:38:24 +11:00
import { upsertDocumentMeta } from '@documenso/lib/server-only/document-meta/upsert-document-meta';
import { createDocument } from '@documenso/lib/server-only/document/create-document';
import { deleteDocument } from '@documenso/lib/server-only/document/delete-document';
2023-11-08 09:25:44 +00:00
import { duplicateDocumentById } from '@documenso/lib/server-only/document/duplicate-document-by-id';
2024-02-15 18:20:10 +11:00
import { findDocumentAuditLogs } from '@documenso/lib/server-only/document/find-document-audit-logs';
import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id';
import { getDocumentAndSenderByToken } from '@documenso/lib/server-only/document/get-document-by-token';
2023-11-16 07:35:45 +05:30
import { resendDocument } from '@documenso/lib/server-only/document/resend-document';
import { searchDocumentsWithKeyword } from '@documenso/lib/server-only/document/search-documents-with-keyword';
import { sendDocument } from '@documenso/lib/server-only/document/send-document';
2024-03-17 14:17:49 +08:00
import { updateDocumentSettings } from '@documenso/lib/server-only/document/update-document-settings';
import { updateTitle } from '@documenso/lib/server-only/document/update-title';
import { symmetricEncrypt } from '@documenso/lib/universal/crypto';
import { extractNextApiRequestMetadata } from '@documenso/lib/universal/extract-request-metadata';
import { authenticatedProcedure, procedure, router } from '../trpc';
import {
ZCreateDocumentMutationSchema,
ZDeleteDraftDocumentMutationSchema as ZDeleteDocumentMutationSchema,
2024-02-15 18:20:10 +11:00
ZFindDocumentAuditLogsQuerySchema,
ZGetDocumentByIdQuerySchema,
ZGetDocumentByTokenQuerySchema,
2023-11-16 07:35:45 +05:30
ZResendDocumentMutationSchema,
ZSearchDocumentsMutationSchema,
ZSendDocumentMutationSchema,
ZSetPasswordForDocumentMutationSchema,
2024-03-17 14:17:49 +08:00
ZSetSettingsForDocumentMutationSchema,
ZSetTitleForDocumentMutationSchema,
} from './schema';
export const documentRouter = router({
getDocumentById: authenticatedProcedure
.input(ZGetDocumentByIdQuerySchema)
.query(async ({ input, ctx }) => {
try {
return await getDocumentById({
...input,
userId: ctx.user.id,
});
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to find this document. Please try again later.',
});
}
}),
2024-03-17 14:17:49 +08:00
getDocumentByToken: procedure
.input(ZGetDocumentByTokenQuerySchema)
.query(async ({ input, ctx }) => {
try {
const { token } = input;
2024-03-17 14:17:49 +08:00
return await getDocumentAndSenderByToken({
token,
userId: ctx.user?.id,
});
} catch (err) {
console.error(err);
2024-03-17 14:17:49 +08:00
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to find this document. Please try again later.',
});
}
}),
createDocument: authenticatedProcedure
.input(ZCreateDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {
try {
const { title, documentDataId, teamId } = input;
const { remaining } = await getServerLimits({ email: ctx.user.email, teamId });
2023-10-15 20:26:32 +11:00
if (remaining.documents <= 0) {
throw new TRPCError({
code: 'BAD_REQUEST',
message:
'You have reached your document limit for this month. Please upgrade your plan.',
});
}
return await createDocument({
userId: ctx.user.id,
teamId,
title,
documentDataId,
requestMetadata: extractNextApiRequestMetadata(ctx.req),
});
} catch (err) {
2023-10-15 20:26:32 +11:00
if (err instanceof TRPCError) {
throw err;
}
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to create this document. Please try again later.',
});
}
}),
deleteDocument: authenticatedProcedure
.input(ZDeleteDocumentMutationSchema)
2023-10-10 08:25:58 +05:30
.mutation(async ({ input, ctx }) => {
try {
const { id, teamId } = input;
2023-10-10 08:25:58 +05:30
const userId = ctx.user.id;
2024-02-15 18:20:10 +11:00
return await deleteDocument({
id,
userId,
teamId,
2024-02-15 18:20:10 +11:00
requestMetadata: extractNextApiRequestMetadata(ctx.req),
});
2023-10-10 08:25:58 +05:30
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to delete this document. Please try again later.',
});
}
}),
2024-02-15 18:20:10 +11:00
findDocumentAuditLogs: authenticatedProcedure
.input(ZFindDocumentAuditLogsQuerySchema)
.query(async ({ input, ctx }) => {
try {
2024-02-22 19:13:35 +11:00
const { page, perPage, documentId, cursor, filterForRecentActivity, orderBy } = input;
2024-02-15 18:20:10 +11:00
return await findDocumentAuditLogs({
2024-02-22 19:13:35 +11:00
page,
2024-02-15 18:20:10 +11:00
perPage,
documentId,
cursor,
filterForRecentActivity,
orderBy,
userId: ctx.user.id,
});
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to find audit logs for this document. Please try again later.',
});
}
}),
2024-03-17 14:17:49 +08:00
// Todo: Add API
setSettingsForDocument: authenticatedProcedure
.input(ZSetSettingsForDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {
try {
const { documentId, teamId, data, meta } = input;
const userId = ctx.user.id;
const requestMetadata = extractNextApiRequestMetadata(ctx.req);
if (meta.timezone || meta.dateFormat || meta.redirectUrl) {
await upsertDocumentMeta({
documentId,
dateFormat: meta.dateFormat,
timezone: meta.timezone,
redirectUrl: meta.redirectUrl,
userId: ctx.user.id,
requestMetadata,
});
}
return await updateDocumentSettings({
userId,
teamId,
documentId,
data,
requestMetadata,
});
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message:
'We were unable to update the settings for this document. Please try again later.',
});
}
}),
setTitleForDocument: authenticatedProcedure
.input(ZSetTitleForDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {
2024-02-26 11:59:32 +11:00
const { documentId, teamId, title } = input;
2023-12-02 09:38:24 +11:00
const userId = ctx.user.id;
return await updateTitle({
title,
userId,
2024-02-26 11:59:32 +11:00
teamId,
documentId,
requestMetadata: extractNextApiRequestMetadata(ctx.req),
});
}),
2024-01-17 17:17:08 +11:00
setPasswordForDocument: authenticatedProcedure
.input(ZSetPasswordForDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {
try {
const { documentId, password } = input;
const key = DOCUMENSO_ENCRYPTION_KEY;
if (!key) {
throw new Error('Missing encryption key');
}
const securePassword = symmetricEncrypt({
data: password,
key,
});
2024-01-17 17:17:08 +11:00
await upsertDocumentMeta({
documentId,
password: securePassword,
2024-01-17 17:17:08 +11:00
userId: ctx.user.id,
requestMetadata: extractNextApiRequestMetadata(ctx.req),
2024-01-17 17:17:08 +11:00
});
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to set the password for this document. Please try again later.',
});
}
}),
sendDocument: authenticatedProcedure
.input(ZSendDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {
try {
2024-02-26 11:59:32 +11:00
const { documentId, teamId, meta } = input;
2023-12-02 09:38:24 +11:00
if (meta.message || meta.subject || meta.timezone || meta.dateFormat || meta.redirectUrl) {
2023-12-02 09:38:24 +11:00
await upsertDocumentMeta({
documentId,
subject: meta.subject,
message: meta.message,
dateFormat: meta.dateFormat,
timezone: meta.timezone,
redirectUrl: meta.redirectUrl,
2024-01-03 20:10:50 +11:00
userId: ctx.user.id,
requestMetadata: extractNextApiRequestMetadata(ctx.req),
2023-12-02 09:38:24 +11:00
});
}
return await sendDocument({
userId: ctx.user.id,
documentId,
2024-02-26 11:59:32 +11:00
teamId,
requestMetadata: extractNextApiRequestMetadata(ctx.req),
});
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to send this document. Please try again later.',
});
}
}),
2023-11-08 09:25:44 +00:00
2023-11-16 07:35:45 +05:30
resendDocument: authenticatedProcedure
.input(ZResendDocumentMutationSchema)
.mutation(async ({ input, ctx }) => {
try {
return await resendDocument({
userId: ctx.user.id,
...input,
requestMetadata: extractNextApiRequestMetadata(ctx.req),
2023-11-16 07:35:45 +05:30
});
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to resend this document. Please try again later.',
});
}
}),
2023-11-08 09:25:44 +00:00
duplicateDocument: authenticatedProcedure
.input(ZGetDocumentByIdQuerySchema)
.mutation(async ({ input, ctx }) => {
try {
return await duplicateDocumentById({
userId: ctx.user.id,
...input,
2023-11-08 09:25:44 +00:00
});
} catch (err) {
console.log(err);
2023-11-08 09:25:44 +00:00
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We are unable to duplicate this document. Please try again later.',
});
}
}),
searchDocuments: authenticatedProcedure
.input(ZSearchDocumentsMutationSchema)
.query(async ({ input, ctx }) => {
const { query } = input;
try {
const documents = await searchDocumentsWithKeyword({
query,
userId: ctx.user.id,
});
return documents;
} catch (error) {
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We are unable to search for documents. Please try again later.',
});
}
}),
});