diff --git a/apps/services/auth/delegation-api/src/app/delegations/test/delegation-index/delegation-index.controller.spec.ts b/apps/services/auth/delegation-api/src/app/delegations/test/delegation-index/delegation-index.controller.spec.ts index 10afbe6133d2..dfef8879fda8 100644 --- a/apps/services/auth/delegation-api/src/app/delegations/test/delegation-index/delegation-index.controller.spec.ts +++ b/apps/services/auth/delegation-api/src/app/delegations/test/delegation-index/delegation-index.controller.spec.ts @@ -7,7 +7,11 @@ import { createNationalId, } from '@island.is/testing/fixtures' import { AuthScope } from '@island.is/auth/scopes' -import { DelegationIndex } from '@island.is/auth-api-lib' +import { + DelegationIndex, + DelegationProviderModel, + DelegationTypeModel, +} from '@island.is/auth-api-lib' import { AuthDelegationProvider, AuthDelegationType, @@ -70,7 +74,29 @@ const invalidDelegationTypeAndProviderMapTestcases: Record< ], } +const DELEGATION_PROVIDERS = [ + { + provider: AuthDelegationProvider.NationalRegistry, + type: AuthDelegationType.LegalGuardian, + }, + { + provider: AuthDelegationProvider.Custom, + type: AuthDelegationType.Custom, + }, + { + provider: AuthDelegationProvider.PersonalRepresentativeRegistry, + type: AuthDelegationType.PersonalRepresentativePostbox, + }, + { + provider: AuthDelegationProvider.CompanyRegistry, + type: AuthDelegationType.ProcurationHolder, + }, +] + describe('DelegationIndexController', () => { + let delegationTypeModel: typeof DelegationTypeModel + let delegationProviderModel: typeof DelegationProviderModel + describe('Without valid scope', () => { let app: TestApp let server: request.SuperTest @@ -85,6 +111,8 @@ describe('DelegationIndexController', () => { }) server = request(app.getHttpServer()) + ;({ delegationProviderModel, delegationTypeModel } = + await setupDelegationModels(app)) }) afterAll(async () => { @@ -143,6 +171,8 @@ describe('DelegationIndexController', () => { }) server = request(app.getHttpServer()) + ;({ delegationProviderModel, delegationTypeModel } = + await setupDelegationModels(app)) }) afterAll(async () => { @@ -207,6 +237,8 @@ describe('DelegationIndexController', () => { }) server = request(app.getHttpServer()) + ;({ delegationProviderModel, delegationTypeModel } = + await setupDelegationModels(app)) }) afterAll(async () => { @@ -265,6 +297,8 @@ describe('DelegationIndexController', () => { server = request(app.getHttpServer()) delegationIndexModel = app.get(getModelToken(DelegationIndex)) + ;({ delegationProviderModel, delegationTypeModel } = + await setupDelegationModels(app)) }) afterAll(async () => { @@ -414,3 +448,43 @@ describe('DelegationIndexController', () => { }) }) }) + +async function setupDelegationModels(app: TestApp) { + const delegationProviderModel = app.get( + getModelToken(DelegationProviderModel), + ) + const delegationTypeModel = app.get(getModelToken(DelegationTypeModel)) + + await createDelegationProvidersAndTypes( + delegationProviderModel, + delegationTypeModel, + ) + + return { delegationProviderModel, delegationTypeModel } +} + +async function createDelegationProvidersAndTypes( + delegationProviderModel: typeof DelegationProviderModel, + delegationTypeModel: typeof DelegationTypeModel, +) { + for (const { provider, type } of DELEGATION_PROVIDERS) { + const [providerInstance] = await delegationProviderModel.findOrCreate({ + where: { id: provider }, + defaults: { + id: provider, + name: type, + description: 'Testing', + }, + }) + + await delegationTypeModel.findOrCreate({ + where: { id: type }, + defaults: { + id: type, + name: type, + description: 'Testing', + providerId: providerInstance.id, + }, + }) + } +} diff --git a/libs/api/domains/auth/src/lib/models/delegation.model.ts b/libs/api/domains/auth/src/lib/models/delegation.model.ts index 48065a23658b..9f7bd9dc158e 100644 --- a/libs/api/domains/auth/src/lib/models/delegation.model.ts +++ b/libs/api/domains/auth/src/lib/models/delegation.model.ts @@ -30,6 +30,8 @@ const exhaustiveCheck = (param: never) => { return ProcuringHolderDelegation case AuthDelegationType.PersonalRepresentative: return PersonalRepresentativeDelegation + case AuthDelegationType.PersonalRepresentativepostholf: + return PersonalRepresentativePostboxDelegation case AuthDelegationType.Custom: return CustomDelegation case AuthDelegationType.GeneralMandate: @@ -79,6 +81,11 @@ export class ProcuringHolderDelegation extends Delegation {} }) export class PersonalRepresentativeDelegation extends Delegation {} +@ObjectType('AuthPersonalRepresentativePostboxDelegation', { + implements: Delegation, +}) +export class PersonalRepresentativePostboxDelegation extends Delegation {} + @ObjectType('AuthGeneralMandate', { implements: Delegation, }) diff --git a/libs/auth-api-lib/src/lib/delegations/delegations-index.service.ts b/libs/auth-api-lib/src/lib/delegations/delegations-index.service.ts index 22747d838416..ea5c7262c0c0 100644 --- a/libs/auth-api-lib/src/lib/delegations/delegations-index.service.ts +++ b/libs/auth-api-lib/src/lib/delegations/delegations-index.service.ts @@ -30,6 +30,7 @@ import { import { DelegationDTO } from './dto/delegation.dto' import { DelegationIndexMeta } from './models/delegation-index-meta.model' import { DelegationIndex } from './models/delegation-index.model' +import { DelegationTypeModel } from './models/delegation-type.model' import { DelegationDirection } from './types/delegationDirection' import { DelegationRecordType, @@ -37,7 +38,6 @@ import { } from './types/delegationRecord' import { delegationProviderTypeMap, - validateDelegationTypeAndProvider, validateToAndFromNationalId, } from './utils/delegations' @@ -103,25 +103,6 @@ const getTimeUntilEighteen = (nationalId: string) => { return timeUntilEighteen > 0 ? new Date(timeUntilEighteen) : null } -const validateCrudParams = (delegation: DelegationRecordInputDTO) => { - if (!validateDelegationTypeAndProvider(delegation)) { - throw new BadRequestException( - 'Invalid delegation type and provider combination', - ) - } - - if (!validateToAndFromNationalId(delegation)) { - throw new BadRequestException('Invalid national ids') - } - - if ( - delegation.validTo && - new Date(delegation.validTo).getTime() <= new Date().getTime() - ) { - throw new BadRequestException('Invalid validTo') - } -} - const hasAllSameScopes = ( a: string[] | undefined, b: string[] | undefined, @@ -164,6 +145,8 @@ export class DelegationsIndexService { private apiScopeModel: typeof ApiScope, @InjectModel(DelegationIndex) private delegationIndexModel: typeof DelegationIndex, + @InjectModel(DelegationTypeModel) + private delegationTypeModel: typeof DelegationTypeModel, @InjectModel(DelegationIndexMeta) private delegationIndexMetaModel: typeof DelegationIndexMeta, private delegationsIncomingCustomService: DelegationsIncomingCustomService, @@ -305,7 +288,7 @@ export class DelegationsIndexService { delegation: DelegationRecordInputDTO, auth: Auth, ) { - validateCrudParams(delegation) + await this.validateCrudParams(delegation) const [updatedDelegation] = await this.auditService.auditPromise( { @@ -329,7 +312,7 @@ export class DelegationsIndexService { delegation: DelegationRecordInputDTO, auth: Auth, ) { - validateCrudParams(delegation) + await this.validateCrudParams(delegation) await this.auditService.auditPromise( { @@ -741,4 +724,43 @@ export class DelegationsIndexService { }) .then((d) => d.map((d) => d.toDTO())) } + + private async validateDelegationTypeAndProvider( + delegation: DelegationRecordInputDTO, + ) { + const { type, provider } = delegation + + const validTypes = await this.delegationTypeModel + .findAll({ + where: { + provider, + }, + }) + .then((d) => d.map((d) => d.name)) + + return validTypes.includes(type) + } + + private async validateCrudParams(delegation: DelegationRecordInputDTO) { + const isValidDelegationType = await this.validateDelegationTypeAndProvider( + delegation, + ) + + if (!isValidDelegationType) { + throw new BadRequestException( + 'Invalid delegation type and provider combination', + ) + } + + if (!validateToAndFromNationalId(delegation)) { + throw new BadRequestException('Invalid national ids') + } + + if ( + delegation.validTo && + new Date(delegation.validTo).getTime() <= new Date().getTime() + ) { + throw new BadRequestException('Invalid validTo') + } + } } diff --git a/libs/auth-api-lib/src/lib/delegations/utils/delegations.ts b/libs/auth-api-lib/src/lib/delegations/utils/delegations.ts index f4f36b46df77..7a49b69d6689 100644 --- a/libs/auth-api-lib/src/lib/delegations/utils/delegations.ts +++ b/libs/auth-api-lib/src/lib/delegations/utils/delegations.ts @@ -37,22 +37,6 @@ export const getDelegationNoActorWhereClause = (user: User): WhereOptions => { return {} } -export const validateDelegationTypeAndProvider = ({ - type, - provider, -}: { - type: DelegationRecordType - provider: AuthDelegationProvider -}) => { - const validTypes = delegationProviderTypeMap[provider] - - if (!validTypes) { - return false - } - - return validTypes.includes(type) -} - export const validateToAndFromNationalId = ({ fromNationalId, toNationalId, diff --git a/libs/shared/types/src/lib/delegation.ts b/libs/shared/types/src/lib/delegation.ts index b2923b02ebab..ed4ad0dd3d7a 100644 --- a/libs/shared/types/src/lib/delegation.ts +++ b/libs/shared/types/src/lib/delegation.ts @@ -3,6 +3,7 @@ export enum AuthDelegationType { LegalGuardian = 'LegalGuardian', Custom = 'Custom', PersonalRepresentative = 'PersonalRepresentative', + PersonalRepresentativePostbox = 'PersonalRepresentative:postholf', LegalRepresentative = 'LegalRepresentative', GeneralMandate = 'GeneralMandate', }