diff --git a/config/config.dev.json b/config/config.dev.json index a82c5aab7..85f176116 100644 --- a/config/config.dev.json +++ b/config/config.dev.json @@ -9,9 +9,9 @@ "SESSION_SECRET": "SessionSecretForDevelopment", "SESSION_TTL_MS": 3600000, "BACKEND_ADDRESS": "http://127.0.0.1:9090", - "OIDC_CALLBACK_URL": "http://localhost:8099/api/frontend/login", - "DEFAULT_LOGIN_REDIRECT": "http://localhost:8099/", - "LOGOUT_REDIRECT": "http://localhost:8099/" + "OIDC_CALLBACK_URL": "https://localhost:8099/api/frontend/login", + "DEFAULT_LOGIN_REDIRECT": "https://localhost:8099/", + "LOGOUT_REDIRECT": "https://localhost:8099/" }, "DB": { "CLIENT_URL": "postgres://admin:password@127.0.0.1:5432", diff --git a/dev-realm-spsh.json b/dev-realm-spsh.json index f5df18333..6009673b4 100644 --- a/dev-realm-spsh.json +++ b/dev-realm-spsh.json @@ -829,7 +829,7 @@ "secret": "YDp6fYkbUcj4ZkyAOnbAHGQ9O72htc5M", "redirectUris": [ "http://localhost:9091/*", - "http://localhost:8099/*", + "https://localhost:8099/*", "/*" ], "webOrigins": [ @@ -2364,4 +2364,4 @@ "clientPolicies": { "policies": [] } -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json index 970e7fdc8..aa82a8e4b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,7 @@ "express-session": "^1.17.3", "lodash": "^4.17.21", "lodash-es": "^4.17.21", - "nest-commander": "^3.12.2", + "nest-commander": "~3.10", "nest-keycloak-connect": "^1.9.2", "openid-client": "^5.6.0", "passport": "^0.6.0", @@ -1093,6 +1093,14 @@ "node": ">=10" } }, + "node_modules/@golevelup/nestjs-discovery": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@golevelup/nestjs-discovery/-/nestjs-discovery-3.0.0.tgz", + "integrity": "sha512-ZvkXtobTKxXB1LJanP/l6Z/Fing88IMBr3uabQpU2IWjfsstjh02qYDSU2cfD6CSmNldX5ewW5Pd+SdK2lU8Sw==", + "dependencies": { + "lodash": "^4.17.15" + } + }, "node_modules/@golevelup/ts-jest": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@golevelup/ts-jest/-/ts-jest-0.4.0.tgz", @@ -4957,6 +4965,7 @@ "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, "dependencies": { "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", @@ -7417,6 +7426,7 @@ "version": "8.2.6", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "dev": true, "dependencies": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.1", @@ -7442,6 +7452,7 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -9222,15 +9233,14 @@ "dev": true }, "node_modules/nest-commander": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/nest-commander/-/nest-commander-3.12.2.tgz", - "integrity": "sha512-iOIVzwepP21fFfU629lxGeWABhDRXfOmJeNsuqmdonx/TEYUpWuPJCPYMKRKOpv/UQj0vf/8hjbzq25VfU+0xQ==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/nest-commander/-/nest-commander-3.10.0.tgz", + "integrity": "sha512-rm9VO9ufBMLYoXLihLNAY+zXy6nbqRUatP6sKLGxg1YypsJfxMhFNgZk//6ees8qryTlio1hPgL86zM5EruZDg==", "dependencies": { - "@fig/complete-commander": "^2.0.1", - "@golevelup/nestjs-discovery": "4.0.0", + "@golevelup/nestjs-discovery": "3.0.0", "commander": "11.0.0", - "cosmiconfig": "8.3.6", - "inquirer": "8.2.6" + "cosmiconfig": "8.2.0", + "inquirer": "8.2.5" }, "peerDependencies": { "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", @@ -9238,29 +9248,6 @@ "@types/inquirer": "^8.1.3" } }, - "node_modules/nest-commander/node_modules/@fig/complete-commander": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@fig/complete-commander/-/complete-commander-2.0.1.tgz", - "integrity": "sha512-AbGETely7iwD4F7XHe4g7pW6icWYYqJMdQog8CdEi9syU/av5L0O24BvCfgEeGO6TRPMpC+rFL7ZDJsqRtckOA==", - "dependencies": { - "prettier": "^2.3.2" - }, - "peerDependencies": { - "commander": "^8.0.0" - } - }, - "node_modules/nest-commander/node_modules/@golevelup/nestjs-discovery": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@golevelup/nestjs-discovery/-/nestjs-discovery-4.0.0.tgz", - "integrity": "sha512-iyZLYip9rhVMR0C93vo860xmboRrD5g5F5iEOfpeblGvYSz8ymQrL9RAST7x/Fp3n+TAXSeOLzDIASt+rak68g==", - "dependencies": { - "lodash": "^4.17.21" - }, - "peerDependencies": { - "@nestjs/common": "^10.x", - "@nestjs/core": "^10.x" - } - }, "node_modules/nest-commander/node_modules/commander": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", @@ -9269,18 +9256,46 @@ "node": ">=16" } }, - "node_modules/nest-commander/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "bin": { - "prettier": "bin-prettier.js" + "node_modules/nest-commander/node_modules/cosmiconfig": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", + "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", + "dependencies": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=14" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/nest-commander/node_modules/inquirer": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", + "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" } }, "node_modules/nest-keycloak-connect": { @@ -12152,7 +12167,7 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", - "devOptional": true, + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index f92e961f2..362a3b005 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "express-session": "^1.17.3", "lodash": "^4.17.21", "lodash-es": "^4.17.21", - "nest-commander": "^3.12.2", + "nest-commander": "~3.10", "nest-keycloak-connect": "^1.9.2", "openid-client": "^5.6.0", "passport": "^0.6.0", diff --git a/src/modules/frontend/api/frontend.controller.spec.ts b/src/modules/frontend/api/frontend.controller.spec.ts index 278674130..75ccddc86 100644 --- a/src/modules/frontend/api/frontend.controller.spec.ts +++ b/src/modules/frontend/api/frontend.controller.spec.ts @@ -235,6 +235,7 @@ describe('FrontendController', () => { geschlecht: Geschlecht.M, lokalisierung: '', vertrauensstufe: Vertrauensstufe.VOLL, + revision: '1', }; const personenKontextResponse: PersonenkontextResponse[] = []; const response: PersonendatensatzResponse = { diff --git a/src/modules/frontend/auth/user.decorator.ts b/src/modules/frontend/auth/user.decorator.ts index 8d30e37ba..def5e0db3 100644 --- a/src/modules/frontend/auth/user.decorator.ts +++ b/src/modules/frontend/auth/user.decorator.ts @@ -1,10 +1,10 @@ -import { ExecutionContext, createParamDecorator } from '@nestjs/common'; +import { createParamDecorator, ExecutionContext } from '@nestjs/common'; import { Request } from 'express'; import { UserinfoResponse } from 'openid-client'; type UserDecoratorFactory = () => ParameterDecorator; -export type User = { id_token: string; access_token: string; userinfo: UserinfoResponse } & Express.User; +export type User = { id_token: string; access_token: string; userinfo: UserinfoResponse }; export const CurrentUser: UserDecoratorFactory = createParamDecorator((_data: unknown, ctx: ExecutionContext) => { const request: Request = ctx.switchToHttp().getRequest(); diff --git a/src/modules/person/api/person-api.mapper.profile.ts b/src/modules/person/api/person-api.mapper.profile.ts index dd3b32164..f32261f75 100644 --- a/src/modules/person/api/person-api.mapper.profile.ts +++ b/src/modules/person/api/person-api.mapper.profile.ts @@ -97,6 +97,7 @@ export class PersonApiMapperProfile extends AutomapperProfile { forMember((dest: PersonDo) => dest.id, ignore()), forMember((dest: PersonDo) => dest.createdAt, ignore()), forMember((dest: PersonDo) => dest.updatedAt, ignore()), + forMember((dest: PersonDo) => dest.revision, ignore()), ); createMap( mapper, @@ -200,6 +201,7 @@ export class PersonApiMapperProfile extends AutomapperProfile { forMember((dest: PersonDo) => dest.lokalisierung, ignore()), forMember((dest: PersonDo) => dest.vertrauensstufe, ignore()), forMember((dest: PersonDo) => dest.auskunftssperre, ignore()), + forMember((dest: PersonDo) => dest.revision, ignore()), ); createMap(mapper, CreatePersonDto, UserDo); diff --git a/src/modules/person/api/person.controller.spec.ts b/src/modules/person/api/person.controller.spec.ts index 65c32a7d0..cc7a6c3ae 100644 --- a/src/modules/person/api/person.controller.spec.ts +++ b/src/modules/person/api/person.controller.spec.ts @@ -68,7 +68,8 @@ describe('PersonController', () => { describe('when creating a person', () => { it('should not throw', async () => { - personUcMock.createPerson.mockResolvedValue(); + const personDto: PersonDto = {} as PersonDto; + personUcMock.createPerson.mockResolvedValue(personDto); const params: CreatePersonBodyParams = { username: faker.internet.userName(), mandant: faker.string.uuid(), diff --git a/src/modules/person/api/person.controller.ts b/src/modules/person/api/person.controller.ts index 8d0e7c752..9ef8cb62a 100644 --- a/src/modules/person/api/person.controller.ts +++ b/src/modules/person/api/person.controller.ts @@ -37,6 +37,7 @@ import { CreatedPersonenkontextDto } from './created-personenkontext.dto.js'; import { FindPersonendatensatzDto } from './find-personendatensatz.dto.js'; import { FindPersonenkontextDto } from './find-personenkontext.dto.js'; import { PersonByIdParams } from './person-by-id.param.js'; +import { PersonDto } from './person.dto.js'; import { PersonenQueryParams } from './personen-query.param.js'; import { PersonendatensatzDto } from './personendatensatz.dto.js'; import { PersonendatensatzResponse } from './personendatensatz.response.js'; @@ -56,14 +57,25 @@ export class PersonController { ) {} @Post() + @HttpCode(200) @ApiCreatedResponse({ description: 'The person was successfully created.' }) @ApiBadRequestResponse({ description: 'The person already exists.' }) @ApiUnauthorizedResponse({ description: 'Not authorized to create the person.' }) @ApiForbiddenResponse({ description: 'Insufficient permissions to create the person.' }) @ApiInternalServerErrorResponse({ description: 'Internal server error while creating the person.' }) - public async createPerson(@Body() params: CreatePersonBodyParams): Promise { + public async createPerson(@Body() params: CreatePersonBodyParams): Promise { const dto: CreatePersonDto = this.mapper.map(params, CreatePersonBodyParams, CreatePersonDto); - await this.personUc.createPerson(dto); + const person: PersonDto = await this.personUc.createPerson(dto); + const personendatensatzDto: PersonendatensatzDto = { + person: person, + personenkontexte: [], + }; + const personendatensatzResponse: PersonendatensatzResponse = this.mapper.map( + personendatensatzDto, + PersonendatensatzDto, + PersonendatensatzResponse, + ); + return personendatensatzResponse; } @Get(':personId') diff --git a/src/modules/person/api/person.dto.ts b/src/modules/person/api/person.dto.ts index 50abcf693..94035b4cc 100644 --- a/src/modules/person/api/person.dto.ts +++ b/src/modules/person/api/person.dto.ts @@ -42,4 +42,7 @@ export class PersonDto { @AutoMap() public auskunftssperre?: boolean; + + @AutoMap() + public revision!: string; } diff --git a/src/modules/person/api/person.response.spec.ts b/src/modules/person/api/person.response.spec.ts index 5a94848b2..32324af91 100644 --- a/src/modules/person/api/person.response.spec.ts +++ b/src/modules/person/api/person.response.spec.ts @@ -27,6 +27,7 @@ describe('PersonResponse', () => { geschlecht: faker.person.gender(), lokalisierung: faker.location.country(), vertrauensstufe: Vertrauensstufe.VOLL, + revision: '1', }; it('should convert plain object of person response to a class of person response', () => { @@ -39,6 +40,7 @@ describe('PersonResponse', () => { geschlecht: personResponse.geschlecht, lokalisierung: personResponse.lokalisierung, vertrauensstufe: personResponse.vertrauensstufe, + revision: personResponse.revision, }; const mappedParams: PersonResponse = plainToInstance(PersonResponse, person, {}); expect(mappedParams).toBeInstanceOf(PersonResponse); diff --git a/src/modules/person/api/person.response.ts b/src/modules/person/api/person.response.ts index cc8988374..a3ff849c0 100644 --- a/src/modules/person/api/person.response.ts +++ b/src/modules/person/api/person.response.ts @@ -40,4 +40,8 @@ export class PersonResponse { @AutoMap(() => String) @ApiProperty({ enum: Vertrauensstufe }) public vertrauensstufe!: Vertrauensstufe; + + @AutoMap() + @ApiProperty() + public revision!: string; } diff --git a/src/modules/person/api/person.uc.ts b/src/modules/person/api/person.uc.ts index b1ebf1e4d..55188df12 100644 --- a/src/modules/person/api/person.uc.ts +++ b/src/modules/person/api/person.uc.ts @@ -24,7 +24,7 @@ export class PersonUc { @Inject(getMapperToken()) private readonly mapper: Mapper, ) {} - public async createPerson(personDto: CreatePersonDto): Promise { + public async createPerson(personDto: CreatePersonDto): Promise { // create user const userDo: UserDo = this.mapper.map(personDto, CreatePersonDto, UserDo); const userIdResult: Result = await this.userService.create(userDo); @@ -38,7 +38,8 @@ export class PersonUc { const result: Result> = await this.personService.createPerson(personDo); if (result.ok) { - return; + const resPersonDto: PersonDto = this.mapper.map(personDo, PersonDo, PersonDto); + return resPersonDto; } // delete user if person could not be created diff --git a/src/modules/person/domain/person.do.ts b/src/modules/person/domain/person.do.ts index a6069822b..f8c2accce 100644 --- a/src/modules/person/domain/person.do.ts +++ b/src/modules/person/domain/person.do.ts @@ -77,4 +77,7 @@ export class PersonDo implements DoBase { id: undefined, createdAt: undefined, updatedAt: undefined, + revision: '1', }); expect(result).toEqual>>({ ok: true, @@ -83,6 +84,7 @@ describe('PersonService', () => { id: undefined, createdAt: undefined, updatedAt: undefined, + revision: '1', }); expect(result).toEqual>>({ ok: false, diff --git a/src/modules/person/persistence/person.entity.ts b/src/modules/person/persistence/person.entity.ts index f5a07ab2a..590175479 100644 --- a/src/modules/person/persistence/person.entity.ts +++ b/src/modules/person/persistence/person.entity.ts @@ -95,4 +95,8 @@ export class PersonEntity extends TimestampedEntity { @ManyToOne({ nullable: true }) public dataProvider?: DataProviderEntity; + + @AutoMap() + @Property({ nullable: false, default: '1' }) + public revision!: string; } diff --git a/src/modules/rolle/api/provider.controller.ts b/src/modules/rolle/api/provider.controller.ts index f8fc1bb1c..5d9d9e346 100644 --- a/src/modules/rolle/api/provider.controller.ts +++ b/src/modules/rolle/api/provider.controller.ts @@ -4,7 +4,7 @@ import { ApiTags, ApiUnauthorizedResponse } from '@nestjs/swagger'; import { AuthenticatedUser } from 'nest-keycloak-connect'; import { GetServiceProviderInfoDo } from '../domain/get-service-provider-info.do.js'; -@ApiTags('rolle') +@ApiTags('provider') @Controller({ path: 'provider' }) export class ProviderController { public constructor(private readonly rolleService: RolleService) {} diff --git a/test/utils/do-factory.ts b/test/utils/do-factory.ts index fc8a6d951..1cc6c9b64 100644 --- a/test/utils/do-factory.ts +++ b/test/utils/do-factory.ts @@ -42,6 +42,7 @@ export class DoFactory { id: withId ? faker.string.uuid() : undefined, createdAt: withId ? faker.date.past() : undefined, updatedAt: withId ? faker.date.recent() : undefined, + revision: '1', }; return Object.assign(new PersonDo(), person, props); }