Skip to content

Commit

Permalink
feat(ids-api): index delegations when IDS gets delegations (#15079)
Browse files Browse the repository at this point in the history
* index delegations when IDS gets delegations

* fix tests

* don't fail requests if indexing fails

* mock delegation indexing in controller tests

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
Herdismaria and kodiakhq[bot] authored Jun 5, 2024
1 parent ebcf5c8 commit 9e1ff00
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
Delegation,
DelegationDTO,
DelegationProviderModel,
DelegationType,
DelegationsIndexService,
DelegationTypeModel,
Domain,
InactiveReason,
Expand Down Expand Up @@ -56,7 +56,7 @@ import {
getScopePermission,
personalRepresentativeType,
} from '../../../test/stubs/personalRepresentativeStubs'
import { AuthDelegationProvider } from 'delegation'
import { AuthDelegationType, AuthDelegationProvider } from 'delegation'
import { getPersonalRepresentativeDelegationType } from '@island.is/shared/types'

describe('DelegationsController', () => {
Expand All @@ -74,6 +74,7 @@ describe('DelegationsController', () => {
let delegationTypeModel: typeof DelegationTypeModel
let nationalRegistryApi: NationalRegistryClientService
let delegationProviderModel: typeof DelegationProviderModel
let delegationIndexService: DelegationsIndexService

const userNationalId = getFakeNationalId()

Expand Down Expand Up @@ -125,6 +126,7 @@ describe('DelegationsController', () => {
getModelToken(DelegationProviderModel),
)
nationalRegistryApi = app.get(NationalRegistryClientService)
delegationIndexService = app.get(DelegationsIndexService)
})

afterAll(async () => {
Expand Down Expand Up @@ -223,6 +225,7 @@ describe('DelegationsController', () => {
nationalRegistryErrors: number,
) => {
let nationalRegistryApiSpy: jest.SpyInstance
let delegationIndexServiceSpy: jest.SpyInstance
const validRepresentedPersons: NameIdTuple[] = []
const outdatedRepresentedPersons: NameIdTuple[] = []
const unactivatedRepresentedPersons: NameIdTuple[] = []
Expand Down Expand Up @@ -378,6 +381,10 @@ describe('DelegationsController', () => {

return user ?? null
})

delegationIndexServiceSpy = jest
.spyOn(delegationIndexService, 'indexDelegations')
.mockImplementation()
})

afterAll(async () => {
Expand Down Expand Up @@ -463,7 +470,8 @@ describe('DelegationsController', () => {
it('should have the delegation type claims of PersonalRepresentative', () => {
expect(
body.every(
(d) => d.types[0] === DelegationType.PersonalRepresentative,
(d) =>
d.types[0] === AuthDelegationType.PersonalRepresentative,
),
).toBeTruthy()
})
Expand Down Expand Up @@ -500,6 +508,10 @@ describe('DelegationsController', () => {
// Assert
expect(expectedModels.length).toEqual(errorNationalIds.length)
})

it('should index delegations', () => {
expect(delegationIndexServiceSpy).toHaveBeenCalled()
})
})
},
)
Expand Down Expand Up @@ -623,7 +635,7 @@ describe('DelegationsController', () => {
beforeAll(async () => {
response = await server.get(`${path}`).query({
fromNationalId: representeeNationalId,
delegationType: DelegationType.PersonalRepresentative,
delegationType: AuthDelegationType.PersonalRepresentative,
})
body = response.body
})
Expand Down Expand Up @@ -899,8 +911,13 @@ describe('DelegationsController', () => {
const path = '/delegations'
let response: request.Response
let body: DelegationDTO[]
let delegationIndexServiceSpy: jest.SpyInstance

beforeAll(async () => {
delegationIndexServiceSpy = jest
.spyOn(delegationIndexService, 'indexDelegations')
.mockImplementation()

response = await server.get(path)
body = response.body
})
Expand Down Expand Up @@ -956,7 +973,7 @@ describe('DelegationsController', () => {
it('should have the delegation type claims of PersonalRepresentative', () => {
expect(
body.every(
(d) => d.type === DelegationType.PersonalRepresentative,
(d) => d.type === AuthDelegationType.PersonalRepresentative,
),
).toBeTruthy()
})
Expand Down Expand Up @@ -993,6 +1010,10 @@ describe('DelegationsController', () => {
// Assert
expect(expectedModels.length).toEqual(errorNationalIds.length)
})

it('should index delegations', () => {
expect(delegationIndexServiceSpy).toHaveBeenCalled()
})
})
},
)
Expand Down Expand Up @@ -1123,7 +1144,7 @@ describe('DelegationsController', () => {
beforeAll(async () => {
response = await server.get(`${path}`).query({
fromNationalId: representeeNationalId,
delegationType: DelegationType.PersonalRepresentative,
delegationType: AuthDelegationType.PersonalRepresentative,
})
body = response.body
})
Expand Down Expand Up @@ -1247,7 +1268,10 @@ describe('DelegationsController', () => {
it('should return a single merged delegation', async () => {
expect(body.length).toEqual(1)
expect(body[0].types.sort()).toEqual(
[DelegationType.Custom, DelegationType.LegalGuardian].sort(),
[
AuthDelegationType.Custom,
AuthDelegationType.LegalGuardian,
].sort(),
)
})
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
Controller,
Get,
Inject,
ParseArrayPipe,
Query,
UseGuards,
Expand All @@ -9,14 +10,16 @@ import {
} from '@nestjs/common'
import { ApiOkResponse, ApiTags } from '@nestjs/swagger'

import type { Logger } from '@island.is/logging'
import { LOGGER_PROVIDER } from '@island.is/logging'
import {
DelegationDTO,
DelegationScope,
DelegationScopeService,
DelegationsIncomingService,
DelegationsService,
DelegationType,
MergedDelegationDTO,
DelegationsIndexService,
} from '@island.is/auth-api-lib'
import type { User } from '@island.is/auth-nest-tools'
import {
Expand All @@ -25,6 +28,7 @@ import {
Scopes,
ScopesGuard,
} from '@island.is/auth-nest-tools'
import { AuthDelegationType } from 'delegation'

@UseGuards(IdsUserGuard, ScopesGuard)
@ApiTags('delegations')
Expand All @@ -34,16 +38,28 @@ import {
})
export class DelegationsController {
constructor(
@Inject(LOGGER_PROVIDER)
protected readonly logger: Logger,
private readonly delegationsService: DelegationsService,
private readonly delegationScopeService: DelegationScopeService,
private readonly delegationsIncomingService: DelegationsIncomingService,
private readonly delegationIndexService: DelegationsIndexService,
) {}

@Scopes('@identityserver.api/authentication')
@Get()
@ApiOkResponse({ isArray: true })
async findAllToV1(@CurrentUser() user: User): Promise<DelegationDTO[]> {
return this.delegationsService.findAllIncoming(user)
const delegations = await this.delegationsService.findAllIncoming(user)

// don't fail the request if indexing fails
try {
void this.delegationIndexService.indexDelegations(user)
} catch {
this.logger.error('Failed to index delegations')
}

return delegations
}

@Scopes('@identityserver.api/authentication')
Expand All @@ -58,10 +74,19 @@ export class DelegationsController {
)
requestedScopes: Array<string>,
): Promise<MergedDelegationDTO[]> {
return this.delegationsIncomingService.findAllAvailable({
const delegations = await this.delegationsIncomingService.findAllAvailable({
user,
requestedScopes,
})

// don't fail the request if indexing fails
try {
void this.delegationIndexService.indexDelegations(user)
} catch {
this.logger.error('Failed to index delegations')
}

return delegations
}

@Scopes('@identityserver.api/authentication')
Expand All @@ -74,27 +99,27 @@ export class DelegationsController {
'delegationType',
new ParseArrayPipe({ optional: true, items: String, separator: ',' }),
)
delegationType: Array<DelegationType>,
delegationType: Array<AuthDelegationType>,
): Promise<string[]> {
const scopePromises = []

if (delegationType.includes(DelegationType.ProcurationHolder))
if (delegationType.includes(AuthDelegationType.ProcurationHolder))
scopePromises.push(this.delegationScopeService.findAllProcurationScopes())

if (delegationType.includes(DelegationType.LegalGuardian))
if (delegationType.includes(AuthDelegationType.LegalGuardian))
scopePromises.push(
this.delegationScopeService.findAllLegalGuardianScopes(),
)

if (delegationType.includes(DelegationType.PersonalRepresentative))
if (delegationType.includes(AuthDelegationType.PersonalRepresentative))
scopePromises.push(
this.delegationScopeService.findPersonalRepresentativeScopes(
user.nationalId,
fromNationalId,
),
)

if (delegationType.includes(DelegationType.Custom))
if (delegationType.includes(AuthDelegationType.Custom))
scopePromises.push(
this.delegationScopeService
.findAllValidCustomScopesTo(user.nationalId, fromNationalId)
Expand All @@ -109,8 +134,8 @@ export class DelegationsController {

if (
scopes.length > 0 ||
delegationType.includes(DelegationType.ProcurationHolder) ||
delegationType.includes(DelegationType.LegalGuardian)
delegationType.includes(AuthDelegationType.ProcurationHolder) ||
delegationType.includes(AuthDelegationType.LegalGuardian)
) {
scopes = [
...scopes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from '@island.is/auth-api-lib'

import { DelegationsController } from './delegations.controller'
import { logger, LOGGER_PROVIDER } from '@island.is/logging'

@Module({
imports: [
Expand All @@ -15,6 +16,11 @@ import { DelegationsController } from './delegations.controller'
PersonalRepresentativeModule,
],
controllers: [DelegationsController],
providers: [],
providers: [
{
provide: LOGGER_PROVIDER,
useValue: logger,
},
],
})
export class DelegationsModule {}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import faker from 'faker'
import { setupWithAuth } from '../../../../test/setup'
import { createNationalRegistryUser } from '@island.is/testing/fixtures'
import { NationalRegistryClientService } from '@island.is/clients/national-registry-v2'
import { DelegationDTO } from '@island.is/auth-api-lib'
import { DelegationDTO, DelegationsIndexService } from '@island.is/auth-api-lib'
import { RskRelationshipsClient } from '@island.is/clients-rsk-relationships'
import { user } from './delegations-filters-types'
import { Sequelize } from 'sequelize-typescript'
Expand All @@ -20,6 +20,7 @@ describe('DelegationsController', () => {
let factory: FixtureFactory
let nationalRegistryApi: NationalRegistryClientService
let rskApi: RskRelationshipsClient
let delegationIndexService: DelegationsIndexService

beforeAll(async () => {
app = await setupWithAuth({
Expand All @@ -29,6 +30,7 @@ describe('DelegationsController', () => {

server = request(app.getHttpServer())

delegationIndexService = app.get(DelegationsIndexService)
nationalRegistryApi = app.get(NationalRegistryClientService)
jest
.spyOn(nationalRegistryApi, 'getIndividual')
Expand All @@ -38,6 +40,7 @@ describe('DelegationsController', () => {
name: faker.name.findName(),
}),
)
jest.spyOn(delegationIndexService, 'indexDelegations').mockImplementation()

rskApi = app.get(RskRelationshipsClient)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import faker from 'faker'
import { Sequelize } from 'sequelize-typescript'
import request from 'supertest'

import { DelegationType } from '@island.is/auth-api-lib'
import {
DelegationsIndexService,
DelegationType,
} from '@island.is/auth-api-lib'
import { FixtureFactory } from '@island.is/services/auth/testing'
import {
createCurrentUser,
Expand Down Expand Up @@ -89,6 +92,7 @@ describe('DelegationsController', () => {
let app: TestApp
let server: request.SuperTest<request.Test>
let factory: FixtureFactory
let delegationIndexService: DelegationsIndexService

beforeAll(async () => {
app = await setupWithAuth({
Expand All @@ -99,6 +103,9 @@ describe('DelegationsController', () => {
server = request(app.getHttpServer())

factory = new FixtureFactory(app)

delegationIndexService = app.get(DelegationsIndexService)
jest.spyOn(delegationIndexService, 'indexDelegations').mockImplementation()
})

afterAll(async () => {
Expand Down

0 comments on commit 9e1ff00

Please sign in to comment.