Conversation
* main: feat: move event manager options to contructor feat: fix tsdoc type feat: implement event manager on dependent modules feat: add event manager
packages/nestjs-common/src/domain/role/interfaces/role-ownable.interface.ts
Outdated
Show resolved
Hide resolved
packages/nestjs-common/src/domain/user/interfaces/user-roles.interface.ts
Outdated
Show resolved
Hide resolved
packages/nestjs-password/src/interfaces/password-strength-service.interface.ts
Outdated
Show resolved
Hide resolved
|
Just a couple of high level things before deeper review of the latest commits.
|
| import { RoleInterface } from './role.interface'; | ||
|
|
||
| export interface RoleOwnableInterface { | ||
| roleId?: ReferenceId; |
There was a problem hiding this comment.
roleId property should be required
| roleId?: ReferenceId; | |
| roleId: ReferenceId; |
| import { RoleOwnableInterface } from '../../role/interfaces/role-ownable.interface'; | ||
|
|
||
| export interface PasswordStrengthTransformOptionsInterface { | ||
| roles: RoleOwnableInterface[]; |
There was a problem hiding this comment.
roles propert should be optional
| roles: RoleOwnableInterface[]; | |
| roles?: RoleOwnableInterface[]; |
| * Optional password strength requirement. If provided, will validate | ||
| * that password meets minimum strength requirements. | ||
| */ | ||
| passwordStrength?: PasswordStrengthEnum | null; |
There was a problem hiding this comment.
undefined is better
| passwordStrength?: PasswordStrengthEnum | null; | |
| passwordStrength?: PasswordStrengthEnum | undefined; |
| * Password Strength Options Interface | ||
| */ | ||
| export interface PasswordStrengthOptionsInterface { | ||
| passwordStrength?: PasswordStrengthEnum | null; |
There was a problem hiding this comment.
undefined is better
| passwordStrength?: PasswordStrengthEnum | null; | |
| passwordStrength?: PasswordStrengthEnum | undefined; |
| !this.passwordStrengthService.isStrong(password, { | ||
| passwordStrength: options?.passwordStrength, | ||
| }) |
There was a problem hiding this comment.
should we have a try/catch here?
| ): boolean { | ||
| const { passwordStrength } = options || {}; | ||
|
|
||
| // TODO: Should we allow overriding the minimum password strength even if the provided strength is lower than the configured minimum? |
There was a problem hiding this comment.
did you align with Gabriel on this point?
There was a problem hiding this comment.
Yes, what ever user define with the roles should overwrite
| passwordStrength || | ||
| this.settings?.minPasswordStrength || | ||
| PasswordStrengthEnum.None; |
There was a problem hiding this comment.
coalesce is safer i think in case strength is explicitly zero? recommend test coverage to be sure.
| passwordStrength || | |
| this.settings?.minPasswordStrength || | |
| PasswordStrengthEnum.None; | |
| passwordStrength ?? | |
| this.settings?.minPasswordStrength ?? | |
| PasswordStrengthEnum.None; |
| */ | ||
| getUserRoles( | ||
| userDto: UserRolesInterface, | ||
| userToUpdateId?: ReferenceId, |
There was a problem hiding this comment.
i think this is redundant, it would always be the id in the UserDto
There was a problem hiding this comment.
Not always, on create user for example we wont have a userId inside dto, however now that i review maybe we can remove the dto from this function, and keep function only to get roles based on user id, like

then i can verify before i call this function if i actually need it
this.userRoleService.resolvePasswordStrength
| * @returns Array of role names, or empty array if no roles found | ||
| */ | ||
| getUserRoles( | ||
| userDto: UserRolesInterface, |
There was a problem hiding this comment.
should require the user id on the object?
| userDto: UserRolesInterface, | |
| userDto: ReferenceIdInterface & UserRolesInterface, |
There was a problem hiding this comment.
maybe we dont even need that object anymore, it was only being used to get the userRoles of it
| */ | ||
| resolvePasswordStrength( | ||
| roles?: RoleOwnableInterface[], | ||
| ): PasswordStrengthEnum | null | undefined; |
There was a problem hiding this comment.
i think null doesn't make sense
| ): PasswordStrengthEnum | null | undefined; | |
| ): PasswordStrengthEnum | undefined; |
|
|
||
| protected async transform<T extends DeepPartial<UserEntityInterface>>( | ||
| user: T | (T & PasswordPlainInterface), | ||
| user: T | (T & PasswordPlainInterface & UserRolesInterface), |
There was a problem hiding this comment.
adding roles interface like this is slightly weird because the only property is optional, we need to review this.
There was a problem hiding this comment.
we need this to pass to getPasswordStrength to be able to get strength based on roles
| @Optional() | ||
| @Inject(UserRoleService) | ||
| private userRoleService?: UserRoleServiceInterface, |
There was a problem hiding this comment.
should be last parameter for better back compat
| this.userRoleService.getUserRoles && | ||
| this.userRoleService.resolvePasswordStrength |
There was a problem hiding this comment.
if you need to check that these methods exist, is a weird smell
There was a problem hiding this comment.
true, i had injected wrong service, thats why lol,
| const roles = await this.userRoleService.getUserRoles( | ||
| userDto, | ||
| userToUpdateId, | ||
| ); | ||
| passwordStrength = await this.userRoleService.resolvePasswordStrength( | ||
| roles, | ||
| ); |
There was a problem hiding this comment.
we should only be making one call to the service, resolving the roles here is not necessary
There was a problem hiding this comment.
lets discuss this one
| const user: (ReferenceIdInterface<string> & UserRolesInterface) | null = | ||
| await this.userLookupService.byId(userToUpdateId); |
| if (userToUpdateId) { | ||
| const user: (ReferenceIdInterface<string> & UserRolesInterface) | null = | ||
| await this.userLookupService.byId(userToUpdateId); | ||
| if (user && user.userRoles) return user.userRoles; |
| } | ||
|
|
||
| // get roles from payload | ||
| if (userDto.userRoles && userDto.userRoles.length > 0) |
| return ( | ||
| roles && | ||
| this.userSettings.passwordStrength?.passwordStrengthTransform && | ||
| this.userSettings.passwordStrength?.passwordStrengthTransform({ roles }) |
There was a problem hiding this comment.
must have a try/catch on this
| } | ||
|
|
||
| export type PasswordStrengthTransform = ( | ||
| options: PasswordStrengthTransformOptionsInterface, |
There was a problem hiding this comment.
options parameter should be optional
| options: PasswordStrengthTransformOptionsInterface, | |
| options?: PasswordStrengthTransformOptionsInterface, |
|
|
||
| export type PasswordStrengthTransform = ( | ||
| options: PasswordStrengthTransformOptionsInterface, | ||
| ) => PasswordStrengthEnum | null; |
There was a problem hiding this comment.
undefined is better than null
| ) => PasswordStrengthEnum | null; | |
| ) => PasswordStrengthEnum | undefined; |
|
|
||
| export const defaultPasswordStrengthTransform: PasswordStrengthTransform = ( | ||
| options: PasswordStrengthTransformOptionsInterface, | ||
| ): PasswordStrengthEnum | null => { |
There was a problem hiding this comment.
undefined is better than null
| ): PasswordStrengthEnum | null => { | |
| ): PasswordStrengthEnum | undefined => { |
| import { PasswordStrengthTransformOptionsInterface } from '@concepta/nestjs-common'; | ||
|
|
||
| export const defaultPasswordStrengthTransform: PasswordStrengthTransform = ( | ||
| options: PasswordStrengthTransformOptionsInterface, |
There was a problem hiding this comment.
options parameter should be optional
| options: PasswordStrengthTransformOptionsInterface, | |
| options?: PasswordStrengthTransformOptionsInterface, |
| ): PasswordStrengthEnum | null => { | ||
| const { roles } = options; | ||
|
|
||
| if (roles.some((role) => role.role?.name === 'admin')) { |
There was a problem hiding this comment.
role param in lambda needs to be typed
| if (roles.some((role) => role.role?.name === 'admin')) { | ||
| return PasswordStrengthEnum.VeryStrong; | ||
| } | ||
| if (roles.some((role) => role.role?.name === 'user')) { |
There was a problem hiding this comment.
role param in lambda needs to be typed
Defining password strength based on role