mirror of
https://github.com/documenso/documenso.git
synced 2025-11-14 08:42:12 +10:00
feat: upload template via API (#1842)
Allow users to upload templates via both v1 and v2 APIs. Similar to uploading documents.
This commit is contained in:
@ -1,5 +1,10 @@
|
||||
import { initContract } from '@ts-rest/core';
|
||||
|
||||
import {
|
||||
ZCreateTemplateV2RequestSchema,
|
||||
ZCreateTemplateV2ResponseSchema,
|
||||
} from '@documenso/trpc/server/template-router/schema';
|
||||
|
||||
import {
|
||||
ZAuthorizationHeadersSchema,
|
||||
ZCreateDocumentFromTemplateMutationResponseSchema,
|
||||
@ -87,6 +92,18 @@ export const ApiContractV1 = c.router(
|
||||
summary: 'Upload a new document and get a presigned URL',
|
||||
},
|
||||
|
||||
createTemplate: {
|
||||
method: 'POST',
|
||||
path: '/api/v1/templates',
|
||||
body: ZCreateTemplateV2RequestSchema,
|
||||
responses: {
|
||||
200: ZCreateTemplateV2ResponseSchema,
|
||||
401: ZUnsuccessfulResponseSchema,
|
||||
404: ZUnsuccessfulResponseSchema,
|
||||
},
|
||||
summary: 'Create a new template and get a presigned URL',
|
||||
},
|
||||
|
||||
deleteTemplate: {
|
||||
method: 'DELETE',
|
||||
path: '/api/v1/templates/:id',
|
||||
|
||||
@ -30,6 +30,7 @@ import { setDocumentRecipients } from '@documenso/lib/server-only/recipient/set-
|
||||
import { updateDocumentRecipients } from '@documenso/lib/server-only/recipient/update-document-recipients';
|
||||
import { createDocumentFromTemplate } from '@documenso/lib/server-only/template/create-document-from-template';
|
||||
import { createDocumentFromTemplateLegacy } from '@documenso/lib/server-only/template/create-document-from-template-legacy';
|
||||
import { createTemplate } from '@documenso/lib/server-only/template/create-template';
|
||||
import { deleteTemplate } from '@documenso/lib/server-only/template/delete-template';
|
||||
import { findTemplates } from '@documenso/lib/server-only/template/find-templates';
|
||||
import { getTemplateById } from '@documenso/lib/server-only/template/get-template-by-id';
|
||||
@ -400,6 +401,109 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, {
|
||||
}
|
||||
}),
|
||||
|
||||
createTemplate: authenticatedMiddleware(async (args, user, team) => {
|
||||
const { body } = args;
|
||||
const {
|
||||
title,
|
||||
folderId,
|
||||
externalId,
|
||||
visibility,
|
||||
globalAccessAuth,
|
||||
globalActionAuth,
|
||||
publicTitle,
|
||||
publicDescription,
|
||||
type,
|
||||
meta,
|
||||
} = body;
|
||||
|
||||
try {
|
||||
if (process.env.NEXT_PUBLIC_UPLOAD_TRANSPORT !== 's3') {
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
message: 'Create template is not available without S3 transport.',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const dateFormat = meta?.dateFormat
|
||||
? DATE_FORMATS.find((format) => format.value === meta?.dateFormat)
|
||||
: DATE_FORMATS.find((format) => format.value === DEFAULT_DOCUMENT_DATE_FORMAT);
|
||||
|
||||
if (meta?.dateFormat && !dateFormat) {
|
||||
return {
|
||||
status: 400,
|
||||
body: {
|
||||
message: 'Invalid date format. Please provide a valid date format',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const timezone = meta?.timezone
|
||||
? TIME_ZONES.find((tz) => tz === meta?.timezone)
|
||||
: DEFAULT_DOCUMENT_TIME_ZONE;
|
||||
|
||||
const isTimeZoneValid = meta?.timezone ? TIME_ZONES.includes(String(timezone)) : true;
|
||||
|
||||
if (!isTimeZoneValid) {
|
||||
return {
|
||||
status: 400,
|
||||
body: {
|
||||
message: 'Invalid timezone. Please provide a valid timezone',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const fileName = title?.endsWith('.pdf') ? title : `${title}.pdf`;
|
||||
|
||||
const { url, key } = await getPresignPostUrl(fileName, 'application/pdf');
|
||||
|
||||
const templateDocumentData = await createDocumentData({
|
||||
data: key,
|
||||
type: DocumentDataType.S3_PATH,
|
||||
});
|
||||
|
||||
const createdTemplate = await createTemplate({
|
||||
userId: user.id,
|
||||
teamId: team.id,
|
||||
templateDocumentDataId: templateDocumentData.id,
|
||||
data: {
|
||||
title,
|
||||
folderId,
|
||||
externalId,
|
||||
visibility,
|
||||
globalAccessAuth,
|
||||
globalActionAuth,
|
||||
publicTitle,
|
||||
publicDescription,
|
||||
type,
|
||||
},
|
||||
meta,
|
||||
});
|
||||
|
||||
const fullTemplate = await getTemplateById({
|
||||
id: createdTemplate.id,
|
||||
userId: user.id,
|
||||
teamId: team.id,
|
||||
});
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
||||
uploadUrl: url,
|
||||
template: fullTemplate,
|
||||
},
|
||||
};
|
||||
} catch (err) {
|
||||
return {
|
||||
status: 404,
|
||||
body: {
|
||||
message: 'An error has occured while creating the template',
|
||||
},
|
||||
};
|
||||
}
|
||||
}),
|
||||
|
||||
deleteTemplate: authenticatedMiddleware(async (args, user, team, { logger }) => {
|
||||
const { id: templateId } = args.params;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user