Fix calendar events & messages fetching + fix timeline design (#11840)
Preview : <img width="501" alt="Screenshot 2025-05-02 at 16 24 34" src="https://github.com/user-attachments/assets/0c649df1-0e26-4ddc-8e13-ebd78af7ec09" /> Done : - Fix getCalendarEventsFromPersonIds and getCalendarEventsFromCompanyId (include accountOwner check) - Fix permission check on pre-hook - Pre-hook seems useless, calendar events are always on METADATA or SHARE_EVERYTHING visibility, else post hook always has the responsibility of returning the data user can access. >> To delete or to keep in case other visibility options are added ? - Add post hook to secure finOne / findMany calendarEvents resolver - Update design To do : - same on messages (PR to arrive) closes : https://github.com/twentyhq/twenty/issues/9826
This commit is contained in:
@ -0,0 +1,35 @@
|
||||
import { WorkspaceQueryPostHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { UserInputError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { ApplyCalendarEventsVisibilityRestrictionsService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service';
|
||||
import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity';
|
||||
|
||||
@WorkspaceQueryHook({
|
||||
key: `calendarEvent.findMany`,
|
||||
type: WorkspaceQueryHookType.PostHook,
|
||||
})
|
||||
export class CalendarEventFindManyPostQueryHook
|
||||
implements WorkspaceQueryPostHookInstance
|
||||
{
|
||||
constructor(
|
||||
private readonly applyCalendarEventsVisibilityRestrictionsService: ApplyCalendarEventsVisibilityRestrictionsService,
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
_objectName: string,
|
||||
payload: CalendarEventWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
if (!authContext.workspaceMemberId) {
|
||||
throw new UserInputError('Workspace member id is required');
|
||||
}
|
||||
|
||||
await this.applyCalendarEventsVisibilityRestrictionsService.applyCalendarEventsVisibilityRestrictions(
|
||||
authContext.workspaceMemberId,
|
||||
payload,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,7 @@ import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||
import { CanAccessCalendarEventService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-event.service';
|
||||
import { CanAccessCalendarEventsService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-events.service';
|
||||
import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity';
|
||||
|
||||
@WorkspaceQueryHook({
|
||||
@ -18,7 +18,7 @@ export class CalendarEventFindManyPreQueryHook
|
||||
{
|
||||
constructor(
|
||||
private readonly twentyORMManager: TwentyORMManager,
|
||||
private readonly canAccessCalendarEventService: CanAccessCalendarEventService,
|
||||
private readonly canAccessCalendarEventsService: CanAccessCalendarEventsService,
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
@ -51,7 +51,7 @@ export class CalendarEventFindManyPreQueryHook
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
await this.canAccessCalendarEventService.canAccessCalendarEvent(
|
||||
await this.canAccessCalendarEventsService.canAccessCalendarEvents(
|
||||
authContext.user.id,
|
||||
authContext.workspace.id,
|
||||
calendarChannelCalendarEventAssociations,
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
import { WorkspaceQueryPostHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
|
||||
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { WorkspaceQueryHookType } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/types/workspace-query-hook.type';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { UserInputError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { ApplyCalendarEventsVisibilityRestrictionsService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service';
|
||||
import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity';
|
||||
|
||||
@WorkspaceQueryHook({
|
||||
key: `calendarEvent.findOne`,
|
||||
type: WorkspaceQueryHookType.PostHook,
|
||||
})
|
||||
export class CalendarEventFindOnePostQueryHook
|
||||
implements WorkspaceQueryPostHookInstance
|
||||
{
|
||||
constructor(
|
||||
private readonly applyCalendarEventsVisibilityRestrictionsService: ApplyCalendarEventsVisibilityRestrictionsService,
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
authContext: AuthContext,
|
||||
_objectName: string,
|
||||
payload: CalendarEventWorkspaceEntity[],
|
||||
): Promise<void> {
|
||||
if (!authContext.workspaceMemberId) {
|
||||
throw new UserInputError('Workspace member id is required');
|
||||
}
|
||||
|
||||
await this.applyCalendarEventsVisibilityRestrictionsService.applyCalendarEventsVisibilityRestrictions(
|
||||
authContext.workspaceMemberId,
|
||||
payload,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,7 @@ import { FindOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-b
|
||||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/decorators/workspace-query-hook.decorator';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||
import { CanAccessCalendarEventService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-event.service';
|
||||
import { CanAccessCalendarEventsService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-events.service';
|
||||
import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity';
|
||||
|
||||
@WorkspaceQueryHook({
|
||||
@ -18,7 +18,7 @@ export class CalendarEventFindOnePreQueryHook
|
||||
{
|
||||
constructor(
|
||||
private readonly twentyORMManager: TwentyORMManager,
|
||||
private readonly canAccessCalendarEventService: CanAccessCalendarEventService,
|
||||
private readonly canAccessCalendarEventsService: CanAccessCalendarEventsService,
|
||||
) {}
|
||||
|
||||
async execute(
|
||||
@ -51,7 +51,7 @@ export class CalendarEventFindOnePreQueryHook
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
await this.canAccessCalendarEventService.canAccessCalendarEvent(
|
||||
await this.canAccessCalendarEventsService.canAccessCalendarEvents(
|
||||
authContext.user.id,
|
||||
authContext.workspace.id,
|
||||
calendarChannelCalendarEventAssociations,
|
||||
|
||||
@ -0,0 +1,249 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED } from 'twenty-shared/constants';
|
||||
|
||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||
import { CalendarChannelVisibility } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
|
||||
import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity';
|
||||
|
||||
import { ApplyCalendarEventsVisibilityRestrictionsService } from './apply-calendar-events-visibility-restrictions.service';
|
||||
|
||||
const createMockCalendarEvent = (
|
||||
id: string,
|
||||
title: string,
|
||||
description: string,
|
||||
): CalendarEventWorkspaceEntity => ({
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
isCanceled: false,
|
||||
isFullDay: false,
|
||||
startsAt: '2024-03-20T10:00:00Z',
|
||||
endsAt: '2024-03-20T11:00:00Z',
|
||||
location: '',
|
||||
conferenceLink: {
|
||||
primaryLinkLabel: '',
|
||||
primaryLinkUrl: '',
|
||||
secondaryLinks: null,
|
||||
},
|
||||
externalCreatedAt: '2024-03-20T09:00:00Z',
|
||||
externalUpdatedAt: '2024-03-20T09:00:00Z',
|
||||
deletedAt: null,
|
||||
createdAt: '2024-03-20T09:00:00Z',
|
||||
updatedAt: '2024-03-20T09:00:00Z',
|
||||
iCalUID: '',
|
||||
conferenceSolution: '',
|
||||
calendarChannelEventAssociations: [],
|
||||
calendarEventParticipants: [],
|
||||
});
|
||||
|
||||
describe('ApplyCalendarEventsVisibilityRestrictionsService', () => {
|
||||
let service: ApplyCalendarEventsVisibilityRestrictionsService;
|
||||
|
||||
const mockCalendarEventAssociationRepository = {
|
||||
find: jest.fn(),
|
||||
};
|
||||
|
||||
const mockConnectedAccountRepository = {
|
||||
find: jest.fn(),
|
||||
};
|
||||
|
||||
const mockTwentyORMManager = {
|
||||
getRepository: jest.fn().mockImplementation((name) => {
|
||||
if (name === 'calendarChannelEventAssociation') {
|
||||
return mockCalendarEventAssociationRepository;
|
||||
}
|
||||
if (name === 'connectedAccount') {
|
||||
return mockConnectedAccountRepository;
|
||||
}
|
||||
}),
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
ApplyCalendarEventsVisibilityRestrictionsService,
|
||||
{
|
||||
provide: TwentyORMManager,
|
||||
useValue: mockTwentyORMManager,
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get<ApplyCalendarEventsVisibilityRestrictionsService>(
|
||||
ApplyCalendarEventsVisibilityRestrictionsService,
|
||||
);
|
||||
|
||||
// Clear all mocks before each test
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should return calendar event without obfuscated title and description if the visibility is SHARE_EVERYTHING', async () => {
|
||||
const calendarEvents = [
|
||||
createMockCalendarEvent('1', 'Test Event', 'Test Description'),
|
||||
];
|
||||
|
||||
mockCalendarEventAssociationRepository.find.mockResolvedValue([
|
||||
{
|
||||
calendarEventId: '1',
|
||||
calendarChannel: {
|
||||
id: '1',
|
||||
visibility: CalendarChannelVisibility.SHARE_EVERYTHING,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const result = await service.applyCalendarEventsVisibilityRestrictions(
|
||||
'workspace-member-id',
|
||||
calendarEvents,
|
||||
);
|
||||
|
||||
expect(result).toEqual(calendarEvents);
|
||||
expect(
|
||||
result.every(
|
||||
(item) =>
|
||||
item.title !== FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED &&
|
||||
item.description !== FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED,
|
||||
),
|
||||
).toBe(true);
|
||||
expect(mockConnectedAccountRepository.find).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return calendar event with obfuscated title and description if the visibility is METADATA', async () => {
|
||||
const calendarEvents = [
|
||||
createMockCalendarEvent('1', 'Test Event', 'Test Description'),
|
||||
];
|
||||
|
||||
mockCalendarEventAssociationRepository.find.mockResolvedValue([
|
||||
{
|
||||
calendarEventId: '1',
|
||||
calendarChannel: {
|
||||
id: '1',
|
||||
visibility: CalendarChannelVisibility.METADATA,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
mockConnectedAccountRepository.find.mockResolvedValue([]);
|
||||
|
||||
const result = await service.applyCalendarEventsVisibilityRestrictions(
|
||||
'workspace-member-id',
|
||||
calendarEvents,
|
||||
);
|
||||
|
||||
expect(result).toEqual([
|
||||
{
|
||||
...calendarEvents[0],
|
||||
title: FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED,
|
||||
description: FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return calendar event without obfuscated title and description if the workspace member is the owner of the calendar event', async () => {
|
||||
const calendarEvents = [
|
||||
createMockCalendarEvent('1', 'Test Event', 'Test Description'),
|
||||
];
|
||||
|
||||
mockCalendarEventAssociationRepository.find.mockResolvedValue([
|
||||
{
|
||||
calendarEventId: '1',
|
||||
calendarChannel: {
|
||||
id: '1',
|
||||
visibility: CalendarChannelVisibility.METADATA,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
mockConnectedAccountRepository.find.mockResolvedValue([{ id: '1' }]);
|
||||
|
||||
const result = await service.applyCalendarEventsVisibilityRestrictions(
|
||||
'workspace-member-id',
|
||||
calendarEvents,
|
||||
);
|
||||
|
||||
expect(result).toEqual(calendarEvents);
|
||||
expect(
|
||||
result.every(
|
||||
(item) =>
|
||||
item.title !== FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED &&
|
||||
item.description !== FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED,
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should not return calendar event if visibility is not SHARE_EVERYTHING or METADATA and the workspace member is not the owner of the calendar event', async () => {
|
||||
const calendarEvents = [
|
||||
createMockCalendarEvent('1', 'Test Event', 'Test Description'),
|
||||
];
|
||||
|
||||
mockCalendarEventAssociationRepository.find.mockResolvedValue([
|
||||
{
|
||||
calendarEventId: '1',
|
||||
calendarChannel: {
|
||||
id: '1',
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
mockConnectedAccountRepository.find.mockResolvedValue([]);
|
||||
|
||||
const result = await service.applyCalendarEventsVisibilityRestrictions(
|
||||
'workspace-member-id',
|
||||
calendarEvents,
|
||||
);
|
||||
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return all calendar events with the right visibility', async () => {
|
||||
const calendarEvents = [
|
||||
createMockCalendarEvent('1', 'Event 1', 'Description 1'),
|
||||
createMockCalendarEvent('2', 'Event 2', 'Description 2'),
|
||||
createMockCalendarEvent('3', 'Event 3', 'Description 3'),
|
||||
];
|
||||
|
||||
mockCalendarEventAssociationRepository.find.mockResolvedValue([
|
||||
{
|
||||
calendarEventId: '1',
|
||||
calendarChannel: {
|
||||
id: '1',
|
||||
visibility: CalendarChannelVisibility.SHARE_EVERYTHING,
|
||||
},
|
||||
},
|
||||
{
|
||||
calendarEventId: '2',
|
||||
calendarChannel: {
|
||||
id: '2',
|
||||
visibility: CalendarChannelVisibility.METADATA,
|
||||
},
|
||||
},
|
||||
{
|
||||
calendarEventId: '3',
|
||||
calendarChannel: {
|
||||
id: '3',
|
||||
visibility: CalendarChannelVisibility.METADATA,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
mockConnectedAccountRepository.find
|
||||
.mockResolvedValueOnce([]) // request for calendar event 3
|
||||
.mockResolvedValueOnce([{ id: '1' }]); // request for calendar event 2
|
||||
|
||||
const result = await service.applyCalendarEventsVisibilityRestrictions(
|
||||
'workspace-member-id',
|
||||
calendarEvents,
|
||||
);
|
||||
|
||||
expect(result).toEqual([
|
||||
calendarEvents[0],
|
||||
calendarEvents[1],
|
||||
{
|
||||
...calendarEvents[2],
|
||||
title: FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED,
|
||||
description: FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,91 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import groupBy from 'lodash.groupby';
|
||||
import { FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED } from 'twenty-shared/constants';
|
||||
import { In } from 'typeorm';
|
||||
|
||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||
import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity';
|
||||
import { CalendarChannelVisibility } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
|
||||
import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity';
|
||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||
|
||||
@Injectable()
|
||||
export class ApplyCalendarEventsVisibilityRestrictionsService {
|
||||
constructor(private readonly twentyORMManager: TwentyORMManager) {}
|
||||
|
||||
public async applyCalendarEventsVisibilityRestrictions(
|
||||
workspaceMemberId: string,
|
||||
calendarEvents: CalendarEventWorkspaceEntity[],
|
||||
) {
|
||||
const calendarChannelEventAssociationRepository =
|
||||
await this.twentyORMManager.getRepository<CalendarChannelEventAssociationWorkspaceEntity>(
|
||||
'calendarChannelEventAssociation',
|
||||
);
|
||||
|
||||
const calendarChannelCalendarEventsAssociations =
|
||||
await calendarChannelEventAssociationRepository.find({
|
||||
where: {
|
||||
calendarEventId: In(calendarEvents.map((event) => event.id)),
|
||||
},
|
||||
relations: ['calendarChannel', 'calendarChannel.connectedAccount'],
|
||||
});
|
||||
|
||||
const connectedAccountRepository =
|
||||
await this.twentyORMManager.getRepository<ConnectedAccountWorkspaceEntity>(
|
||||
'connectedAccount',
|
||||
);
|
||||
|
||||
for (let i = calendarEvents.length - 1; i >= 0; i--) {
|
||||
const calendarChannelCalendarEventAssociations =
|
||||
calendarChannelCalendarEventsAssociations.filter(
|
||||
(association) => association.calendarEventId === calendarEvents[i].id,
|
||||
);
|
||||
|
||||
const calendarChannels = calendarChannelCalendarEventAssociations.map(
|
||||
(association) => association.calendarChannel,
|
||||
);
|
||||
|
||||
const calendarChannelsGroupByVisibility = groupBy(
|
||||
calendarChannels,
|
||||
(channel) => channel.visibility,
|
||||
);
|
||||
|
||||
if (
|
||||
calendarChannelsGroupByVisibility[
|
||||
CalendarChannelVisibility.SHARE_EVERYTHING
|
||||
]
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const connectedAccounts = await connectedAccountRepository.find({
|
||||
select: ['id'],
|
||||
where: {
|
||||
calendarChannels: {
|
||||
id: In(calendarChannels.map((channel) => channel.id)),
|
||||
},
|
||||
accountOwnerId: workspaceMemberId,
|
||||
},
|
||||
});
|
||||
|
||||
if (connectedAccounts.length > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
calendarChannelsGroupByVisibility[CalendarChannelVisibility.METADATA]
|
||||
) {
|
||||
calendarEvents[i].title =
|
||||
FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED;
|
||||
calendarEvents[i].description =
|
||||
FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED;
|
||||
continue;
|
||||
}
|
||||
|
||||
calendarEvents.splice(i, 1);
|
||||
}
|
||||
|
||||
return calendarEvents;
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,9 @@
|
||||
import { ForbiddenException, Injectable } from '@nestjs/common';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import groupBy from 'lodash.groupby';
|
||||
import { Any } from 'typeorm';
|
||||
import { In } from 'typeorm';
|
||||
|
||||
import { ForbiddenError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||
import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity';
|
||||
@ -12,14 +13,14 @@ import { WorkspaceMemberRepository } from 'src/modules/workspace-member/reposito
|
||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
|
||||
@Injectable()
|
||||
export class CanAccessCalendarEventService {
|
||||
export class CanAccessCalendarEventsService {
|
||||
constructor(
|
||||
private readonly twentyORMManager: TwentyORMManager,
|
||||
@InjectObjectMetadataRepository(WorkspaceMemberWorkspaceEntity)
|
||||
private readonly workspaceMemberService: WorkspaceMemberRepository,
|
||||
) {}
|
||||
|
||||
public async canAccessCalendarEvent(
|
||||
public async canAccessCalendarEvents(
|
||||
userId: string,
|
||||
workspaceId: string,
|
||||
calendarChannelCalendarEventAssociations: CalendarChannelEventAssociationWorkspaceEntity[],
|
||||
@ -36,7 +37,8 @@ export class CanAccessCalendarEventService {
|
||||
if (
|
||||
calendarChannelsGroupByVisibility[
|
||||
CalendarChannelVisibility.SHARE_EVERYTHING
|
||||
]
|
||||
] ||
|
||||
calendarChannelsGroupByVisibility[CalendarChannelVisibility.METADATA]
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@ -52,7 +54,9 @@ export class CanAccessCalendarEventService {
|
||||
const connectedAccounts = await connectedAccountRepository.find({
|
||||
select: ['id'],
|
||||
where: {
|
||||
calendarChannels: Any(calendarChannels.map((channel) => channel.id)),
|
||||
calendarChannels: {
|
||||
id: In(calendarChannels.map((channel) => channel.id)),
|
||||
},
|
||||
accountOwnerId: currentWorkspaceMember.id,
|
||||
},
|
||||
});
|
||||
@ -61,6 +65,6 @@ export class CanAccessCalendarEventService {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new ForbiddenException();
|
||||
throw new ForbiddenError('Calendar events not shared');
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||
import { CalendarEventFindManyPostQueryHook } from 'src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-many.post-query.hook';
|
||||
import { CalendarEventFindManyPreQueryHook } from 'src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook';
|
||||
import { CalendarEventFindOnePostQueryHook } from 'src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-one.post-query.hook';
|
||||
import { CalendarEventFindOnePreQueryHook } from 'src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook';
|
||||
import { CanAccessCalendarEventService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-event.service';
|
||||
import { ApplyCalendarEventsVisibilityRestrictionsService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service';
|
||||
import { CanAccessCalendarEventsService } from 'src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-events.service';
|
||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
|
||||
@Module({
|
||||
@ -11,9 +14,12 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta
|
||||
ObjectMetadataRepositoryModule.forFeature([WorkspaceMemberWorkspaceEntity]),
|
||||
],
|
||||
providers: [
|
||||
CanAccessCalendarEventService,
|
||||
CanAccessCalendarEventsService,
|
||||
ApplyCalendarEventsVisibilityRestrictionsService,
|
||||
CalendarEventFindOnePreQueryHook,
|
||||
CalendarEventFindManyPreQueryHook,
|
||||
CalendarEventFindOnePostQueryHook,
|
||||
CalendarEventFindManyPostQueryHook,
|
||||
],
|
||||
})
|
||||
export class CalendarQueryHookModule {}
|
||||
|
||||
Reference in New Issue
Block a user