feat(API): Implement users account quota guards (#6434)

* feat(cli): Implement users account quota guards

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Remove comment

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Address PR comments

- Getting `usersQuota` from `Settings` repo
- Revert `isUserManagementEnabled` helper
- Fix FE listing of users

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Refactor isWithinUserQuota getter and fix tests

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Revert testDb.ts changes

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Cleanup & improve types

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Fix duplicated method

* Fix failing test

* Remove `isUserManagementEnabled` completely

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Check for globalRole.name to determine if user is owner

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Fix unit tests

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Set isInstanceOwnerSetUp in specs

* Fix SettingsUserView UM

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* refactor: License typings suggestions for users quota guards (#6636)

refactor: License typings suggestions

* Update packages/cli/src/Ldap/helpers.ts

Co-authored-by: Iván Ovejero <ivov.src@gmail.com>

* Update packages/cli/test/integration/shared/utils.ts

Co-authored-by: Iván Ovejero <ivov.src@gmail.com>

* Address PR comments

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

* Use 403 for all user quota related errors

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>

---------

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
This commit is contained in:
OlegIvaniv
2023-07-12 14:11:46 +02:00
committed by GitHub
parent 26046f6fe8
commit e5620ab1e4
33 changed files with 271 additions and 94 deletions

View File

@@ -23,8 +23,11 @@ import { PasswordResetRequest } from '@/requests';
import type { IDatabaseCollections, IExternalHooksClass, IInternalHooksClass } from '@/Interfaces';
import { issueCookie } from '@/auth/jwt';
import { isLdapEnabled } from '@/Ldap/helpers';
import { isSamlCurrentAuthenticationMethod } from '../sso/ssoHelpers';
import { UserService } from '../user/user.service';
import { isSamlCurrentAuthenticationMethod } from '@/sso/ssoHelpers';
import { UserService } from '@/user/user.service';
import { License } from '@/License';
import { Container } from 'typedi';
import { RESPONSE_ERROR_MESSAGES } from '@/constants';
@RestController()
export class PasswordResetController {
@@ -103,6 +106,12 @@ export class PasswordResetController {
relations: ['authIdentities', 'globalRole'],
});
if (!user?.isOwner && !Container.get(License).isWithinUsersLimit()) {
this.logger.debug(
'Request to send password reset email failed because the user limit was reached',
);
throw new UnauthorizedError(RESPONSE_ERROR_MESSAGES.USERS_QUOTA_REACHED);
}
if (
isSamlCurrentAuthenticationMethod() &&
!(user?.globalRole.name === 'owner' || user?.settings?.allowSSOManualLogin === true)
@@ -116,7 +125,6 @@ export class PasswordResetController {
}
const ldapIdentity = user?.authIdentities?.find((i) => i.providerType === 'ldap');
if (!user?.password || (ldapIdentity && user.disabled)) {
this.logger.debug(
'Request to send password reset email failed because no user was found for the provided email',
@@ -182,12 +190,21 @@ export class PasswordResetController {
// Timestamp is saved in seconds
const currentTimestamp = Math.floor(Date.now() / 1000);
const user = await this.userRepository.findOneBy({
id,
resetPasswordToken,
resetPasswordTokenExpiration: MoreThanOrEqual(currentTimestamp),
const user = await this.userRepository.findOne({
where: {
id,
resetPasswordToken,
resetPasswordTokenExpiration: MoreThanOrEqual(currentTimestamp),
},
relations: ['globalRole'],
});
if (!user?.isOwner && !Container.get(License).isWithinUsersLimit()) {
this.logger.debug(
'Request to resolve password token failed because the user limit was reached',
{ userId: id },
);
throw new UnauthorizedError(RESPONSE_ERROR_MESSAGES.USERS_QUOTA_REACHED);
}
if (!user) {
this.logger.debug(
'Request to resolve password token failed because no user was found for the provided user ID and reset password token',