diff --git a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-many.post-query.hook.ts b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-many.post-query.hook.ts index 431e1e02b..d7cfb3587 100644 --- a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-many.post-query.hook.ts +++ b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-many.post-query.hook.ts @@ -1,9 +1,11 @@ +import { isDefined } from 'twenty-shared/utils'; + import { WorkspacePostQueryHookInstance } 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 { ForbiddenError } 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'; @@ -23,13 +25,15 @@ export class CalendarEventFindManyPostQueryHook _objectName: string, payload: CalendarEventWorkspaceEntity[], ): Promise { - if (!authContext.workspaceMemberId) { - throw new UserInputError('Workspace member id is required'); + const { user, apiKey } = authContext; + + if (!isDefined(user) && !isDefined(apiKey)) { + throw new ForbiddenError('User is required'); } await this.applyCalendarEventsVisibilityRestrictionsService.applyCalendarEventsVisibilityRestrictions( - authContext.workspaceMemberId, payload, + user?.id, ); } } diff --git a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-one.post-query.hook.ts b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-one.post-query.hook.ts index 6e58b7c81..407694962 100644 --- a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-one.post-query.hook.ts +++ b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-one.post-query.hook.ts @@ -1,9 +1,11 @@ +import { isDefined } from 'twenty-shared/utils'; + import { WorkspacePostQueryHookInstance } 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 { ForbiddenError } 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'; @@ -23,13 +25,15 @@ export class CalendarEventFindOnePostQueryHook _objectName: string, payload: CalendarEventWorkspaceEntity[], ): Promise { - if (!authContext.workspaceMemberId) { - throw new UserInputError('Workspace member id is required'); + const { user, apiKey } = authContext; + + if (!isDefined(user) && !isDefined(apiKey)) { + throw new ForbiddenError('User is required'); } await this.applyCalendarEventsVisibilityRestrictionsService.applyCalendarEventsVisibilityRestrictions( - authContext.workspaceMemberId, payload, + user?.id, ); } } diff --git a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service.spec.ts b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service.spec.ts index 3f9055dd1..17d7eb6f2 100644 --- a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service.spec.ts +++ b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service.spec.ts @@ -48,6 +48,10 @@ describe('ApplyCalendarEventsVisibilityRestrictionsService', () => { find: jest.fn(), }; + const mockWorkspaceMemberRepository = { + findOneByOrFail: jest.fn(), + }; + const mockTwentyORMManager = { getRepository: jest.fn().mockImplementation((name) => { if (name === 'calendarChannelEventAssociation') { @@ -56,6 +60,9 @@ describe('ApplyCalendarEventsVisibilityRestrictionsService', () => { if (name === 'connectedAccount') { return mockConnectedAccountRepository; } + if (name === 'workspaceMember') { + return mockWorkspaceMemberRepository; + } }), }; @@ -83,6 +90,10 @@ describe('ApplyCalendarEventsVisibilityRestrictionsService', () => { createMockCalendarEvent('1', 'Test Event', 'Test Description'), ]; + mockWorkspaceMemberRepository.findOneByOrFail.mockResolvedValue({ + id: 'workspace-member-id', + }); + mockCalendarEventAssociationRepository.find.mockResolvedValue([ { calendarEventId: '1', @@ -94,8 +105,8 @@ describe('ApplyCalendarEventsVisibilityRestrictionsService', () => { ]); const result = await service.applyCalendarEventsVisibilityRestrictions( - 'workspace-member-id', calendarEvents, + 'user-id', ); expect(result).toEqual(calendarEvents); @@ -124,11 +135,15 @@ describe('ApplyCalendarEventsVisibilityRestrictionsService', () => { }, ]); + mockWorkspaceMemberRepository.findOneByOrFail.mockResolvedValue({ + id: 'workspace-member-id', + }); + mockConnectedAccountRepository.find.mockResolvedValue([]); const result = await service.applyCalendarEventsVisibilityRestrictions( - 'workspace-member-id', calendarEvents, + 'user-id', ); expect(result).toEqual([ @@ -155,11 +170,15 @@ describe('ApplyCalendarEventsVisibilityRestrictionsService', () => { }, ]); + mockWorkspaceMemberRepository.findOneByOrFail.mockResolvedValue({ + id: 'workspace-member-account-owner-id', + }); + mockConnectedAccountRepository.find.mockResolvedValue([{ id: '1' }]); const result = await service.applyCalendarEventsVisibilityRestrictions( - 'workspace-member-id', calendarEvents, + 'user-id', ); expect(result).toEqual(calendarEvents); @@ -186,11 +205,15 @@ describe('ApplyCalendarEventsVisibilityRestrictionsService', () => { }, ]); + mockWorkspaceMemberRepository.findOneByOrFail.mockResolvedValue({ + id: 'workspace-member-not-account-owner-id', + }); + mockConnectedAccountRepository.find.mockResolvedValue([]); const result = await service.applyCalendarEventsVisibilityRestrictions( - 'workspace-member-id', calendarEvents, + 'user-id', ); expect(result).toEqual([]); @@ -203,6 +226,10 @@ describe('ApplyCalendarEventsVisibilityRestrictionsService', () => { createMockCalendarEvent('3', 'Event 3', 'Description 3'), ]; + mockWorkspaceMemberRepository.findOneByOrFail.mockResolvedValue({ + id: 'workspace-member-id', + }); + mockCalendarEventAssociationRepository.find.mockResolvedValue([ { calendarEventId: '1', @@ -232,8 +259,63 @@ describe('ApplyCalendarEventsVisibilityRestrictionsService', () => { .mockResolvedValueOnce([{ id: '1' }]); // request for calendar event 2 const result = await service.applyCalendarEventsVisibilityRestrictions( - 'workspace-member-id', calendarEvents, + 'user-id', + ); + + expect(result).toEqual([ + calendarEvents[0], + calendarEvents[1], + { + ...calendarEvents[2], + title: FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED, + description: FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED, + }, + ]); + }); + + it('should return all calendar events with the right visibility when userId is undefined (api key request)', async () => { + const calendarEvents = [ + createMockCalendarEvent('1', 'Event 1', 'Description 1'), + createMockCalendarEvent('2', 'Event 2', 'Description 2'), + createMockCalendarEvent('3', 'Event 3', 'Description 3'), + ]; + + mockWorkspaceMemberRepository.findOneByOrFail.mockResolvedValue({ + id: 'workspace-member-id', + }); + + 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( + calendarEvents, + undefined, ); expect(result).toEqual([ diff --git a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service.ts b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service.ts index c19278fb3..dfeebe996 100644 --- a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service.ts +++ b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/apply-calendar-events-visibility-restrictions.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import groupBy from 'lodash.groupby'; import { FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED } from 'twenty-shared/constants'; +import { isDefined } from 'twenty-shared/utils'; import { In } from 'typeorm'; import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager'; @@ -9,14 +10,15 @@ import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/cale 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'; +import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @Injectable() export class ApplyCalendarEventsVisibilityRestrictionsService { constructor(private readonly twentyORMManager: TwentyORMManager) {} public async applyCalendarEventsVisibilityRestrictions( - workspaceMemberId: string, calendarEvents: CalendarEventWorkspaceEntity[], + userId?: string, // undefined when request is made with api key ) { const calendarChannelEventAssociationRepository = await this.twentyORMManager.getRepository( @@ -36,6 +38,11 @@ export class ApplyCalendarEventsVisibilityRestrictionsService { 'connectedAccount', ); + const workspaceMemberRepository = + await this.twentyORMManager.getRepository( + 'workspaceMember', + ); + for (let i = calendarEvents.length - 1; i >= 0; i--) { const calendarChannelCalendarEventAssociations = calendarChannelCalendarEventsAssociations.filter( @@ -59,18 +66,26 @@ export class ApplyCalendarEventsVisibilityRestrictionsService { continue; } - const connectedAccounts = await connectedAccountRepository.find({ - select: ['id'], - where: { - calendarChannels: { - id: In(calendarChannels.map((channel) => channel.id)), + if (isDefined(userId)) { + const workspaceMember = await workspaceMemberRepository.findOneByOrFail( + { + userId: userId, }, - accountOwnerId: workspaceMemberId, - }, - }); + ); - if (connectedAccounts.length > 0) { - continue; + const connectedAccounts = await connectedAccountRepository.find({ + select: ['id'], + where: { + calendarChannels: { + id: In(calendarChannels.map((channel) => channel.id)), + }, + accountOwnerId: workspaceMember.id, + }, + }); + + if (connectedAccounts.length > 0) { + continue; + } } if ( diff --git a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service.spec.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service.spec.ts index 345e6dde0..7a01d1262 100644 --- a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service.spec.ts +++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service.spec.ts @@ -38,6 +38,10 @@ describe('ApplyMessagesVisibilityRestrictionsService', () => { find: jest.fn(), }; + const mockWorkspaceMemberRepository = { + findOneByOrFail: jest.fn(), + }; + const mockTwentyORMManager = { getRepository: jest.fn().mockImplementation((name) => { if (name === 'messageChannelMessageAssociation') { @@ -46,6 +50,9 @@ describe('ApplyMessagesVisibilityRestrictionsService', () => { if (name === 'connectedAccount') { return mockConnectedAccountRepository; } + if (name === 'workspaceMember') { + return mockWorkspaceMemberRepository; + } }), }; @@ -83,8 +90,8 @@ describe('ApplyMessagesVisibilityRestrictionsService', () => { ]); const result = await service.applyMessagesVisibilityRestrictions( - 'workspace-member-id', messages, + 'user-id', ); expect(result).toEqual(messages); @@ -114,9 +121,13 @@ describe('ApplyMessagesVisibilityRestrictionsService', () => { mockConnectedAccountRepository.find.mockResolvedValue([]); + mockWorkspaceMemberRepository.findOneByOrFail.mockResolvedValue({ + id: 'workspace-member-id', + }); + const result = await service.applyMessagesVisibilityRestrictions( - 'workspace-member-id', messages, + 'user-id', ); expect(result).toEqual([ @@ -144,9 +155,13 @@ describe('ApplyMessagesVisibilityRestrictionsService', () => { mockConnectedAccountRepository.find.mockResolvedValue([]); + mockWorkspaceMemberRepository.findOneByOrFail.mockResolvedValue({ + id: 'workspace-member-id', + }); + const result = await service.applyMessagesVisibilityRestrictions( - 'workspace-member-id', messages, + 'user-id', ); expect(result).toEqual([ @@ -173,11 +188,15 @@ describe('ApplyMessagesVisibilityRestrictionsService', () => { }, ]); + mockWorkspaceMemberRepository.findOneByOrFail.mockResolvedValue({ + id: 'workspace-member-account-owner-id', + }); + mockConnectedAccountRepository.find.mockResolvedValue([{ id: '1' }]); const result = await service.applyMessagesVisibilityRestrictions( - 'workspace-member-id', messages, + 'user-id', ); expect(result).toEqual(messages); @@ -203,11 +222,15 @@ describe('ApplyMessagesVisibilityRestrictionsService', () => { }, ]); + mockWorkspaceMemberRepository.findOneByOrFail.mockResolvedValue({ + id: 'workspace-member-not-account-owner-id', + }); + mockConnectedAccountRepository.find.mockResolvedValue([]); const result = await service.applyMessagesVisibilityRestrictions( - 'workspace-member-id', messages, + 'user-id', ); expect(result).toEqual([]); @@ -244,13 +267,75 @@ describe('ApplyMessagesVisibilityRestrictionsService', () => { }, ]); + mockWorkspaceMemberRepository.findOneByOrFail.mockResolvedValue({ + id: 'workspace-member-id', + }); + mockConnectedAccountRepository.find .mockResolvedValueOnce([]) // request for message 3 .mockResolvedValueOnce([]); // request for message 2 const result = await service.applyMessagesVisibilityRestrictions( - 'workspace-member-id', messages, + 'user-id', + ); + + expect(result).toEqual([ + messages[0], + { + ...messages[1], + text: FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED, + }, + { + ...messages[2], + subject: FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED, + text: FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED, + }, + ]); + }); + + it('should return all messages with the right visibility when userId is undefined (api key request)', async () => { + const messages = [ + createMockMessage('1', 'Subject 1', 'Message 1'), + createMockMessage('2', 'Subject 2', 'Message 2'), + createMockMessage('3', 'Subject 3', 'Message 3'), + ]; + + mockMessageChannelMessageAssociationRepository.find.mockResolvedValue([ + { + messageId: '1', + messageChannel: { + id: '1', + visibility: MessageChannelVisibility.SHARE_EVERYTHING, + }, + }, + { + messageId: '2', + messageChannel: { + id: '2', + visibility: MessageChannelVisibility.SUBJECT, + }, + }, + { + messageId: '3', + messageChannel: { + id: '3', + visibility: MessageChannelVisibility.METADATA, + }, + }, + ]); + + mockWorkspaceMemberRepository.findOneByOrFail.mockResolvedValue({ + id: 'workspace-member-id', + }); + + mockConnectedAccountRepository.find + .mockResolvedValueOnce([]) // request for message 3 + .mockResolvedValueOnce([]); // request for message 2 + + const result = await service.applyMessagesVisibilityRestrictions( + messages, + undefined, ); expect(result).toEqual([ diff --git a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service.ts index e87e3857d..3800543ec 100644 --- a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import groupBy from 'lodash.groupby'; import { FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED } from 'twenty-shared/constants'; +import { isDefined } from 'twenty-shared/utils'; import { In } from 'typeorm'; import { NotFoundError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; @@ -10,14 +11,15 @@ import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/s import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; import { MessageChannelVisibility } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; +import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @Injectable() export class ApplyMessagesVisibilityRestrictionsService { constructor(private readonly twentyORMManager: TwentyORMManager) {} public async applyMessagesVisibilityRestrictions( - workspaceMemberId: string, messages: MessageWorkspaceEntity[], + userId?: string, // undefined when request is made with api key ) { const messageChannelMessageAssociationRepository = await this.twentyORMManager.getRepository( @@ -37,6 +39,11 @@ export class ApplyMessagesVisibilityRestrictionsService { 'connectedAccount', ); + const workspaceMemberRepository = + await this.twentyORMManager.getRepository( + 'workspaceMember', + ); + for (let i = messages.length - 1; i >= 0; i--) { const messageChannelMessageAssociations = messageChannelMessagesAssociations.filter( @@ -66,19 +73,28 @@ export class ApplyMessagesVisibilityRestrictionsService { continue; } - const connectedAccounts = await connectedAccountRepository.find({ - select: ['id'], - where: { - messageChannels: { - id: In(messageChannels.map((channel) => channel.id)), + if (isDefined(userId)) { + const workspaceMember = await workspaceMemberRepository.findOneByOrFail( + { + userId, }, - accountOwnerId: workspaceMemberId, - }, - }); + ); - if (connectedAccounts.length > 0) { - continue; + const connectedAccounts = await connectedAccountRepository.find({ + select: ['id'], + where: { + messageChannels: { + id: In(messageChannels.map((channel) => channel.id)), + }, + accountOwnerId: workspaceMember.id, + }, + }); + + if (connectedAccounts.length > 0) { + continue; + } } + if (messageChannelsGroupByVisibility[MessageChannelVisibility.SUBJECT]) { messages[i].text = FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED; continue; diff --git a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.post-query.hook.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.post-query.hook.ts index 220c81f46..8c03a7668 100644 --- a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.post-query.hook.ts +++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.post-query.hook.ts @@ -1,9 +1,11 @@ +import { isDefined } from 'twenty-shared/utils'; + import { WorkspacePostQueryHookInstance } 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 { ForbiddenError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { ApplyMessagesVisibilityRestrictionsService } from 'src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service'; import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; @@ -23,13 +25,15 @@ export class MessageFindManyPostQueryHook _objectName: string, payload: MessageWorkspaceEntity[], ): Promise { - if (!authContext.workspaceMemberId) { - throw new UserInputError('Workspace member id is required'); + const { user, apiKey } = authContext; + + if (!isDefined(user) && !isDefined(apiKey)) { + throw new ForbiddenError('User is required'); } await this.applyMessagesVisibilityRestrictionsService.applyMessagesVisibilityRestrictions( - authContext.workspaceMemberId, payload, + user?.id, ); } } diff --git a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.post-query.hook.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.post-query.hook.ts index 64b9f4e89..05863d7d4 100644 --- a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.post-query.hook.ts +++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.post-query.hook.ts @@ -1,9 +1,11 @@ +import { isDefined } from 'twenty-shared/utils'; + import { WorkspacePostQueryHookInstance } 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 { ForbiddenError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { ApplyMessagesVisibilityRestrictionsService } from 'src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service'; import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; @@ -23,13 +25,15 @@ export class MessageFindOnePostQueryHook _objectName: string, payload: MessageWorkspaceEntity[], ): Promise { - if (!authContext.workspaceMemberId) { - throw new UserInputError('Workspace member id is required'); + const { user, apiKey } = authContext; + + if (!isDefined(user) && !isDefined(apiKey)) { + throw new ForbiddenError('User is required'); } await this.applyMessagesVisibilityRestrictionsService.applyMessagesVisibilityRestrictions( - authContext.workspaceMemberId, payload, + user?.id, ); } }