Add missing overrides on entityManager (#12471)
In this PR 1. Add missing override of insert() method on WorkspaceSelectQueryBuilder to return our custom WorkspaceInsertQueryBuilder with permission checks. 2. Replace override implementation of methods on WorkspaceEntityManager that call createQueryBuilder at a nested internal layer of typeORM (i.e. not directly in the initial implementation of EntityManager - unlike findBy for instance -, but in calls done under the hood at a level which would force us to override entire other classes to pass on our permissionOptions. It is the case for methods which call typeORM's EntityPersistExecutor for instance.), to validate permissions and then allow the subsequent calls to be made without permission checks 3. adapt tests --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -2,7 +2,7 @@ import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory';
|
||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter';
|
||||
import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity';
|
||||
import { MatchParticipantService } from 'src/modules/match-participant/match-participant.service';
|
||||
@ -12,7 +12,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta
|
||||
|
||||
describe('MatchParticipantService', () => {
|
||||
let service: MatchParticipantService<MessageParticipantWorkspaceEntity>;
|
||||
let twentyORMManager: TwentyORMManager;
|
||||
let twentyORMGlobalManager: TwentyORMGlobalManager;
|
||||
let workspaceEventEmitter: WorkspaceEventEmitter;
|
||||
let scopedWorkspaceContextFactory: ScopedWorkspaceContextFactory;
|
||||
|
||||
@ -95,22 +95,24 @@ describe('MatchParticipantService', () => {
|
||||
providers: [
|
||||
MatchParticipantService,
|
||||
{
|
||||
provide: TwentyORMManager,
|
||||
provide: TwentyORMGlobalManager,
|
||||
useValue: {
|
||||
getRepository: jest.fn().mockImplementation((entityName) => {
|
||||
switch (entityName) {
|
||||
case 'messageParticipant':
|
||||
return mockMessageParticipantRepository;
|
||||
case 'calendarEventParticipant':
|
||||
return mockCalendarEventParticipantRepository;
|
||||
case 'person':
|
||||
return mockPersonRepository;
|
||||
case 'workspaceMember':
|
||||
return mockWorkspaceMemberRepository;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}),
|
||||
getRepositoryForWorkspace: jest
|
||||
.fn()
|
||||
.mockImplementation((_workspaceId, entityName) => {
|
||||
switch (entityName) {
|
||||
case 'messageParticipant':
|
||||
return mockMessageParticipantRepository;
|
||||
case 'calendarEventParticipant':
|
||||
return mockCalendarEventParticipantRepository;
|
||||
case 'person':
|
||||
return mockPersonRepository;
|
||||
case 'workspaceMember':
|
||||
return mockWorkspaceMemberRepository;
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -133,7 +135,9 @@ describe('MatchParticipantService', () => {
|
||||
service = module.get<
|
||||
MatchParticipantService<MessageParticipantWorkspaceEntity>
|
||||
>(MatchParticipantService);
|
||||
twentyORMManager = module.get<TwentyORMManager>(TwentyORMManager);
|
||||
twentyORMGlobalManager = module.get<TwentyORMGlobalManager>(
|
||||
TwentyORMGlobalManager,
|
||||
);
|
||||
workspaceEventEmitter = module.get<WorkspaceEventEmitter>(
|
||||
WorkspaceEventEmitter,
|
||||
);
|
||||
@ -287,7 +291,7 @@ describe('MatchParticipantService', () => {
|
||||
const calendarService =
|
||||
new MatchParticipantService<CalendarEventParticipantWorkspaceEntity>(
|
||||
workspaceEventEmitter,
|
||||
twentyORMManager,
|
||||
twentyORMGlobalManager,
|
||||
scopedWorkspaceContextFactory,
|
||||
);
|
||||
|
||||
@ -705,23 +709,25 @@ describe('MatchParticipantService', () => {
|
||||
describe('getParticipantRepository', () => {
|
||||
it('should return message participant repository for messageParticipant', async () => {
|
||||
const repository = await (service as any).getParticipantRepository(
|
||||
mockWorkspaceId,
|
||||
'messageParticipant',
|
||||
);
|
||||
|
||||
expect(twentyORMManager.getRepository).toHaveBeenCalledWith(
|
||||
'messageParticipant',
|
||||
);
|
||||
expect(
|
||||
twentyORMGlobalManager.getRepositoryForWorkspace,
|
||||
).toHaveBeenCalledWith(mockWorkspaceId, 'messageParticipant');
|
||||
expect(repository).toBe(mockMessageParticipantRepository);
|
||||
});
|
||||
|
||||
it('should return calendar event participant repository for calendarEventParticipant', async () => {
|
||||
const repository = await (service as any).getParticipantRepository(
|
||||
mockWorkspaceId,
|
||||
'calendarEventParticipant',
|
||||
);
|
||||
|
||||
expect(twentyORMManager.getRepository).toHaveBeenCalledWith(
|
||||
'calendarEventParticipant',
|
||||
);
|
||||
expect(
|
||||
twentyORMGlobalManager.getRepositoryForWorkspace,
|
||||
).toHaveBeenCalledWith(mockWorkspaceId, 'calendarEventParticipant');
|
||||
expect(repository).toBe(mockCalendarEventParticipantRepository);
|
||||
});
|
||||
});
|
||||
|
||||
@ -4,7 +4,7 @@ import { Any, Equal } from 'typeorm';
|
||||
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory';
|
||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter';
|
||||
import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity';
|
||||
import { addPersonEmailFiltersToQueryBuilder } from 'src/modules/match-participant/utils/add-person-email-filters-to-query-builder';
|
||||
@ -21,20 +21,23 @@ export class MatchParticipantService<
|
||||
> {
|
||||
constructor(
|
||||
private readonly workspaceEventEmitter: WorkspaceEventEmitter,
|
||||
private readonly twentyORMManager: TwentyORMManager,
|
||||
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
private readonly scopedWorkspaceContextFactory: ScopedWorkspaceContextFactory,
|
||||
) {}
|
||||
|
||||
private async getParticipantRepository(
|
||||
workspaceId: string,
|
||||
objectMetadataName: 'messageParticipant' | 'calendarEventParticipant',
|
||||
) {
|
||||
if (objectMetadataName === 'messageParticipant') {
|
||||
return await this.twentyORMManager.getRepository<MessageParticipantWorkspaceEntity>(
|
||||
return await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageParticipantWorkspaceEntity>(
|
||||
workspaceId,
|
||||
objectMetadataName,
|
||||
);
|
||||
}
|
||||
|
||||
return await this.twentyORMManager.getRepository<CalendarEventParticipantWorkspaceEntity>(
|
||||
return await this.twentyORMGlobalManager.getRepositoryForWorkspace<CalendarEventParticipantWorkspaceEntity>(
|
||||
workspaceId,
|
||||
objectMetadataName,
|
||||
);
|
||||
}
|
||||
@ -52,14 +55,15 @@ export class MatchParticipantService<
|
||||
return;
|
||||
}
|
||||
|
||||
const participantRepository =
|
||||
await this.getParticipantRepository(objectMetadataName);
|
||||
|
||||
const workspaceId = this.scopedWorkspaceContextFactory.create().workspaceId;
|
||||
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace ID is required');
|
||||
}
|
||||
const participantRepository = await this.getParticipantRepository(
|
||||
workspaceId,
|
||||
objectMetadataName,
|
||||
);
|
||||
|
||||
const participantIds = participants.map((participant) => participant.id);
|
||||
const uniqueParticipantsHandles = [
|
||||
@ -67,8 +71,10 @@ export class MatchParticipantService<
|
||||
];
|
||||
|
||||
const personRepository =
|
||||
await this.twentyORMManager.getRepository<PersonWorkspaceEntity>(
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<PersonWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'person',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const queryBuilder = addPersonEmailFiltersToQueryBuilder({
|
||||
@ -83,7 +89,8 @@ export class MatchParticipantService<
|
||||
const people = await personRepository.formatResult(rawPeople);
|
||||
|
||||
const workspaceMemberRepository =
|
||||
await this.twentyORMManager.getRepository<WorkspaceMemberWorkspaceEntity>(
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workspaceMember',
|
||||
);
|
||||
|
||||
@ -152,14 +159,15 @@ export class MatchParticipantService<
|
||||
personId?: string;
|
||||
workspaceMemberId?: string;
|
||||
}) {
|
||||
const participantRepository =
|
||||
await this.getParticipantRepository(objectMetadataName);
|
||||
|
||||
const workspaceId = this.scopedWorkspaceContextFactory.create().workspaceId;
|
||||
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace ID is required');
|
||||
}
|
||||
const participantRepository = await this.getParticipantRepository(
|
||||
workspaceId,
|
||||
objectMetadataName,
|
||||
);
|
||||
|
||||
if (personId) {
|
||||
await participantRepository.update(
|
||||
@ -172,8 +180,10 @@ export class MatchParticipantService<
|
||||
);
|
||||
|
||||
const personRepository =
|
||||
await this.twentyORMManager.getRepository<PersonWorkspaceEntity>(
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<PersonWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'person',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const queryBuilder = addPersonEmailFiltersToQueryBuilder({
|
||||
@ -253,8 +263,10 @@ export class MatchParticipantService<
|
||||
throw new Error('Workspace ID is required');
|
||||
}
|
||||
|
||||
const participantRepository =
|
||||
await this.getParticipantRepository(objectMetadataName);
|
||||
const participantRepository = await this.getParticipantRepository(
|
||||
workspaceId,
|
||||
objectMetadataName,
|
||||
);
|
||||
|
||||
const participantsToUpdate = await participantRepository.find({
|
||||
where: {
|
||||
@ -340,8 +352,10 @@ export class MatchParticipantService<
|
||||
throw new Error('Workspace ID is required');
|
||||
}
|
||||
|
||||
const participantRepository =
|
||||
await this.getParticipantRepository(objectMetadataName);
|
||||
const participantRepository = await this.getParticipantRepository(
|
||||
workspaceId,
|
||||
objectMetadataName,
|
||||
);
|
||||
|
||||
const participantsToUpdate = await participantRepository.find({
|
||||
where: {
|
||||
|
||||
Reference in New Issue
Block a user