diff --git a/apps/services/auth/admin-api/src/app/v2/delegations/test/delegation-admin.spec.ts b/apps/services/auth/admin-api/src/app/v2/delegations/test/delegation-admin.spec.ts index 19cc29c1c92f..6d0637535db9 100644 --- a/apps/services/auth/admin-api/src/app/v2/delegations/test/delegation-admin.spec.ts +++ b/apps/services/auth/admin-api/src/app/v2/delegations/test/delegation-admin.spec.ts @@ -25,6 +25,7 @@ import { getModelToken } from '@nestjs/sequelize' import { faker } from '@island.is/shared/mocking' import { TicketStatus, ZendeskService } from '@island.is/clients/zendesk' import { NationalRegistryClientService } from '@island.is/clients/national-registry-v2' +import { ErrorCodes } from '@island.is/shared/utils' const currentUser = createCurrentUser({ scope: [DelegationAdminScopes.read, DelegationAdminScopes.admin], @@ -339,6 +340,85 @@ describe('DelegationAdmin - With authentication', () => { expect(res.status).toEqual(400) }) + it('POST /delegation-admin should not create delegation since it already exists', async () => { + // Arrange + const { toNationalId, fromNationalId } = { + toNationalId: '0101302399', + fromNationalId: '0101307789', + } + + mockZendeskService(toNationalId, fromNationalId) + + const existingDelegation = await factory.createCustomDelegation({ + fromNationalId, + toNationalId, + domainName: null, + scopes: [{ scopeName: 's1' }], + referenceId: 'ref1', + }) + + const delegation: CreatePaperDelegationDto = { + toNationalId: existingDelegation.toNationalId, + fromNationalId: existingDelegation.fromNationalId, + referenceId: 'ref2', + } + + // Act + const res = await getRequestMethod( + server, + 'POST', + )('/delegation-admin').send(delegation) + + // Assert + expect(res.status).toEqual(400) + expect(res.body).toMatchObject({ + status: 400, + type: 'https://httpstatuses.org/400', + title: ErrorCodes.COULD_NOT_CREATE_DELEGATION, + detail: 'Could not create delegation', + }) + }) + + it('POST /delegation-admin should not create delegation since the delegation id already exists', async () => { + // Arrange + const { toNationalId, fromNationalId } = { + toNationalId: '0101302399', + fromNationalId: '0101307789', + } + + mockZendeskService(fromNationalId, toNationalId) + + const existingDelegation = await factory.createCustomDelegation({ + fromNationalId, + toNationalId, + domainName: null, + scopes: [{ scopeName: 's1' }], + referenceId: 'ref1', + }) + + // Send in opposite national ids so they will not exist in db + const delegation: CreatePaperDelegationDto = { + toNationalId: existingDelegation.fromNationalId, + fromNationalId: existingDelegation.toNationalId, + referenceId: 'ref1', + } + + // Act + const res = await getRequestMethod( + server, + 'POST', + )('/delegation-admin').send(delegation) + + // Assert + expect(res.status).toEqual(400) + expect(res.body).toMatchObject({ + status: 400, + type: 'https://httpstatuses.org/400', + title: ErrorCodes.REFERENCE_ID_ALREADY_EXISTS, + detail: 'Delegation with the same reference id already exists', + }) + }) + it('POST /delegation-admin should not create delegation with incorrect zendesk ticket status', async () => { // Arrange mockZendeskService(toNationalId, fromNationalId, { diff --git a/libs/auth-api-lib/src/lib/delegations/admin/delegation-admin-custom.service.ts b/libs/auth-api-lib/src/lib/delegations/admin/delegation-admin-custom.service.ts index 212577223606..5cbb11d913b5 100644 --- a/libs/auth-api-lib/src/lib/delegations/admin/delegation-admin-custom.service.ts +++ b/libs/auth-api-lib/src/lib/delegations/admin/delegation-admin-custom.service.ts @@ -29,6 +29,7 @@ import { DelegationDelegationType } from '../models/delegation-delegation-type.m import { DelegationsIncomingCustomService } from '../delegations-incoming-custom.service' import { DelegationValidity } from '../types/delegationValidity' import { ErrorCodes } from '@island.is/shared/utils' +import { Op } from 'sequelize' @Injectable() export class DelegationAdminCustomService { @@ -303,6 +304,36 @@ export class DelegationAdminCustomService { this.namesService.getPersonName(delegation.toNationalId), ]) + const existingDelegation = await this.delegationModel.findOne({ + where: { + [Op.or]: [ + { + fromNationalId: delegation.fromNationalId, + toNationalId: delegation.toNationalId, + }, + { + referenceId: delegation.referenceId, + }, + ], + }, + }) + + if (existingDelegation) { + // Throw error if reference ID already exists in db. + if (existingDelegation.referenceId === delegation.referenceId) { + throw new BadRequestException({ + message: 'Delegation with the same reference id already exists', + error: ErrorCodes.REFERENCE_ID_ALREADY_EXISTS, + }) + } else { + // Throw generic error if delegation already exists. + throw new BadRequestException({ + message: 'Could not create delegation', + error: ErrorCodes.COULD_NOT_CREATE_DELEGATION, + }) + } + } + return this.sequelize.transaction(async (transaction) => { return this.delegationModel.create( { diff --git a/libs/auth-api-lib/src/lib/delegations/models/delegation.model.ts b/libs/auth-api-lib/src/lib/delegations/models/delegation.model.ts index a750ab22c691..ac49efc3cae1 100644 --- a/libs/auth-api-lib/src/lib/delegations/models/delegation.model.ts +++ b/libs/auth-api-lib/src/lib/delegations/models/delegation.model.ts @@ -84,7 +84,7 @@ export class Delegation extends Model< allowNull: true, }) @ForeignKey(() => Domain) - domainName?: string + domainName?: string | null /** * ReferenceId is a field for storing a reference to the zendesk ticket id diff --git a/libs/portals/admin/delegation-admin/src/constants/errors.ts b/libs/portals/admin/delegation-admin/src/constants/errors.ts index ca4a8a0d020b..ac8b1476dc6e 100644 --- a/libs/portals/admin/delegation-admin/src/constants/errors.ts +++ b/libs/portals/admin/delegation-admin/src/constants/errors.ts @@ -12,4 +12,6 @@ export const FORM_ERRORS: Record = { [ErrorCodes.INPUT_VALIDATION_SAME_NATIONAL_ID]: m.sameNationalIdError, [ErrorCodes.INPUT_VALIDATION_INVALID_PERSON]: m.validPersonError, [ErrorCodes.INVALID_DATE_FORMAT]: m.invalidDateFormatError, + [ErrorCodes.COULD_NOT_CREATE_DELEGATION]: m.couldNotCreateDelegationError, + [ErrorCodes.REFERENCE_ID_ALREADY_EXISTS]: m.referenceIdAlreadyExistsError, } diff --git a/libs/portals/admin/delegation-admin/src/lib/messages.ts b/libs/portals/admin/delegation-admin/src/lib/messages.ts index 9bd273bf7545..990743fc4a0d 100644 --- a/libs/portals/admin/delegation-admin/src/lib/messages.ts +++ b/libs/portals/admin/delegation-admin/src/lib/messages.ts @@ -159,4 +159,12 @@ export const m = defineMessages({ id: 'admin.delegationAdmin:invalidDateFormatError', defaultMessage: 'Dagsetning er ekki á réttu sniði', }, + couldNotCreateDelegationError: { + id: 'admin.delegationAdmin:couldNotCreateDelegationError', + defaultMessage: 'Ekki tókst að skrá umboð', + }, + referenceIdAlreadyExistsError: { + id: 'admin.delegationAdmin:referenceIdAlreadyExistsError', + defaultMessage: 'Númer máls í Zendesk er þegar til', + }, }) diff --git a/libs/services/auth/testing/src/fixtures/types.ts b/libs/services/auth/testing/src/fixtures/types.ts index 8b96406dd1e3..60f34ce8e514 100644 --- a/libs/services/auth/testing/src/fixtures/types.ts +++ b/libs/services/auth/testing/src/fixtures/types.ts @@ -37,11 +37,14 @@ export type CreateCustomDelegationScope = Optional< export type CreateCustomDelegation = Optional< Pick< DelegationDTO, - 'toNationalId' | 'fromNationalId' | 'fromName' | 'referenceId' + | 'toNationalId' + | 'fromNationalId' + | 'fromName' + | 'referenceId' + | 'domainName' >, - 'toNationalId' | 'fromNationalId' | 'fromName' | 'referenceId' + 'toNationalId' | 'fromNationalId' | 'fromName' | 'referenceId' | 'domainName' > & { - domainName: string scopes?: CreateCustomDelegationScope[] } diff --git a/libs/shared/utils/src/lib/errorCodes.ts b/libs/shared/utils/src/lib/errorCodes.ts index 54ed91b8d870..3eeb74879619 100644 --- a/libs/shared/utils/src/lib/errorCodes.ts +++ b/libs/shared/utils/src/lib/errorCodes.ts @@ -6,4 +6,6 @@ export enum ErrorCodes { INPUT_VALIDATION_SAME_NATIONAL_ID = 'INPUT_VALIDATION_SAME_NATIONAL_ID', INPUT_VALIDATION_INVALID_PERSON = 'INPUT_VALIDATION_INVALID_PERSON', INVALID_DATE_FORMAT = 'INVALID_DATE_FORMAT', + COULD_NOT_CREATE_DELEGATION = 'COULD_NOT_CREATE_DELEGATION', + REFERENCE_ID_ALREADY_EXISTS = 'REFERENCE_ID_ALREADY_EXISTS', }