mirror of
https://github.com/documenso/documenso.git
synced 2025-11-12 15:53:02 +10:00
Merge branch 'main' into feat/webhook-implementation
This commit is contained in:
@ -1,9 +1,10 @@
|
||||
import { TRPCError } from '@trpc/server';
|
||||
|
||||
import { updateUser } from '@documenso/lib/server-only/admin/update-user';
|
||||
import { upsertSiteSetting } from '@documenso/lib/server-only/site-settings/upsert-site-setting';
|
||||
|
||||
import { adminProcedure, router } from '../trpc';
|
||||
import { ZUpdateProfileMutationByAdminSchema } from './schema';
|
||||
import { ZUpdateProfileMutationByAdminSchema, ZUpdateSiteSettingMutationSchema } from './schema';
|
||||
|
||||
export const adminRouter = router({
|
||||
updateUser: adminProcedure
|
||||
@ -20,4 +21,24 @@ export const adminRouter = router({
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
updateSiteSetting: adminProcedure
|
||||
.input(ZUpdateSiteSettingMutationSchema)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
try {
|
||||
const { id, enabled, data } = input;
|
||||
|
||||
return await upsertSiteSetting({
|
||||
id,
|
||||
enabled,
|
||||
data,
|
||||
userId: ctx.user.id,
|
||||
});
|
||||
} catch (err) {
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to update the site setting provided.',
|
||||
});
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { Role } from '@prisma/client';
|
||||
import z from 'zod';
|
||||
|
||||
import { ZSiteSettingSchema } from '@documenso/lib/server-only/site-settings/schema';
|
||||
|
||||
export const ZUpdateProfileMutationByAdminSchema = z.object({
|
||||
id: z.number().min(1),
|
||||
name: z.string().nullish(),
|
||||
@ -11,3 +13,7 @@ export const ZUpdateProfileMutationByAdminSchema = z.object({
|
||||
export type TUpdateProfileMutationByAdminSchema = z.infer<
|
||||
typeof ZUpdateProfileMutationByAdminSchema
|
||||
>;
|
||||
|
||||
export const ZUpdateSiteSettingMutationSchema = ZSiteSettingSchema;
|
||||
|
||||
export type TUpdateSiteSettingMutationSchema = z.infer<typeof ZUpdateSiteSettingMutationSchema>;
|
||||
|
||||
83
packages/trpc/server/api-token-router/router.ts
Normal file
83
packages/trpc/server/api-token-router/router.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import { TRPCError } from '@trpc/server';
|
||||
|
||||
import { createApiToken } from '@documenso/lib/server-only/public-api/create-api-token';
|
||||
import { deleteTokenById } from '@documenso/lib/server-only/public-api/delete-api-token-by-id';
|
||||
import { getUserTokens } from '@documenso/lib/server-only/public-api/get-all-user-tokens';
|
||||
import { getApiTokenById } from '@documenso/lib/server-only/public-api/get-api-token-by-id';
|
||||
|
||||
import { authenticatedProcedure, router } from '../trpc';
|
||||
import {
|
||||
ZCreateTokenMutationSchema,
|
||||
ZDeleteTokenByIdMutationSchema,
|
||||
ZGetApiTokenByIdQuerySchema,
|
||||
} from './schema';
|
||||
|
||||
export const apiTokenRouter = router({
|
||||
getTokens: authenticatedProcedure.query(async ({ ctx }) => {
|
||||
try {
|
||||
return await getUserTokens({ userId: ctx.user.id });
|
||||
} catch (e) {
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to find your API tokens. Please try again.',
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
getTokenById: authenticatedProcedure
|
||||
.input(ZGetApiTokenByIdQuerySchema)
|
||||
.query(async ({ input, ctx }) => {
|
||||
try {
|
||||
const { id } = input;
|
||||
|
||||
return await getApiTokenById({
|
||||
id,
|
||||
userId: ctx.user.id,
|
||||
});
|
||||
} catch (e) {
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to find this API token. Please try again.',
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
createToken: authenticatedProcedure
|
||||
.input(ZCreateTokenMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const { tokenName, teamId, expirationDate } = input;
|
||||
|
||||
return await createApiToken({
|
||||
userId: ctx.user.id,
|
||||
teamId,
|
||||
tokenName,
|
||||
expiresIn: expirationDate,
|
||||
});
|
||||
} catch (e) {
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to create an API token. Please try again.',
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
deleteTokenById: authenticatedProcedure
|
||||
.input(ZDeleteTokenByIdMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const { id, teamId } = input;
|
||||
|
||||
return await deleteTokenById({
|
||||
id,
|
||||
teamId,
|
||||
userId: ctx.user.id,
|
||||
});
|
||||
} catch (e) {
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to delete this API Token. Please try again.',
|
||||
});
|
||||
}
|
||||
}),
|
||||
});
|
||||
22
packages/trpc/server/api-token-router/schema.ts
Normal file
22
packages/trpc/server/api-token-router/schema.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const ZGetApiTokenByIdQuerySchema = z.object({
|
||||
id: z.number().min(1),
|
||||
});
|
||||
|
||||
export type TGetApiTokenByIdQuerySchema = z.infer<typeof ZGetApiTokenByIdQuerySchema>;
|
||||
|
||||
export const ZCreateTokenMutationSchema = z.object({
|
||||
teamId: z.number().optional(),
|
||||
tokenName: z.string().min(3, { message: 'The token name should be 3 characters or longer' }),
|
||||
expirationDate: z.string().nullable(),
|
||||
});
|
||||
|
||||
export type TCreateTokenMutationSchema = z.infer<typeof ZCreateTokenMutationSchema>;
|
||||
|
||||
export const ZDeleteTokenByIdMutationSchema = z.object({
|
||||
id: z.number().min(1),
|
||||
teamId: z.number().optional(),
|
||||
});
|
||||
|
||||
export type TDeleteTokenByIdMutationSchema = z.infer<typeof ZDeleteTokenByIdMutationSchema>;
|
||||
@ -6,29 +6,27 @@ import { upsertDocumentMeta } from '@documenso/lib/server-only/document-meta/ups
|
||||
import { createDocument } from '@documenso/lib/server-only/document/create-document';
|
||||
import { deleteDocument } from '@documenso/lib/server-only/document/delete-document';
|
||||
import { duplicateDocumentById } from '@documenso/lib/server-only/document/duplicate-document-by-id';
|
||||
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';
|
||||
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';
|
||||
import { updateTitle } from '@documenso/lib/server-only/document/update-title';
|
||||
import { setFieldsForDocument } from '@documenso/lib/server-only/field/set-fields-for-document';
|
||||
import { setRecipientsForDocument } from '@documenso/lib/server-only/recipient/set-recipients-for-document';
|
||||
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,
|
||||
ZDeleteDraftDocumentMutationSchema as ZDeleteDocumentMutationSchema,
|
||||
ZFindDocumentAuditLogsQuerySchema,
|
||||
ZGetDocumentByIdQuerySchema,
|
||||
ZGetDocumentByTokenQuerySchema,
|
||||
ZResendDocumentMutationSchema,
|
||||
ZSearchDocumentsMutationSchema,
|
||||
ZSendDocumentMutationSchema,
|
||||
ZSetFieldsForDocumentMutationSchema,
|
||||
ZSetPasswordForDocumentMutationSchema,
|
||||
ZSetRecipientsForDocumentMutationSchema,
|
||||
ZSetTitleForDocumentMutationSchema,
|
||||
} from './schema';
|
||||
|
||||
@ -104,14 +102,19 @@ export const documentRouter = router({
|
||||
}),
|
||||
|
||||
deleteDocument: authenticatedProcedure
|
||||
.input(ZDeleteDraftDocumentMutationSchema)
|
||||
.input(ZDeleteDocumentMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const { id, status } = input;
|
||||
const { id, teamId } = input;
|
||||
|
||||
const userId = ctx.user.id;
|
||||
|
||||
return await deleteDocument({ id, userId, status });
|
||||
return await deleteDocument({
|
||||
id,
|
||||
userId,
|
||||
teamId,
|
||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
@ -122,66 +125,47 @@ export const documentRouter = router({
|
||||
}
|
||||
}),
|
||||
|
||||
findDocumentAuditLogs: authenticatedProcedure
|
||||
.input(ZFindDocumentAuditLogsQuerySchema)
|
||||
.query(async ({ input, ctx }) => {
|
||||
try {
|
||||
const { page, perPage, documentId, cursor, filterForRecentActivity, orderBy } = input;
|
||||
|
||||
return await findDocumentAuditLogs({
|
||||
page,
|
||||
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.',
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
setTitleForDocument: authenticatedProcedure
|
||||
.input(ZSetTitleForDocumentMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { documentId, title } = input;
|
||||
const { documentId, teamId, title } = input;
|
||||
|
||||
const userId = ctx.user.id;
|
||||
|
||||
return await updateTitle({
|
||||
title,
|
||||
userId,
|
||||
teamId,
|
||||
documentId,
|
||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||
});
|
||||
}),
|
||||
|
||||
setRecipientsForDocument: authenticatedProcedure
|
||||
.input(ZSetRecipientsForDocumentMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const { documentId, recipients } = input;
|
||||
|
||||
return await setRecipientsForDocument({
|
||||
userId: ctx.user.id,
|
||||
documentId,
|
||||
recipients,
|
||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message:
|
||||
'We were unable to set the recipients for this document. Please try again later.',
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
setFieldsForDocument: authenticatedProcedure
|
||||
.input(ZSetFieldsForDocumentMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const { documentId, fields } = input;
|
||||
|
||||
return await setFieldsForDocument({
|
||||
userId: ctx.user.id,
|
||||
documentId,
|
||||
fields,
|
||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to set the fields for this document. Please try again later.',
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
setPasswordForDocument: authenticatedProcedure
|
||||
.input(ZSetPasswordForDocumentMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
@ -219,7 +203,7 @@ export const documentRouter = router({
|
||||
.input(ZSendDocumentMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const { documentId, meta } = input;
|
||||
const { documentId, teamId, meta } = input;
|
||||
|
||||
if (meta.message || meta.subject || meta.timezone || meta.dateFormat || meta.redirectUrl) {
|
||||
await upsertDocumentMeta({
|
||||
@ -237,6 +221,7 @@ export const documentRouter = router({
|
||||
return await sendDocument({
|
||||
userId: ctx.user.id,
|
||||
documentId,
|
||||
teamId,
|
||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||
});
|
||||
} catch (err) {
|
||||
|
||||
@ -1,7 +1,20 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { URL_REGEX } from '@documenso/lib/constants/url-regex';
|
||||
import { DocumentStatus, FieldType, RecipientRole } from '@documenso/prisma/client';
|
||||
import { ZBaseTableSearchParamsSchema } from '@documenso/lib/types/search-params';
|
||||
import { FieldType, RecipientRole } from '@documenso/prisma/client';
|
||||
|
||||
export const ZFindDocumentAuditLogsQuerySchema = ZBaseTableSearchParamsSchema.extend({
|
||||
documentId: z.number().min(1),
|
||||
cursor: z.string().optional(),
|
||||
filterForRecentActivity: z.boolean().optional(),
|
||||
orderBy: z
|
||||
.object({
|
||||
column: z.enum(['createdAt', 'type']),
|
||||
direction: z.enum(['asc', 'desc']),
|
||||
})
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export const ZGetDocumentByIdQuerySchema = z.object({
|
||||
id: z.number().min(1),
|
||||
@ -26,6 +39,7 @@ export type TCreateDocumentMutationSchema = z.infer<typeof ZCreateDocumentMutati
|
||||
|
||||
export const ZSetTitleForDocumentMutationSchema = z.object({
|
||||
documentId: z.number(),
|
||||
teamId: z.number().min(1).optional(),
|
||||
title: z.string().min(1),
|
||||
});
|
||||
|
||||
@ -33,6 +47,7 @@ export type TSetTitleForDocumentMutationSchema = z.infer<typeof ZSetTitleForDocu
|
||||
|
||||
export const ZSetRecipientsForDocumentMutationSchema = z.object({
|
||||
documentId: z.number(),
|
||||
teamId: z.number().min(1).optional(),
|
||||
recipients: z.array(
|
||||
z.object({
|
||||
id: z.number().nullish(),
|
||||
@ -69,6 +84,7 @@ export type TSetFieldsForDocumentMutationSchema = z.infer<
|
||||
|
||||
export const ZSendDocumentMutationSchema = z.object({
|
||||
documentId: z.number(),
|
||||
teamId: z.number().optional(),
|
||||
meta: z.object({
|
||||
subject: z.string(),
|
||||
message: z.string(),
|
||||
@ -102,7 +118,7 @@ export type TSendDocumentMutationSchema = z.infer<typeof ZSendDocumentMutationSc
|
||||
|
||||
export const ZDeleteDraftDocumentMutationSchema = z.object({
|
||||
id: z.number().min(1),
|
||||
status: z.nativeEnum(DocumentStatus),
|
||||
teamId: z.number().min(1).optional(),
|
||||
});
|
||||
|
||||
export type TDeleteDraftDocumentMutationSchema = z.infer<typeof ZDeleteDraftDocumentMutationSchema>;
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { TRPCError } from '@trpc/server';
|
||||
|
||||
import { deleteUser } from '@documenso/lib/server-only/user/delete-user';
|
||||
import { findUserSecurityAuditLogs } from '@documenso/lib/server-only/user/find-user-security-audit-logs';
|
||||
import { forgotPassword } from '@documenso/lib/server-only/user/forgot-password';
|
||||
import { getUserById } from '@documenso/lib/server-only/user/get-user-by-id';
|
||||
@ -155,4 +156,23 @@ export const profileRouter = router({
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
deleteAccount: authenticatedProcedure.mutation(async ({ ctx }) => {
|
||||
try {
|
||||
const user = ctx.user;
|
||||
|
||||
return await deleteUser(user);
|
||||
} catch (err) {
|
||||
let message = 'We were unable to delete your account. Please try again.';
|
||||
|
||||
if (err instanceof Error) {
|
||||
message = err.message;
|
||||
}
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message,
|
||||
});
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
@ -17,11 +17,12 @@ export const recipientRouter = router({
|
||||
.input(ZAddSignersMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const { documentId, signers } = input;
|
||||
const { documentId, teamId, signers } = input;
|
||||
|
||||
return await setRecipientsForDocument({
|
||||
userId: ctx.user.id,
|
||||
documentId,
|
||||
teamId,
|
||||
recipients: signers.map((signer) => ({
|
||||
id: signer.nativeId,
|
||||
email: signer.email,
|
||||
@ -53,6 +54,7 @@ export const recipientRouter = router({
|
||||
id: signer.nativeId,
|
||||
email: signer.email,
|
||||
name: signer.name,
|
||||
role: signer.role,
|
||||
})),
|
||||
});
|
||||
} catch (err) {
|
||||
|
||||
@ -5,6 +5,7 @@ import { RecipientRole } from '@documenso/prisma/client';
|
||||
export const ZAddSignersMutationSchema = z
|
||||
.object({
|
||||
documentId: z.number(),
|
||||
teamId: z.number().optional(),
|
||||
signers: z.array(
|
||||
z.object({
|
||||
nativeId: z.number().optional(),
|
||||
@ -34,6 +35,7 @@ export const ZAddTemplateSignersMutationSchema = z
|
||||
nativeId: z.number().optional(),
|
||||
email: z.string().email().min(1),
|
||||
name: z.string(),
|
||||
role: z.nativeEnum(RecipientRole),
|
||||
}),
|
||||
),
|
||||
})
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { adminRouter } from './admin-router/router';
|
||||
import { apiTokenRouter } from './api-token-router/router';
|
||||
import { authRouter } from './auth-router/router';
|
||||
import { cryptoRouter } from './crypto/router';
|
||||
import { documentRouter } from './document-router/router';
|
||||
@ -22,6 +23,7 @@ export const appRouter = router({
|
||||
recipient: recipientRouter,
|
||||
admin: adminRouter,
|
||||
shareLink: shareLinkRouter,
|
||||
apiToken: apiTokenRouter,
|
||||
singleplayer: singleplayerRouter,
|
||||
team: teamRouter,
|
||||
template: templateRouter,
|
||||
|
||||
@ -22,6 +22,7 @@ export const mapField = (
|
||||
.with(FieldType.DATE, () => DateTime.now().toFormat('yyyy-MM-dd hh:mm a'))
|
||||
.with(FieldType.EMAIL, () => signer.email)
|
||||
.with(FieldType.NAME, () => signer.name)
|
||||
.with(FieldType.TEXT, () => signer.customText)
|
||||
.otherwise(() => '');
|
||||
|
||||
return {
|
||||
|
||||
@ -12,6 +12,7 @@ export const ZCreateSinglePlayerDocumentMutationSchema = z.object({
|
||||
email: z.string().email().min(1),
|
||||
name: z.string(),
|
||||
signature: z.string(),
|
||||
customText: z.string(),
|
||||
}),
|
||||
fields: z.array(
|
||||
z.object({
|
||||
|
||||
@ -3,10 +3,11 @@ import { z } from 'zod';
|
||||
import { PROTECTED_TEAM_URLS } from '@documenso/lib/constants/teams';
|
||||
import { TeamMemberRole } from '@documenso/prisma/client';
|
||||
|
||||
// Consider refactoring to use ZBaseTableSearchParamsSchema.
|
||||
const GenericFindQuerySchema = z.object({
|
||||
term: z.string().optional(),
|
||||
page: z.number().optional(),
|
||||
perPage: z.number().optional(),
|
||||
page: z.number().min(1).optional(),
|
||||
perPage: z.number().min(1).optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@ -41,7 +41,7 @@ export const templateRouter = router({
|
||||
.input(ZCreateDocumentFromTemplateMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const { templateId } = input;
|
||||
const { templateId, teamId } = input;
|
||||
|
||||
const limits = await getServerLimits({ email: ctx.user.email });
|
||||
|
||||
@ -51,7 +51,9 @@ export const templateRouter = router({
|
||||
|
||||
return await createDocumentFromTemplate({
|
||||
templateId,
|
||||
teamId,
|
||||
userId: ctx.user.id,
|
||||
recipients: input.recipients,
|
||||
});
|
||||
} catch (err) {
|
||||
throw new TRPCError({
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { RecipientRole } from '@documenso/prisma/client';
|
||||
|
||||
export const ZCreateTemplateMutationSchema = z.object({
|
||||
title: z.string().min(1).trim(),
|
||||
teamId: z.number().optional(),
|
||||
@ -8,6 +10,16 @@ export const ZCreateTemplateMutationSchema = z.object({
|
||||
|
||||
export const ZCreateDocumentFromTemplateMutationSchema = z.object({
|
||||
templateId: z.number(),
|
||||
teamId: z.number().optional(),
|
||||
recipients: z
|
||||
.array(
|
||||
z.object({
|
||||
email: z.string().email(),
|
||||
name: z.string(),
|
||||
role: z.nativeEnum(RecipientRole),
|
||||
}),
|
||||
)
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export const ZDuplicateTemplateMutationSchema = z.object({
|
||||
|
||||
Reference in New Issue
Block a user