[Permissions] Implement getRoles (#9955)
In this PR - introducing roles module to separate roles logic (assign a Role, get a workspace's roles etc.) from permission logic (check if a user has a permission) - Introduces getRoles endpoint to fetch a workspace's roles - introduces the first permission check: getRoles in only accessible to users with permission on ROLE setting. Implemented validatesUserHasWorkspaceSettingPermissionOrThrow
This commit is contained in:
@ -3,8 +3,10 @@ import { Module } from '@nestjs/common';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { RelationMetadataModule } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.module';
|
||||
import { RemoteServerModule } from 'src/engine/metadata-modules/remote-server/remote-server.module';
|
||||
import { RoleModule } from 'src/engine/metadata-modules/role/role.module';
|
||||
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
@ -19,6 +21,8 @@ import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-
|
||||
WorkspaceMetadataVersionModule,
|
||||
WorkspaceMigrationModule,
|
||||
RemoteServerModule,
|
||||
RoleModule,
|
||||
PermissionsModule,
|
||||
],
|
||||
providers: [],
|
||||
exports: [
|
||||
@ -28,6 +32,8 @@ import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-
|
||||
RelationMetadataModule,
|
||||
ServerlessFunctionModule,
|
||||
RemoteServerModule,
|
||||
RoleModule,
|
||||
PermissionsModule,
|
||||
],
|
||||
})
|
||||
export class MetadataEngineModule {}
|
||||
|
||||
@ -12,4 +12,6 @@ export enum PermissionsExceptionCode {
|
||||
USER_WORKSPACE_NOT_FOUND = 'USER_WORKSPACE_NOT_FOUND',
|
||||
WORKSPACE_ID_ROLE_USER_WORKSPACE_MISMATCH = 'WORKSPACE_ID_ROLE_USER_WORKSPACE_MISMATCH',
|
||||
TOO_MANY_ADMIN_CANDIDATES = 'TOO_MANY_ADMIN_CANDIDATES',
|
||||
USER_WORKSPACE_ALREADY_HAS_ROLE = 'USER_WORKSPACE_ALREADY_HAS_ROLE',
|
||||
PERMISSION_DENIED = 'PERMISSION_DENIED',
|
||||
}
|
||||
|
||||
@ -1,17 +1,21 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { EnvironmentModule } from 'src/engine/core-modules/environment/environment.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/permissions/role.entity';
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/permissions/user-workspace-role.entity';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/role/user-workspace-role.entity';
|
||||
import { UserRoleModule } from 'src/engine/metadata-modules/userRole/userRole.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([RoleEntity, UserWorkspaceRoleEntity], 'metadata'),
|
||||
FeatureFlagModule,
|
||||
TypeOrmModule.forFeature([UserWorkspace], 'core'),
|
||||
EnvironmentModule,
|
||||
UserRoleModule,
|
||||
],
|
||||
providers: [PermissionsService],
|
||||
exports: [PermissionsService],
|
||||
|
||||
@ -1,71 +1,62 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import { SettingsFeatures } from 'twenty-shared';
|
||||
|
||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { ADMIN_ROLE_LABEL } from 'src/engine/metadata-modules/permissions/constants/admin-role-label.constants';
|
||||
import {
|
||||
PermissionsException,
|
||||
PermissionsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/permissions/permissions.exception';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/permissions/role.entity';
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/permissions/user-workspace-role.entity';
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/userRole/userRole.service';
|
||||
|
||||
@Injectable()
|
||||
export class PermissionsService {
|
||||
constructor(
|
||||
@InjectRepository(RoleEntity, 'metadata')
|
||||
private readonly roleRepository: Repository<RoleEntity>,
|
||||
@InjectRepository(UserWorkspaceRoleEntity, 'metadata')
|
||||
private readonly userWorkspaceRoleRepository: Repository<UserWorkspaceRoleEntity>,
|
||||
@InjectRepository(UserWorkspace, 'core')
|
||||
private readonly userWorkspaceRepository: Repository<UserWorkspace>,
|
||||
private readonly environmentService: EnvironmentService,
|
||||
private readonly userRoleService: UserRoleService,
|
||||
) {}
|
||||
|
||||
public async createAdminRole({
|
||||
workspaceId,
|
||||
public async getUserWorkspaceSettingsPermissions({
|
||||
userWorkspaceId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
}): Promise<RoleEntity> {
|
||||
return this.roleRepository.save({
|
||||
label: ADMIN_ROLE_LABEL,
|
||||
description: 'Admin role',
|
||||
canUpdateAllSettings: true,
|
||||
isEditable: false,
|
||||
workspaceId,
|
||||
});
|
||||
userWorkspaceId: string;
|
||||
}): Promise<Record<SettingsFeatures, boolean>> {
|
||||
const roleOfUserWorkspace =
|
||||
await this.userRoleService.getRoleForUserWorkspace(userWorkspaceId);
|
||||
|
||||
let hasPermissionOnSettingFeature = false;
|
||||
|
||||
if (roleOfUserWorkspace?.canUpdateAllSettings === true) {
|
||||
hasPermissionOnSettingFeature = true;
|
||||
}
|
||||
|
||||
return Object.keys(SettingsFeatures).reduce(
|
||||
(acc, feature) => ({
|
||||
...acc,
|
||||
[feature]: hasPermissionOnSettingFeature,
|
||||
}),
|
||||
{} as Record<SettingsFeatures, boolean>,
|
||||
);
|
||||
}
|
||||
|
||||
public async assignRoleToUserWorkspace({
|
||||
workspaceId,
|
||||
public async validateUserHasWorkspaceSettingPermissionOrThrow({
|
||||
userWorkspaceId,
|
||||
roleId,
|
||||
setting,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
userWorkspaceId: string;
|
||||
roleId: string;
|
||||
setting: SettingsFeatures;
|
||||
}): Promise<void> {
|
||||
const userWorkspace = await this.userWorkspaceRepository.findOne({
|
||||
where: {
|
||||
id: userWorkspaceId,
|
||||
},
|
||||
});
|
||||
const userWorkspaceRole =
|
||||
await this.userRoleService.getRoleForUserWorkspace(userWorkspaceId);
|
||||
|
||||
if (!isDefined(userWorkspace)) {
|
||||
throw new PermissionsException(
|
||||
'User workspace not found',
|
||||
PermissionsExceptionCode.USER_WORKSPACE_NOT_FOUND,
|
||||
);
|
||||
if (userWorkspaceRole?.canUpdateAllSettings === true) {
|
||||
return;
|
||||
}
|
||||
await this.userWorkspaceRoleRepository.save({
|
||||
roleId,
|
||||
userWorkspaceId: userWorkspace.id,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
throw new PermissionsException(
|
||||
`User does not have permission to update this setting: ${setting}`,
|
||||
PermissionsExceptionCode.PERMISSION_DENIED,
|
||||
);
|
||||
}
|
||||
|
||||
public async isPermissionsEnabled(): Promise<boolean> {
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
import {
|
||||
ForbiddenError,
|
||||
InternalServerError,
|
||||
} from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import {
|
||||
PermissionsException,
|
||||
PermissionsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/permissions/permissions.exception';
|
||||
|
||||
export const permissionsGraphqlApiExceptionHandler = (error: Error) => {
|
||||
if (error instanceof PermissionsException) {
|
||||
switch (error.code) {
|
||||
case PermissionsExceptionCode.PERMISSION_DENIED:
|
||||
throw new ForbiddenError(error.message);
|
||||
default:
|
||||
throw new InternalServerError(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
throw error;
|
||||
};
|
||||
@ -0,0 +1,30 @@
|
||||
import { Field, HideField, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { Relation } from 'typeorm';
|
||||
|
||||
import { WorkspaceMember } from 'src/engine/core-modules/user/dtos/workspace-member.dto';
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/role/user-workspace-role.entity';
|
||||
|
||||
@ObjectType()
|
||||
export class RoleDTO {
|
||||
@Field({ nullable: false })
|
||||
id: string;
|
||||
|
||||
@Field({ nullable: false })
|
||||
label: string;
|
||||
|
||||
@Field({ nullable: false })
|
||||
canUpdateAllSettings: boolean;
|
||||
|
||||
@Field({ nullable: true })
|
||||
description: string;
|
||||
|
||||
@Field({ nullable: false })
|
||||
isEditable: boolean;
|
||||
|
||||
@HideField()
|
||||
userWorkspaceRoles: Relation<UserWorkspaceRoleEntity[]>;
|
||||
|
||||
@Field(() => [WorkspaceMember], { nullable: true })
|
||||
workspaceMembers?: WorkspaceMember[];
|
||||
}
|
||||
@ -8,7 +8,7 @@ import {
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/permissions/user-workspace-role.entity';
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/role/user-workspace-role.entity';
|
||||
|
||||
@Entity('role')
|
||||
export class RoleEntity {
|
||||
@ -0,0 +1,22 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { RoleResolver } from 'src/engine/metadata-modules/role/role.resolver';
|
||||
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/role/user-workspace-role.entity';
|
||||
import { UserRoleModule } from 'src/engine/metadata-modules/userRole/userRole.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([RoleEntity, UserWorkspaceRoleEntity], 'metadata'),
|
||||
TypeOrmModule.forFeature([UserWorkspace], 'core'),
|
||||
UserRoleModule,
|
||||
PermissionsModule,
|
||||
],
|
||||
providers: [RoleService, RoleResolver],
|
||||
exports: [RoleService],
|
||||
})
|
||||
export class RoleModule {}
|
||||
@ -0,0 +1,65 @@
|
||||
import { Parent, Query, ResolveField, Resolver } from '@nestjs/graphql';
|
||||
|
||||
import { SettingsFeatures } from 'twenty-shared';
|
||||
|
||||
import { WorkspaceMember } from 'src/engine/core-modules/user/dtos/workspace-member.dto';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthUserWorkspaceId } from 'src/engine/decorators/auth/auth-user-workspace-id.decorator';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
|
||||
import { permissionsGraphqlApiExceptionHandler } from 'src/engine/metadata-modules/permissions/utils/permissions-graphql-api-exception-handler';
|
||||
import { RoleDTO } from 'src/engine/metadata-modules/role/dtos/role.dto';
|
||||
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/userRole/userRole.service';
|
||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
|
||||
@Resolver(() => RoleDTO)
|
||||
export class RoleResolver {
|
||||
constructor(
|
||||
private readonly userRoleService: UserRoleService,
|
||||
private readonly permissionsService: PermissionsService,
|
||||
private readonly roleService: RoleService,
|
||||
) {}
|
||||
|
||||
@Query(() => [RoleDTO])
|
||||
async getRoles(
|
||||
@AuthUserWorkspaceId() userWorkspaceId: string,
|
||||
@AuthWorkspace() workspace: Workspace,
|
||||
): Promise<RoleDTO[]> {
|
||||
try {
|
||||
await this.permissionsService.validateUserHasWorkspaceSettingPermissionOrThrow(
|
||||
{
|
||||
userWorkspaceId,
|
||||
setting: SettingsFeatures.ROLES,
|
||||
},
|
||||
);
|
||||
|
||||
const roles = await this.roleService.getWorkspaceRoles(workspace.id);
|
||||
|
||||
return roles.map((role) => ({
|
||||
id: role.id,
|
||||
label: role.label,
|
||||
canUpdateAllSettings: role.canUpdateAllSettings,
|
||||
description: role.description,
|
||||
workspaceId: role.workspaceId,
|
||||
createdAt: role.createdAt,
|
||||
updatedAt: role.updatedAt,
|
||||
isEditable: role.isEditable,
|
||||
userWorkspaceRoles: role.userWorkspaceRoles,
|
||||
}));
|
||||
} catch (error) {
|
||||
return permissionsGraphqlApiExceptionHandler(error);
|
||||
}
|
||||
}
|
||||
|
||||
@ResolveField('workspaceMembers', () => [WorkspaceMember])
|
||||
async getWorkspaceMembersAssignedToRole(
|
||||
@Parent() role: RoleDTO,
|
||||
@AuthWorkspace() workspace: Workspace,
|
||||
): Promise<WorkspaceMemberWorkspaceEntity[]> {
|
||||
return this.userRoleService.getWorkspaceMembersAssignedToRole(
|
||||
role.id,
|
||||
workspace.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { ADMIN_ROLE_LABEL } from 'src/engine/metadata-modules/permissions/constants/admin-role-label.constants';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
|
||||
export class RoleService {
|
||||
constructor(
|
||||
@InjectRepository(RoleEntity, 'metadata')
|
||||
private readonly roleRepository: Repository<RoleEntity>,
|
||||
) {}
|
||||
|
||||
public async getWorkspaceRoles(workspaceId: string): Promise<RoleEntity[]> {
|
||||
return this.roleRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
},
|
||||
relations: ['userWorkspaceRoles'],
|
||||
});
|
||||
}
|
||||
|
||||
public async createAdminRole({
|
||||
workspaceId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
}): Promise<RoleEntity> {
|
||||
return this.roleRepository.save({
|
||||
label: ADMIN_ROLE_LABEL,
|
||||
description: 'Admin role',
|
||||
canUpdateAllSettings: true,
|
||||
isEditable: false,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@ import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
Relation,
|
||||
@ -9,7 +10,7 @@ import {
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/permissions/role.entity';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
|
||||
@Entity('userWorkspaceRole')
|
||||
@Unique('IndexOnUserWorkspaceRoleUnique', ['userWorkspaceId', 'roleId'])
|
||||
@ -26,6 +27,7 @@ export class UserWorkspaceRoleEntity {
|
||||
@ManyToOne(() => RoleEntity, (role) => role.userWorkspaceRoles, {
|
||||
onDelete: 'CASCADE',
|
||||
})
|
||||
@JoinColumn({ name: 'roleId' })
|
||||
role: Relation<RoleEntity>;
|
||||
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
@ -0,0 +1,17 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/role/user-workspace-role.entity';
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/userRole/userRole.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([RoleEntity, UserWorkspaceRoleEntity], 'metadata'),
|
||||
TypeOrmModule.forFeature([UserWorkspace], 'core'),
|
||||
],
|
||||
providers: [UserRoleService],
|
||||
exports: [UserRoleService],
|
||||
})
|
||||
export class UserRoleModule {}
|
||||
@ -0,0 +1,148 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import isEmpty from 'lodash.isempty';
|
||||
import { isDefined } from 'twenty-shared';
|
||||
import { In, Repository } from 'typeorm';
|
||||
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import {
|
||||
PermissionsException,
|
||||
PermissionsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/permissions/permissions.exception';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/role/user-workspace-role.entity';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
|
||||
export class UserRoleService {
|
||||
constructor(
|
||||
@InjectRepository(RoleEntity, 'metadata')
|
||||
private readonly roleRepository: Repository<RoleEntity>,
|
||||
@InjectRepository(UserWorkspaceRoleEntity, 'metadata')
|
||||
private readonly userWorkspaceRoleRepository: Repository<UserWorkspaceRoleEntity>,
|
||||
@InjectRepository(UserWorkspace, 'core')
|
||||
private readonly userWorkspaceRepository: Repository<UserWorkspace>,
|
||||
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
) {}
|
||||
|
||||
public async unassignRolesFromUserWorkspace({
|
||||
userWorkspaceId,
|
||||
workspaceId,
|
||||
}: {
|
||||
userWorkspaceId: string;
|
||||
workspaceId: string;
|
||||
}): Promise<void> {
|
||||
const userWorkspaceRoles = await this.userWorkspaceRoleRepository.find({
|
||||
where: {
|
||||
userWorkspaceId,
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!isEmpty(userWorkspaceRoles)) {
|
||||
userWorkspaceRoles.forEach(async (userWorkspaceRole) => {
|
||||
await this.userWorkspaceRoleRepository.delete({
|
||||
id: userWorkspaceRole.id,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async assignRoleToUserWorkspace({
|
||||
workspaceId,
|
||||
userWorkspaceId,
|
||||
roleId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
userWorkspaceId: string;
|
||||
roleId: string;
|
||||
}): Promise<void> {
|
||||
const userWorkspace = await this.userWorkspaceRepository.findOne({
|
||||
where: {
|
||||
id: userWorkspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!isDefined(userWorkspace)) {
|
||||
throw new PermissionsException(
|
||||
'User workspace not found',
|
||||
PermissionsExceptionCode.USER_WORKSPACE_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
await this.unassignRolesFromUserWorkspace({
|
||||
userWorkspaceId: userWorkspace.id,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.userWorkspaceRoleRepository.save({
|
||||
roleId,
|
||||
userWorkspaceId: userWorkspace.id,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
public async getRoleForUserWorkspace(
|
||||
userWorkspaceId: string,
|
||||
): Promise<RoleEntity | null> {
|
||||
if (!isDefined(userWorkspaceId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const userWorkspaceRole = await this.userWorkspaceRoleRepository.findOne({
|
||||
where: {
|
||||
userWorkspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!isDefined(userWorkspaceRole)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return await this.roleRepository.findOne({
|
||||
where: {
|
||||
id: userWorkspaceRole.roleId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public async getWorkspaceMembersAssignedToRole(
|
||||
roleId: string,
|
||||
workspaceId: string,
|
||||
): Promise<WorkspaceMemberWorkspaceEntity[]> {
|
||||
const userWorkspaceRoles = await this.userWorkspaceRoleRepository.find({
|
||||
where: {
|
||||
roleId,
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
const userIds = await this.userWorkspaceRepository
|
||||
.find({
|
||||
where: {
|
||||
id: In(
|
||||
userWorkspaceRoles.map(
|
||||
(userWorkspaceRole) => userWorkspaceRole.userWorkspaceId,
|
||||
),
|
||||
),
|
||||
},
|
||||
})
|
||||
.then((userWorkspaces) =>
|
||||
userWorkspaces.map((userWorkspace) => userWorkspace.userId),
|
||||
);
|
||||
|
||||
const workspaceMemberRepository =
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workspaceMember',
|
||||
);
|
||||
|
||||
const workspaceMembers = await workspaceMemberRepository.find({
|
||||
where: {
|
||||
userId: In(userIds),
|
||||
},
|
||||
});
|
||||
|
||||
return workspaceMembers;
|
||||
}
|
||||
}
|
||||
@ -146,6 +146,7 @@ export class MiddlewareService {
|
||||
request.workspaceId = data.workspace.id;
|
||||
request.workspaceMetadataVersion = metadataVersion;
|
||||
request.workspaceMemberId = data.workspaceMemberId;
|
||||
request.userWorkspaceId = data.userWorkspaceId;
|
||||
}
|
||||
|
||||
private getStatus(error: any): number {
|
||||
|
||||
@ -6,6 +6,8 @@ import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-works
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { RoleModule } from 'src/engine/metadata-modules/role/role.module';
|
||||
import { UserRoleModule } from 'src/engine/metadata-modules/userRole/userRole.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
import { SeederModule } from 'src/engine/seeder/seeder.module';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
@ -26,6 +28,8 @@ import { WorkspaceManagerService } from './workspace-manager.service';
|
||||
FeatureFlagModule,
|
||||
PermissionsModule,
|
||||
TypeOrmModule.forFeature([UserWorkspace], 'core'),
|
||||
RoleModule,
|
||||
UserRoleModule,
|
||||
],
|
||||
exports: [WorkspaceManagerService],
|
||||
providers: [WorkspaceManagerService],
|
||||
|
||||
@ -13,6 +13,8 @@ import {
|
||||
PermissionsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/permissions/permissions.exception';
|
||||
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
|
||||
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/userRole/userRole.service';
|
||||
import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service';
|
||||
import { PETS_DATA_SEEDS } from 'src/engine/seeder/data-seeds/pets-data-seeds';
|
||||
import { SURVEY_RESULTS_DATA_SEEDS } from 'src/engine/seeder/data-seeds/survey-results-data-seeds';
|
||||
@ -36,6 +38,8 @@ export class WorkspaceManagerService {
|
||||
private readonly permissionsService: PermissionsService,
|
||||
@InjectRepository(UserWorkspace, 'core')
|
||||
private readonly userWorkspaceRepository: Repository<UserWorkspace>,
|
||||
private readonly roleService: RoleService,
|
||||
private readonly userRoleService: UserRoleService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@ -188,7 +192,7 @@ export class WorkspaceManagerService {
|
||||
}
|
||||
|
||||
private async initPermissions(workspaceId: string) {
|
||||
const adminRole = await this.permissionsService.createAdminRole({
|
||||
const adminRole = await this.roleService.createAdminRole({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
@ -212,7 +216,7 @@ export class WorkspaceManagerService {
|
||||
);
|
||||
}
|
||||
|
||||
await this.permissionsService.assignRoleToUserWorkspace({
|
||||
await this.userRoleService.assignRoleToUserWorkspace({
|
||||
workspaceId,
|
||||
userWorkspaceId: userWorkspace[0].id,
|
||||
roleId: adminRole.id,
|
||||
|
||||
9
packages/twenty-shared/src/constants/SettingsFeatures.ts
Normal file
9
packages/twenty-shared/src/constants/SettingsFeatures.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export enum SettingsFeatures {
|
||||
API_KEYS_AND_WEBHOOKS = 'API_KEYS_AND_WEBHOOKS',
|
||||
WORKSPACE_SETTINGS = 'WORKSPACE_SETTINGS',
|
||||
WORKSPACE_USERS = 'WORKSPACE_USERS',
|
||||
ROLES = 'WORKSPACE_ROLES',
|
||||
DATA_MODEL = 'DATA_MODEL',
|
||||
ADMIN_PANEL = 'ADMIN_PANEL',
|
||||
SECURITY_SETTINGS = 'SECURITY_SETTINGS',
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
export * from './constants/FieldForTotalCountAggregateOperation';
|
||||
export * from './constants/Locales';
|
||||
export * from './constants/SettingsFeatures';
|
||||
export * from './constants/TwentyCompaniesBaseUrl';
|
||||
export * from './constants/TwentyIconsBaseUrl';
|
||||
export * from './types/ConnectedAccountProvider';
|
||||
|
||||
Reference in New Issue
Block a user