diff --git a/apps/server/src/modules/account/api/account.controller.ts b/apps/server/src/modules/account/api/account.controller.ts index 84743b3057f..261d052778a 100644 --- a/apps/server/src/modules/account/api/account.controller.ts +++ b/apps/server/src/modules/account/api/account.controller.ts @@ -32,7 +32,7 @@ export class AccountController { @ApiResponse({ status: 200, type: AccountSearchListResponse, description: 'Returns a paged list of accounts.' }) @ApiResponse({ status: 400, type: ValidationError, description: 'Request data has invalid format.' }) @ApiResponse({ status: 403, type: ForbiddenOperationError, description: 'User is not a superhero or administrator.' }) - async searchAccounts( + public async searchAccounts( @CurrentUser() currentUser: ICurrentUser, @Query() query: AccountSearchQueryParams ): Promise { @@ -48,7 +48,7 @@ export class AccountController { @ApiResponse({ status: 400, type: ValidationError, description: 'Request data has invalid format.' }) @ApiResponse({ status: 403, type: ForbiddenOperationError, description: 'User is not a superhero.' }) @ApiResponse({ status: 404, type: EntityNotFoundError, description: 'Account not found.' }) - async findAccountById( + public async findAccountById( @CurrentUser() currentUser: ICurrentUser, @Param() params: AccountByIdParams ): Promise { @@ -65,7 +65,10 @@ export class AccountController { @ApiResponse({ status: 400, type: ValidationError, description: 'Request data has invalid format.' }) @ApiResponse({ status: 403, type: ForbiddenOperationError, description: 'Invalid password.' }) @ApiResponse({ status: 404, type: EntityNotFoundError, description: 'Account not found.' }) - async updateMyAccount(@CurrentUser() currentUser: ICurrentUser, @Body() params: PatchMyAccountParams): Promise { + public updateMyAccount( + @CurrentUser() currentUser: ICurrentUser, + @Body() params: PatchMyAccountParams + ): Promise { const updateData = new UpdateMyAccountDto(params); return this.accountUc.updateMyAccount(currentUser.userId, updateData); } @@ -76,7 +79,7 @@ export class AccountController { @ApiResponse({ status: 400, type: ValidationError, description: 'Request data has invalid format.' }) @ApiResponse({ status: 403, type: ForbiddenOperationError, description: 'User is not a superhero.' }) @ApiResponse({ status: 404, type: EntityNotFoundError, description: 'Account not found.' }) - async updateAccountById( + public async updateAccountById( @CurrentUser() currentUser: ICurrentUser, @Param() params: AccountByIdParams, @Body() body: AccountByIdBodyParams @@ -93,7 +96,7 @@ export class AccountController { @ApiResponse({ status: 400, type: ValidationError, description: 'Request data has invalid format.' }) @ApiResponse({ status: 403, type: ForbiddenOperationError, description: 'User is not a superhero.' }) @ApiResponse({ status: 404, type: EntityNotFoundError, description: 'Account not found.' }) - async deleteAccountById( + public async deleteAccountById( @CurrentUser() currentUser: ICurrentUser, @Param() params: AccountByIdParams ): Promise { @@ -107,7 +110,7 @@ export class AccountController { @ApiResponse({ status: 400, type: ValidationError, description: 'Request data has invalid format.' }) @ApiResponse({ status: 403, type: ForbiddenOperationError, description: 'Invalid password.' }) @ApiResponse({ status: 404, type: EntityNotFoundError, description: 'Account or user not found.' }) - async replaceMyPassword( + public replaceMyPassword( @CurrentUser() currentUser: ICurrentUser, @Body() params: PatchMyPasswordParams ): Promise { diff --git a/apps/server/src/modules/account/api/account.uc.ts b/apps/server/src/modules/account/api/account.uc.ts index 87b15f6088f..8856cc393e4 100644 --- a/apps/server/src/modules/account/api/account.uc.ts +++ b/apps/server/src/modules/account/api/account.uc.ts @@ -174,7 +174,7 @@ export class AccountUc { * @param currentUserId the current user * @param updateMyAccountDto account details */ - public async updateMyAccount(currentUserId: EntityId, updateMyAccountDto: UpdateMyAccountDto) { + public async updateMyAccount(currentUserId: EntityId, updateMyAccountDto: UpdateMyAccountDto): Promise { const user = await this.authorizationService.getUserWithPermissions(currentUserId); if ( (updateMyAccountDto.firstName && user.firstName !== updateMyAccountDto.firstName) || @@ -205,7 +205,7 @@ export class AccountUc { currentUser: User, targetUser: User, action: 'READ' | 'UPDATE' | 'DELETE' | 'CREATE' - ) { + ): boolean { if (this.hasRole(currentUser, RoleName.SUPERHERO)) { return true; } @@ -267,7 +267,7 @@ export class AccountUc { ); } - private hasRole(user: User, roleName: string) { + private hasRole(user: User, roleName: string): boolean { return user.roles.getItems().some((role) => role.name === roleName); } diff --git a/apps/server/src/modules/account/api/dto/account-search.dto.ts b/apps/server/src/modules/account/api/dto/account-search.dto.ts index eee0889d6a7..ebf1cd2f3e8 100644 --- a/apps/server/src/modules/account/api/dto/account-search.dto.ts +++ b/apps/server/src/modules/account/api/dto/account-search.dto.ts @@ -1,13 +1,13 @@ import { AccountSearchType } from '../../domain/type/account-search-type'; export class AccountSearchDto { - type!: AccountSearchType; + public type!: AccountSearchType; - value!: string; + public value!: string; - skip?: number = 0; + public skip?: number = 0; - limit?: number = 10; + public limit?: number = 10; constructor(search: AccountSearchDto) { this.type = search.type; diff --git a/apps/server/src/modules/account/api/dto/param/account-by-id.body.params.ts b/apps/server/src/modules/account/api/dto/param/account-by-id.body.params.ts index 9bbee259656..9266f2270db 100644 --- a/apps/server/src/modules/account/api/dto/param/account-by-id.body.params.ts +++ b/apps/server/src/modules/account/api/dto/param/account-by-id.body.params.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { PrivacyProtect, SanitizeHtml } from '@shared/controller'; import { IsBoolean, IsString, IsOptional, Matches, IsEmail } from 'class-validator'; -import { passwordPattern } from '../password-pattern'; +import { passwordPattern } from '../../../domain/password-pattern'; export class AccountByIdBodyParams { @IsOptional() @@ -13,7 +13,7 @@ export class AccountByIdBodyParams { required: false, nullable: true, }) - username?: string; + public username?: string; @PrivacyProtect() @IsOptional() @@ -24,7 +24,7 @@ export class AccountByIdBodyParams { required: false, nullable: true, }) - password?: string; + public password?: string; @IsOptional() @IsBoolean() @@ -33,5 +33,5 @@ export class AccountByIdBodyParams { required: false, nullable: true, }) - activated?: boolean; + public activated?: boolean; } diff --git a/apps/server/src/modules/account/api/dto/param/account-by-id.params.ts b/apps/server/src/modules/account/api/dto/param/account-by-id.params.ts index a5557db516c..a024741e822 100644 --- a/apps/server/src/modules/account/api/dto/param/account-by-id.params.ts +++ b/apps/server/src/modules/account/api/dto/param/account-by-id.params.ts @@ -8,5 +8,5 @@ export class AccountByIdParams { required: true, nullable: false, }) - id!: string; + public id!: string; } diff --git a/apps/server/src/modules/account/api/dto/param/account-search.query.params.ts b/apps/server/src/modules/account/api/dto/param/account-search.query.params.ts index e82c7ecd2f2..e43240f587b 100644 --- a/apps/server/src/modules/account/api/dto/param/account-search.query.params.ts +++ b/apps/server/src/modules/account/api/dto/param/account-search.query.params.ts @@ -11,7 +11,7 @@ export class AccountSearchQueryParams extends PaginationParams { required: true, nullable: false, }) - type!: AccountSearchType; + public type!: AccountSearchType; @IsString() @SanitizeHtml() @@ -20,5 +20,5 @@ export class AccountSearchQueryParams extends PaginationParams { required: true, nullable: false, }) - value!: string; + public value!: string; } diff --git a/apps/server/src/modules/account/api/dto/param/patch-my-account.params.ts b/apps/server/src/modules/account/api/dto/param/patch-my-account.params.ts index efb8f3a95a4..93d03777692 100644 --- a/apps/server/src/modules/account/api/dto/param/patch-my-account.params.ts +++ b/apps/server/src/modules/account/api/dto/param/patch-my-account.params.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { PrivacyProtect, SanitizeHtml } from '@shared/controller'; import { IsEmail, IsOptional, IsString, Matches } from 'class-validator'; -import { passwordPattern } from '../password-pattern'; +import { passwordPattern } from '../../../domain/password-pattern'; export class PatchMyAccountParams { @IsString() @@ -10,7 +10,7 @@ export class PatchMyAccountParams { required: true, nullable: false, }) - passwordOld!: string; + public passwordOld!: string; @PrivacyProtect() @IsString() @@ -21,7 +21,7 @@ export class PatchMyAccountParams { required: false, nullable: true, }) - passwordNew?: string; + public passwordNew?: string; @IsEmail() @SanitizeHtml() @@ -31,7 +31,7 @@ export class PatchMyAccountParams { required: false, nullable: true, }) - email?: string; + public email?: string; @IsString() @SanitizeHtml() @@ -42,7 +42,7 @@ export class PatchMyAccountParams { required: false, nullable: true, }) - firstName?: string; + public firstName?: string; @IsString() @SanitizeHtml() @@ -53,5 +53,5 @@ export class PatchMyAccountParams { required: false, nullable: true, }) - lastName?: string; + public lastName?: string; } diff --git a/apps/server/src/modules/account/api/dto/param/patch-my-password.params.ts b/apps/server/src/modules/account/api/dto/param/patch-my-password.params.ts index 386356fc404..6e1f21faac4 100644 --- a/apps/server/src/modules/account/api/dto/param/patch-my-password.params.ts +++ b/apps/server/src/modules/account/api/dto/param/patch-my-password.params.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { PrivacyProtect } from '@shared/controller'; import { IsString, Matches } from 'class-validator'; -import { passwordPattern } from '../password-pattern'; +import { passwordPattern } from '../../../domain/password-pattern'; export class PatchMyPasswordParams { @PrivacyProtect() @@ -12,7 +12,7 @@ export class PatchMyPasswordParams { required: true, nullable: false, }) - password!: string; + public password!: string; @PrivacyProtect() @IsString() @@ -22,5 +22,5 @@ export class PatchMyPasswordParams { required: true, nullable: false, }) - confirmPassword!: string; + public confirmPassword!: string; } diff --git a/apps/server/src/modules/account/api/dto/resolved-account.dto.ts b/apps/server/src/modules/account/api/dto/resolved-account.dto.ts index a2bcaed4503..738c8113de9 100644 --- a/apps/server/src/modules/account/api/dto/resolved-account.dto.ts +++ b/apps/server/src/modules/account/api/dto/resolved-account.dto.ts @@ -1,64 +1,66 @@ -import { EntityId } from '@shared/domain/types'; -import { IsBoolean, IsDate, IsMongoId, IsNotEmpty, IsOptional, IsString, Matches } from 'class-validator'; +/* eslint-disable max-classes-per-file */ +import { ApiPropertyOptional } from '@nestjs/swagger'; import { PrivacyProtect } from '@shared/controller'; -import { passwordPattern } from './password-pattern'; +import { EntityId } from '@shared/domain/types'; +import { IsBoolean, IsDate, IsMongoId, IsNotEmpty, IsString, Matches } from 'class-validator'; +import { passwordPattern } from '../../domain/password-pattern'; export class ResolvedAccountDto { - @IsOptional() + @ApiPropertyOptional() @IsMongoId() - readonly id: EntityId; + public readonly id: EntityId; - @IsOptional() + @ApiPropertyOptional() @IsDate() - readonly createdAt?: Date; + public readonly createdAt?: Date; - @IsOptional() + @ApiPropertyOptional() @IsDate() - readonly updatedAt?: Date; + public readonly updatedAt?: Date; @IsString() @IsNotEmpty() - username: string; + public username: string; @PrivacyProtect() - @IsOptional() + @ApiPropertyOptional() @Matches(passwordPattern) - password?: string; + public password?: string; - @IsOptional() + @ApiPropertyOptional() @IsString() - token?: string; + public token?: string; - @IsOptional() + @ApiPropertyOptional() @IsString() - credentialHash?: string; + public credentialHash?: string; - @IsOptional() + @ApiPropertyOptional() @IsMongoId() - userId?: EntityId; + public userId?: EntityId; - @IsOptional() + @ApiPropertyOptional() @IsMongoId() - systemId?: EntityId; + public systemId?: EntityId; - @IsOptional() + @ApiPropertyOptional() @IsDate() - lasttriedFailedLogin?: Date; + public lasttriedFailedLogin?: Date; - @IsOptional() + @ApiPropertyOptional() @IsDate() - expiresAt?: Date; + public expiresAt?: Date; - @IsOptional() + @ApiPropertyOptional() @IsBoolean() - activated?: boolean; + public activated?: boolean; - @IsOptional() - idmReferenceId?: string; + @ApiPropertyOptional() + public idmReferenceId?: string; - @IsOptional() + @ApiPropertyOptional() @IsDate() - deactivatedAt?: Date; + public deactivatedAt?: Date; constructor(account: ResolvedAccountDto) { this.id = account.id; @@ -79,13 +81,13 @@ export class ResolvedAccountDto { } export class ResolvedSearchListAccountDto { - data: ResolvedAccountDto[]; + public data: ResolvedAccountDto[]; - total: number; + public total: number; - skip?: number; + public skip?: number; - limit?: number; + public limit?: number; constructor(data: ResolvedAccountDto[], total: number, skip?: number, limit?: number) { this.data = data; diff --git a/apps/server/src/modules/account/api/dto/response/account-search-list.response.ts b/apps/server/src/modules/account/api/dto/response/account-search-list.response.ts index 388d309abf5..113fe6c6e48 100644 --- a/apps/server/src/modules/account/api/dto/response/account-search-list.response.ts +++ b/apps/server/src/modules/account/api/dto/response/account-search-list.response.ts @@ -9,5 +9,5 @@ export class AccountSearchListResponse extends PaginationResponse AccountResponseMapper.mapToAccountResponse(resolvedAccount)); } - static mapToAccountSearchListResponse( + public static mapToAccountSearchListResponse( resolvedSearchListAccountDto: ResolvedSearchListAccountDto ): AccountSearchListResponse { return new AccountSearchListResponse( diff --git a/apps/server/src/modules/account/api/mapper/account-uc.mapper.ts b/apps/server/src/modules/account/api/mapper/account-uc.mapper.ts index c8b64573fa7..5d91eff0f45 100644 --- a/apps/server/src/modules/account/api/mapper/account-uc.mapper.ts +++ b/apps/server/src/modules/account/api/mapper/account-uc.mapper.ts @@ -3,19 +3,19 @@ import { Account } from '../../domain'; import { ResolvedAccountDto } from '../dto/resolved-account.dto'; export class AccountUcMapper { - static mapToResolvedAccountDto(account: Account): ResolvedAccountDto { + public static mapToResolvedAccountDto(account: Account): ResolvedAccountDto { return new ResolvedAccountDto({ ...account.getProps(), }); } - static mapSearchResult(accounts: Counted): Counted { + public static mapSearchResult(accounts: Counted): Counted { const foundAccounts = accounts[0]; const accountDos: ResolvedAccountDto[] = AccountUcMapper.mapAccountsToDo(foundAccounts); return [accountDos, accounts[1]]; } - static mapAccountsToDo(accounts: Account[]): ResolvedAccountDto[] { + public static mapAccountsToDo(accounts: Account[]): ResolvedAccountDto[] { return accounts.map((account) => AccountUcMapper.mapToResolvedAccountDto(account)); } } diff --git a/apps/server/src/modules/account/domain/account.ts b/apps/server/src/modules/account/domain/account.ts index 2b15037c12c..96475c6362c 100644 --- a/apps/server/src/modules/account/domain/account.ts +++ b/apps/server/src/modules/account/domain/account.ts @@ -22,91 +22,91 @@ export interface AccountProps extends AuthorizableObject { } export class Account extends DomainObject { - public get id(): EntityId { + get id(): EntityId { return this.props.id; } - public get createdAt(): Date | undefined { + get createdAt(): Date | undefined { return this.props.createdAt; } - public get updatedAt(): Date | undefined { + get updatedAt(): Date | undefined { return this.props.updatedAt; } - public get userId(): EntityId | undefined { + get userId(): EntityId | undefined { return this.props.userId; } - public set userId(userId: EntityId | undefined) { + set userId(userId: EntityId | undefined) { this.props.userId = userId; } - public get systemId(): EntityId | undefined { + get systemId(): EntityId | undefined { return this.props.systemId; } - public set systemId(systemId: EntityId | undefined) { + set systemId(systemId: EntityId | undefined) { this.props.systemId = systemId; } - public get username(): string { + get username(): string { return this.props.username; } - public set username(username: string) { + set username(username: string) { this.props.username = username; } - public get password(): string | undefined { + get password(): string | undefined { return this.props.password; } - public set password(password: string | undefined) { + set password(password: string | undefined) { this.props.password = password; } - public get token(): string | undefined { + get token(): string | undefined { return this.props.token; } - public get credentialHash(): string | undefined { + get credentialHash(): string | undefined { return this.props.credentialHash; } - public get lastLogin(): Date | undefined { + get lastLogin(): Date | undefined { return this.props.lastLogin; } - public set lastLogin(lastLogin: Date | undefined) { + set lastLogin(lastLogin: Date | undefined) { this.props.lastLogin = lastLogin; } - public get lasttriedFailedLogin(): Date | undefined { + get lasttriedFailedLogin(): Date | undefined { return this.props.lasttriedFailedLogin; } - public set lasttriedFailedLogin(lasttriedFailedLogin: Date | undefined) { + set lasttriedFailedLogin(lasttriedFailedLogin: Date | undefined) { this.props.lasttriedFailedLogin = lasttriedFailedLogin; } - public get expiresAt(): Date | undefined { + get expiresAt(): Date | undefined { return this.props.expiresAt; } - public get activated(): boolean | undefined { + get activated(): boolean | undefined { return this.props.activated; } - public set activated(activated: boolean | undefined) { + set activated(activated: boolean | undefined) { this.props.activated = activated; } - public get idmReferenceId(): string | undefined { + get idmReferenceId(): string | undefined { return this.props.idmReferenceId; } - public get deactivatedAt(): Date | undefined { + get deactivatedAt(): Date | undefined { return this.props.deactivatedAt; } diff --git a/apps/server/src/modules/account/domain/error/deleted-account-with-user-id.loggable.ts b/apps/server/src/modules/account/domain/error/deleted-account-with-user-id.loggable.ts index c99ca026491..ed6d9eab2a8 100644 --- a/apps/server/src/modules/account/domain/error/deleted-account-with-user-id.loggable.ts +++ b/apps/server/src/modules/account/domain/error/deleted-account-with-user-id.loggable.ts @@ -3,7 +3,7 @@ import { Loggable, LogMessage } from '@src/core/logger'; export class DeletedAccountWithUserIdLoggable implements Loggable { constructor(private readonly userId: string) {} - getLogMessage(): LogMessage { + public getLogMessage(): LogMessage { const message = { message: `Account deleted`, data: { userId: this.userId }, diff --git a/apps/server/src/modules/account/domain/error/deleted-account.loggable.ts b/apps/server/src/modules/account/domain/error/deleted-account.loggable.ts index b848664c4e5..35706fdfb79 100644 --- a/apps/server/src/modules/account/domain/error/deleted-account.loggable.ts +++ b/apps/server/src/modules/account/domain/error/deleted-account.loggable.ts @@ -3,7 +3,7 @@ import { Loggable, LogMessage } from '@src/core/logger'; export class DeletedAccountLoggable implements Loggable { constructor(private readonly accountId: string) {} - getLogMessage(): LogMessage { + public getLogMessage(): LogMessage { const message = { message: `Account deleted`, data: { accountId: this.accountId }, diff --git a/apps/server/src/modules/account/domain/error/deleted-user-data.loggable.ts b/apps/server/src/modules/account/domain/error/deleted-user-data.loggable.ts index 6160bc283de..4ead185b6ef 100644 --- a/apps/server/src/modules/account/domain/error/deleted-user-data.loggable.ts +++ b/apps/server/src/modules/account/domain/error/deleted-user-data.loggable.ts @@ -3,7 +3,7 @@ import { Loggable, LogMessage } from '@src/core/logger'; export class DeletedUserDataLoggable implements Loggable { constructor(private readonly userId: string) {} - getLogMessage(): LogMessage { + public getLogMessage(): LogMessage { const message = { message: `User data deleted from account collection`, data: { userId: this.userId }, diff --git a/apps/server/src/modules/account/domain/error/deleting-account-with-user-id.loggable.ts b/apps/server/src/modules/account/domain/error/deleting-account-with-user-id.loggable.ts index 83d0f519eb0..1c911715ad0 100644 --- a/apps/server/src/modules/account/domain/error/deleting-account-with-user-id.loggable.ts +++ b/apps/server/src/modules/account/domain/error/deleting-account-with-user-id.loggable.ts @@ -3,7 +3,7 @@ import { Loggable, LogMessage } from '@src/core/logger'; export class DeletingAccountWithUserIdLoggable implements Loggable { constructor(private readonly userId: string) {} - getLogMessage(): LogMessage { + public getLogMessage(): LogMessage { const message = { message: `Deleting account ...`, data: { userId: this.userId }, diff --git a/apps/server/src/modules/account/domain/error/deleting-account.loggable.ts b/apps/server/src/modules/account/domain/error/deleting-account.loggable.ts index 93390555545..a1ad8a7e129 100644 --- a/apps/server/src/modules/account/domain/error/deleting-account.loggable.ts +++ b/apps/server/src/modules/account/domain/error/deleting-account.loggable.ts @@ -3,7 +3,7 @@ import { Loggable, LogMessage } from '@src/core/logger'; export class DeletingAccountLoggable implements Loggable { constructor(private readonly accountId: string) {} - getLogMessage(): LogMessage { + public getLogMessage(): LogMessage { const message = { message: `Deleting account ...`, data: { accountId: this.accountId }, diff --git a/apps/server/src/modules/account/domain/error/deleting-user-data.loggable.ts b/apps/server/src/modules/account/domain/error/deleting-user-data.loggable.ts index f044d9ab0e3..c722ce2f183 100644 --- a/apps/server/src/modules/account/domain/error/deleting-user-data.loggable.ts +++ b/apps/server/src/modules/account/domain/error/deleting-user-data.loggable.ts @@ -3,7 +3,7 @@ import { Loggable, LogMessage } from '@src/core/logger'; export class DeletingUserDataLoggable implements Loggable { constructor(private readonly userId: string) {} - getLogMessage(): LogMessage { + public getLogMessage(): LogMessage { const message = { message: `Start deleting user data in account collection`, data: { userId: this.userId }, diff --git a/apps/server/src/modules/account/domain/error/find-account-by-user-id.loggable.ts b/apps/server/src/modules/account/domain/error/find-account-by-user-id.loggable.ts index 4873f0cf267..0aa8da99e10 100644 --- a/apps/server/src/modules/account/domain/error/find-account-by-user-id.loggable.ts +++ b/apps/server/src/modules/account/domain/error/find-account-by-user-id.loggable.ts @@ -3,7 +3,7 @@ import { Loggable, LogMessage } from '@src/core/logger'; export class FindAccountByDbcUserIdLoggable implements Loggable { constructor(private readonly userId: string) {} - getLogMessage(): LogMessage { + public getLogMessage(): LogMessage { const message = { message: `Error while searching for account`, data: { userId: this.userId }, diff --git a/apps/server/src/modules/account/domain/error/get-idm-account-by-id.loggable.ts b/apps/server/src/modules/account/domain/error/get-idm-account-by-id.loggable.ts index 18e2c4a4b25..6bb45906231 100644 --- a/apps/server/src/modules/account/domain/error/get-idm-account-by-id.loggable.ts +++ b/apps/server/src/modules/account/domain/error/get-idm-account-by-id.loggable.ts @@ -3,7 +3,7 @@ import { Loggable, LogMessage } from '@src/core/logger'; export class GetOptionalIdmAccountLoggable implements Loggable { constructor(private readonly accountId: string) {} - getLogMessage(): LogMessage { + public getLogMessage(): LogMessage { const message = { message: `Account ID could not be resolved. Creating new account and ID ...`, data: { accountId: this.accountId }, diff --git a/apps/server/src/modules/account/domain/error/idm-callback-loggable-exception.ts b/apps/server/src/modules/account/domain/error/idm-callback-loggable-exception.ts index 2a897cd8090..3a6d2223ad4 100644 --- a/apps/server/src/modules/account/domain/error/idm-callback-loggable-exception.ts +++ b/apps/server/src/modules/account/domain/error/idm-callback-loggable-exception.ts @@ -1,9 +1,9 @@ import { ErrorLogMessage, LogMessage, Loggable, ValidationErrorLogMessage } from '@src/core/logger'; export class IdmCallbackLoggableException implements Loggable { - constructor(private readonly callbackError: any) {} + constructor(private readonly callbackError: Error | unknown) {} - getLogMessage(): LogMessage | ErrorLogMessage | ValidationErrorLogMessage { + public getLogMessage(): LogMessage | ErrorLogMessage | ValidationErrorLogMessage { if (this.callbackError instanceof Error) { return { type: this.callbackError.name, diff --git a/apps/server/src/modules/account/api/dto/password-patter.spec.ts b/apps/server/src/modules/account/domain/password-patter.spec.ts similarity index 100% rename from apps/server/src/modules/account/api/dto/password-patter.spec.ts rename to apps/server/src/modules/account/domain/password-patter.spec.ts diff --git a/apps/server/src/modules/account/api/dto/password-pattern.ts b/apps/server/src/modules/account/domain/password-pattern.ts similarity index 100% rename from apps/server/src/modules/account/api/dto/password-pattern.ts rename to apps/server/src/modules/account/domain/password-pattern.ts diff --git a/apps/server/src/modules/account/domain/services/account-db.service.spec.ts b/apps/server/src/modules/account/domain/services/account-db.service.spec.ts index 4b5911267a8..278002c24a4 100644 --- a/apps/server/src/modules/account/domain/services/account-db.service.spec.ts +++ b/apps/server/src/modules/account/domain/services/account-db.service.spec.ts @@ -313,24 +313,12 @@ describe('AccountDbService', () => { describe('when user does not exist', () => { const setup = () => { - const mockTeacherUser = userFactory.buildWithId(); - const mockTeacherAccount = accountDoFactory.build({ - userId: mockTeacherUser.id, - password: defaultPassword, - }); - - accountRepo.findByUserIdOrFail.mockImplementation((userId: EntityId | ObjectId): Promise => { - if (mockTeacherUser.id === userId) { - return Promise.resolve(mockTeacherAccount); - } - throw new EntityNotFoundError(AccountEntity.name); - }); - return {}; + accountRepo.findByUserIdOrFail.mockRejectedValue(new EntityNotFoundError(AccountEntity.name)); }; it('should throw EntityNotFoundError', async () => { setup(); - await expect(accountService.findByUserIdOrFail('nonExistentId')).rejects.toThrow(EntityNotFoundError); + await expect(accountService.findByUserIdOrFail('nonExistentId')).rejects.toBeInstanceOf(EntityNotFoundError); }); }); }); @@ -720,6 +708,7 @@ describe('AccountDbService', () => { const theNewDate = new Date(); accountRepo.findById.mockResolvedValue(mockTeacherAccount); + accountRepo.save.mockResolvedValue(mockTeacherAccount); return { mockTeacherAccount, theNewDate }; }; @@ -739,6 +728,7 @@ describe('AccountDbService', () => { const theNewDate = new Date(); accountRepo.findById.mockResolvedValue(mockTeacherAccount); + accountRepo.save.mockResolvedValue(mockTeacherAccount); return { mockTeacherAccount, theNewDate }; }; @@ -808,7 +798,7 @@ describe('AccountDbService', () => { const newPassword = 'newPassword'; accountRepo.findById.mockResolvedValue(mockTeacherAccount); - + accountRepo.save.mockResolvedValue(mockTeacherAccount); return { mockTeacherAccount, newPassword }; }; @@ -820,8 +810,6 @@ describe('AccountDbService', () => { expect(ret).toBeDefined(); if (ret.password) { await expect(bcrypt.compare(newPassword, ret.password)).resolves.toBe(true); - } else { - fail('return password is undefined'); } }); }); diff --git a/apps/server/src/modules/account/domain/services/account-db.service.ts b/apps/server/src/modules/account/domain/services/account-db.service.ts index 36df25fb82b..fcacb58512b 100644 --- a/apps/server/src/modules/account/domain/services/account-db.service.ts +++ b/apps/server/src/modules/account/domain/services/account-db.service.ts @@ -21,29 +21,37 @@ export class AccountServiceDb extends AbstractAccountService { super(); } - async findById(id: EntityId): Promise { + public async findById(id: EntityId): Promise { const internalId = await this.getInternalId(id); return this.accountRepo.findById(internalId); } - async findMultipleByUserId(userIds: EntityId[]): Promise { - return this.accountRepo.findMultipleByUserId(userIds); + public findMultipleByUserId(userIds: EntityId[]): Promise { + const accounts = this.accountRepo.findMultipleByUserId(userIds); + + return accounts; } - async findByUserId(userId: EntityId): Promise { - return this.accountRepo.findByUserId(userId); + public findByUserId(userId: EntityId): Promise { + const account = this.accountRepo.findByUserId(userId); + + return account; } - async findByUserIdOrFail(userId: EntityId): Promise { - return this.accountRepo.findByUserIdOrFail(userId); + public findByUserIdOrFail(userId: EntityId): Promise { + const account = this.accountRepo.findByUserIdOrFail(userId); + + return account; } - async findByUsernameAndSystemId(username: string, systemId: EntityId | ObjectId): Promise { - return this.accountRepo.findByUsernameAndSystemId(username, systemId); + public findByUsernameAndSystemId(username: string, systemId: EntityId | ObjectId): Promise { + const account = this.accountRepo.findByUsernameAndSystemId(username, systemId); + + return account; } - async save(accountSave: AccountSave): Promise { + public async save(accountSave: AccountSave): Promise { let account: Account; if (accountSave.id) { const internalId = await this.getInternalId(accountSave.id); @@ -56,7 +64,7 @@ export class AccountServiceDb extends AbstractAccountService { return this.accountRepo.save(account); } - async updateUsername(accountId: EntityId, username: string): Promise { + public async updateUsername(accountId: EntityId, username: string): Promise { const internalId = await this.getInternalId(accountId); const account = await this.accountRepo.findById(internalId); account.username = username; @@ -64,49 +72,57 @@ export class AccountServiceDb extends AbstractAccountService { return account; } - async updateLastLogin(accountId: EntityId, lastLogin: Date): Promise { + public async updateLastLogin(accountId: EntityId, lastLogin: Date): Promise { const internalId = await this.getInternalId(accountId); const account = await this.accountRepo.findById(internalId); account.lastLogin = lastLogin; - await this.accountRepo.save(account); - return account; + + const savedAccount = this.accountRepo.save(account); + + return savedAccount; } - async updateLastTriedFailedLogin(accountId: EntityId, lastTriedFailedLogin: Date): Promise { + public async updateLastTriedFailedLogin(accountId: EntityId, lastTriedFailedLogin: Date): Promise { const internalId = await this.getInternalId(accountId); const account = await this.accountRepo.findById(internalId); account.lasttriedFailedLogin = lastTriedFailedLogin; - await this.accountRepo.save(account); - return account; + + const savedAccount = this.accountRepo.save(account); + + return savedAccount; } - async updatePassword(accountId: EntityId, password: string): Promise { + public async updatePassword(accountId: EntityId, password: string): Promise { const internalId = await this.getInternalId(accountId); const account = await this.accountRepo.findById(internalId); account.password = await this.encryptPassword(password); - await this.accountRepo.save(account); - return account; + const savedAccount = this.accountRepo.save(account); + + return savedAccount; } - async delete(id: EntityId): Promise { + public async delete(id: EntityId): Promise { const internalId = await this.getInternalId(id); return this.accountRepo.deleteById(internalId); } - async deleteByUserId(userId: EntityId): Promise { - return this.accountRepo.deleteByUserId(userId); + public deleteByUserId(userId: EntityId): Promise { + const entityId = this.accountRepo.deleteByUserId(userId); + return entityId; } - async searchByUsernamePartialMatch(userName: string, skip: number, limit: number): Promise> { - return this.accountRepo.searchByUsernamePartialMatch(userName, skip, limit); + public searchByUsernamePartialMatch(userName: string, skip: number, limit: number): Promise> { + const accounts = this.accountRepo.searchByUsernamePartialMatch(userName, skip, limit); + return accounts; } - async searchByUsernameExactMatch(userName: string): Promise> { - return this.accountRepo.searchByUsernameExactMatch(userName); + public searchByUsernameExactMatch(userName: string): Promise> { + const accounts = this.accountRepo.searchByUsernameExactMatch(userName); + return accounts; } - validatePassword(account: Account, comparePassword: string): Promise { + public validatePassword(account: Account, comparePassword: string): Promise { if (!account.password) { return Promise.resolve(false); } @@ -137,8 +153,9 @@ export class AccountServiceDb extends AbstractAccountService { return bcrypt.hash(password, 10); } - async findMany(offset = 0, limit = 100): Promise { - return this.accountRepo.findMany(offset, limit); + public findMany(offset = 0, limit = 100): Promise { + const accounts = this.accountRepo.findMany(offset, limit); + return accounts; } private createAccount(accountSave: AccountSave): Account { diff --git a/apps/server/src/modules/account/domain/services/account-idm.service.integration.spec.ts b/apps/server/src/modules/account/domain/services/account-idm.service.integration.spec.ts index 2f1c6d32edd..48f9a9c65b2 100644 --- a/apps/server/src/modules/account/domain/services/account-idm.service.integration.spec.ts +++ b/apps/server/src/modules/account/domain/services/account-idm.service.integration.spec.ts @@ -29,7 +29,7 @@ describe('AccountIdmService Integration', () => { systemId: new ObjectId().toString(), idmReferenceId: testDbcAccountId, } as AccountSave; - const createAccount = async (): Promise => + const createAccount = (): Promise => identityManagementService.createAccount( { username: testAccount.username, diff --git a/apps/server/src/modules/account/domain/services/account-idm.service.ts b/apps/server/src/modules/account/domain/services/account-idm.service.ts index c20b1ec7b14..d8206b65eb9 100644 --- a/apps/server/src/modules/account/domain/services/account-idm.service.ts +++ b/apps/server/src/modules/account/domain/services/account-idm.service.ts @@ -24,13 +24,13 @@ export class AccountServiceIdm extends AbstractAccountService { super(); } - async findById(id: EntityId): Promise { + public async findById(id: EntityId): Promise { const result = await this.identityManager.findAccountById(id); const account = this.accountIdmToDoMapper.mapToDo(result); return account; } - async findMultipleByUserId(userIds: EntityId[]): Promise { + public async findMultipleByUserId(userIds: EntityId[]): Promise { const resultAccounts = new Array(); const promises = userIds.map((userId) => this.identityManager.findAccountByDbcUserId(userId).catch(() => null)); @@ -48,7 +48,7 @@ export class AccountServiceIdm extends AbstractAccountService { return resultAccounts; } - async findByUserId(userId: EntityId): Promise { + public async findByUserId(userId: EntityId): Promise { try { const result = await this.identityManager.findAccountByDbcUserId(userId); return this.accountIdmToDoMapper.mapToDo(result); @@ -58,7 +58,7 @@ export class AccountServiceIdm extends AbstractAccountService { } } - async findByUserIdOrFail(userId: EntityId): Promise { + public async findByUserIdOrFail(userId: EntityId): Promise { try { const result = await this.identityManager.findAccountByDbcUserId(userId); return this.accountIdmToDoMapper.mapToDo(result); @@ -67,25 +67,29 @@ export class AccountServiceIdm extends AbstractAccountService { } } - async findByUsernameAndSystemId(username: string, systemId: EntityId | ObjectId): Promise { + public async findByUsernameAndSystemId(username: string, systemId: EntityId | ObjectId): Promise { const [accounts] = await this.searchByUsernameExactMatch(username); const account = accounts.find((tempAccount) => tempAccount.systemId === systemId) || null; return account; } - async searchByUsernamePartialMatch(userName: string, skip: number, limit: number): Promise> { + public async searchByUsernamePartialMatch( + userName: string, + skip: number, + limit: number + ): Promise> { const [results, total] = await this.identityManager.findAccountsByUsername(userName, { skip, limit, exact: false }); const accounts = results.map((result) => this.accountIdmToDoMapper.mapToDo(result)); return [accounts, total]; } - async searchByUsernameExactMatch(userName: string): Promise> { + public async searchByUsernameExactMatch(userName: string): Promise> { const [results, total] = await this.identityManager.findAccountsByUsername(userName, { exact: true }); const accounts = results.map((result) => this.accountIdmToDoMapper.mapToDo(result)); return [accounts, total]; } - async updateLastTriedFailedLogin(accountId: EntityId, lastTriedFailedLogin: Date): Promise { + public async updateLastTriedFailedLogin(accountId: EntityId, lastTriedFailedLogin: Date): Promise { const attributeName = 'lastTriedFailedLogin'; const id = await this.getIdmAccountId(accountId); await this.identityManager.setUserAttribute(id, attributeName, lastTriedFailedLogin.toISOString()); @@ -93,7 +97,7 @@ export class AccountServiceIdm extends AbstractAccountService { return this.accountIdmToDoMapper.mapToDo(updatedAccount); } - async save(accountSave: AccountSave): Promise { + public async save(accountSave: AccountSave): Promise { let accountId: string; const idmAccount: IdmAccountUpdate = { username: accountSave.username, @@ -130,31 +134,31 @@ export class AccountServiceIdm extends AbstractAccountService { return accountId; } - async updateUsername(accountRefId: EntityId, username: string): Promise { + public async updateUsername(accountRefId: EntityId, username: string): Promise { const id = await this.getIdmAccountId(accountRefId); await this.identityManager.updateAccount(id, { username }); const updatedAccount = await this.identityManager.findAccountById(id); return this.accountIdmToDoMapper.mapToDo(updatedAccount); } - async updatePassword(accountRefId: EntityId, password: string): Promise { + public async updatePassword(accountRefId: EntityId, password: string): Promise { const id = await this.getIdmAccountId(accountRefId); await this.identityManager.updateAccountPassword(id, password); const updatedAccount = await this.identityManager.findAccountById(id); return this.accountIdmToDoMapper.mapToDo(updatedAccount); } - async validatePassword(account: Account, comparePassword: string): Promise { + public async validatePassword(account: Account, comparePassword: string): Promise { const jwt = await this.idmOauthService.resourceOwnerPasswordGrant(account.username, comparePassword); return jwt !== undefined; } - async delete(accountRefId: EntityId): Promise { + public async delete(accountRefId: EntityId): Promise { const id = await this.getIdmAccountId(accountRefId); await this.identityManager.deleteAccountById(id); } - async deleteByUserId(userId: EntityId): Promise { + public async deleteByUserId(userId: EntityId): Promise { const idmAccount = await this.identityManager.findAccountByDbcUserId(userId); const deletedAccountId = await this.identityManager.deleteAccountById(idmAccount.id); @@ -162,7 +166,7 @@ export class AccountServiceIdm extends AbstractAccountService { } // eslint-disable-next-line @typescript-eslint/require-await, @typescript-eslint/no-unused-vars - async findMany(_offset: number, _limit: number): Promise { + public async findMany(_offset: number, _limit: number): Promise { throw new NotImplementedException(); } diff --git a/apps/server/src/modules/account/domain/services/account.service.abstract.ts b/apps/server/src/modules/account/domain/services/account.service.abstract.ts index 80a48cd718b..f2709d87702 100644 --- a/apps/server/src/modules/account/domain/services/account.service.abstract.ts +++ b/apps/server/src/modules/account/domain/services/account.service.abstract.ts @@ -7,45 +7,49 @@ export abstract class AbstractAccountService { * The following methods are only needed by nest */ - abstract searchByUsernamePartialMatch(userName: string, skip: number, limit: number): Promise>; + public abstract searchByUsernamePartialMatch( + userName: string, + skip: number, + limit: number + ): Promise>; - abstract validatePassword(account: Account, comparePassword: string): Promise; + public abstract validatePassword(account: Account, comparePassword: string): Promise; /** * @deprecated For migration purpose only */ - abstract findMany(offset?: number, limit?: number): Promise; + public abstract findMany(offset?: number, limit?: number): Promise; /* * The following methods are also needed by feathers */ - abstract findById(id: EntityId): Promise; + public abstract findById(id: EntityId): Promise; - abstract findMultipleByUserId(userIds: EntityId[]): Promise; + public abstract findMultipleByUserId(userIds: EntityId[]): Promise; - abstract findByUserId(userId: EntityId): Promise; + public abstract findByUserId(userId: EntityId): Promise; - abstract findByUserIdOrFail(userId: EntityId): Promise; + public abstract findByUserIdOrFail(userId: EntityId): Promise; // HINT: it would be preferable to use entityId here. Needs to be checked if this is blocked by lecacy code - abstract findByUsernameAndSystemId(username: string, systemId: EntityId | ObjectId): Promise; + public abstract findByUsernameAndSystemId(username: string, systemId: EntityId | ObjectId): Promise; - abstract save(accountSave: AccountSave): Promise; + public abstract save(accountSave: AccountSave): Promise; - abstract updateUsername(accountId: EntityId, username: string): Promise; + public abstract updateUsername(accountId: EntityId, username: string): Promise; /** * @deprecated Used for brute force detection, but will become subject to IDM thus be removed. */ - abstract updateLastTriedFailedLogin(accountId: EntityId, lastTriedFailedLogin: Date): Promise; + public abstract updateLastTriedFailedLogin(accountId: EntityId, lastTriedFailedLogin: Date): Promise; - abstract updatePassword(accountId: EntityId, password: string): Promise; + public abstract updatePassword(accountId: EntityId, password: string): Promise; - abstract delete(id: EntityId): Promise; + public abstract delete(id: EntityId): Promise; - abstract deleteByUserId(userId: EntityId): Promise; + public abstract deleteByUserId(userId: EntityId): Promise; - abstract searchByUsernameExactMatch(userName: string): Promise>; + public abstract searchByUsernameExactMatch(userName: string): Promise>; - abstract isUniqueEmail(email: string): Promise; + public abstract isUniqueEmail(email: string): Promise; } diff --git a/apps/server/src/modules/account/domain/services/account.service.ts b/apps/server/src/modules/account/domain/services/account.service.ts index c2f79223a5b..d425d2aac61 100644 --- a/apps/server/src/modules/account/domain/services/account.service.ts +++ b/apps/server/src/modules/account/domain/services/account.service.ts @@ -72,7 +72,7 @@ export class AccountService extends AbstractAccountService implements DeletionSe } } - public async updateMyAccount(user: User, account: Account, updateData: UpdateMyAccount) { + public async updateMyAccount(user: User, account: Account, updateData: UpdateMyAccount): Promise { await this.checkUpdateMyAccountPrerequisites(updateData, account); const accountSave = new AccountSave({ @@ -144,7 +144,7 @@ export class AccountService extends AbstractAccountService implements DeletionSe return updateUserName; } - private async checkUpdateMyAccountPrerequisites(updateData: UpdateMyAccount, account: Account) { + private async checkUpdateMyAccountPrerequisites(updateData: UpdateMyAccount, account: Account): Promise { if (account.systemId) { throw new ForbiddenOperationError('External account details can not be changed.'); } @@ -244,35 +244,46 @@ export class AccountService extends AbstractAccountService implements DeletionSe await this.eventBus.publish(new DataDeletedEvent(deletionRequestId, dataDeleted)); } - async findById(id: string): Promise { - return this.accountImpl.findById(id); + public async findById(id: string): Promise { + const account = await this.accountImpl.findById(id); + return account; } - async findMultipleByUserId(userIds: string[]): Promise { - return this.accountImpl.findMultipleByUserId(userIds); + public async findMultipleByUserId(userIds: string[]): Promise { + const accounts = await this.accountImpl.findMultipleByUserId(userIds); + return accounts; } - async findByUserId(userId: string): Promise { - return this.accountImpl.findByUserId(userId); + public async findByUserId(userId: string): Promise { + const account = await this.accountImpl.findByUserId(userId); + return account; } - async findByUserIdOrFail(userId: string): Promise { - return this.accountImpl.findByUserIdOrFail(userId); + public async findByUserIdOrFail(userId: string): Promise { + const account = await this.accountImpl.findByUserIdOrFail(userId); + return account; } - async findByUsernameAndSystemId(username: string, systemId: string | ObjectId): Promise { - return this.accountImpl.findByUsernameAndSystemId(username, systemId); + public async findByUsernameAndSystemId(username: string, systemId: string | ObjectId): Promise { + const account = await this.accountImpl.findByUsernameAndSystemId(username, systemId); + return account; } - async searchByUsernamePartialMatch(userName: string, skip: number, limit: number): Promise> { - return this.accountImpl.searchByUsernamePartialMatch(userName, skip, limit); + public async searchByUsernamePartialMatch( + userName: string, + skip: number, + limit: number + ): Promise> { + const result = await this.accountImpl.searchByUsernamePartialMatch(userName, skip, limit); + return result; } - async searchByUsernameExactMatch(userName: string): Promise> { - return this.accountImpl.searchByUsernameExactMatch(userName); + public async searchByUsernameExactMatch(userName: string): Promise> { + const result = await this.accountImpl.searchByUsernameExactMatch(userName); + return result; } - async save(accountSave: AccountSave): Promise { + public async save(accountSave: AccountSave): Promise { const ret = await this.accountDb.save(accountSave); const newAccount = new AccountSave({ ...accountSave, @@ -299,7 +310,7 @@ export class AccountService extends AbstractAccountService implements DeletionSe return new Account({ ...ret.getProps(), idmReferenceId: idmAccount?.idmReferenceId }); } - async validateAccountBeforeSaveOrReject(accountSave: AccountSave) { + public async validateAccountBeforeSaveOrReject(accountSave: AccountSave): Promise { // if username is undefined or empty, throw error ✔ if (!accountSave.username || !isNotEmpty(accountSave.username)) { throw new ValidationError('username can not be empty'); @@ -335,12 +346,12 @@ export class AccountService extends AbstractAccountService implements DeletionSe // } } - async saveWithValidation(accountSave: AccountSave): Promise { + public async saveWithValidation(accountSave: AccountSave): Promise { await this.validateAccountBeforeSaveOrReject(accountSave); await this.save(accountSave); } - async updateUsername(accountId: string, username: string): Promise { + public async updateUsername(accountId: string, username: string): Promise { const ret = await this.accountDb.updateUsername(accountId, username); const idmAccount = await this.executeIdmMethod(async () => { this.logger.debug(new UpdatingAccountUsernameLoggable(accountId)); @@ -351,11 +362,11 @@ export class AccountService extends AbstractAccountService implements DeletionSe return new Account({ ...ret.getProps(), idmReferenceId: idmAccount?.idmReferenceId }); } - async updateLastLogin(accountId: string, lastLogin: Date): Promise { + public async updateLastLogin(accountId: string, lastLogin: Date): Promise { await this.accountDb.updateLastLogin(accountId, lastLogin); } - async updateLastTriedFailedLogin(accountId: string, lastTriedFailedLogin: Date): Promise { + public async updateLastTriedFailedLogin(accountId: string, lastTriedFailedLogin: Date): Promise { const ret = await this.accountDb.updateLastTriedFailedLogin(accountId, lastTriedFailedLogin); const idmAccount = await this.executeIdmMethod(async () => { this.logger.debug(new UpdatingLastFailedLoginLoggable(accountId)); @@ -366,7 +377,7 @@ export class AccountService extends AbstractAccountService implements DeletionSe return new Account({ ...ret.getProps(), idmReferenceId: idmAccount?.idmReferenceId }); } - async updatePassword(accountId: string, password: string): Promise { + public async updatePassword(accountId: string, password: string): Promise { const ret = await this.accountDb.updatePassword(accountId, password); const idmAccount = await this.executeIdmMethod(async () => { this.logger.debug(new UpdatingAccountPasswordLoggable(accountId)); @@ -377,11 +388,12 @@ export class AccountService extends AbstractAccountService implements DeletionSe return new Account({ ...ret.getProps(), idmReferenceId: idmAccount?.idmReferenceId }); } - async validatePassword(account: Account, comparePassword: string): Promise { - return this.accountImpl.validatePassword(account, comparePassword); + public async validatePassword(account: Account, comparePassword: string): Promise { + const result = await this.accountImpl.validatePassword(account, comparePassword); + return result; } - async delete(accountId: string): Promise { + public async delete(accountId: string): Promise { await this.accountDb.delete(accountId); await this.executeIdmMethod(async () => { this.logger.debug(new DeletingAccountLoggable(accountId)); @@ -418,11 +430,12 @@ export class AccountService extends AbstractAccountService implements DeletionSe /** * @deprecated For migration purpose only */ - async findMany(offset = 0, limit = 100): Promise { - return this.accountDb.findMany(offset, limit); + public async findMany(offset = 0, limit = 100): Promise { + const accounts = await this.accountDb.findMany(offset, limit); + return accounts; } - private async executeIdmMethod(idmCallback: () => Promise) { + private async executeIdmMethod(idmCallback: () => Promise): Promise { if (this.configService.get('FEATURE_IDENTITY_MANAGEMENT_STORE_ENABLED') === true) { try { return await idmCallback(); @@ -439,7 +452,7 @@ export class AccountService extends AbstractAccountService implements DeletionSe } } - async findByUserIdsAndSystemId(usersIds: string[], systemId: string): Promise { + public async findByUserIdsAndSystemId(usersIds: string[], systemId: string): Promise { const foundAccounts = await this.accountRepo.findByUserIdsAndSystemId(usersIds, systemId); return foundAccounts; diff --git a/apps/server/src/modules/account/domain/update-account.ts b/apps/server/src/modules/account/domain/update-account.ts index 8dde8829eee..48a8e41a80d 100644 --- a/apps/server/src/modules/account/domain/update-account.ts +++ b/apps/server/src/modules/account/domain/update-account.ts @@ -1,9 +1,9 @@ export class UpdateAccount { - username?: string; + public username?: string; - password?: string; + public password?: string; - activated?: boolean; + public activated?: boolean; constructor(props: UpdateAccount) { this.username = props.username; diff --git a/apps/server/src/modules/account/domain/update-my-account.ts b/apps/server/src/modules/account/domain/update-my-account.ts index 433b7338cff..90a8606fee7 100644 --- a/apps/server/src/modules/account/domain/update-my-account.ts +++ b/apps/server/src/modules/account/domain/update-my-account.ts @@ -1,13 +1,13 @@ export class UpdateMyAccount { - passwordOld!: string; + public passwordOld!: string; - passwordNew?: string; + public passwordNew?: string; - email?: string; + public email?: string; - firstName?: string; + public firstName?: string; - lastName?: string; + public lastName?: string; constructor(props: UpdateMyAccount) { this.passwordOld = props.passwordOld; diff --git a/apps/server/src/modules/account/repo/micro-orm/account.repo.integration.spec.ts b/apps/server/src/modules/account/repo/micro-orm/account.repo.integration.spec.ts index 76aff5bad1a..7ece22e5e25 100644 --- a/apps/server/src/modules/account/repo/micro-orm/account.repo.integration.spec.ts +++ b/apps/server/src/modules/account/repo/micro-orm/account.repo.integration.spec.ts @@ -1,5 +1,5 @@ import { MongoMemoryDatabaseModule } from '@infra/database'; -import { NotFoundError } from '@mikro-orm/core'; +import { EntityData, NotFoundError } from '@mikro-orm/core'; import { EntityManager, ObjectId } from '@mikro-orm/mongodb'; import { Test, TestingModule } from '@nestjs/testing'; import { User } from '@shared/domain/entity'; @@ -9,18 +9,24 @@ import { accountDoFactory, accountFactory } from '../../testing'; import { AccountRepo } from './account.repo'; import { AccountEntityToDoMapper } from './mapper'; import { AccountDoToEntityMapper } from './mapper/account-do-to-entity.mapper'; +import { Account } from '../../domain'; +class AccountRepoSpec extends AccountRepo { + mapDOToEntityPropertiesSpec(entityDO: Account): EntityData { + return super.mapDOToEntityProperties(entityDO); + } +} describe('account repo', () => { let module: TestingModule; let em: EntityManager; - let repo: AccountRepo; + let repo: AccountRepoSpec; beforeAll(async () => { module = await Test.createTestingModule({ imports: [MongoMemoryDatabaseModule.forRoot()], - providers: [AccountRepo], + providers: [AccountRepoSpec], }).compile(); - repo = module.get(AccountRepo); + repo = module.get(AccountRepoSpec); em = module.get(EntityManager); }); @@ -36,6 +42,17 @@ describe('account repo', () => { expect(repo.entityName).toBe(AccountEntity); }); + describe('mapDOToEntityProperties', () => { + describe('When an account is given', () => { + it('should map the account to an entity', () => { + const account = accountDoFactory.build(); + const entityProps: EntityData = repo.mapDOToEntityPropertiesSpec(account); + + expect(entityProps).toEqual(expect.objectContaining(account.getProps())); + }); + }); + }); + describe('save', () => { describe('When an account is given', () => { it('should save an account', async () => { diff --git a/apps/server/src/modules/account/repo/micro-orm/account.repo.ts b/apps/server/src/modules/account/repo/micro-orm/account.repo.ts index 3f62fc2fefd..b56fbcb6388 100644 --- a/apps/server/src/modules/account/repo/micro-orm/account.repo.ts +++ b/apps/server/src/modules/account/repo/micro-orm/account.repo.ts @@ -1,8 +1,9 @@ -import { AnyEntity, EntityName, FilterQuery, Primary } from '@mikro-orm/core'; +import { AnyEntity, EntityData, EntityName, FilterQuery, Primary } from '@mikro-orm/core'; import { EntityManager, ObjectId } from '@mikro-orm/mongodb'; import { Injectable } from '@nestjs/common'; import { SortOrder } from '@shared/domain/interface'; import { Counted, EntityId } from '@shared/domain/types'; +import { BaseDomainObjectRepo } from '@shared/repo/base-domain-object.repo'; import { Account } from '../../domain/account'; import { AccountEntity } from '../../domain/entity/account.entity'; import { AccountEntityToDoMapper } from './mapper'; @@ -10,10 +11,18 @@ import { AccountDoToEntityMapper } from './mapper/account-do-to-entity.mapper'; import { AccountScope } from './scope/account-scope'; @Injectable() -export class AccountRepo { - constructor(private readonly em: EntityManager) {} +export class AccountRepo extends BaseDomainObjectRepo { + protected mapDOToEntityProperties(entityDO: Account): EntityData { + const entityProps: EntityData = AccountDoToEntityMapper.mapToEntity(entityDO); - get entityName() { + return entityProps; + } + + constructor(protected readonly em: EntityManager) { + super(em); + } + + get entityName(): EntityName { return AccountEntity; } @@ -86,7 +95,7 @@ export class AccountRepo { return AccountEntityToDoMapper.mapToDo(entity); } - getObjectReference>( + public getObjectReference>( entityName: EntityName, id: Primary | Primary[] ): Entity { @@ -175,7 +184,7 @@ export class AccountRepo { return AccountEntityToDoMapper.mapEntitiesToDos(result); } - async findByUserIdsAndSystemId(userIds: string[], systemId: string): Promise { + public async findByUserIdsAndSystemId(userIds: string[], systemId: string): Promise { const scope = new AccountScope(); const userIdScope = new AccountScope(); diff --git a/apps/server/src/modules/account/repo/micro-orm/mapper/account-entity-to-do.mapper.ts b/apps/server/src/modules/account/repo/micro-orm/mapper/account-entity-to-do.mapper.ts index 000ece5001a..221bdf7a147 100644 --- a/apps/server/src/modules/account/repo/micro-orm/mapper/account-entity-to-do.mapper.ts +++ b/apps/server/src/modules/account/repo/micro-orm/mapper/account-entity-to-do.mapper.ts @@ -3,7 +3,7 @@ import { Account } from '../../../domain/account'; import { AccountEntity } from '../../../domain/entity/account.entity'; export class AccountEntityToDoMapper { - static mapToDo(account: AccountEntity): Account { + public static mapToDo(account: AccountEntity): Account { return new Account({ id: account.id, createdAt: account.createdAt, @@ -22,13 +22,13 @@ export class AccountEntityToDoMapper { }); } - static mapCountedEntities(accountEntities: Counted): Counted { + public static mapCountedEntities(accountEntities: Counted): Counted { const foundAccounts = accountEntities[0]; const accountDtos: Account[] = AccountEntityToDoMapper.mapEntitiesToDos(foundAccounts); return [accountDtos, accountEntities[1]]; } - static mapEntitiesToDos(accounts: AccountEntity[]): Account[] { + public static mapEntitiesToDos(accounts: AccountEntity[]): Account[] { return accounts.map((accountEntity) => AccountEntityToDoMapper.mapToDo(accountEntity)); } } diff --git a/apps/server/src/modules/account/repo/micro-orm/mapper/account-idm-to-do.mapper.abstract.ts b/apps/server/src/modules/account/repo/micro-orm/mapper/account-idm-to-do.mapper.abstract.ts index 955e2b42da6..034a6c63107 100644 --- a/apps/server/src/modules/account/repo/micro-orm/mapper/account-idm-to-do.mapper.abstract.ts +++ b/apps/server/src/modules/account/repo/micro-orm/mapper/account-idm-to-do.mapper.abstract.ts @@ -4,5 +4,5 @@ import { Account } from '../../../domain/account'; @Injectable() export abstract class AccountIdmToDoMapper { - abstract mapToDo(account: IdmAccount): Account; + public abstract mapToDo(account: IdmAccount): Account; } diff --git a/apps/server/src/modules/account/repo/micro-orm/mapper/account-idm-to-do.mapper.db.ts b/apps/server/src/modules/account/repo/micro-orm/mapper/account-idm-to-do.mapper.db.ts index 1d8b0be686d..8dc47c32fd8 100644 --- a/apps/server/src/modules/account/repo/micro-orm/mapper/account-idm-to-do.mapper.db.ts +++ b/apps/server/src/modules/account/repo/micro-orm/mapper/account-idm-to-do.mapper.db.ts @@ -3,7 +3,7 @@ import { Account } from '../../../domain/account'; import { AccountIdmToDoMapper } from './account-idm-to-do.mapper.abstract'; export class AccountIdmToDoMapperDb extends AccountIdmToDoMapper { - mapToDo(account: IdmAccount): Account { + public mapToDo(account: IdmAccount): Account { const createdDate = account.createdDate ? account.createdDate : new Date(); return new Account({ id: account.attDbcAccountId ?? '', diff --git a/apps/server/src/modules/account/repo/micro-orm/mapper/account-idm-to-do.mapper.idm.ts b/apps/server/src/modules/account/repo/micro-orm/mapper/account-idm-to-do.mapper.idm.ts index b5402ed58a2..9f96d653480 100644 --- a/apps/server/src/modules/account/repo/micro-orm/mapper/account-idm-to-do.mapper.idm.ts +++ b/apps/server/src/modules/account/repo/micro-orm/mapper/account-idm-to-do.mapper.idm.ts @@ -3,7 +3,7 @@ import { Account } from '../../../domain/account'; import { AccountIdmToDoMapper } from './account-idm-to-do.mapper.abstract'; export class AccountIdmToDoMapperIdm extends AccountIdmToDoMapper { - mapToDo(account: IdmAccount): Account { + public mapToDo(account: IdmAccount): Account { const createdDate = account.createdDate ? account.createdDate : new Date(); return new Account({ id: account.id,