Fix Admin control to disable workspace creation for non-admin users (#14895)
fix #13460 --------- Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
@@ -490,6 +490,10 @@ export class AuthResolver {
|
||||
@AuthUser() currentUser: User,
|
||||
@AuthProvider() authProvider: AuthProviderEnum,
|
||||
): Promise<SignUpOutput> {
|
||||
await this.signInUpService.checkWorkspaceCreationIsAllowedOrThrow(
|
||||
currentUser,
|
||||
);
|
||||
|
||||
const { user, workspace } = await this.signInUpService.signUpOnNewWorkspace(
|
||||
{ type: 'existingUser', existingUser: currentUser },
|
||||
);
|
||||
|
||||
@@ -355,6 +355,36 @@ export class SignInUpService {
|
||||
return { canImpersonate: false, canAccessFullAdminPanel: false };
|
||||
}
|
||||
|
||||
private isWorkspaceCreationLimitedToServerAdmins(): boolean {
|
||||
return this.twentyConfigService.get(
|
||||
'IS_WORKSPACE_CREATION_LIMITED_TO_SERVER_ADMINS',
|
||||
);
|
||||
}
|
||||
|
||||
private async isFirstWorkspaceForUser(userId: string): Promise<boolean> {
|
||||
const count = await this.userWorkspaceService.countUserWorkspaces(userId);
|
||||
|
||||
return count === 0;
|
||||
}
|
||||
|
||||
async checkWorkspaceCreationIsAllowedOrThrow(
|
||||
currentUser: User,
|
||||
): Promise<void> {
|
||||
if (!this.isWorkspaceCreationLimitedToServerAdmins()) return;
|
||||
|
||||
if (await this.isFirstWorkspaceForUser(currentUser.id)) return;
|
||||
|
||||
if (!currentUser.canAccessFullAdminPanel) {
|
||||
throw new AuthException(
|
||||
'Workspace creation is restricted to admins',
|
||||
AuthExceptionCode.FORBIDDEN_EXCEPTION,
|
||||
{
|
||||
userFriendlyMessage: t`Workspace creation is restricted to admins`,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async signUpOnNewWorkspace(
|
||||
userData: ExistingUserOrPartialUserWithPicture['userData'],
|
||||
) {
|
||||
|
||||
@@ -358,6 +358,15 @@ export class ConfigVariables {
|
||||
})
|
||||
EMAIL_SMTP_PASSWORD: string;
|
||||
|
||||
@ConfigVariablesMetadata({
|
||||
group: ConfigVariablesGroup.Other,
|
||||
description:
|
||||
'When enabled, only server admins can create new workspaces. Ignored during initial setup when no workspace exists.',
|
||||
type: ConfigVariableType.BOOLEAN,
|
||||
})
|
||||
@IsOptional()
|
||||
IS_WORKSPACE_CREATION_LIMITED_TO_SERVER_ADMINS = false;
|
||||
|
||||
@ConfigVariablesMetadata({
|
||||
group: ConfigVariablesGroup.StorageConfig,
|
||||
description: 'Type of storage to use (local or S3)',
|
||||
|
||||
+4
@@ -217,6 +217,10 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspace> {
|
||||
return workspace;
|
||||
}
|
||||
|
||||
async countUserWorkspaces(userId: string): Promise<number> {
|
||||
return await this.userWorkspaceRepository.count({ where: { userId } });
|
||||
}
|
||||
|
||||
async findAvailableWorkspacesByEmail(email: string) {
|
||||
const user = await this.userRepository.findOne({
|
||||
where: {
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ describe('roles permissions', () => {
|
||||
|
||||
expect(resp.status).toBe(200);
|
||||
expect(resp.body.errors).toBeUndefined();
|
||||
expect(resp.body.data.getRoles).toHaveLength(5);
|
||||
expect(resp.body.data.getRoles).toHaveLength(7);
|
||||
|
||||
const roles = resp.body.data.getRoles;
|
||||
const guestRole = roles.find((role: any) => role.label === 'Guest');
|
||||
|
||||
Reference in New Issue
Block a user