Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(auth-api): Add column to delegation type indicating if actor discretion is required #16226

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,9 @@ export const indexingTestCases: Record<string, TestCase> = {
createClient({
clientId: clientId,
supportsPersonalRepresentatives: true,
supportedDelegationTypes: [AuthDelegationType.PersonalRepresentative],
supportedDelegationTypes: [
`${AuthDelegationType.PersonalRepresentative}:${prRight1}`,
],
}),
{
fromRepresentative: [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import request from 'supertest'
import { getModelToken } from '@nestjs/sequelize'
import addYears from 'date-fns/addYears'
import kennitala from 'kennitala'
import request from 'supertest'

import { TestApp } from '@island.is/testing/nest'
import {
createCurrentUser,
createNationalId,
} from '@island.is/testing/fixtures'
import { AuthScope } from '@island.is/auth/scopes'
import { DelegationIndex } from '@island.is/auth-api-lib'
import { AuthScope } from '@island.is/auth/scopes'
import { FixtureFactory } from '@island.is/services/auth/testing'
import {
AuthDelegationProvider,
AuthDelegationType,
} from '@island.is/shared/types'
import {
createCurrentUser,
createNationalId,
} from '@island.is/testing/fixtures'
import { TestApp } from '@island.is/testing/nest'

import { setupWithAuth } from '../../../../../test/setup'
import kennitala from 'kennitala'
import addYears from 'date-fns/addYears'

const path = '/v1/delegation-index/.id'
const testNationalId = createNationalId('person')
Expand Down Expand Up @@ -251,6 +252,7 @@ describe('DelegationIndexController', () => {
describe('With valid delegation provider', () => {
let app: TestApp
let server: request.SuperTest<request.Test>
let factory: FixtureFactory

let delegationIndexModel: typeof DelegationIndex
const delegationProvider = AuthDelegationProvider.CompanyRegistry
Expand All @@ -264,6 +266,8 @@ describe('DelegationIndexController', () => {
app = await setupWithAuth({
user,
})
factory = new FixtureFactory(app)
await factory.createAllDelegationTypes()
server = request(app.getHttpServer())

delegationIndexModel = app.get(getModelToken(DelegationIndex))
Expand Down Expand Up @@ -419,6 +423,7 @@ describe('DelegationIndexController', () => {
describe('PUT for Legal guardians', () => {
let app: TestApp
let server: request.SuperTest<request.Test>
let factory: FixtureFactory

let delegationIndexModel: typeof DelegationIndex
const delegationProvider = AuthDelegationProvider.NationalRegistry
Expand All @@ -435,6 +440,8 @@ describe('DelegationIndexController', () => {
server = request(app.getHttpServer())

delegationIndexModel = app.get(getModelToken(DelegationIndex))
factory = new FixtureFactory(app)
await factory.createAllDelegationTypes()
})

afterAll(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,6 @@ import { getConnectionToken, getModelToken } from '@nestjs/sequelize'
import faker from 'faker'
import { Sequelize } from 'sequelize-typescript'

import {
indexingTestCases,
prRight1,
testDate,
} from './delegation-index-test-cases'
import { setupWithAuth } from '../../../../../test/setup'
import {
customScopes,
customScopesOtherDomain,
domainName,
TestCase,
user,
} from './delegations-index-types'

import {
actorSubjectIdType,
audkenniProvider,
Expand All @@ -38,6 +24,20 @@ import {
import { createNationalRegistryUser } from '@island.is/testing/fixtures'
import { TestApp, truncate } from '@island.is/testing/nest'

import { setupWithAuth } from '../../../../../test/setup'
import {
indexingTestCases,
prRight1,
testDate,
} from './delegation-index-test-cases'
import {
customScopes,
customScopesOtherDomain,
domainName,
TestCase,
user,
} from './delegations-index-types'

describe('DelegationsIndexService', () => {
let app: TestApp
let delegationIndexService: DelegationsIndexService
Expand Down Expand Up @@ -210,9 +210,12 @@ describe('DelegationsIndexService', () => {
(type) => {
const testCase = indexingTestCases[type]
testCase.user = user
let factory: FixtureFactory

beforeEach(async () => {
await setup(testCase)
factory = new FixtureFactory(app)
await factory.createAllDelegationTypes()
})

it('should index delegations', async () => {
Expand All @@ -237,9 +240,12 @@ describe('DelegationsIndexService', () => {

describe('Reindex (multiple indexing)', () => {
const testCase = indexingTestCases.custom
let factory: FixtureFactory

beforeEach(async () => {
await setup(testCase)
factory = new FixtureFactory(app)
await factory.createAllDelegationTypes()
})

it('should not duplicate delegations on reindex', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ describe('DelegationsController', () => {

await factory.createClient(testcase.client)
await factory.createDomain(testcase.domain)
await factory.createAllDelegationTypes()

// create api scopes in db
await Promise.all(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import {
DelegationDirection,
PersonalRepresentativeDelegationType,
} from '@island.is/auth-api-lib'
import { AuthDelegationType } from '@island.is/shared/types'
import { createNationalId } from '@island.is/testing/fixtures'

import {
personalRepresentativeRightTypeCodeFinance,
scopes,
TestCase,
} from './delegations.controller-test-types'
import {
DelegationDirection,
PersonalRepresentativeDelegationType,
} from '@island.is/auth-api-lib'

const person1 = createNationalId('person')
const person2 = createNationalId('person')
Expand Down Expand Up @@ -185,7 +187,7 @@ export const validTestCases: Record<
},
{
toNationalId: person1,
type: personalRepresentativeRightTypeCodeFinance as PersonalRepresentativeDelegationType, // type that scope has no permission for
type: `${AuthDelegationType.PersonalRepresentative}:${personalRepresentativeRightTypeCodeFinance}` as PersonalRepresentativeDelegationType, // type that scope has no permission for
},
],
scopes: [scopes.representative], // has permission for postholf right type not finance
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getModelToken } from '@nestjs/sequelize'
import addDays from 'date-fns/addDays'
import request from 'supertest'
import { uuid } from 'uuidv4'
import addDays from 'date-fns/addDays'

import {
ApiScope,
Expand Down Expand Up @@ -465,6 +465,7 @@ describe('DelegationsController', () => {
name: 'custom',
description: 'custom',
providerId: AuthDelegationProvider.Custom,
actorDiscretionRequired: false,
})

await delegationScopesModel.create({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ const delegations: Record<string, DelegationRecordDTO[]> = {
toNationalId: userWithNoDelegations.nationalId,
subjectId: null, // test that 3rd party login is not used if subjectId is null
type: AuthDelegationType.ProcurationHolder,
actorDiscretionRequired: false,
},
],
[userWithDelegations2.nationalId]: [
Expand All @@ -174,6 +175,7 @@ const delegations: Record<string, DelegationRecordDTO[]> = {
toNationalId: userWithDelegations.nationalId,
subjectId: delegationSubjectId,
type: AuthDelegationType.ProcurationHolder,
actorDiscretionRequired: false,
},
],
[userWithSendToDelegationsFeatureFlagDisabled.nationalId]: [
Expand All @@ -182,6 +184,7 @@ const delegations: Record<string, DelegationRecordDTO[]> = {
toNationalId: userWithNoDelegations.nationalId,
subjectId: faker.datatype.uuid(),
type: AuthDelegationType.ProcurationHolder,
actorDiscretionRequired: false,
},
],
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use strict'

module.exports = {
async up(queryInterface, Sequelize) {
return Promise.all([
queryInterface.addColumn('delegation_type', 'actor_discretion_required', {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false,
}),
])
},

async down(queryInterface) {
return Promise.all([
queryInterface.removeColumn(
'delegation_type',
'actor_discretion_required',
),
])
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use strict'

module.exports = {
up: (queryInterface) => {
return Promise.all([
queryInterface.addConstraint('delegation_index', {
fields: ['type'],
type: 'foreign key',
name: 'FK_delegation_index_delegation_type',
references: {
table: 'delegation_type',
field: 'id',
},
}),
queryInterface.addConstraint('delegation_index', {
fields: ['provider'],
type: 'foreign key',
name: 'FK_delegation_index_delegation_provider',
references: {
table: 'delegation_provider',
field: 'id',
},
}),
])
},

down: (queryInterface) => {
return Promise.all([
queryInterface.removeConstraint(
'delegation_index',
'FK_delegation_index_delegation_type',
),
queryInterface.removeConstraint(
'delegation_index',
'FK_delegation_index_delegation_provider',
),
])
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module.exports = {
up(queryInterface) {
return queryInterface.sequelize.query(`
BEGIN;
UPDATE delegation_type
SET actor_discretion_required = true
WHERE id = 'LegalRepresentative';

COMMIT;
`)
},

down(queryInterface) {
return queryInterface.sequelize.query(`
BEGIN;
UPDATE delegation_type
SET actor_discretion_required = false
WHERE id = 'LegalRepresentative';

COMMIT;
`)
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { Op } from 'sequelize'
import * as kennitala from 'kennitala'

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 { AuditService } from '@island.is/nest/audit'
import {
AuthDelegationProvider,
AuthDelegationType,
Expand All @@ -29,6 +29,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,
Expand Down Expand Up @@ -377,6 +378,7 @@ export class DelegationsIndexService {
type: types,
validTo: { [Op.or]: [{ [Op.gte]: new Date() }, { [Op.is]: null }] },
},
include: [{ model: DelegationTypeModel }],
})
.then((d) => d.map((d) => d.toDTO()))
}
Expand Down Expand Up @@ -661,6 +663,7 @@ export class DelegationsIndexService {
customDelegationScopes: { [Op.contains]: [scope.name] },
validTo: { [Op.or]: [{ [Op.gte]: new Date() }, { [Op.is]: null }] },
},
include: [{ model: DelegationTypeModel }],
})
.then((d) => d.map((d) => d.toDTO()))
}
Expand Down Expand Up @@ -696,6 +699,7 @@ export class DelegationsIndexService {
provider: AuthDelegationProvider.PersonalRepresentativeRegistry,
validTo: { [Op.or]: [{ [Op.gte]: new Date() }, { [Op.is]: null }] },
},
include: [{ model: DelegationTypeModel }],
})
.then((d) => d.map((d) => d.toDTO()))
}
Expand All @@ -722,6 +726,7 @@ export class DelegationsIndexService {
provider: AuthDelegationProvider.CompanyRegistry,
validTo: { [Op.or]: [{ [Op.gte]: new Date() }, { [Op.is]: null }] },
},
include: [{ model: DelegationTypeModel }],
})
.then((d) => d.map((d) => d.toDTO()))
}
Expand Down Expand Up @@ -750,6 +755,7 @@ export class DelegationsIndexService {
provider: AuthDelegationProvider.NationalRegistry,
validTo: { [Op.or]: [{ [Op.gte]: new Date() }, { [Op.is]: null }] },
},
include: [{ model: DelegationTypeModel }],
})
.then((d) => d.map((d) => d.toDTO()))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'
import { IsDateString, IsNumber, IsOptional, IsString } from 'class-validator'
import {
IsBoolean,
IsDateString,
IsNumber,
IsOptional,
IsString,
} from 'class-validator'

import { PageInfoDto } from '@island.is/nest/pagination'
import {
Expand All @@ -24,6 +30,11 @@ export class DelegationRecordDTO {
@IsString()
@ApiProperty({ type: String })
type!: AuthDelegationType

@IsOptional()
@IsBoolean()
@ApiProperty({ type: Boolean, nullable: true })
actorDiscretionRequired?: boolean | null
}

export class PaginatedDelegationRecordDTO {
Expand Down
Loading
Loading