From c56200e0304b14919c68070d7b92dc88a63aeba4 Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Fri, 3 Jan 2025 15:38:10 +0100 Subject: [PATCH] feat: ability to delete single legal values (#9058) Co-authored-by: Thomas Heartman --- src/lib/features/context/context-service.ts | 30 +++++++++++++- src/lib/features/context/context.test.ts | 37 ++++++++++++++++++ src/lib/features/context/context.ts | 43 +++++++++++++++++++-- 3 files changed, 106 insertions(+), 4 deletions(-) diff --git a/src/lib/features/context/context-service.ts b/src/lib/features/context/context-service.ts index db4dd29444e1..b96b1e680dc2 100644 --- a/src/lib/features/context/context-service.ts +++ b/src/lib/features/context/context-service.ts @@ -140,7 +140,7 @@ class ContextService { }); } - async updateContextFieldLegalValue( + async updateLegalValue( contextFieldLegalValue: { name: string; legalValue: LegalValueSchema }, auditUser: IAuditUser, ): Promise { @@ -179,6 +179,34 @@ class ContextService { }); } + async deleteLegalValue( + contextFieldLegalValue: { name: string; legalValue: string }, + auditUser: IAuditUser, + ): Promise { + const contextField = await this.contextFieldStore.get( + contextFieldLegalValue.name, + ); + + const newContextField = { + ...contextField, + legalValues: contextField.legalValues?.filter( + (legalValue) => + legalValue.value !== contextFieldLegalValue.legalValue, + ), + }; + + await this.contextFieldStore.update(newContextField); + + await this.eventService.storeEvent({ + type: CONTEXT_FIELD_UPDATED, + createdBy: auditUser.username, + createdByUserId: auditUser.id, + ip: auditUser.ip, + preData: contextField, + data: newContextField, + }); + } + async deleteContextField( name: string, auditUser: IAuditUser, diff --git a/src/lib/features/context/context.test.ts b/src/lib/features/context/context.test.ts index a1cb282acde4..f5e5334379c7 100644 --- a/src/lib/features/context/context.test.ts +++ b/src/lib/features/context/context.test.ts @@ -204,6 +204,43 @@ test('should add and update a single context field with new legal values', async }); }); +test('should delete a single context field legal value', async () => { + expect.assertions(1); + + // add a new context field legal value + await request + .post(`${base}/api/admin/context/environment/legal-values`) + .send({ + value: 'valueA', + }) + .set('Content-Type', 'application/json') + .expect(200); + + await request + .post(`${base}/api/admin/context/environment/legal-values`) + .send({ + value: 'valueB', + }) + .set('Content-Type', 'application/json') + .expect(200); + + await request + .delete(`${base}/api/admin/context/environment/legal-values/valueB`) + .expect(200); + + const { body } = await request.get(`${base}/api/admin/context/environment`); + + expect(body).toMatchObject({ + name: 'environment', + legalValues: [{ value: 'valueA' }], + }); + + // verify delete is idempotent + await request + .delete(`${base}/api/admin/context/environment/legal-values/valueB`) + .expect(200); +}); + test('should not delete a unknown context field', () => { expect.assertions(0); diff --git a/src/lib/features/context/context.ts b/src/lib/features/context/context.ts index 20e28f062b0e..ca21648ac26f 100644 --- a/src/lib/features/context/context.ts +++ b/src/lib/features/context/context.ts @@ -45,6 +45,10 @@ interface ContextParam { contextField: string; } +interface DeleteLegalValueParam extends ContextParam { + legalValue: string; +} + export class ContextController extends Controller { private contextService: ContextService; @@ -172,7 +176,7 @@ export class ContextController extends Controller { this.route({ method: 'post', path: '/:contextField/legal-values', - handler: this.updateContextFieldLegalValue, + handler: this.updateLegalValue, permission: UPDATE_CONTEXT_FIELD, middleware: [ openApiService.validPath({ @@ -188,6 +192,25 @@ export class ContextController extends Controller { ], }); + this.route({ + method: 'delete', + path: '/:contextField/legal-values/:legalValue', + handler: this.deleteLegalValue, + acceptAnyContentType: true, + permission: UPDATE_CONTEXT_FIELD, + middleware: [ + openApiService.validPath({ + tags: ['Context'], + summary: 'Delete legal value for the context field', + description: `Removes the specified custom context field legal value. Does not validate that the legal value is not in use and does not remove usage from constraints that use it.`, + operationId: 'deleteContextFieldLegalValue', + responses: { + 200: emptyResponse, + }, + }), + ], + }); + this.route({ method: 'delete', path: '/:contextField', @@ -291,14 +314,28 @@ export class ContextController extends Controller { res.status(200).end(); } - async updateContextFieldLegalValue( + async updateLegalValue( req: IAuthRequest, res: Response, ): Promise { const name = req.params.contextField; const legalValue = req.body; - await this.contextService.updateContextFieldLegalValue( + await this.contextService.updateLegalValue( + { name, legalValue }, + req.audit, + ); + res.status(200).end(); + } + + async deleteLegalValue( + req: IAuthRequest, + res: Response, + ): Promise { + const name = req.params.contextField; + const legalValue = req.params.legalValue; + + await this.contextService.deleteLegalValue( { name, legalValue }, req.audit, );