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): Adding legal representative #16161

Merged
merged 4 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions apps/services/auth/admin-api/infra/auth-admin-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ export const serviceSetup = (): ServiceBuilder<'services-auth-admin-api'> => {
prod: 'IS/GOV/5402696029/Skatturinn/ft-v1',
},
COMPANY_REGISTRY_REDIS_NODES: REDIS_NODE_CONFIG,
SYSLUMENN_HOST: {
dev: 'https://api.syslumenn.is/staging',
staging: 'https://api.syslumenn.is/staging',
prod: 'https://api.syslumenn.is',
},
SYSLUMENN_TIMEOUT: '3000',
})
.secrets({
CLIENT_SECRET_ENCRYPTION_KEY:
Expand All @@ -67,6 +73,8 @@ export const serviceSetup = (): ServiceBuilder<'services-auth-admin-api'> => {
'/k8s/services-auth/IDENTITY_SERVER_CLIENT_SECRET',
NATIONAL_REGISTRY_IDS_CLIENT_SECRET:
'/k8s/xroad/client/NATIONAL-REGISTRY/IDENTITYSERVER_SECRET',
SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME',
SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD',
})
.xroad(Base, Client, RskProcuring)
.ingress({
Expand Down
18 changes: 10 additions & 8 deletions apps/services/auth/admin-api/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import {
SequelizeConfigService,
} from '@island.is/auth-api-lib'
import { AuthModule } from '@island.is/auth-nest-tools'
import { RskRelationshipsClientConfig } from '@island.is/clients-rsk-relationships'
import { NationalRegistryClientConfig } from '@island.is/clients/national-registry-v2'
import { CompanyRegistryConfig } from '@island.is/clients/rsk/company-registry'
import { SyslumennClientConfig } from '@island.is/clients/syslumenn'
import { AuditModule } from '@island.is/nest/audit'
import { IdsClientConfig, XRoadConfig } from '@island.is/nest/config'
import { FeatureFlagConfig } from '@island.is/nest/feature-flags'
import { ProblemModule } from '@island.is/nest/problem'

import { environment } from '../environments'
Expand All @@ -21,16 +27,11 @@ import { ResourcesModule } from './modules/resources/resources.module'
import { TranslationModule } from './modules/translation/translation.module'
import { UsersModule } from './modules/users/users.module'
import { ClientsModule as ClientsV2Module } from './v2/clients/clients.module'
import { DelegationAdminModule } from './v2/delegations/delegation-admin.module'
import { ProvidersModule } from './v2/providers/providers.module'
import { ScopesModule } from './v2/scopes/scopes.module'
import { ClientSecretsModule } from './v2/secrets/client-secrets.module'
import { TenantsModule } from './v2/tenants/tenants.module'
import { ScopesModule } from './v2/scopes/scopes.module'
import { ProvidersModule } from './v2/providers/providers.module'
import { DelegationAdminModule } from './v2/delegations/delegation-admin.module'
import { RskRelationshipsClientConfig } from '@island.is/clients-rsk-relationships'
import { FeatureFlagConfig } from '@island.is/nest/feature-flags'
import { IdsClientConfig, XRoadConfig } from '@island.is/nest/config'
import { NationalRegistryClientConfig } from '@island.is/clients/national-registry-v2'
import { CompanyRegistryConfig } from '@island.is/clients/rsk/company-registry'

@Module({
imports: [
Expand Down Expand Up @@ -64,6 +65,7 @@ import { CompanyRegistryConfig } from '@island.is/clients/rsk/company-registry'
FeatureFlagConfig,
XRoadConfig,
IdsClientConfig,
SyslumennClientConfig,
],
envFilePath: ['.env', '.env.secret'],
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import {
AdminPatchClientDto,
Client,
clientBaseAttributes,
ClientDelegationType,
ClientGrantType,
defaultAcrValue,
RefreshTokenExpiration,
SequelizeConfigService,
SUPER_USER_DELEGATION_TYPES,
translateRefreshTokenExpiration,
} from '@island.is/auth-api-lib'
import { User } from '@island.is/auth-nest-tools'
Expand Down Expand Up @@ -50,6 +52,10 @@ const createTestClientData = async (app: TestApp, user: User) => {
AuthDelegationType.LegalGuardian,
AuthDelegationProvider.NationalRegistry,
],
[
AuthDelegationType.LegalRepresentative,
AuthDelegationProvider.DistrictCommissionersRegistry,
],
].map(async ([delegationType, provider]) =>
fixtureFactory.createDelegationType({
id: delegationType,
Expand Down Expand Up @@ -619,6 +625,7 @@ describe('MeClientsController with auth', () => {
AuthDelegationType.PersonalRepresentative,
AuthDelegationType.ProcurationHolder,
AuthDelegationType.LegalGuardian,
AuthDelegationType.LegalRepresentative,
],
}

Expand All @@ -635,6 +642,7 @@ describe('MeClientsController with auth', () => {
AuthDelegationType.PersonalRepresentative,
AuthDelegationType.ProcurationHolder,
AuthDelegationType.LegalGuardian,
AuthDelegationType.LegalRepresentative,
]),
)
})
Expand Down Expand Up @@ -985,6 +993,7 @@ describe('MeClientsController with auth', () => {
AuthDelegationType.LegalGuardian,
AuthDelegationType.PersonalRepresentative,
AuthDelegationType.ProcurationHolder,
AuthDelegationType.LegalRepresentative,
],
}

Expand All @@ -997,6 +1006,7 @@ describe('MeClientsController with auth', () => {
AuthDelegationType.LegalGuardian,
AuthDelegationType.PersonalRepresentative,
AuthDelegationType.ProcurationHolder,
AuthDelegationType.LegalRepresentative,
],
supportsCustomDelegation: true,
supportsLegalGuardians: true,
Expand Down Expand Up @@ -1025,6 +1035,7 @@ describe('MeClientsController with auth', () => {
AuthDelegationType.LegalGuardian,
AuthDelegationType.PersonalRepresentative,
AuthDelegationType.ProcurationHolder,
AuthDelegationType.LegalRepresentative,
],
supportsCustomDelegation: true,
supportsLegalGuardians: true,
Expand All @@ -1036,6 +1047,7 @@ describe('MeClientsController with auth', () => {
AuthDelegationType.LegalGuardian,
AuthDelegationType.PersonalRepresentative,
AuthDelegationType.ProcurationHolder,
AuthDelegationType.LegalRepresentative,
],
supportsCustomDelegation: true,
supportsLegalGuardians: true,
Expand All @@ -1049,6 +1061,7 @@ describe('MeClientsController with auth', () => {
AuthDelegationType.LegalGuardian,
AuthDelegationType.PersonalRepresentative,
AuthDelegationType.ProcurationHolder,
AuthDelegationType.LegalRepresentative,
],
}

Expand All @@ -1063,6 +1076,66 @@ describe('MeClientsController with auth', () => {
supportsProcuringHolders: false,
})
})

it.each`
action
${'added'}
${'removed'}
`(
'should not have $action super user delegation type as normal',
async ({ action }) => {
// Arrange
const app = await setupApp({
AppModule,
SequelizeConfigService,
user,
dbType: 'postgres',
})
const server = request(app.getHttpServer())
await createTestClientData(app, user)

// Act
const res = await Promise.all(
SUPER_USER_DELEGATION_TYPES.map((delegationType) =>
server
.patch(
`/v2/me/tenants/${tenantId}/clients/${encodeURIComponent(
clientId,
)}`,
)
.send({
[`${action}DelegationTypes`]: [delegationType],
}),
),
)

// Assert
res.forEach((r) => {
expect(r.status).toEqual(403)
expect(r.body).toEqual({
type: 'https://httpstatuses.org/403',
title: 'Forbidden',
status: 403,
detail:
'User does not have access to update admin controlled fields.',
})
})

// DB assert
const clientDelegationTypeModel = app.get(
getModelToken(ClientDelegationType),
)
const clientDelegationTypes = await clientDelegationTypeModel.findAll(
{
where: {
clientId,
},
},
)

expect(clientDelegationTypes.length).toEqual(0)
},
)
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
ApiScopeDelegationType,
AdminPatchScopeDto,
ApiScope,
SUPER_USER_DELEGATION_TYPES,
} from '@island.is/auth-api-lib'
import { FixtureFactory } from '@island.is/services/auth/testing'
import {
Expand Down Expand Up @@ -126,6 +127,10 @@ const createTestData = async ({
AuthDelegationType.LegalGuardian,
AuthDelegationProvider.NationalRegistry,
],
[
AuthDelegationType.LegalRepresentative,
AuthDelegationProvider.DistrictCommissionersRegistry,
],
].map(async ([delegationType, provider]) =>
fixtureFactory.createDelegationType({
id: delegationType,
Expand Down Expand Up @@ -373,6 +378,8 @@ interface PatchTestCase {
allowExplicitDelegationGrant?: boolean
grantToPersonalRepresentatives?: boolean
isAccessControlled?: boolean
addedDelegationTypes?: AuthDelegationType[]
removedDelegationTypes?: AuthDelegationType[]
}
expected: {
status: number
Expand Down Expand Up @@ -512,6 +519,44 @@ const patchTestCases: Record<string, PatchTestCase> = {
},
}

const expected403Response = {
status: 403,
body: {
title: 'Forbidden',
status: 403,
detail: 'User does not have access to update admin controlled fields',
type: 'https://httpstatuses.org/403',
},
}

SUPER_USER_DELEGATION_TYPES.map((delegationType) => {
const delegationTypeName = AuthDelegationType[delegationType]

patchTestCases[
`should return a forbidden exception when adding super user delegation type: ${delegationTypeName}`
] = {
user: currentUser,
tenantId: TENANT_ID,
scopeName: mockedPatchApiScope.name,
input: {
addedDelegationTypes: [delegationType],
},
expected: expected403Response,
}

patchTestCases[
`should return a forbidden exception when removing super user delegation type: ${delegationTypeName}`
] = {
user: currentUser,
tenantId: TENANT_ID,
scopeName: mockedPatchApiScope.name,
input: {
removedDelegationTypes: [delegationType],
},
expected: expected403Response,
}
})

describe('MeScopesController', () => {
describe('with auth', () => {
// GET: /v2/me/tenants/:tenantId/scopes
Expand Down Expand Up @@ -760,7 +805,7 @@ describe('MeScopesController', () => {
})
})

describe('PATCH: /v2/me/tenants/:tenantId/scopes/:scopeName', () => {
describe('PATCH: /v2/me/tenants/:tenantId/scopes/:scopeName as super user', () => {
let app: TestApp
let server: request.SuperTest<request.Test>
let apiScopeDelegationTypeModel: typeof ApiScopeDelegationType
Expand Down Expand Up @@ -830,6 +875,7 @@ describe('MeScopesController', () => {
AuthDelegationType.LegalGuardian,
AuthDelegationType.ProcurationHolder,
AuthDelegationType.PersonalRepresentative,
AuthDelegationType.LegalRepresentative,
],
},
expected: {
Expand All @@ -842,6 +888,7 @@ describe('MeScopesController', () => {
AuthDelegationType.LegalGuardian,
AuthDelegationType.ProcurationHolder,
AuthDelegationType.PersonalRepresentative,
AuthDelegationType.LegalRepresentative,
],
},
})
Expand All @@ -855,6 +902,7 @@ describe('MeScopesController', () => {
AuthDelegationType.LegalGuardian,
AuthDelegationType.ProcurationHolder,
AuthDelegationType.PersonalRepresentative,
AuthDelegationType.LegalRepresentative,
],
},
expected: {
Expand All @@ -867,6 +915,7 @@ describe('MeScopesController', () => {
AuthDelegationType.LegalGuardian,
AuthDelegationType.ProcurationHolder,
AuthDelegationType.PersonalRepresentative,
AuthDelegationType.LegalRepresentative,
],
},
})
Expand All @@ -878,6 +927,7 @@ describe('MeScopesController', () => {
AuthDelegationType.LegalGuardian,
AuthDelegationType.ProcurationHolder,
AuthDelegationType.PersonalRepresentative,
AuthDelegationType.LegalRepresentative,
],
},
expected: {
Expand Down Expand Up @@ -944,7 +994,7 @@ describe('MeScopesController', () => {
})
})

describe('POST: /v2/me/tenants/:tenantId/scopes', () => {
describe('POST: /v2/me/tenants/:tenantId/scopes as super user', () => {
let app: TestApp
let server: request.SuperTest<request.Test>
let apiScopeDelegationTypeModel: typeof ApiScopeDelegationType
Expand Down Expand Up @@ -1028,7 +1078,7 @@ describe('MeScopesController', () => {
})
})

describe('POST: /v2/me/tenants/:tenantId/scopes', () => {
describe('POST: /v2/me/tenants/:tenantId/scopes as normal user', () => {
let app: TestApp
let server: request.SuperTest<request.Test>
let apiScopeDelegationTypeModel: typeof ApiScopeDelegationType
Expand Down
10 changes: 9 additions & 1 deletion apps/services/auth/delegation-api/infra/delegation-api.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {
json,
ref,
service,
ServiceBuilder,
ref,
} from '../../../../../infra/src/dsl/dsl'
import { Base, Client, RskProcuring } from '../../../../../infra/src/dsl/xroad'

Expand Down Expand Up @@ -54,12 +54,20 @@ export const serviceSetup = (services: {
prod: 'IS/GOV/5402696029/Skatturinn/ft-v1',
},
COMPANY_REGISTRY_REDIS_NODES: REDIS_NODE_CONFIG,
SYSLUMENN_HOST: {
dev: 'https://api.syslumenn.is/staging',
staging: 'https://api.syslumenn.is/staging',
prod: 'https://api.syslumenn.is',
},
SYSLUMENN_TIMEOUT: '3000',
})
.secrets({
IDENTITY_SERVER_CLIENT_SECRET:
'/k8s/services-auth/IDENTITY_SERVER_CLIENT_SECRET',
NATIONAL_REGISTRY_IDS_CLIENT_SECRET:
'/k8s/xroad/client/NATIONAL-REGISTRY/IDENTITYSERVER_SECRET',
SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME',
SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD',
})
.xroad(Base, Client, RskProcuring)
.readiness('/health/check')
Expand Down
Loading
Loading