feat: add authOptions to the API (#1338)

Add the authOptions property to the document and
recipient related API endpoints.

These were previously missing so the only way API
users could set the authOptions was via templates
and using the generateTemplate endpoint.
This commit is contained in:
Lucas Smith
2024-09-10 15:07:40 +10:00
committed by GitHub
parent f6f893fbf7
commit c36306d2c9
3 changed files with 95 additions and 2 deletions

View File

@ -16,6 +16,7 @@ import { getDocumentById } from '@documenso/lib/server-only/document/get-documen
import { resendDocument } from '@documenso/lib/server-only/document/resend-document';
import { sendDocument } from '@documenso/lib/server-only/document/send-document';
import { updateDocument } from '@documenso/lib/server-only/document/update-document';
import { updateDocumentSettings } from '@documenso/lib/server-only/document/update-document-settings';
import { deleteField } from '@documenso/lib/server-only/field/delete-field';
import { getFieldById } from '@documenso/lib/server-only/field/get-field-by-id';
import { updateField } from '@documenso/lib/server-only/field/update-field';
@ -295,6 +296,16 @@ export const ApiContractV1Implementation = createNextRoute(ApiContractV1, {
requestMetadata: extractNextApiRequestMetadata(args.req),
});
if (body.authOptions) {
await updateDocumentSettings({
documentId: document.id,
userId: user.id,
teamId: team?.id,
data: body.authOptions,
requestMetadata: extractNextApiRequestMetadata(args.req),
});
}
const recipients = await setRecipientsForDocument({
userId: user.id,
teamId: team?.id,
@ -465,6 +476,16 @@ export const ApiContractV1Implementation = createNextRoute(ApiContractV1, {
});
}
if (body.authOptions) {
await updateDocumentSettings({
documentId: document.id,
userId: user.id,
teamId: team?.id,
data: body.authOptions,
requestMetadata: extractNextApiRequestMetadata(args.req),
});
}
return {
status: 200,
body: {
@ -547,6 +568,16 @@ export const ApiContractV1Implementation = createNextRoute(ApiContractV1, {
});
}
if (body.authOptions) {
await updateDocumentSettings({
documentId: document.id,
userId: user.id,
teamId: team?.id,
data: body.authOptions,
requestMetadata: extractNextApiRequestMetadata(args.req),
});
}
return {
status: 200,
body: {
@ -682,7 +713,7 @@ export const ApiContractV1Implementation = createNextRoute(ApiContractV1, {
createRecipient: authenticatedMiddleware(async (args, user, team) => {
const { id: documentId } = args.params;
const { name, email, role } = args.body;
const { name, email, role, authOptions } = args.body;
const document = await getDocumentById({
id: Number(documentId),
@ -736,6 +767,7 @@ export const ApiContractV1Implementation = createNextRoute(ApiContractV1, {
email,
name,
role,
actionAuth: authOptions?.actionAuth ?? null,
},
],
requestMetadata: extractNextApiRequestMetadata(args.req),
@ -767,7 +799,7 @@ export const ApiContractV1Implementation = createNextRoute(ApiContractV1, {
updateRecipient: authenticatedMiddleware(async (args, user, team) => {
const { id: documentId, recipientId } = args.params;
const { name, email, role } = args.body;
const { name, email, role, authOptions } = args.body;
const document = await getDocumentById({
id: Number(documentId),
@ -801,6 +833,7 @@ export const ApiContractV1Implementation = createNextRoute(ApiContractV1, {
email,
name,
role,
actionAuth: authOptions?.actionAuth,
requestMetadata: extractNextApiRequestMetadata(args.req),
}).catch(() => null);

View File

@ -5,6 +5,11 @@ import { DATE_FORMATS, DEFAULT_DOCUMENT_DATE_FORMAT } from '@documenso/lib/const
import '@documenso/lib/constants/time-zones';
import { DEFAULT_DOCUMENT_TIME_ZONE, TIME_ZONES } from '@documenso/lib/constants/time-zones';
import { ZUrlSchema } from '@documenso/lib/schemas/common';
import {
ZDocumentAccessAuthTypesSchema,
ZDocumentActionAuthTypesSchema,
ZRecipientActionAuthTypesSchema,
} from '@documenso/lib/types/document-auth';
import { ZFieldMetaSchema } from '@documenso/lib/types/field-meta';
import {
DocumentDataType,
@ -120,6 +125,12 @@ export const ZCreateDocumentMutationSchema = z.object({
redirectUrl: z.string(),
})
.partial(),
authOptions: z
.object({
globalAccessAuth: ZDocumentAccessAuthTypesSchema.optional(),
globalActionAuth: ZDocumentActionAuthTypesSchema.optional(),
})
.optional(),
formValues: z.record(z.string(), z.union([z.string(), z.boolean(), z.number()])).optional(),
});
@ -166,6 +177,12 @@ export const ZCreateDocumentFromTemplateMutationSchema = z.object({
})
.partial()
.optional(),
authOptions: z
.object({
globalAccessAuth: ZDocumentAccessAuthTypesSchema.optional(),
globalActionAuth: ZDocumentActionAuthTypesSchema.optional(),
})
.optional(),
formValues: z.record(z.string(), z.union([z.string(), z.boolean(), z.number()])).optional(),
});
@ -223,6 +240,12 @@ export const ZGenerateDocumentFromTemplateMutationSchema = z.object({
})
.partial()
.optional(),
authOptions: z
.object({
globalAccessAuth: ZDocumentAccessAuthTypesSchema.optional(),
globalActionAuth: ZDocumentActionAuthTypesSchema.optional(),
})
.optional(),
formValues: z.record(z.string(), z.union([z.string(), z.boolean(), z.number()])).optional(),
});
@ -254,6 +277,11 @@ export const ZCreateRecipientMutationSchema = z.object({
name: z.string().min(1),
email: z.string().email().min(1),
role: z.nativeEnum(RecipientRole).optional().default(RecipientRole.SIGNER),
authOptions: z
.object({
actionAuth: ZRecipientActionAuthTypesSchema.optional(),
})
.optional(),
});
/**

View File

@ -1,9 +1,16 @@
import { isUserEnterprise } from '@documenso/ee/server-only/util/is-document-enterprise';
import { prisma } from '@documenso/prisma';
import type { RecipientRole, Team } from '@documenso/prisma/client';
import { AppError, AppErrorCode } from '../../errors/app-error';
import { DOCUMENT_AUDIT_LOG_TYPE } from '../../types/document-audit-logs';
import {
type TRecipientActionAuthTypes,
ZRecipientAuthOptionsSchema,
} from '../../types/document-auth';
import type { RequestMetadata } from '../../universal/extract-request-metadata';
import { createDocumentAuditLogData, diffRecipientChanges } from '../../utils/document-audit-logs';
import { createRecipientAuthOptions } from '../../utils/document-auth';
export type UpdateRecipientOptions = {
documentId: number;
@ -11,6 +18,7 @@ export type UpdateRecipientOptions = {
email?: string;
name?: string;
role?: RecipientRole;
actionAuth?: TRecipientActionAuthTypes | null;
userId: number;
teamId?: number;
requestMetadata?: RequestMetadata;
@ -22,6 +30,7 @@ export const updateRecipient = async ({
email,
name,
role,
actionAuth,
userId,
teamId,
requestMetadata,
@ -48,6 +57,9 @@ export const updateRecipient = async ({
}),
},
},
include: {
Document: true,
},
});
let team: Team | null = null;
@ -75,6 +87,22 @@ export const updateRecipient = async ({
throw new Error('Recipient not found');
}
if (actionAuth) {
const isDocumentEnterprise = await isUserEnterprise({
userId,
teamId,
});
if (!isDocumentEnterprise) {
throw new AppError(
AppErrorCode.UNAUTHORIZED,
'You do not have permission to set the action auth',
);
}
}
const recipientAuthOptions = ZRecipientAuthOptionsSchema.parse(recipient.authOptions);
const updatedRecipient = await prisma.$transaction(async (tx) => {
const persisted = await prisma.recipient.update({
where: {
@ -84,6 +112,10 @@ export const updateRecipient = async ({
email: email?.toLowerCase() ?? recipient.email,
name: name ?? recipient.name,
role: role ?? recipient.role,
authOptions: createRecipientAuthOptions({
accessAuth: recipientAuthOptions.accessAuth,
actionAuth: actionAuth ?? null,
}),
},
});