diff --git a/apps/services/auth/delegation-api/src/app/delegations/delegation-index.controller.ts b/apps/services/auth/delegation-api/src/app/delegations/delegation-index.controller.ts index 3c37004049dc..6929de34458c 100644 --- a/apps/services/auth/delegation-api/src/app/delegations/delegation-index.controller.ts +++ b/apps/services/auth/delegation-api/src/app/delegations/delegation-index.controller.ts @@ -93,11 +93,14 @@ export class DelegationIndexController { ...parsedDelegationInfo, }, }, - this.delegationIndexService.createOrUpdateDelegationRecord({ - ...parsedDelegationInfo, - provider: auth.delegationProvider, - validTo: body.validTo, - }), + this.delegationIndexService.createOrUpdateDelegationRecord( + { + ...parsedDelegationInfo, + provider: auth.delegationProvider, + validTo: body.validTo, + }, + auth, + ), ) } @@ -126,10 +129,13 @@ export class DelegationIndexController { ...parsedDelegationInfo, }, }, - this.delegationIndexService.removeDelegationRecord({ - ...parsedDelegationInfo, - provider: auth.delegationProvider, - }), + this.delegationIndexService.removeDelegationRecord( + { + ...parsedDelegationInfo, + provider: auth.delegationProvider, + }, + auth, + ), ) } } diff --git a/apps/services/auth/delegation-api/src/app/delegations/test/delegation-index/delegation-index.service.spec.ts b/apps/services/auth/delegation-api/src/app/delegations/test/delegation-index/delegation-index.service.spec.ts index bd627e8b37be..d265b3d64fb3 100644 --- a/apps/services/auth/delegation-api/src/app/delegations/test/delegation-index/delegation-index.service.spec.ts +++ b/apps/services/auth/delegation-api/src/app/delegations/test/delegation-index/delegation-index.service.spec.ts @@ -451,7 +451,7 @@ describe('DelegationsIndexService', () => { const nationalId = user.nationalId // Act - await delegationIndexService.indexCustomDelegations(nationalId) + await delegationIndexService.indexCustomDelegations(nationalId, user) // Assert const delegations = await delegationIndexModel.findAll({ @@ -480,7 +480,10 @@ describe('DelegationsIndexService', () => { const nationalId = user.nationalId // Act - await delegationIndexService.indexRepresentativeDelegations(nationalId) + await delegationIndexService.indexRepresentativeDelegations( + nationalId, + user, + ) // Assert const delegations = await delegationIndexModel.findAll({ @@ -625,7 +628,7 @@ describe('DelegationsIndexService', () => { const nationalId = user.nationalId // Act - await delegationIndexService.indexCustomDelegations(nationalId) + await delegationIndexService.indexCustomDelegations(nationalId, user) // Assert const delegations = await delegationModel.findAll({ diff --git a/apps/services/auth/personal-representative/src/app/modules/personalRepresentatives/personalRepresentatives.controller.ts b/apps/services/auth/personal-representative/src/app/modules/personalRepresentatives/personalRepresentatives.controller.ts index 8e7f9a477f4c..00af813def2c 100644 --- a/apps/services/auth/personal-representative/src/app/modules/personalRepresentatives/personalRepresentatives.controller.ts +++ b/apps/services/auth/personal-representative/src/app/modules/personalRepresentatives/personalRepresentatives.controller.ts @@ -99,6 +99,7 @@ export class PersonalRepresentativesController { return personalRepresentative } + /** Removes a personal representative by its id */ @Delete(':id') @Documentation({ @@ -135,6 +136,7 @@ export class PersonalRepresentativesController { // Index personal representative delegations for the personal representative void this.delegationIndexService.indexRepresentativeDelegations( deletedPersonalRepresentative.nationalIdPersonalRepresentative, + user, ) } } @@ -203,6 +205,7 @@ export class PersonalRepresentativesController { // Index personal representative delegations for the personal representative void this.delegationIndexService.indexRepresentativeDelegations( createdPersonalRepresentative.nationalIdPersonalRepresentative, + user, ) } 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 43ced573b3d8..04403fecda27 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 @@ -5,7 +5,7 @@ import kennitala from 'kennitala' import { uuid } from 'uuidv4' import { AuthDelegationType } from '@island.is/shared/types' -import { User } from '@island.is/auth-nest-tools' +import { Auth, User } from '@island.is/auth-nest-tools' import { NoContentException } from '@island.is/nest/problem' import { Ticket, @@ -201,7 +201,7 @@ export class DelegationAdminCustomService { ) // Index delegations for the toNationalId - void this.indexDelegations(delegation.toNationalId) + void this.indexDelegations(delegation.toNationalId, user) return newDelegation.toDTO(AuthDelegationType.GeneralMandate) } @@ -244,7 +244,7 @@ export class DelegationAdminCustomService { } // Index delegations for the toNationalId - void this.indexDelegations(delegation.toNationalId) + void this.indexDelegations(delegation.toNationalId, user) }) } @@ -267,8 +267,11 @@ export class DelegationAdminCustomService { } } - private indexDelegations(nationalId: string) { - void this.delegationIndexService.indexCustomDelegations(nationalId) - void this.delegationIndexService.indexGeneralMandateDelegations(nationalId) + private indexDelegations(nationalId: string, auth: Auth) { + void this.delegationIndexService.indexCustomDelegations(nationalId, auth) + void this.delegationIndexService.indexGeneralMandateDelegations( + nationalId, + auth, + ) } } diff --git a/libs/auth-api-lib/src/lib/delegations/delegation-scope.service.ts b/libs/auth-api-lib/src/lib/delegations/delegation-scope.service.ts index 94e89cc29204..d12b1d8af8e4 100644 --- a/libs/auth-api-lib/src/lib/delegations/delegation-scope.service.ts +++ b/libs/auth-api-lib/src/lib/delegations/delegation-scope.service.ts @@ -28,6 +28,7 @@ import { DelegationTypeModel } from './models/delegation-type.model' import { Delegation } from './models/delegation.model' import type { User } from '@island.is/auth-nest-tools' + @Injectable() export class DelegationScopeService { constructor( @@ -309,24 +310,27 @@ export class DelegationScopeService { } private async findDistrictCommissionersRegistryScopesTo( - toNationalId: string, + user: User, fromNationalId: string, ): Promise { // if no valid delegation exists, return empty array try { const delegationFound = await this.syslumennService.checkIfDelegationExists( - toNationalId, + user.nationalId, fromNationalId, ) if (!delegationFound) { - this.delegationsIndexService.removeDelegationRecord({ - fromNationalId, - toNationalId, - type: AuthDelegationType.LegalRepresentative, - provider: AuthDelegationProvider.DistrictCommissionersRegistry, - }) + void this.delegationsIndexService.removeDelegationRecord( + { + fromNationalId, + toNationalId: user.nationalId, + type: AuthDelegationType.LegalRepresentative, + provider: AuthDelegationProvider.DistrictCommissionersRegistry, + }, + user, + ) return [] } } catch (error) { @@ -429,10 +433,7 @@ export class DelegationScopeService { providers.includes(AuthDelegationProvider.DistrictCommissionersRegistry) ) scopePromises.push( - this.findDistrictCommissionersRegistryScopesTo( - user.nationalId, - fromNationalId, - ), + this.findDistrictCommissionersRegistryScopesTo(user, fromNationalId), ) const scopeSets = await Promise.all(scopePromises) diff --git a/libs/auth-api-lib/src/lib/delegations/delegations-incoming.service.ts b/libs/auth-api-lib/src/lib/delegations/delegations-incoming.service.ts index ca782439de6c..1792164ddb48 100644 --- a/libs/auth-api-lib/src/lib/delegations/delegations-incoming.service.ts +++ b/libs/auth-api-lib/src/lib/delegations/delegations-incoming.service.ts @@ -302,12 +302,15 @@ export class DelegationsIncomingService { if (delegationFound) { return true } else { - this.delegationsIndexService.removeDelegationRecord({ - fromNationalId, - toNationalId: user.nationalId, - type: AuthDelegationType.LegalRepresentative, - provider: AuthDelegationProvider.DistrictCommissionersRegistry, - }) + void this.delegationsIndexService.removeDelegationRecord( + { + fromNationalId, + toNationalId: user.nationalId, + type: AuthDelegationType.LegalRepresentative, + provider: AuthDelegationProvider.DistrictCommissionersRegistry, + }, + user, + ) } } catch (error) { logger.error( 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 46b51cd42f48..de23fd31904d 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 @@ -1,11 +1,13 @@ -import { BadRequestException, Injectable } from '@nestjs/common' +import { BadRequestException, Inject, Injectable } from '@nestjs/common' import { InjectModel } from '@nestjs/sequelize' import startOfDay from 'date-fns/startOfDay' import * as kennitala from 'kennitala' import union from 'lodash/union' import { Op } from 'sequelize' -import { User } from '@island.is/auth-nest-tools' +import { Auth, User } from '@island.is/auth-nest-tools' +import { AuditService } from '@island.is/nest/audit' +import { type Logger, LOGGER_PROVIDER } from '@island.is/logging' import { AuthDelegationProvider, AuthDelegationType, @@ -170,6 +172,9 @@ export class DelegationsIndexService { private delegationsIncomingWardService: DelegationsIncomingWardService, private personalRepresentativeScopePermissionService: PersonalRepresentativeScopePermissionService, private userIdentitiesService: UserIdentitiesService, + @Inject(LOGGER_PROVIDER) + private logger: Logger, + private auditService: AuditService, ) {} /* Lookup delegations in index for user for specific scope */ @@ -258,7 +263,7 @@ export class DelegationsIndexService { this.getWardDelegations(user), ]).then((d) => d.flat()) - await this.saveToIndex(user.nationalId, delegations) + await this.saveToIndex(user.nationalId, delegations, user) // set next reindex to one week in the future await this.delegationIndexMetaModel.update( @@ -275,49 +280,76 @@ export class DelegationsIndexService { } /* Index incoming custom delegations */ - async indexCustomDelegations(nationalId: string) { + async indexCustomDelegations(nationalId: string, auth: Auth) { const delegations = await this.getCustomDelegations(nationalId, true) - await this.saveToIndex(nationalId, delegations) + await this.saveToIndex(nationalId, delegations, auth) } /* Index incoming general mandate delegations */ - async indexGeneralMandateDelegations(nationalId: string) { + async indexGeneralMandateDelegations(nationalId: string, auth: Auth) { const delegations = await this.getGeneralMandateDelegation(nationalId, true) - await this.saveToIndex(nationalId, delegations) + await this.saveToIndex(nationalId, delegations, auth) } /* Index incoming personal representative delegations */ - async indexRepresentativeDelegations(nationalId: string) { + async indexRepresentativeDelegations(nationalId: string, auth: Auth) { const delegations = await this.getRepresentativeDelegations( nationalId, true, ) - await this.saveToIndex(nationalId, delegations) + await this.saveToIndex(nationalId, delegations, auth) } /* Add item to index */ - async createOrUpdateDelegationRecord(delegation: DelegationRecordInputDTO) { + async createOrUpdateDelegationRecord( + delegation: DelegationRecordInputDTO, + auth: Auth, + ) { validateCrudParams(delegation) - const [updatedDelegation] = await this.delegationIndexModel.upsert( - delegation, + const [updatedDelegation] = await this.auditService.auditPromise( + { + auth, + action: + '@island.is/auth/delegation-index/create-or-update-delegation-record', + resources: delegation.toNationalId, + alsoLog: true, + meta: { + delegation, + }, + }, + this.delegationIndexModel.upsert(delegation), ) return updatedDelegation.toDTO() } /* Delete record from index */ - async removeDelegationRecord(delegation: DelegationRecordInputDTO) { + async removeDelegationRecord( + delegation: DelegationRecordInputDTO, + auth: Auth, + ) { validateCrudParams(delegation) - await this.delegationIndexModel.destroy({ - where: { - fromNationalId: delegation.fromNationalId, - toNationalId: delegation.toNationalId, - provider: delegation.provider, - type: delegation.type, + await this.auditService.auditPromise( + { + auth, + action: '@island.is/auth/delegation-index/remove-delegation-record', + resources: delegation.toNationalId, + alsoLog: true, + meta: { + delegation, + }, }, - }) + this.delegationIndexModel.destroy({ + where: { + fromNationalId: delegation.fromNationalId, + toNationalId: delegation.toNationalId, + provider: delegation.provider, + type: delegation.type, + }, + }), + ) } async getAvailableDistrictCommissionersRegistryRecords( @@ -338,7 +370,7 @@ export class DelegationsIndexService { } } - return await this.delegationIndexModel + return this.delegationIndexModel .findAll({ where: { toNationalId: user.nationalId, @@ -356,6 +388,9 @@ export class DelegationsIndexService { private async saveToIndex( nationalId: string, delegations: DelegationIndexInfo[], + // Some entrypoints to indexing do not have a user auth object or have a 3rd party user + // so we take the auth separately from the subject nationalId + auth: Auth, ) { const currRecords = await this.delegationIndexModel.findAll({ where: { @@ -398,6 +433,20 @@ export class DelegationsIndexService { }), ), ]) + + // saveToIndex is used by multiple entry points, when indexing so this + // is the common place to audit updates in the index. + this.auditService.audit({ + auth, + action: '@island.is/auth/delegation-index/save-to-index', + alsoLog: true, + resources: nationalId, + meta: { + created, + updated, + deleted, + }, + }) } private sortDelegation({ diff --git a/libs/auth-api-lib/src/lib/delegations/delegations-outgoing.service.ts b/libs/auth-api-lib/src/lib/delegations/delegations-outgoing.service.ts index 807298a7fa2a..3252f24c3e31 100644 --- a/libs/auth-api-lib/src/lib/delegations/delegations-outgoing.service.ts +++ b/libs/auth-api-lib/src/lib/delegations/delegations-outgoing.service.ts @@ -273,6 +273,7 @@ export class DelegationsOutgoingService { // Index custom delegations for the toNationalId void this.delegationIndexService.indexCustomDelegations( createDelegation.toNationalId, + user, ) return newDelegation @@ -418,11 +419,13 @@ export class DelegationsOutgoingService { // Index custom delegations for the toNationalId void this.delegationIndexService.indexCustomDelegations( delegation.toNationalId, + user, ) const hasExistingScopes = (currentDelegation.delegationScopes?.length ?? 0) > 0 - this.notifyDelegationUpdate(user, delegation, hasExistingScopes) + + void this.notifyDelegationUpdate(user, delegation, hasExistingScopes) return delegation } @@ -457,6 +460,7 @@ export class DelegationsOutgoingService { // Index custom delegations for the toNationalId void this.delegationIndexService.indexCustomDelegations( delegation.toNationalId, + user, ) }