forked from twentyhq/twenty
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
4643 create a pre hook for calendar events (twentyhq#4666)
* copy message pre hook * add CalendarQueryHookModule to workspace-pre-query-hook.module * use CalendarChannelVisibility enum * add calendarEvent to workspace-pre-query-hook.config * fix pre-hook * fix findOne prehook in config * rename fragments * fix import * update findOne prehook and create can-access-calendar-event.provider * replace provider with service * fix type * renaming * remove unnecessary eslint skip --------- Co-authored-by: Weiko <[email protected]>
- Loading branch information
1 parent
c3cc0f6
commit d687523
Showing
13 changed files
with
257 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 0 additions & 20 deletions
20
...s/twenty-front/src/modules/activities/calendar/queries/fragments/calendarEventFragment.ts
This file was deleted.
Oops, something went wrong.
4 changes: 2 additions & 2 deletions
4
...dar/queries/fragments/attendeeFragment.ts → .../timelineCalendarEventAttendeeFragment.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
...-front/src/modules/activities/calendar/queries/fragments/timelineCalendarEventFragment.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { gql } from '@apollo/client'; | ||
|
||
import { timelineCalendarEventAttendeeFragment } from '@/activities/calendar/queries/fragments/timelineCalendarEventAttendeeFragment'; | ||
|
||
export const timelineCalendarEventFragment = gql` | ||
fragment TimelineCalendarEventFragment on TimelineCalendarEvent { | ||
id | ||
title | ||
description | ||
location | ||
startsAt | ||
endsAt | ||
isFullDay | ||
visibility | ||
attendees { | ||
...TimelineCalendarEventAttendeeFragment | ||
} | ||
} | ||
${timelineCalendarEventAttendeeFragment} | ||
`; |
6 changes: 3 additions & 3 deletions
6
...calendarEventFragmentWithTotalFragment.ts → ...timelineCalendarEventWithTotalFragment.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,13 @@ | ||
import { gql } from '@apollo/client'; | ||
|
||
import { calendarEventFragment } from '@/activities/calendar/queries/fragments/calendarEventFragment'; | ||
import { timelineCalendarEventFragment } from '@/activities/calendar/queries/fragments/timelineCalendarEventFragment'; | ||
|
||
export const timelineCalendarEventWithTotalFragment = gql` | ||
fragment TimelineCalendarEventsWithTotalFragment on TimelineCalendarEventsWithTotal { | ||
totalNumberOfCalendarEvents | ||
timelineCalendarEvents { | ||
...CalendarEventFragment | ||
...TimelineCalendarEventFragment | ||
} | ||
} | ||
${calendarEventFragment} | ||
${timelineCalendarEventFragment} | ||
`; |
2 changes: 1 addition & 1 deletion
2
...y-front/src/modules/activities/calendar/queries/getTimelineCalendarEventsFromCompanyId.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...ty-front/src/modules/activities/calendar/queries/getTimelineCalendarEventsFromPersonId.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
...raphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,17 @@ | ||
import { MessageFindManyPreQueryHook } from 'src/modules/messaging/query-hooks/message/message-find-many.pre-query.hook'; | ||
import { MessageFindOnePreQueryHook } from 'src/modules/messaging/query-hooks/message/message-find-one.pre-query-hook'; | ||
import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type'; | ||
import { CalendarEventFindManyPreQueryHook } from 'src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook'; | ||
import { CalendarEventFindOnePreQueryHook } from 'src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook'; | ||
|
||
// TODO: move to a decorator | ||
export const workspacePreQueryHooks: WorkspaceQueryHook = { | ||
message: { | ||
findOne: [MessageFindOnePreQueryHook.name], | ||
findMany: [MessageFindManyPreQueryHook.name], | ||
}, | ||
calendarEvent: { | ||
findOne: [CalendarEventFindOnePreQueryHook.name], | ||
findMany: [CalendarEventFindManyPreQueryHook.name], | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
...rc/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { | ||
BadRequestException, | ||
Injectable, | ||
NotFoundException, | ||
} from '@nestjs/common'; | ||
|
||
import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; | ||
import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; | ||
|
||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; | ||
import { CalendarChannelEventAssociationObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel-event-association.object-metadata'; | ||
import { CalendarChannelEventAssociationRepository } from 'src/modules/calendar/repositories/calendar-channel-event-association.repository'; | ||
import { CanAccessCalendarEventService } from 'src/modules/calendar/query-hooks/calendar-event/services/can-access-calendar-event.service'; | ||
|
||
@Injectable() | ||
export class CalendarEventFindManyPreQueryHook | ||
implements WorkspacePreQueryHook | ||
{ | ||
constructor( | ||
@InjectObjectMetadataRepository( | ||
CalendarChannelEventAssociationObjectMetadata, | ||
) | ||
private readonly calendarChannelEventAssociationRepository: CalendarChannelEventAssociationRepository, | ||
private readonly canAccessCalendarEventService: CanAccessCalendarEventService, | ||
) {} | ||
|
||
async execute( | ||
userId: string, | ||
workspaceId: string, | ||
payload: FindManyResolverArgs, | ||
): Promise<void> { | ||
if (!payload?.filter?.id?.eq) { | ||
throw new BadRequestException('id filter is required'); | ||
} | ||
|
||
const calendarChannelCalendarEventAssociations = | ||
await this.calendarChannelEventAssociationRepository.getByCalendarEventIds( | ||
[payload?.filter?.id?.eq], | ||
workspaceId, | ||
); | ||
|
||
if (calendarChannelCalendarEventAssociations.length === 0) { | ||
throw new NotFoundException(); | ||
} | ||
|
||
await this.canAccessCalendarEventService.canAccessCalendarEvent( | ||
userId, | ||
workspaceId, | ||
calendarChannelCalendarEventAssociations, | ||
); | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
...src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { | ||
BadRequestException, | ||
Injectable, | ||
NotFoundException, | ||
} from '@nestjs/common'; | ||
|
||
import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; | ||
import { FindOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; | ||
|
||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; | ||
import { CanAccessCalendarEventService } from 'src/modules/calendar/query-hooks/calendar-event/services/can-access-calendar-event.service'; | ||
import { CalendarChannelEventAssociationRepository } from 'src/modules/calendar/repositories/calendar-channel-event-association.repository'; | ||
import { CalendarChannelEventAssociationObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel-event-association.object-metadata'; | ||
|
||
@Injectable() | ||
export class CalendarEventFindOnePreQueryHook implements WorkspacePreQueryHook { | ||
constructor( | ||
@InjectObjectMetadataRepository( | ||
CalendarChannelEventAssociationObjectMetadata, | ||
) | ||
private readonly calendarChannelEventAssociationRepository: CalendarChannelEventAssociationRepository, | ||
private readonly canAccessCalendarEventService: CanAccessCalendarEventService, | ||
) {} | ||
|
||
async execute( | ||
userId: string, | ||
workspaceId: string, | ||
payload: FindOneResolverArgs, | ||
): Promise<void> { | ||
if (!payload?.filter?.id?.eq) { | ||
throw new BadRequestException('id filter is required'); | ||
} | ||
|
||
const calendarChannelCalendarEventAssociations = | ||
await this.calendarChannelEventAssociationRepository.getByCalendarEventIds( | ||
[payload?.filter?.id?.eq], | ||
workspaceId, | ||
); | ||
|
||
if (calendarChannelCalendarEventAssociations.length === 0) { | ||
throw new NotFoundException(); | ||
} | ||
|
||
await this.canAccessCalendarEventService.canAccessCalendarEvent( | ||
userId, | ||
workspaceId, | ||
calendarChannelCalendarEventAssociations, | ||
); | ||
} | ||
} |
76 changes: 76 additions & 0 deletions
76
...modules/calendar/query-hooks/calendar-event/services/can-access-calendar-event.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { ForbiddenException, Injectable } from '@nestjs/common'; | ||
|
||
import groupBy from 'lodash.groupby'; | ||
|
||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; | ||
import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; | ||
import { CalendarChannelRepository } from 'src/modules/calendar/repositories/calendar-channel.repository'; | ||
import { CalendarChannelEventAssociationObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel-event-association.object-metadata'; | ||
import { | ||
CalendarChannelObjectMetadata, | ||
CalendarChannelVisibility, | ||
} from 'src/modules/calendar/standard-objects/calendar-channel.object-metadata'; | ||
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; | ||
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata'; | ||
import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository'; | ||
import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; | ||
|
||
@Injectable() | ||
export class CanAccessCalendarEventService { | ||
constructor( | ||
@InjectObjectMetadataRepository(CalendarChannelObjectMetadata) | ||
private readonly calendarChannelRepository: CalendarChannelRepository, | ||
@InjectObjectMetadataRepository(ConnectedAccountObjectMetadata) | ||
private readonly connectedAccountRepository: ConnectedAccountRepository, | ||
@InjectObjectMetadataRepository(WorkspaceMemberObjectMetadata) | ||
private readonly workspaceMemberService: WorkspaceMemberRepository, | ||
) {} | ||
|
||
public async canAccessCalendarEvent( | ||
userId: string, | ||
workspaceId: string, | ||
calendarChannelCalendarEventAssociations: ObjectRecord<CalendarChannelEventAssociationObjectMetadata>[], | ||
) { | ||
const calendarChannels = await this.calendarChannelRepository.getByIds( | ||
calendarChannelCalendarEventAssociations.map( | ||
(association) => association.calendarChannelId, | ||
), | ||
workspaceId, | ||
); | ||
|
||
const calendarChannelsGroupByVisibility = groupBy( | ||
calendarChannels, | ||
(channel) => channel.visibility, | ||
); | ||
|
||
if ( | ||
calendarChannelsGroupByVisibility[ | ||
CalendarChannelVisibility.SHARE_EVERYTHING | ||
] | ||
) { | ||
return; | ||
} | ||
|
||
const currentWorkspaceMember = | ||
await this.workspaceMemberService.getByIdOrFail(userId, workspaceId); | ||
|
||
const calendarChannelsConnectedAccounts = | ||
await this.connectedAccountRepository.getByIds( | ||
calendarChannels.map((channel) => channel.connectedAccountId), | ||
workspaceId, | ||
); | ||
|
||
const calendarChannelsWorkspaceMemberIds = | ||
calendarChannelsConnectedAccounts.map( | ||
(connectedAccount) => connectedAccount.accountOwnerId, | ||
); | ||
|
||
if ( | ||
calendarChannelsWorkspaceMemberIds.includes(currentWorkspaceMember.id) | ||
) { | ||
return; | ||
} | ||
|
||
throw new ForbiddenException(); | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
packages/twenty-server/src/modules/calendar/query-hooks/calendar-query-hook.module.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { Module } from '@nestjs/common'; | ||
|
||
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; | ||
import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata'; | ||
import { ConnectedAccountObjectMetadata } from 'src/modules/connected-account/standard-objects/connected-account.object-metadata'; | ||
import { CalendarChannelEventAssociationObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel-event-association.object-metadata'; | ||
import { CalendarChannelObjectMetadata } from 'src/modules/calendar/standard-objects/calendar-channel.object-metadata'; | ||
import { CalendarEventFindManyPreQueryHook } from 'src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook'; | ||
import { CalendarEventFindOnePreQueryHook } from 'src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook'; | ||
import { CanAccessCalendarEventService } from 'src/modules/calendar/query-hooks/calendar-event/services/can-access-calendar-event.service'; | ||
|
||
@Module({ | ||
imports: [ | ||
ObjectMetadataRepositoryModule.forFeature([ | ||
CalendarChannelEventAssociationObjectMetadata, | ||
CalendarChannelObjectMetadata, | ||
ConnectedAccountObjectMetadata, | ||
WorkspaceMemberObjectMetadata, | ||
]), | ||
], | ||
providers: [ | ||
CanAccessCalendarEventService, | ||
{ | ||
provide: CalendarEventFindOnePreQueryHook.name, | ||
useClass: CalendarEventFindOnePreQueryHook, | ||
}, | ||
{ | ||
provide: CalendarEventFindManyPreQueryHook.name, | ||
useClass: CalendarEventFindManyPreQueryHook, | ||
}, | ||
], | ||
}) | ||
export class CalendarQueryHookModule {} |