From 05efd954722d768818de1c5cd8a99fcc4299ed64 Mon Sep 17 00:00:00 2001 From: Sheen Capadngan Date: Thu, 15 Aug 2024 15:46:35 +0800 Subject: [PATCH] feat: completed certificate template schema endpoints --- backend/src/server/routes/index.ts | 13 ++- .../routes/v1/certificate-template-router.ts | 51 +++++++++-- backend/src/server/routes/v1/index.ts | 2 + .../certificate-template-service.ts | 89 ++++++++++++++++++- .../certificate-template-types.ts | 12 +++ 5 files changed, 155 insertions(+), 12 deletions(-) diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index dbd223d7b..46e241075 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -89,6 +89,8 @@ import { certificateAuthorityDALFactory } from "@app/services/certificate-author import { certificateAuthorityQueueFactory } from "@app/services/certificate-authority/certificate-authority-queue"; import { certificateAuthoritySecretDALFactory } from "@app/services/certificate-authority/certificate-authority-secret-dal"; import { certificateAuthorityServiceFactory } from "@app/services/certificate-authority/certificate-authority-service"; +import { certificateTemplateDALFactory } from "@app/services/certificate-template/certificate-template-dal"; +import { certificateTemplateServiceFactory } from "@app/services/certificate-template/certificate-template-service"; import { groupProjectDALFactory } from "@app/services/group-project/group-project-dal"; import { groupProjectMembershipRoleDALFactory } from "@app/services/group-project/group-project-membership-role-dal"; import { groupProjectServiceFactory } from "@app/services/group-project/group-project-service"; @@ -584,6 +586,7 @@ export const registerRoutes = async ( const certificateAuthorityCertDAL = certificateAuthorityCertDALFactory(db); const certificateAuthoritySecretDAL = certificateAuthoritySecretDALFactory(db); const certificateAuthorityCrlDAL = certificateAuthorityCrlDALFactory(db); + const certificateTemplateDAL = certificateTemplateDALFactory(db); const certificateDAL = certificateDALFactory(db); const certificateBodyDAL = certificateBodyDALFactory(db); @@ -636,6 +639,12 @@ export const registerRoutes = async ( licenseService }); + const certificateTemplateService = certificateTemplateServiceFactory({ + certificateTemplateDAL, + certificateAuthorityDAL, + permissionService + }); + const pkiAlertService = pkiAlertServiceFactory({ pkiAlertDAL, pkiCollectionDAL, @@ -673,7 +682,8 @@ export const registerRoutes = async ( identityProjectMembershipRoleDAL, keyStore, kmsService, - projectBotDAL + projectBotDAL, + certificateTemplateDAL }); const projectEnvService = projectEnvServiceFactory({ @@ -1140,6 +1150,7 @@ export const registerRoutes = async ( auditLogStream: auditLogStreamService, certificate: certificateService, certificateAuthority: certificateAuthorityService, + certificateTemplate: certificateTemplateService, certificateAuthorityCrl: certificateAuthorityCrlService, pkiAlert: pkiAlertService, pkiCollection: pkiCollectionService, diff --git a/backend/src/server/routes/v1/certificate-template-router.ts b/backend/src/server/routes/v1/certificate-template-router.ts index 854c668ba..7b71cbbd1 100644 --- a/backend/src/server/routes/v1/certificate-template-router.ts +++ b/backend/src/server/routes/v1/certificate-template-router.ts @@ -84,33 +84,68 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid server.route({ method: "PATCH", - url: "/", + url: "/:certificateTemplateId", config: { rateLimit: writeLimit }, schema: { - params: z.object({}), + body: z.object({ + caId: z.string().optional(), + name: z.string().optional(), + commonName: z.string().optional(), + ttl: z.string().optional() + }), + params: z.object({ + certificateTemplateId: z.string() + }), response: { - 200: z.object({}) + 200: z.object({ + certificateTemplate: sanitizedCertificateTemplate + }) } }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), - handler: async (req) => {} + handler: async (req) => { + const certificateTemplate = await server.services.certificateTemplate.updateCertTemplate({ + ...req.body, + id: req.params.certificateTemplateId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + return { certificateTemplate }; + } }); server.route({ method: "DELETE", - url: "/", + url: "/:certificateTemplateId", config: { rateLimit: writeLimit }, schema: { - params: z.object({}), + params: z.object({ + certificateTemplateId: z.string() + }), response: { - 200: z.object({}) + 200: z.object({ + certificateTemplate: sanitizedCertificateTemplate + }) } }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]), - handler: async (req) => {} + handler: async (req) => { + const certificateTemplate = await server.services.certificateTemplate.deleteCertTemplate({ + id: req.params.certificateTemplateId, + actor: req.permission.type, + actorId: req.permission.id, + actorAuthMethod: req.permission.authMethod, + actorOrgId: req.permission.orgId + }); + + return { certificateTemplate }; + } }); }; diff --git a/backend/src/server/routes/v1/index.ts b/backend/src/server/routes/v1/index.ts index 1a5a56bd0..c588187c4 100644 --- a/backend/src/server/routes/v1/index.ts +++ b/backend/src/server/routes/v1/index.ts @@ -3,6 +3,7 @@ import { registerAuthRoutes } from "./auth-router"; import { registerProjectBotRouter } from "./bot-router"; import { registerCaRouter } from "./certificate-authority-router"; import { registerCertRouter } from "./certificate-router"; +import { registerCertificateTemplateRouter } from "./certificate-template-router"; import { registerIdentityAccessTokenRouter } from "./identity-access-token-router"; import { registerIdentityAwsAuthRouter } from "./identity-aws-iam-auth-router"; import { registerIdentityAzureAuthRouter } from "./identity-azure-auth-router"; @@ -76,6 +77,7 @@ export const registerV1Routes = async (server: FastifyZodProvider) => { async (pkiRouter) => { await pkiRouter.register(registerCaRouter, { prefix: "/ca" }); await pkiRouter.register(registerCertRouter, { prefix: "/certificates" }); + await pkiRouter.register(registerCertificateTemplateRouter, { prefix: "/certificate-templates" }); await server.register(registerPkiAlertRouter, { prefix: "/alerts" }); await server.register(registerPkiCollectionRouter, { prefix: "/collections" }); }, diff --git a/backend/src/services/certificate-template/certificate-template-service.ts b/backend/src/services/certificate-template/certificate-template-service.ts index 2739c4b45..a294fee81 100644 --- a/backend/src/services/certificate-template/certificate-template-service.ts +++ b/backend/src/services/certificate-template/certificate-template-service.ts @@ -2,11 +2,16 @@ import { ForbiddenError } from "@casl/ability"; import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service"; import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission"; -import { NotFoundError } from "@app/lib/errors"; +import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { TCertificateAuthorityDALFactory } from "../certificate-authority/certificate-authority-dal"; import { TCertificateTemplateDALFactory } from "./certificate-template-dal"; -import { TCreateCertTemplateDTO, TGetCertTemplateDTO } from "./certificate-template-types"; +import { + TCreateCertTemplateDTO, + TDeleteCertTemplateDTO, + TGetCertTemplateDTO, + TUpdateCertTemplateDTO +} from "./certificate-template-types"; type TCertificateTemplateServiceFactoryDep = { certificateTemplateDAL: TCertificateTemplateDALFactory; @@ -60,6 +65,82 @@ export const certificateTemplateServiceFactory = ({ return certificateTemplate; }; + const updateCertTemplate = async ({ + id, + caId, + name, + commonName, + ttl, + actorId, + actorAuthMethod, + actor, + actorOrgId + }: TUpdateCertTemplateDTO) => { + const certTemplate = await certificateTemplateDAL.getById(id); + if (!certTemplate) { + throw new NotFoundError({ + message: "Certificate template not found." + }); + } + + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + certTemplate.projectId, + actorAuthMethod, + actorOrgId + ); + + ForbiddenError.from(permission).throwUnlessCan( + ProjectPermissionActions.Edit, + ProjectPermissionSub.CertificateTemplates + ); + + if (caId) { + const ca = await certificateAuthorityDAL.findById(caId); + if (!ca || ca.projectId !== certTemplate.projectId) { + throw new BadRequestError({ + message: "Invalid CA" + }); + } + } + + const updatedCertTemplate = await certificateTemplateDAL.updateById(certTemplate.id, { + caId, + commonName, + name, + ttl + }); + + return updatedCertTemplate; + }; + + const deleteCertTemplate = async ({ id, actorId, actorAuthMethod, actor, actorOrgId }: TDeleteCertTemplateDTO) => { + const certTemplate = await certificateTemplateDAL.getById(id); + if (!certTemplate) { + throw new NotFoundError({ + message: "Certificate template not found." + }); + } + + const { permission } = await permissionService.getProjectPermission( + actor, + actorId, + certTemplate.projectId, + actorAuthMethod, + actorOrgId + ); + + ForbiddenError.from(permission).throwUnlessCan( + ProjectPermissionActions.Delete, + ProjectPermissionSub.CertificateTemplates + ); + + const deletedCertTemplate = await certificateTemplateDAL.deleteById(certTemplate.id); + + return deletedCertTemplate; + }; + const getCertTemplate = async ({ id, actorId, actorAuthMethod, actor, actorOrgId }: TGetCertTemplateDTO) => { const certTemplate = await certificateTemplateDAL.getById(id); if (!certTemplate) { @@ -86,6 +167,8 @@ export const certificateTemplateServiceFactory = ({ return { createCertTemplate, - getCertTemplate + getCertTemplate, + deleteCertTemplate, + updateCertTemplate }; }; diff --git a/backend/src/services/certificate-template/certificate-template-types.ts b/backend/src/services/certificate-template/certificate-template-types.ts index 471666e19..556215790 100644 --- a/backend/src/services/certificate-template/certificate-template-types.ts +++ b/backend/src/services/certificate-template/certificate-template-types.ts @@ -7,6 +7,18 @@ export type TCreateCertTemplateDTO = { ttl: string; } & Omit; +export type TUpdateCertTemplateDTO = { + id: string; + caId?: string; + name?: string; + commonName?: string; + ttl?: string; +} & Omit; + export type TGetCertTemplateDTO = { id: string; } & Omit; + +export type TDeleteCertTemplateDTO = { + id: string; +} & Omit;