diff --git a/apps/services/auth/admin-api/infra/auth-admin-api.ts b/apps/services/auth/admin-api/infra/auth-admin-api.ts index fe1fe79e2480..8e9d21d11f06 100644 --- a/apps/services/auth/admin-api/infra/auth-admin-api.ts +++ b/apps/services/auth/admin-api/infra/auth-admin-api.ts @@ -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: @@ -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({ diff --git a/apps/services/auth/admin-api/src/app/app.module.ts b/apps/services/auth/admin-api/src/app/app.module.ts index b409548fb8a2..982ab803273f 100644 --- a/apps/services/auth/admin-api/src/app/app.module.ts +++ b/apps/services/auth/admin-api/src/app/app.module.ts @@ -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' @@ -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: [ @@ -64,6 +65,7 @@ import { CompanyRegistryConfig } from '@island.is/clients/rsk/company-registry' FeatureFlagConfig, XRoadConfig, IdsClientConfig, + SyslumennClientConfig, ], envFilePath: ['.env', '.env.secret'], }), diff --git a/apps/services/auth/delegation-api/infra/delegation-api.ts b/apps/services/auth/delegation-api/infra/delegation-api.ts index 1ceff205f6d3..60202a6822d8 100644 --- a/apps/services/auth/delegation-api/infra/delegation-api.ts +++ b/apps/services/auth/delegation-api/infra/delegation-api.ts @@ -1,8 +1,8 @@ import { json, + ref, service, ServiceBuilder, - ref, } from '../../../../../infra/src/dsl/dsl' import { Base, Client, RskProcuring } from '../../../../../infra/src/dsl/xroad' @@ -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') diff --git a/apps/services/auth/delegation-api/src/app/app.module.ts b/apps/services/auth/delegation-api/src/app/app.module.ts index 10b6209d5bce..b425506e3878 100644 --- a/apps/services/auth/delegation-api/src/app/app.module.ts +++ b/apps/services/auth/delegation-api/src/app/app.module.ts @@ -7,9 +7,10 @@ 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 { RskRelationshipsClientConfig } from '@island.is/clients-rsk-relationships' +import { SyslumennClientConfig } from '@island.is/clients/syslumenn' import { AuditModule } from '@island.is/nest/audit' import { ConfigModule, @@ -50,6 +51,7 @@ import { ScopesModule } from './scopes/scopes.module' CompanyRegistryConfig, XRoadConfig, DelegationApiUserSystemNotificationConfig, + SyslumennClientConfig, ], }), ], diff --git a/apps/services/auth/ids-api/infra/ids-api.ts b/apps/services/auth/ids-api/infra/ids-api.ts index efae3c5d56d9..e72a270d0d37 100644 --- a/apps/services/auth/ids-api/infra/ids-api.ts +++ b/apps/services/auth/ids-api/infra/ids-api.ts @@ -83,6 +83,12 @@ export const serviceSetup = (): ServiceBuilder<'services-auth-ids-api'> => { // Origin for Android prod app 'android:apk-key-hash:EsLTUu5kaY7XPmMl2f7nbq4amu-PNzdYu3FecNf90wU', ]), + 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: @@ -92,6 +98,8 @@ export const serviceSetup = (): ServiceBuilder<'services-auth-ids-api'> => { NOVA_PASSWORD: '/k8s/services-auth/NOVA_PASSWORD', NATIONAL_REGISTRY_B2C_CLIENT_SECRET: '/k8s/services-auth/NATIONAL_REGISTRY_B2C_CLIENT_SECRET', + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME', + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD', }) .xroad(Base, Client, RskProcuring, NationalRegistryAuthB2C) .readiness('/health/check') diff --git a/apps/services/auth/ids-api/src/app/app.module.ts b/apps/services/auth/ids-api/src/app/app.module.ts index 4f8a3e3d670f..f4aeb431e8c8 100644 --- a/apps/services/auth/ids-api/src/app/app.module.ts +++ b/apps/services/auth/ids-api/src/app/app.module.ts @@ -11,6 +11,7 @@ import { RskRelationshipsClientConfig } from '@island.is/clients-rsk-relationshi import { NationalRegistryClientConfig } from '@island.is/clients/national-registry-v2' import { NationalRegistryV3ClientConfig } from '@island.is/clients/national-registry-v3' import { CompanyRegistryConfig } from '@island.is/clients/rsk/company-registry' +import { SyslumennClientConfig } from '@island.is/clients/syslumenn' import { UserProfileClientConfig } from '@island.is/clients/user-profile' import { AuditModule } from '@island.is/nest/audit' import { @@ -28,12 +29,12 @@ import { DelegationsModule } from './delegations/delegations.module' import { GrantsModule } from './grants/grants.module' import { LoginRestrictionsModule } from './login-restrictions/login-restrictions.module' import { NotificationsModule } from './notifications/notifications.module' +import { PasskeysModule } from './passkeys/passkeys.module' import { PermissionsModule } from './permissions/permissions.module' import { ResourcesModule } from './resources/resources.module' import { TranslationModule } from './translation/translation.module' import { UserProfileModule } from './user-profile/user-profile.module' import { UsersModule } from './users/users.module' -import { PasskeysModule } from './passkeys/passkeys.module' @Module({ imports: [ @@ -68,6 +69,7 @@ import { PasskeysModule } from './passkeys/passkeys.module' PasskeysCoreConfig, NationalRegistryV3ClientConfig, smsModuleConfig, + SyslumennClientConfig, ], }), ], diff --git a/apps/services/auth/ids-api/src/app/delegations/delegation-verification-result.dto.ts b/apps/services/auth/ids-api/src/app/delegations/delegation-verification-result.dto.ts new file mode 100644 index 000000000000..6f99d970922f --- /dev/null +++ b/apps/services/auth/ids-api/src/app/delegations/delegation-verification-result.dto.ts @@ -0,0 +1,8 @@ +import { ApiProperty } from '@nestjs/swagger' +import { IsBoolean } from 'class-validator' + +export class DelegationVerificationResult { + @IsBoolean() + @ApiProperty() + verified!: boolean +} diff --git a/apps/services/auth/ids-api/src/app/delegations/delegation-verification.dto.ts b/apps/services/auth/ids-api/src/app/delegations/delegation-verification.dto.ts new file mode 100644 index 000000000000..aa799809529d --- /dev/null +++ b/apps/services/auth/ids-api/src/app/delegations/delegation-verification.dto.ts @@ -0,0 +1,19 @@ +import { ApiProperty } from '@nestjs/swagger' +import { IsArray, IsEnum, IsString } from 'class-validator' + +import { AuthDelegationType } from '@island.is/shared/types' + +export class DelegationVerification { + @IsString() + @ApiProperty() + fromNationalId!: string + + @IsArray() + @IsEnum(AuthDelegationType, { each: true }) + @ApiProperty({ + enum: AuthDelegationType, + enumName: 'AuthDelegationType', + isArray: true, + }) + delegationTypes!: AuthDelegationType[] +} diff --git a/apps/services/auth/ids-api/src/app/delegations/delegations.controller.ts b/apps/services/auth/ids-api/src/app/delegations/delegations.controller.ts index df91500afe6e..8310d931d823 100644 --- a/apps/services/auth/ids-api/src/app/delegations/delegations.controller.ts +++ b/apps/services/auth/ids-api/src/app/delegations/delegations.controller.ts @@ -1,8 +1,10 @@ import { + Body, Controller, Get, Inject, ParseArrayPipe, + Post, Query, UseGuards, Version, @@ -25,11 +27,14 @@ import { ScopesGuard, } from '@island.is/auth-nest-tools' import { LOGGER_PROVIDER } from '@island.is/logging' +import { Documentation } from '@island.is/nest/swagger' import { AuthDelegationType } from '@island.is/shared/types' +import { DelegationVerificationResult } from './delegation-verification-result.dto' +import { DelegationVerification } from './delegation-verification.dto' + import type { Logger } from '@island.is/logging' import type { User } from '@island.is/auth-nest-tools' - @UseGuards(IdsUserGuard, ScopesGuard) @ApiTags('delegations') @Controller({ @@ -110,4 +115,26 @@ export class DelegationsController { delegationType, ) } + + @Scopes('@identityserver.api/authentication') + @Post('verify') + @Documentation({ + description: 'Verifies a delegation at the source.', + response: { status: 200, type: DelegationVerificationResult }, + }) + @ApiOkResponse({ type: DelegationVerificationResult }) + async verify( + @CurrentUser() user: User, + @Body() + request: DelegationVerification, + ): Promise { + const verified = + await this.delegationsIncomingService.verifyDelegationAtProvider( + user, + request.fromNationalId, + request.delegationTypes, + ) + + return { verified } + } } diff --git a/apps/services/auth/ids-api/src/app/delegations/test/delegations-filters.spec.ts b/apps/services/auth/ids-api/src/app/delegations/test/delegations-filters.spec.ts index c6032e1def00..526bf4262a4a 100644 --- a/apps/services/auth/ids-api/src/app/delegations/test/delegations-filters.spec.ts +++ b/apps/services/auth/ids-api/src/app/delegations/test/delegations-filters.spec.ts @@ -15,7 +15,10 @@ import { import { createNationalRegistryUser } from '@island.is/testing/fixtures' import { TestApp, truncate } from '@island.is/testing/nest' -import { setupWithAuth } from '../../../../test/setup' +import { + nonExistingLegalRepresentativeNationalId, + setupWithAuth, +} from '../../../../test/setup' import { testCases } from './delegations-filters-test-cases' import { user } from './delegations-filters-types' @@ -128,4 +131,58 @@ describe('DelegationsController', () => { }) }, ) + + describe('verify', () => { + const testCase = testCases['legalRepresentative1'] + testCase.user = user + const path = '/v1/delegations/verify' + + beforeAll(async () => { + await truncate(sequelize) + + await Promise.all( + testCase.domains.map((domain) => factory.createDomain(domain)), + ) + + await factory.createClient(testCase.client) + + await Promise.all( + testCase.clientAllowedScopes.map((scope) => + factory.createClientAllowedScope(scope), + ), + ) + + await Promise.all( + testCase.apiScopes.map((scope) => factory.createApiScope(scope)), + ) + + await factory.createDelegationIndexRecord({ + fromNationalId: nonExistingLegalRepresentativeNationalId, + toNationalId: testCase.user.nationalId, + type: AuthDelegationType.LegalRepresentative, + provider: AuthDelegationProvider.DistrictCommissionersRegistry, + }) + }) + + let res: request.Response + it(`POST ${path} returns verified response`, async () => { + res = await server.post(path).send({ + fromNationalId: testCase.fromLegalRepresentative[0], + delegationTypes: [AuthDelegationType.LegalRepresentative], + }) + + expect(res.status).toEqual(200) + expect(res.body.verified).toEqual(true) + }) + + it(`POST ${path} returns non-verified response`, async () => { + res = await server.post(path).send({ + fromNationalId: nonExistingLegalRepresentativeNationalId, + delegationTypes: [AuthDelegationType.LegalRepresentative], + }) + + expect(res.status).toEqual(200) + expect(res.body.verified).toEqual(false) + }) + }) }) diff --git a/apps/services/auth/ids-api/src/app/delegations/test/delegations-scopes.spec.ts b/apps/services/auth/ids-api/src/app/delegations/test/delegations-scopes.spec.ts index 31915631e076..61367667d5c2 100644 --- a/apps/services/auth/ids-api/src/app/delegations/test/delegations-scopes.spec.ts +++ b/apps/services/auth/ids-api/src/app/delegations/test/delegations-scopes.spec.ts @@ -22,12 +22,14 @@ const legalGuardianScopes = ['lg1', 'lg2'] const procurationHolderScopes = ['ph1', 'ph2'] const customScopes1 = ['cu1', 'cu2'] const customScopes2 = ['cu3', 'cu4'] +const legalRepresentativeScopes = ['lr1', 'lr2'] const apiScopes = [ ...legalGuardianScopes, ...procurationHolderScopes, ...customScopes1, ...customScopes2, + ...legalRepresentativeScopes, ] const fromCustom = [ @@ -48,6 +50,9 @@ const supportedDelegationTypes = (scopeName: string): AuthDelegationType[] => { if (customScopes1.includes(scopeName) || customScopes2.includes(scopeName)) { result.push(AuthDelegationType.Custom) } + if (legalRepresentativeScopes.includes(scopeName)) { + result.push(AuthDelegationType.LegalRepresentative) + } return result } @@ -98,6 +103,11 @@ const testCases: Record = { ], expected: [...legalGuardianScopes, ...identityResources], }, + '7': { + fromNationalId: createNationalId('person'), + delegationType: [AuthDelegationType.LegalRepresentative], + expected: [...legalRepresentativeScopes, ...identityResources], + }, } const user = createCurrentUser({ diff --git a/apps/services/auth/ids-api/test/setup.ts b/apps/services/auth/ids-api/test/setup.ts index c6b7ae7f9e7b..a04e722bfcc8 100644 --- a/apps/services/auth/ids-api/test/setup.ts +++ b/apps/services/auth/ids-api/test/setup.ts @@ -12,6 +12,7 @@ import { RskRelationshipsClient } from '@island.is/clients-rsk-relationships' import { NationalRegistryClientService } from '@island.is/clients/national-registry-v2' import { NationalRegistryV3ClientService } from '@island.is/clients/national-registry-v3' import { CompanyRegistryClientService } from '@island.is/clients/rsk/company-registry' +import { SyslumennService } from '@island.is/clients/syslumenn' import { V2MeApi } from '@island.is/clients/user-profile' import { FeatureFlagService, Features } from '@island.is/nest/feature-flags' import { @@ -21,6 +22,7 @@ import { } from '@island.is/services/auth/testing' import { createCurrentUser, + createNationalId, createUniqueWords, } from '@island.is/testing/fixtures' import { @@ -67,6 +69,8 @@ export const defaultScopes: Scopes = { }, } +export const nonExistingLegalRepresentativeNationalId = createNationalId() + class MockNationalRegistryClientService implements Partial { @@ -85,6 +89,13 @@ class MockUserProfile { meUserProfileControllerFindUserProfile = jest.fn().mockResolvedValue({}) } +class MockSyslumennService { + checkIfDelegationExists = jest.fn( + (_toNationalId: string, fromNationalId: string) => + fromNationalId !== nonExistingLegalRepresentativeNationalId, + ) +} + interface SetupOptions { user: User scopes?: Scopes @@ -125,6 +136,8 @@ export const setupWithAuth = async ({ .useValue({ getIndividualRelationships: jest.fn().mockResolvedValue(null), }) + .overrideProvider(SyslumennService) + .useClass(MockSyslumennService) .overrideProvider(FeatureFlagService) .useValue({ getValue: (feature: Features) => diff --git a/apps/services/auth/personal-representative/infra/personal-representative.ts b/apps/services/auth/personal-representative/infra/personal-representative.ts index 9a54b8c4206b..bb3c79004506 100644 --- a/apps/services/auth/personal-representative/infra/personal-representative.ts +++ b/apps/services/auth/personal-representative/infra/personal-representative.ts @@ -42,10 +42,18 @@ export const serviceSetup = 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', + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME', + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD', }) .xroad(Base, Client, RskProcuring) .ingress({ diff --git a/apps/services/auth/personal-representative/src/app/app.module.ts b/apps/services/auth/personal-representative/src/app/app.module.ts index 14a44d76dc13..74d0e3f0c759 100644 --- a/apps/services/auth/personal-representative/src/app/app.module.ts +++ b/apps/services/auth/personal-representative/src/app/app.module.ts @@ -1,26 +1,29 @@ -import { RightTypesModule } from './modules/rightTypes/rightTypes.module' -import { PersonalRepresentativesModule } from './modules/personalRepresentatives/personalRepresentatives.module' -import { PersonalRepresentativeTypesModule } from './modules/personalRepresentativeTypes/personalRepresentativeTypes.module' -import { AccessLogsModule } from './modules/accessLogs/accessLogs.module' +import { Module } from '@nestjs/common' +import { SequelizeModule } from '@nestjs/sequelize' + import { DelegationConfig, SequelizeConfigService, } from '@island.is/auth-api-lib' -import { Module } from '@nestjs/common' -import { SequelizeModule } from '@nestjs/sequelize' -import { environment } from '../environments' -import { AuditModule } from '@island.is/nest/audit' 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 { ConfigModule, 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' -import { RskRelationshipsClientConfig } from '@island.is/clients-rsk-relationships' import { FeatureFlagConfig } from '@island.is/nest/feature-flags' +import { environment } from '../environments' +import { AccessLogsModule } from './modules/accessLogs/accessLogs.module' +import { PersonalRepresentativesModule } from './modules/personalRepresentatives/personalRepresentatives.module' +import { PersonalRepresentativeTypesModule } from './modules/personalRepresentativeTypes/personalRepresentativeTypes.module' +import { RightTypesModule } from './modules/rightTypes/rightTypes.module' + @Module({ imports: [ AuditModule.forRoot(environment.audit), @@ -38,6 +41,7 @@ import { FeatureFlagConfig } from '@island.is/nest/feature-flags' CompanyRegistryConfig, XRoadConfig, FeatureFlagConfig, + SyslumennClientConfig, ], }), RightTypesModule, diff --git a/apps/services/auth/public-api/infra/auth-public-api.ts b/apps/services/auth/public-api/infra/auth-public-api.ts index 68c82c383cf0..28e81a88467a 100644 --- a/apps/services/auth/public-api/infra/auth-public-api.ts +++ b/apps/services/auth/public-api/infra/auth-public-api.ts @@ -1,5 +1,4 @@ -import { service, ServiceBuilder } from '../../../../../infra/src/dsl/dsl' -import { json } from '../../../../../infra/src/dsl/dsl' +import { json, service, ServiceBuilder } from '../../../../../infra/src/dsl/dsl' import { Base, Client, RskProcuring } from '../../../../../infra/src/dsl/xroad' const REDIS_NODE_CONFIG = { @@ -64,12 +63,20 @@ export const serviceSetup = (): ServiceBuilder<'services-auth-public-api'> => { // Origin for Android prod app 'android:apk-key-hash:EsLTUu5kaY7XPmMl2f7nbq4amu-PNzdYu3FecNf90wU', ]), + 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) .ingress({ diff --git a/apps/services/auth/public-api/src/app/app.module.ts b/apps/services/auth/public-api/src/app/app.module.ts index 299a9219a419..a6863c79a866 100644 --- a/apps/services/auth/public-api/src/app/app.module.ts +++ b/apps/services/auth/public-api/src/app/app.module.ts @@ -2,11 +2,15 @@ import { Module } from '@nestjs/common' import { SequelizeModule } from '@nestjs/sequelize' import { - SequelizeConfigService, DelegationConfig, PasskeysCoreConfig, + 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 { ConfigModule, @@ -15,9 +19,6 @@ import { } from '@island.is/nest/config' import { FeatureFlagConfig } from '@island.is/nest/feature-flags' import { ProblemModule } from '@island.is/nest/problem' -import { NationalRegistryClientConfig } from '@island.is/clients/national-registry-v2' -import { CompanyRegistryConfig } from '@island.is/clients/rsk/company-registry' -import { RskRelationshipsClientConfig } from '@island.is/clients-rsk-relationships' import { environment } from '../environments' import { DelegationsModule } from './modules/delegations/delegations.module' @@ -44,6 +45,7 @@ import { PasskeysModule } from './modules/passkeys/passkeys.module' CompanyRegistryConfig, XRoadConfig, PasskeysCoreConfig, + SyslumennClientConfig, ], }), ], diff --git a/charts/identity-server/values.dev.yaml b/charts/identity-server/values.dev.yaml index 6795fd24a227..d654243b8f1c 100644 --- a/charts/identity-server/values.dev.yaml +++ b/charts/identity-server/values.dev.yaml @@ -225,6 +225,8 @@ services-auth-admin-api: LOG_LEVEL: 'info' NODE_OPTIONS: '--max-old-space-size=691 -r dd-trace/init' SERVERSIDE_FEATURES_ON: '' + SYSLUMENN_HOST: 'https://api.syslumenn.is/staging' + SYSLUMENN_TIMEOUT: '3000' XROAD_BASE_PATH: 'http://securityserver.dev01.devland.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.dev01.devland.is/r1/IS-DEV' XROAD_CLIENT_ID: 'IS-DEV/GOV/10000/island-is-client' @@ -291,6 +293,8 @@ services-auth-admin-api: DB_PASS: '/k8s/servicesauth/DB_PASSWORD' IDENTITY_SERVER_CLIENT_SECRET: '/k8s/services-auth/IDENTITY_SERVER_CLIENT_SECRET' NATIONAL_REGISTRY_IDS_CLIENT_SECRET: '/k8s/xroad/client/NATIONAL-REGISTRY/IDENTITYSERVER_SECRET' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false @@ -308,6 +312,8 @@ services-auth-delegation-api: LOG_LEVEL: 'info' NODE_OPTIONS: '--max-old-space-size=460 -r dd-trace/init' SERVERSIDE_FEATURES_ON: '' + SYSLUMENN_HOST: 'https://api.syslumenn.is/staging' + SYSLUMENN_TIMEOUT: '3000' USER_NOTIFICATION_API_URL: 'http://web-user-notification.user-notification.svc.cluster.local' XROAD_BASE_PATH: 'http://securityserver.dev01.devland.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.dev01.devland.is/r1/IS-DEV' @@ -374,6 +380,8 @@ services-auth-delegation-api: DB_PASS: '/k8s/servicesauth/DB_PASSWORD' IDENTITY_SERVER_CLIENT_SECRET: '/k8s/services-auth/IDENTITY_SERVER_CLIENT_SECRET' NATIONAL_REGISTRY_IDS_CLIENT_SECRET: '/k8s/xroad/client/NATIONAL-REGISTRY/IDENTITYSERVER_SECRET' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false @@ -404,6 +412,8 @@ services-auth-ids-api: PUBLIC_URL: 'https://identity-server.dev01.devland.is/api' REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' SERVERSIDE_FEATURES_ON: '' + SYSLUMENN_HOST: 'https://api.syslumenn.is/staging' + SYSLUMENN_TIMEOUT: '3000' USER_PROFILE_CLIENT_SCOPE: '["@island.is/user-profile:read"]' USER_PROFILE_CLIENT_URL: 'http://web-service-portal-api.service-portal.svc.cluster.local' XROAD_BASE_PATH: 'http://securityserver.dev01.devland.is' @@ -498,6 +508,8 @@ services-auth-ids-api: NOVA_PASSWORD: '/k8s/services-auth/NOVA_PASSWORD' NOVA_URL: '/k8s/services-auth/NOVA_URL' NOVA_USERNAME: '/k8s/services-auth/NOVA_USERNAME' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false @@ -574,6 +586,8 @@ services-auth-personal-representative: LOG_LEVEL: 'info' NODE_OPTIONS: '--max-old-space-size=460 -r dd-trace/init' SERVERSIDE_FEATURES_ON: '' + SYSLUMENN_HOST: 'https://api.syslumenn.is/staging' + SYSLUMENN_TIMEOUT: '3000' XROAD_BASE_PATH: 'http://securityserver.dev01.devland.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.dev01.devland.is/r1/IS-DEV' XROAD_CLIENT_ID: 'IS-DEV/GOV/10000/island-is-client' @@ -642,6 +656,8 @@ services-auth-personal-representative: CONFIGCAT_SDK_KEY: '/k8s/configcat/CONFIGCAT_SDK_KEY' DB_PASS: '/k8s/servicesauth/DB_PASSWORD' IDENTITY_SERVER_CLIENT_SECRET: '/k8s/services-auth/IDENTITY_SERVER_CLIENT_SECRET' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false @@ -735,6 +751,8 @@ services-auth-public-api: PUBLIC_URL: 'https://identity-server.dev01.devland.is/api' REDIS_NODES: '["clustercfg.general-redis-cluster-group.5fzau3.euw1.cache.amazonaws.com:6379"]' SERVERSIDE_FEATURES_ON: '' + SYSLUMENN_HOST: 'https://api.syslumenn.is/staging' + SYSLUMENN_TIMEOUT: '3000' XROAD_BASE_PATH: 'http://securityserver.dev01.devland.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.dev01.devland.is/r1/IS-DEV' XROAD_CLIENT_ID: 'IS-DEV/GOV/10000/island-is-client' @@ -805,6 +823,8 @@ services-auth-public-api: DB_PASS: '/k8s/servicesauth/DB_PASSWORD' IDENTITY_SERVER_CLIENT_SECRET: '/k8s/services-auth/IDENTITY_SERVER_CLIENT_SECRET' NATIONAL_REGISTRY_IDS_CLIENT_SECRET: '/k8s/xroad/client/NATIONAL-REGISTRY/IDENTITYSERVER_SECRET' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false diff --git a/charts/identity-server/values.prod.yaml b/charts/identity-server/values.prod.yaml index 96bafb5febeb..1e365eced0e1 100644 --- a/charts/identity-server/values.prod.yaml +++ b/charts/identity-server/values.prod.yaml @@ -222,6 +222,8 @@ services-auth-admin-api: LOG_LEVEL: 'info' NODE_OPTIONS: '--max-old-space-size=691 -r dd-trace/init' SERVERSIDE_FEATURES_ON: 'driving-license-use-v1-endpoint-for-v2-comms' + SYSLUMENN_HOST: 'https://api.syslumenn.is' + SYSLUMENN_TIMEOUT: '3000' XROAD_BASE_PATH: 'http://securityserver.island.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.island.is/r1/IS' XROAD_CLIENT_ID: 'IS/GOV/5501692829/island-is-client' @@ -288,6 +290,8 @@ services-auth-admin-api: DB_PASS: '/k8s/servicesauth/DB_PASSWORD' IDENTITY_SERVER_CLIENT_SECRET: '/k8s/services-auth/IDENTITY_SERVER_CLIENT_SECRET' NATIONAL_REGISTRY_IDS_CLIENT_SECRET: '/k8s/xroad/client/NATIONAL-REGISTRY/IDENTITYSERVER_SECRET' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false @@ -305,6 +309,8 @@ services-auth-delegation-api: LOG_LEVEL: 'info' NODE_OPTIONS: '--max-old-space-size=460 -r dd-trace/init' SERVERSIDE_FEATURES_ON: 'driving-license-use-v1-endpoint-for-v2-comms' + SYSLUMENN_HOST: 'https://api.syslumenn.is' + SYSLUMENN_TIMEOUT: '3000' USER_NOTIFICATION_API_URL: 'https://user-notification.internal.island.is' XROAD_BASE_PATH: 'http://securityserver.island.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.island.is/r1/IS' @@ -371,6 +377,8 @@ services-auth-delegation-api: DB_PASS: '/k8s/servicesauth/DB_PASSWORD' IDENTITY_SERVER_CLIENT_SECRET: '/k8s/services-auth/IDENTITY_SERVER_CLIENT_SECRET' NATIONAL_REGISTRY_IDS_CLIENT_SECRET: '/k8s/xroad/client/NATIONAL-REGISTRY/IDENTITYSERVER_SECRET' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false @@ -401,6 +409,8 @@ services-auth-ids-api: PUBLIC_URL: 'https://innskra.island.is/api' REDIS_NODES: '["clustercfg.general-redis-cluster-group.dnugi2.euw1.cache.amazonaws.com:6379"]' SERVERSIDE_FEATURES_ON: 'driving-license-use-v1-endpoint-for-v2-comms' + SYSLUMENN_HOST: 'https://api.syslumenn.is' + SYSLUMENN_TIMEOUT: '3000' USER_PROFILE_CLIENT_SCOPE: '["@island.is/user-profile:read"]' USER_PROFILE_CLIENT_URL: 'https://service-portal-api.internal.island.is' XROAD_BASE_PATH: 'http://securityserver.island.is' @@ -495,6 +505,8 @@ services-auth-ids-api: NOVA_PASSWORD: '/k8s/services-auth/NOVA_PASSWORD' NOVA_URL: '/k8s/services-auth/NOVA_URL' NOVA_USERNAME: '/k8s/services-auth/NOVA_USERNAME' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false @@ -571,6 +583,8 @@ services-auth-personal-representative: LOG_LEVEL: 'info' NODE_OPTIONS: '--max-old-space-size=460 -r dd-trace/init' SERVERSIDE_FEATURES_ON: 'driving-license-use-v1-endpoint-for-v2-comms' + SYSLUMENN_HOST: 'https://api.syslumenn.is' + SYSLUMENN_TIMEOUT: '3000' XROAD_BASE_PATH: 'http://securityserver.island.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.island.is/r1/IS' XROAD_CLIENT_ID: 'IS/GOV/5501692829/island-is-client' @@ -631,6 +645,8 @@ services-auth-personal-representative: CONFIGCAT_SDK_KEY: '/k8s/configcat/CONFIGCAT_SDK_KEY' DB_PASS: '/k8s/servicesauth/DB_PASSWORD' IDENTITY_SERVER_CLIENT_SECRET: '/k8s/services-auth/IDENTITY_SERVER_CLIENT_SECRET' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false @@ -724,6 +740,8 @@ services-auth-public-api: PUBLIC_URL: 'https://innskra.island.is/api' REDIS_NODES: '["clustercfg.general-redis-cluster-group.dnugi2.euw1.cache.amazonaws.com:6379"]' SERVERSIDE_FEATURES_ON: 'driving-license-use-v1-endpoint-for-v2-comms' + SYSLUMENN_HOST: 'https://api.syslumenn.is' + SYSLUMENN_TIMEOUT: '3000' XROAD_BASE_PATH: 'http://securityserver.island.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.island.is/r1/IS' XROAD_CLIENT_ID: 'IS/GOV/5501692829/island-is-client' @@ -794,6 +812,8 @@ services-auth-public-api: DB_PASS: '/k8s/servicesauth/DB_PASSWORD' IDENTITY_SERVER_CLIENT_SECRET: '/k8s/services-auth/IDENTITY_SERVER_CLIENT_SECRET' NATIONAL_REGISTRY_IDS_CLIENT_SECRET: '/k8s/xroad/client/NATIONAL-REGISTRY/IDENTITYSERVER_SECRET' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false diff --git a/charts/identity-server/values.staging.yaml b/charts/identity-server/values.staging.yaml index 7c5eeccdd189..3c2233c431e0 100644 --- a/charts/identity-server/values.staging.yaml +++ b/charts/identity-server/values.staging.yaml @@ -225,6 +225,8 @@ services-auth-admin-api: LOG_LEVEL: 'info' NODE_OPTIONS: '--max-old-space-size=691 -r dd-trace/init' SERVERSIDE_FEATURES_ON: '' + SYSLUMENN_HOST: 'https://api.syslumenn.is/staging' + SYSLUMENN_TIMEOUT: '3000' XROAD_BASE_PATH: 'http://securityserver.staging01.devland.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.staging01.devland.is/r1/IS-TEST' XROAD_CLIENT_ID: 'IS-TEST/GOV/5501692829/island-is-client' @@ -291,6 +293,8 @@ services-auth-admin-api: DB_PASS: '/k8s/servicesauth/DB_PASSWORD' IDENTITY_SERVER_CLIENT_SECRET: '/k8s/services-auth/IDENTITY_SERVER_CLIENT_SECRET' NATIONAL_REGISTRY_IDS_CLIENT_SECRET: '/k8s/xroad/client/NATIONAL-REGISTRY/IDENTITYSERVER_SECRET' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false @@ -308,6 +312,8 @@ services-auth-delegation-api: LOG_LEVEL: 'info' NODE_OPTIONS: '--max-old-space-size=460 -r dd-trace/init' SERVERSIDE_FEATURES_ON: '' + SYSLUMENN_HOST: 'https://api.syslumenn.is/staging' + SYSLUMENN_TIMEOUT: '3000' USER_NOTIFICATION_API_URL: 'http://web-user-notification.user-notification.svc.cluster.local' XROAD_BASE_PATH: 'http://securityserver.staging01.devland.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.staging01.devland.is/r1/IS-TEST' @@ -374,6 +380,8 @@ services-auth-delegation-api: DB_PASS: '/k8s/servicesauth/DB_PASSWORD' IDENTITY_SERVER_CLIENT_SECRET: '/k8s/services-auth/IDENTITY_SERVER_CLIENT_SECRET' NATIONAL_REGISTRY_IDS_CLIENT_SECRET: '/k8s/xroad/client/NATIONAL-REGISTRY/IDENTITYSERVER_SECRET' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false @@ -404,6 +412,8 @@ services-auth-ids-api: PUBLIC_URL: 'https://identity-server.staging01.devland.is/api' REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' SERVERSIDE_FEATURES_ON: '' + SYSLUMENN_HOST: 'https://api.syslumenn.is/staging' + SYSLUMENN_TIMEOUT: '3000' USER_PROFILE_CLIENT_SCOPE: '["@island.is/user-profile:read"]' USER_PROFILE_CLIENT_URL: 'http://web-service-portal-api.service-portal.svc.cluster.local' XROAD_BASE_PATH: 'http://securityserver.staging01.devland.is' @@ -498,6 +508,8 @@ services-auth-ids-api: NOVA_PASSWORD: '/k8s/services-auth/NOVA_PASSWORD' NOVA_URL: '/k8s/services-auth/NOVA_URL' NOVA_USERNAME: '/k8s/services-auth/NOVA_USERNAME' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false @@ -574,6 +586,8 @@ services-auth-personal-representative: LOG_LEVEL: 'info' NODE_OPTIONS: '--max-old-space-size=460 -r dd-trace/init' SERVERSIDE_FEATURES_ON: '' + SYSLUMENN_HOST: 'https://api.syslumenn.is/staging' + SYSLUMENN_TIMEOUT: '3000' XROAD_BASE_PATH: 'http://securityserver.staging01.devland.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.staging01.devland.is/r1/IS-TEST' XROAD_CLIENT_ID: 'IS-TEST/GOV/5501692829/island-is-client' @@ -634,6 +648,8 @@ services-auth-personal-representative: CONFIGCAT_SDK_KEY: '/k8s/configcat/CONFIGCAT_SDK_KEY' DB_PASS: '/k8s/servicesauth/DB_PASSWORD' IDENTITY_SERVER_CLIENT_SECRET: '/k8s/services-auth/IDENTITY_SERVER_CLIENT_SECRET' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false @@ -727,6 +743,8 @@ services-auth-public-api: PUBLIC_URL: 'https://identity-server.staging01.devland.is/api' REDIS_NODES: '["clustercfg.general-redis-cluster-group.ab9ckb.euw1.cache.amazonaws.com:6379"]' SERVERSIDE_FEATURES_ON: '' + SYSLUMENN_HOST: 'https://api.syslumenn.is/staging' + SYSLUMENN_TIMEOUT: '3000' XROAD_BASE_PATH: 'http://securityserver.staging01.devland.is' XROAD_BASE_PATH_WITH_ENV: 'http://securityserver.staging01.devland.is/r1/IS-TEST' XROAD_CLIENT_ID: 'IS-TEST/GOV/5501692829/island-is-client' @@ -797,6 +815,8 @@ services-auth-public-api: DB_PASS: '/k8s/servicesauth/DB_PASSWORD' IDENTITY_SERVER_CLIENT_SECRET: '/k8s/services-auth/IDENTITY_SERVER_CLIENT_SECRET' NATIONAL_REGISTRY_IDS_CLIENT_SECRET: '/k8s/xroad/client/NATIONAL-REGISTRY/IDENTITYSERVER_SECRET' + SYSLUMENN_PASSWORD: '/k8s/services-auth/SYSLUMENN_PASSWORD' + SYSLUMENN_USERNAME: '/k8s/services-auth/SYSLUMENN_USERNAME' securityContext: allowPrivilegeEscalation: false privileged: false 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 bb6f5a332112..94e89cc29204 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 @@ -6,6 +6,8 @@ import startOfDay from 'date-fns/startOfDay' import { Op, Transaction } from 'sequelize' import { uuid } from 'uuidv4' +import { SyslumennService } from '@island.is/clients/syslumenn' +import { logger } from '@island.is/logging' import { AuthDelegationProvider, AuthDelegationType, @@ -18,14 +20,14 @@ import { ApiScope } from '../resources/models/api-scope.model' import { IdentityResource } from '../resources/models/identity-resource.model' import { DelegationProviderService } from './delegation-provider.service' import { DelegationConfig } from './DelegationConfig' +import { DelegationsIndexService } from './delegations-index.service' import { UpdateDelegationScopeDTO } from './dto/delegation-scope.dto' +import { DelegationDelegationType } from './models/delegation-delegation-type.model' import { DelegationScope } from './models/delegation-scope.model' import { DelegationTypeModel } from './models/delegation-type.model' import { Delegation } from './models/delegation.model' import type { User } from '@island.is/auth-nest-tools' -import { DelegationDelegationType } from './models/delegation-delegation-type.model' - @Injectable() export class DelegationScopeService { constructor( @@ -40,6 +42,8 @@ export class DelegationScopeService { @Inject(DelegationConfig.KEY) private delegationConfig: ConfigType, private delegationProviderService: DelegationProviderService, + private readonly syslumennService: SyslumennService, + private readonly delegationsIndexService: DelegationsIndexService, ) {} async createOrUpdate( @@ -304,6 +308,55 @@ export class DelegationScopeService { return apiScopes.map((s) => s.name) } + private async findDistrictCommissionersRegistryScopesTo( + toNationalId: string, + fromNationalId: string, + ): Promise { + // if no valid delegation exists, return empty array + try { + const delegationFound = + await this.syslumennService.checkIfDelegationExists( + toNationalId, + fromNationalId, + ) + + if (!delegationFound) { + this.delegationsIndexService.removeDelegationRecord({ + fromNationalId, + toNationalId, + type: AuthDelegationType.LegalRepresentative, + provider: AuthDelegationProvider.DistrictCommissionersRegistry, + }) + return [] + } + } catch (error) { + logger.error( + `Failed checking if delegation exists at provider '${AuthDelegationProvider.DistrictCommissionersRegistry}'`, + ) + return [] + } + + // else return all enabled scopes for this provider and provided delegation types + const apiScopes = await this.apiScopeModel.findAll({ + attributes: ['name'], + where: { + enabled: true, + }, + include: [ + { + model: DelegationTypeModel, + required: true, + where: { + id: AuthDelegationType.LegalRepresentative, + provider: AuthDelegationProvider.DistrictCommissionersRegistry, + }, + }, + ], + }) + + return apiScopes.map((s) => s.name) + } + private async findAllAutomaticScopes(): Promise { const apiScopes = await this.apiScopeModel.findAll({ attributes: ['name'], @@ -372,6 +425,16 @@ export class DelegationScopeService { ) } + if ( + providers.includes(AuthDelegationProvider.DistrictCommissionersRegistry) + ) + scopePromises.push( + this.findDistrictCommissionersRegistryScopesTo( + user.nationalId, + fromNationalId, + ), + ) + const scopeSets = await Promise.all(scopePromises) let scopes = ([] as string[]).concat(...scopeSets) 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 30eb53b694c3..56355428a63e 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 @@ -1,4 +1,4 @@ -import { BadRequestException, Inject, Injectable } from '@nestjs/common' +import { BadRequestException, Injectable } from '@nestjs/common' import { InjectModel } from '@nestjs/sequelize' import { User } from '@island.is/auth-nest-tools' @@ -6,7 +6,8 @@ import { IndividualDto, NationalRegistryClientService, } from '@island.is/clients/national-registry-v2' -import { type Logger, LOGGER_PROVIDER } from '@island.is/logging' +import { SyslumennService } from '@island.is/clients/syslumenn' +import { logger } from '@island.is/logging' import { FeatureFlagService, Features } from '@island.is/nest/feature-flags' import { AuthDelegationProvider, @@ -53,8 +54,6 @@ interface FindAvailableInput { @Injectable() export class DelegationsIncomingService { constructor( - @Inject(LOGGER_PROVIDER) - protected readonly logger: Logger, @InjectModel(Client) private clientModel: typeof Client, @InjectModel(ClientAllowedScope) @@ -69,6 +68,7 @@ export class DelegationsIncomingService { private delegationProviderService: DelegationProviderService, private nationalRegistryClient: NationalRegistryClientService, private readonly featureFlagService: FeatureFlagService, + private readonly syslumennService: SyslumennService, ) {} async findAllValid( @@ -272,6 +272,45 @@ export class DelegationsIncomingService { return [...mergedDelegationMap.values()] } + async verifyDelegationAtProvider( + user: User, + fromNationalId: string, + delegationTypes: AuthDelegationType[], + ): Promise { + const providers = await this.delegationProviderService.findProviders( + delegationTypes, + ) + + if ( + providers.includes(AuthDelegationProvider.DistrictCommissionersRegistry) + ) { + try { + const delegationFound = + await this.syslumennService.checkIfDelegationExists( + user.nationalId, + fromNationalId, + ) + + if (delegationFound) { + return true + } else { + this.delegationsIndexService.removeDelegationRecord({ + fromNationalId, + toNationalId: user.nationalId, + type: AuthDelegationType.LegalRepresentative, + provider: AuthDelegationProvider.DistrictCommissionersRegistry, + }) + } + } catch (error) { + logger.error( + `Failed checking if delegation exists at provider '${AuthDelegationProvider.DistrictCommissionersRegistry}'`, + ) + } + } + + return false + } + private async getAvailableDistrictCommissionersRegistryDelegations( user: User, types: AuthDelegationType[], diff --git a/libs/auth-api-lib/src/lib/delegations/delegations.module.ts b/libs/auth-api-lib/src/lib/delegations/delegations.module.ts index c74aaca8a940..e5f79d1aab6c 100644 --- a/libs/auth-api-lib/src/lib/delegations/delegations.module.ts +++ b/libs/auth-api-lib/src/lib/delegations/delegations.module.ts @@ -1,40 +1,41 @@ import { Module } from '@nestjs/common' import { SequelizeModule } from '@nestjs/sequelize' -import { NationalRegistryClientModule } from '@island.is/clients/national-registry-v2' import { RskRelationshipsClientModule } from '@island.is/clients-rsk-relationships' +import { NationalRegistryClientModule } from '@island.is/clients/national-registry-v2' import { CompanyRegistryClientModule } from '@island.is/clients/rsk/company-registry' +import { SyslumennClientModule } from '@island.is/clients/syslumenn' import { FeatureFlagModule } from '@island.is/nest/feature-flags' -import { UserSystemNotificationModule } from '../user-notification' import { ClientAllowedScope } from '../clients/models/client-allowed-scope.model' import { Client } from '../clients/models/client.model' import { PersonalRepresentativeModule } from '../personal-representative/personal-representative.module' +import { ApiScopeDelegationType } from '../resources/models/api-scope-delegation-type.model' +import { ApiScopeUserAccess } from '../resources/models/api-scope-user-access.model' import { ApiScope } from '../resources/models/api-scope.model' import { IdentityResource } from '../resources/models/identity-resource.model' import { ResourcesModule } from '../resources/resources.module' +import { UserIdentitiesModule } from '../user-identities/user-identities.module' +import { UserSystemNotificationModule } from '../user-notification' +import { DelegationAdminCustomService } from './admin/delegation-admin-custom.service' +import { DelegationProviderService } from './delegation-provider.service' import { DelegationScopeService } from './delegation-scope.service' -import { DelegationsOutgoingService } from './delegations-outgoing.service' -import { DelegationsService } from './delegations.service' -import { DelegationsIncomingService } from './delegations-incoming.service' -import { DelegationScope } from './models/delegation-scope.model' -import { Delegation } from './models/delegation.model' -import { NamesService } from './names.service' -import { DelegationsIncomingWardService } from './delegations-incoming-ward.service' import { IncomingDelegationsCompanyService } from './delegations-incoming-company.service' import { DelegationsIncomingCustomService } from './delegations-incoming-custom.service' import { DelegationsIncomingRepresentativeService } from './delegations-incoming-representative.service' -import { ApiScopeUserAccess } from '../resources/models/api-scope-user-access.model' -import { DelegationIndex } from './models/delegation-index.model' -import { DelegationIndexMeta } from './models/delegation-index-meta.model' +import { DelegationsIncomingWardService } from './delegations-incoming-ward.service' +import { DelegationsIncomingService } from './delegations-incoming.service' import { DelegationsIndexService } from './delegations-index.service' -import { UserIdentitiesModule } from '../user-identities/user-identities.module' -import { DelegationTypeModel } from './models/delegation-type.model' -import { DelegationProviderModel } from './models/delegation-provider.model' -import { DelegationProviderService } from './delegation-provider.service' -import { ApiScopeDelegationType } from '../resources/models/api-scope-delegation-type.model' -import { DelegationAdminCustomService } from './admin/delegation-admin-custom.service' +import { DelegationsOutgoingService } from './delegations-outgoing.service' +import { DelegationsService } from './delegations.service' import { DelegationDelegationType } from './models/delegation-delegation-type.model' +import { DelegationIndexMeta } from './models/delegation-index-meta.model' +import { DelegationIndex } from './models/delegation-index.model' +import { DelegationProviderModel } from './models/delegation-provider.model' +import { DelegationScope } from './models/delegation-scope.model' +import { DelegationTypeModel } from './models/delegation-type.model' +import { Delegation } from './models/delegation.model' +import { NamesService } from './names.service' @Module({ imports: [ @@ -61,6 +62,7 @@ import { DelegationDelegationType } from './models/delegation-delegation-type.mo DelegationDelegationType, ]), UserSystemNotificationModule, + SyslumennClientModule, ], providers: [ DelegationsService, diff --git a/libs/clients/syslumenn/src/clientConfig.json b/libs/clients/syslumenn/src/clientConfig.json index 22ef380cfc45..3c6ac47e291a 100644 --- a/libs/clients/syslumenn/src/clientConfig.json +++ b/libs/clients/syslumenn/src/clientConfig.json @@ -472,6 +472,58 @@ ] } }, + "/api/Logradamadur/{audkenni}": { + "get": { + "tags": ["Syslumenn"], + "operationId": "Logradamadur_Get", + "parameters": [ + { + "type": "string", + "name": "audkenni", + "in": "path", + "required": true, + "x-nullable": false + }, + { + "type": "string", + "name": "kennitala", + "in": "query", + "x-nullable": true + } + ], + "responses": { + "200": { + "x-nullable": false, + "description": "Success", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/LogradamadurSvar" + } + } + }, + "500": { + "x-nullable": false, + "description": "Internal server error", + "schema": { + "$ref": "#/definitions/ProblemDetails" + } + }, + "401": { + "x-nullable": false, + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/ProblemDetails" + } + } + }, + "security": [ + { + "JWT Token": [] + } + ] + } + }, "/api/Logmannalisti": { "get": { "tags": ["Syslumenn"], @@ -862,6 +914,99 @@ ] } }, + "/v1/Heimagistingar/{audkenni}": { + "put": { + "tags": ["Syslumenn"], + "operationId": "Heimagistingar_Put", + "consumes": ["application/json", "text/json", "application/*+json"], + "parameters": [ + { + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/UppfaeraHeimagistingarModel" + }, + "x-nullable": false + }, + { + "type": "string", + "name": "audkenni", + "in": "path", + "required": true, + "x-nullable": false + } + ], + "responses": { + "200": { + "description": "" + }, + "401": { + "x-nullable": false, + "description": "", + "schema": { + "$ref": "#/definitions/ProblemDetails" + } + }, + "default": { + "x-nullable": false, + "description": "", + "schema": { + "$ref": "#/definitions/ProblemDetails" + } + } + }, + "security": [ + { + "JWT Token": [] + } + ] + }, + "get": { + "tags": ["Syslumenn"], + "operationId": "Heimagistingar_Get", + "parameters": [ + { + "type": "string", + "name": "audkenni", + "in": "path", + "required": true, + "x-nullable": false + } + ], + "responses": { + "200": { + "x-nullable": false, + "description": "", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/HeimagistingarModel" + } + } + }, + "401": { + "x-nullable": false, + "description": "", + "schema": { + "$ref": "#/definitions/ProblemDetails" + } + }, + "default": { + "x-nullable": false, + "description": "", + "schema": { + "$ref": "#/definitions/ProblemDetails" + } + } + }, + "security": [ + { + "JWT Token": [] + } + ] + } + }, "/v1/VirkarHeimagistingar/{audkenni}": { "get": { "tags": ["Syslumenn"], @@ -1154,13 +1299,7 @@ }, { "type": "string", - "name": "Hjonaefni1", - "in": "query", - "x-nullable": true - }, - { - "type": "string", - "name": "Hjonaefni2", + "name": "kennitala", "in": "query", "x-nullable": true } @@ -1356,7 +1495,7 @@ "type": "string", "name": "malsnumer", "in": "query", - "x-nullable": false + "x-nullable": true }, { "type": "string", @@ -3356,6 +3495,18 @@ } } }, + "LogradamadurSvar": { + "type": "object", + "properties": { + "kennitala": { + "type": "string" + }, + "gildirTil": { + "type": "string", + "format": "date-time" + } + } + }, "Logmenn": { "type": "object", "properties": { @@ -3672,6 +3823,62 @@ } } }, + "UppfaeraHeimagistingarModel": { + "type": "object", + "properties": { + "leyfi": { + "type": "array", + "items": { + "$ref": "#/definitions/UppfaeraHeimagistingDetail" + } + } + } + }, + "UppfaeraHeimagistingDetail": { + "type": "object", + "properties": { + "tegund": { + "type": "string" + }, + "numer": { + "type": "string" + }, + "markadsefniSlod": { + "type": "string" + }, + "fannst": { + "type": "boolean" + } + } + }, + "HeimagistingarModel": { + "type": "object", + "properties": { + "leyfi": { + "type": "array", + "items": { + "$ref": "#/definitions/HeimagistingDetail" + } + } + } + }, + "HeimagistingDetail": { + "type": "object", + "properties": { + "tegund": { + "type": "string" + }, + "numerLeyfist": { + "type": "string" + }, + "virkt": { + "type": "boolean" + }, + "utgefid": { + "type": "string" + } + } + }, "VirkarHeimagistingar": { "type": "object", "properties": { @@ -4012,6 +4219,12 @@ }, "skyring": { "type": "string" + }, + "simi": { + "type": "string" + }, + "netfang": { + "type": "string" } } }, diff --git a/libs/clients/syslumenn/src/lib/syslumennClient.service.ts b/libs/clients/syslumenn/src/lib/syslumennClient.service.ts index 92dcdcb6990c..d606178c5ff7 100644 --- a/libs/clients/syslumenn/src/lib/syslumennClient.service.ts +++ b/libs/clients/syslumenn/src/lib/syslumennClient.service.ts @@ -1,80 +1,83 @@ +import { Inject, Injectable } from '@nestjs/common' +import startOfDay from 'date-fns/startOfDay' + +import { AuthHeaderMiddleware } from '@island.is/auth-nest-tools' +import { createEnhancedFetch } from '@island.is/clients/middlewares' + +import { + Configuration, + InnsigludSkjol, + LogradamadurSvar, + Skilabod, + SvarSkeyti, + SyslumennApi, + VedbandayfirlitRegluverkGeneralSvar, + VedbondTegundAndlags, + VirkLeyfiGetRequest, +} from '../../gen/fetch' +import { SyslumennClientConfig } from './syslumennClient.config' import { AlcoholLicence, - SyslumennAuction, - Homestay, - PaginatedOperatingLicenses, - OperatingLicensesCSV, + AssetName, + AssetType, + Attachment, + Broker, CertificateInfoResponse, - DistrictCommissionerAgencies, DataUploadResponse, - Person, - Attachment, - AssetType, - MortgageCertificate, - MortgageCertificateValidation, - AssetName, + DistrictCommissionerAgencies, + EstateInfo, EstateRegistrant, EstateRelations, - EstateInfo, - RealEstateAgent, + Homestay, + InheritanceReportInfo, + InheritanceTax, Lawyer, - Broker, + ManyPropertyDetail, + MortgageCertificate, + MortgageCertificateValidation, + OperatingLicensesCSV, + PaginatedOperatingLicenses, + Person, PropertyDetail, + RealEstateAgent, + RegistryPerson, + SyslumennAuction, TemporaryEventLicence, VehicleRegistration, - RegistryPerson, - InheritanceTax, - InheritanceReportInfo, - ManyPropertyDetail, } from './syslumennClient.types' import { - mapSyslumennAuction, - mapHomestay, - mapPaginatedOperatingLicenses, - mapOperatingLicensesCSV, - mapCertificateInfo, - mapDistrictCommissionersAgenciesResponse, - mapDataUploadResponse, + cleanPropertyNumber, constructUploadDataObject, + mapAlcoholLicence, mapAssetName, - mapEstateRegistrant, - mapEstateInfo, - mapRealEstateAgent, - mapLawyer, mapBroker, - mapAlcoholLicence, - cleanPropertyNumber, - mapTemporaryEventLicence, - mapMasterLicence, - mapVehicle, + mapCertificateInfo, + mapDataUploadResponse, mapDepartedToRegistryPerson, - mapInheritanceTax, + mapDistrictCommissionersAgenciesResponse, + mapEstateInfo, + mapEstateRegistrant, mapEstateToInheritanceReportInfo, + mapHomestay, + mapInheritanceTax, mapJourneymanLicence, + mapLawyer, + mapMasterLicence, + mapOperatingLicensesCSV, + mapPaginatedOperatingLicenses, mapProfessionRight, - mapVehicleResponse, + mapPropertyCertificate, + mapRealEstateAgent, mapRealEstateResponse, mapShipResponse, - mapPropertyCertificate, + mapSyslumennAuction, + mapTemporaryEventLicence, + mapVehicle, + mapVehicleResponse, } from './syslumennClient.utils' -import { Injectable, Inject } from '@nestjs/common' -import { - SyslumennApi, - SvarSkeyti, - Configuration, - VirkLeyfiGetRequest, - VedbondTegundAndlags, - Skilabod, - VedbandayfirlitRegluverkGeneralSvar, - InnsigludSkjol, -} from '../../gen/fetch' -import { SyslumennClientConfig } from './syslumennClient.config' -import type { ConfigType } from '@island.is/nest/config' -import { AuthHeaderMiddleware } from '@island.is/auth-nest-tools' -import { createEnhancedFetch } from '@island.is/clients/middlewares' +import type { ConfigType } from '@island.is/nest/config' const UPLOAD_DATA_SUCCESS = 'Gögn móttekin' - @Injectable() export class SyslumennService { constructor( @@ -674,4 +677,22 @@ export class SyslumennService { kennitala: nationalId, }) } + + async checkIfDelegationExists( + toNationalId: string, + fromNationalId: string, + ): Promise { + const { id, api } = await this.createApi() + const delegations: LogradamadurSvar[] = await api.logradamadurGet({ + audkenni: id, + kennitala: toNationalId, + }) + + return delegations.some( + (delegation) => + delegation.kennitala === fromNationalId && + (!delegation.gildirTil || + delegation.gildirTil > startOfDay(new Date())), + ) + } }