From 6710f26f241026f35625db14cbf5286e8d33b45c Mon Sep 17 00:00:00 2001 From: Kristoff Kiefer Date: Wed, 22 Nov 2023 12:38:40 +0100 Subject: [PATCH] Added counter if username already exists and accessing KC for it --- src/modules/user/user.repository.ts | 32 +++++++++++++++++++ ...ame-generator.service.integration-spec.ts} | 14 ++++---- .../user/username-generator.service.ts | 2 +- 3 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 src/modules/user/user.repository.ts rename src/modules/user/{username-generator.service.spec.ts => username-generator.service.integration-spec.ts} (89%) diff --git a/src/modules/user/user.repository.ts b/src/modules/user/user.repository.ts new file mode 100644 index 000000000..9c803ffb2 --- /dev/null +++ b/src/modules/user/user.repository.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@nestjs/common'; +import { KeycloakUserService, UserDo } from '../keycloak-administration/index.js'; +import { DomainError, EntityNotFoundError } from '../../shared/error/index.js'; + +@Injectable() +export class UserRepository { + public constructor(private kcUserService: KeycloakUserService) {} + + public async usernameExists(username: string): Promise { + const searchResult: Result, DomainError> | { ok: false; error: DomainError } = + await this.kcUserService.findOne({ username: username }); + if (searchResult.ok) { + return true; + } else { + if (searchResult.error instanceof EntityNotFoundError) { + return false; + } + } + throw searchResult.error; + } + + public async getNextAvailableUsername(calculatedUsername: string): Promise { + if (!(await this.usernameExists(calculatedUsername))) { + return calculatedUsername; + } + let counter: number = 1; + while (await this.usernameExists(calculatedUsername + counter)) { + counter = counter + 1; + } + return calculatedUsername + counter; + } +} diff --git a/src/modules/user/username-generator.service.spec.ts b/src/modules/user/username-generator.service.integration-spec.ts similarity index 89% rename from src/modules/user/username-generator.service.spec.ts rename to src/modules/user/username-generator.service.integration-spec.ts index 2b0f0ba95..b5e8df4a4 100644 --- a/src/modules/user/username-generator.service.spec.ts +++ b/src/modules/user/username-generator.service.integration-spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { UsernameGeneratorService } from './username-generator.service.js'; import { createMock, DeepMocked } from '@golevelup/ts-jest'; -import { KeycloakUserService, UserDo } from '../keycloak-administration/index.js'; +import { FindUserFilter, KeycloakUserService, UserDo } from '../keycloak-administration/index.js'; import { UserRepository } from './user.repository.js'; import { EntityNotFoundError } from '../../shared/error/index.js'; @@ -73,20 +73,20 @@ describe('The UsernameGenerator Service', () => { }); it('should add a number when username already exists', async () => { - kcUserService.findOne.mockResolvedValueOnce({ ok: true, value: new UserDo() }); - const generatedUsername = await service.generateUsername('Max', 'Meyer'); + kcUserService.findOne + .mockResolvedValueOnce({ ok: true, value: new UserDo() }) + .mockResolvedValueOnce({ ok: false, error: new EntityNotFoundError('Not found') }); + const generatedUsername: string = await service.generateUsername('Max', 'Meyer'); expect(generatedUsername).toBe('mmeyer1'); }); it('should increment the counter when a username would exist more than twice', async () => { - /* kcUserService.findOne.mockImplementation((userFilter: FindUserFilter) => { if (userFilter.username == 'mmeyer' || userFilter.username == 'mmeyer1') { return Promise.resolve({ ok: true, value: new UserDo() }); } else return Promise.resolve({ ok: false, error: new EntityNotFoundError('Not found') }); - });*/ - kcUserService.findOne.mockRejectedValueOnce('Blah'); - const generatedUsername = await service.generateUsername('Max', 'Meyer'); + }); + const generatedUsername: string = await service.generateUsername('Max', 'Meyer'); expect(generatedUsername).toBe('mmeyer2'); }); }); diff --git a/src/modules/user/username-generator.service.ts b/src/modules/user/username-generator.service.ts index 139c46dc4..7f246d8e2 100644 --- a/src/modules/user/username-generator.service.ts +++ b/src/modules/user/username-generator.service.ts @@ -12,7 +12,7 @@ export class UsernameGeneratorService { if (lastname.length == 0) { throw new Error('Last name not given'); } - const calculatedUsername = this.cleanString(firstname)[0] + this.cleanString(lastname); + const calculatedUsername: string = this.cleanString(firstname)[0] + this.cleanString(lastname); return this.repository.getNextAvailableUsername(calculatedUsername); }