[demo] Allow workspace to work with a non-system workspaceMember object (#15547)
For demo purposes, we want to work with workspaceMember has a non-system object, allowing it to be displayed on the product, to be added custom fields etc. It is something we may want to do later anyway. This PR adds a bypassPermissionChecks on workspaceMember repository calls. This does not provide more permissions than before for other workspaces: workspaceMember being a system object, permissions are already bypassed for this one. (Note that actions such inviting a new workspaceMember, updating a workspaceMember are protected by a system permission checked in the relevant places). This work does **not** allow any workspace to switch their workspaceMember object to non-system, the switch is still manual.
This commit is contained in:
+2
-1
@@ -7,13 +7,13 @@ import { Repository } from 'typeorm';
|
||||
import { buildCreatedByFromApiKey } from 'src/engine/core-modules/actor/utils/build-created-by-from-api-key.util';
|
||||
import { buildCreatedByFromFullNameMetadata } from 'src/engine/core-modules/actor/utils/build-created-by-from-full-name-metadata.util';
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
import { type ActorMetadata } from 'src/engine/metadata-modules/field-metadata/composite-types/actor.composite-type';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { getObjectMetadataMapItemByNameSingular } from 'src/engine/metadata-modules/utils/get-object-metadata-map-item-by-name-singular.util';
|
||||
import { WorkspaceMetadataCacheService } from 'src/engine/metadata-modules/workspace-metadata-cache/services/workspace-metadata-cache.service';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
import { WorkspaceNotFoundDefaultError } from 'src/engine/core-modules/workspace/workspace.exception';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type CreateInput = Record<string, any>;
|
||||
@@ -119,6 +119,7 @@ export class CreatedByFromAuthContextService {
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspace.id,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const workspaceMember = await workspaceMemberRepository.findOneOrFail({
|
||||
|
||||
+1
@@ -40,6 +40,7 @@ export class ApprovedAccessDomainResolver {
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
currentWorkspace.id,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const workspaceMember = await workspaceMemberRepository.findOneOrFail({
|
||||
|
||||
@@ -173,6 +173,7 @@ export class GoogleAPIsService {
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const workspaceMember = await workspaceMemberRepository.findOneOrFail(
|
||||
|
||||
+1
@@ -82,6 +82,7 @@ export class AccessTokenService {
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const workspaceMember = await workspaceMemberRepository.findOne({
|
||||
|
||||
+3
-1
@@ -885,7 +885,9 @@ describe('UserWorkspaceService', () => {
|
||||
|
||||
expect(
|
||||
twentyORMGlobalManager.getRepositoryForWorkspace,
|
||||
).toHaveBeenCalledWith(workspaceId, 'workspaceMember');
|
||||
).toHaveBeenCalledWith(workspaceId, 'workspaceMember', {
|
||||
shouldBypassPermissionChecks: true,
|
||||
});
|
||||
expect(workspaceMemberRepository.findOne).toHaveBeenCalledWith({
|
||||
where: {
|
||||
id: workspaceMemberId,
|
||||
|
||||
+2
@@ -86,6 +86,7 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspaceEntit
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const userWorkspace = await this.userWorkspaceRepository.findOneOrFail({
|
||||
@@ -314,6 +315,7 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspaceEntit
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const workspaceMember = await workspaceMemberRepository.findOne({
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import { Test, type TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
|
||||
import { type Repository } from 'typeorm';
|
||||
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
|
||||
import { type Repository } from 'typeorm';
|
||||
|
||||
import { type WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
|
||||
import { AuthException } from 'src/engine/core-modules/auth/auth.exception';
|
||||
import { UserService } from 'src/engine/core-modules/user/services/user.service';
|
||||
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
|
||||
import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
|
||||
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
import { AuthException } from 'src/engine/core-modules/auth/auth.exception';
|
||||
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import {
|
||||
PermissionsException,
|
||||
PermissionsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/permissions/permissions.exception';
|
||||
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
|
||||
import { type WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
|
||||
describe('UserService', () => {
|
||||
let service: UserService;
|
||||
@@ -107,7 +107,9 @@ describe('UserService', () => {
|
||||
|
||||
expect(
|
||||
twentyORMGlobalManager.getRepositoryForWorkspace,
|
||||
).toHaveBeenCalledWith('w1', 'workspaceMember');
|
||||
).toHaveBeenCalledWith('w1', 'workspaceMember', {
|
||||
shouldBypassPermissionChecks: true,
|
||||
});
|
||||
expect(mockWorkspaceMemberRepo.findOne).toHaveBeenCalledWith({
|
||||
where: { userId: 'u1' },
|
||||
});
|
||||
|
||||
@@ -4,9 +4,9 @@ import assert from 'assert';
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
||||
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
|
||||
import { isWorkspaceActiveOrSuspended } from 'twenty-shared/workspace';
|
||||
import { IsNull, Not, Repository } from 'typeorm';
|
||||
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
AuthException,
|
||||
@@ -46,6 +46,7 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspace.id,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
return await workspaceMemberRepository.findOne({
|
||||
@@ -64,6 +65,7 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspace.id,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
return await workspaceMemberRepository.find({ withDeleted: withDeleted });
|
||||
@@ -78,6 +80,7 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspace.id,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
return await workspaceMemberRepository.find({
|
||||
@@ -104,6 +107,7 @@ export class UserService extends TypeOrmQueryService<UserEntity> {
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const workspaceMembers = await workspaceMemberRepository.find();
|
||||
|
||||
+1
@@ -71,6 +71,7 @@ export class WorkflowTriggerResolver {
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspace.id,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const workspaceMember = await workspaceMemberRepository.findOneOrFail({
|
||||
|
||||
+2
@@ -60,6 +60,7 @@ export class WorkspaceInvitationResolver {
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspace.id,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const workspaceMember = await workspaceMemberRepository.findOneOrFail({
|
||||
@@ -100,6 +101,7 @@ export class WorkspaceInvitationResolver {
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspace.id,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const workspaceMember = await workspaceMemberRepository.findOneOrFail({
|
||||
|
||||
+1
@@ -29,6 +29,7 @@ export class ConnectedAccountListener {
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
const workspaceMember = await workspaceMemberRepository.findOneOrFail({
|
||||
where: { id: workspaceMemberId },
|
||||
|
||||
@@ -110,6 +110,7 @@ export class MatchParticipantService<
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const chunkSize = 200;
|
||||
|
||||
Reference in New Issue
Block a user