diff --git a/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventCardMessage.tsx b/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventCardMessage.tsx
index b549003f0..a5c84bc88 100644
--- a/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventCardMessage.tsx
+++ b/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventCardMessage.tsx
@@ -1,11 +1,12 @@
import styled from '@emotion/styled';
-import { isUndefined } from '@sniptt/guards';
import { EmailThreadMessage } from '@/activities/emails/types/EmailThreadMessage';
-import { EventCardMessageNotShared } from '@/activities/timeline-activities/rows/message/components/EventCardMessageNotShared';
+import { EventCardMessageBodyNotShared } from '@/activities/timeline-activities/rows/message/components/EventCardMessageBodyNotShared';
+import { EventCardMessageForbidden } from '@/activities/timeline-activities/rows/message/components/EventCardMessageForbidden';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
+import { FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED } from 'twenty-shared/constants';
import { isDefined } from 'twenty-shared/utils';
import { OverflowingTextWithTooltip } from 'twenty-ui/display';
@@ -85,7 +86,7 @@ export const EventCardMessage = ({
);
if (shouldHideMessageContent) {
- return ;
+ return ;
}
const shouldHandleNotFound = error.graphQLErrors.some(
@@ -99,7 +100,7 @@ export const EventCardMessage = ({
return
Error loading message
;
}
- if (loading || isUndefined(message)) {
+ if (loading || !isDefined(message)) {
return Loading...
;
}
@@ -112,12 +113,21 @@ export const EventCardMessage = ({
- {message.subject}
+
+ {message.subject !==
+ FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED
+ ? message.subject
+ : 'Subject not shared'}
+
- {message.text}
+ {message.text !== FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED ? (
+ {message.text}
+ ) : (
+
+ )}
);
diff --git a/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventCardMessageBodyNotShared.tsx b/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventCardMessageBodyNotShared.tsx
new file mode 100644
index 000000000..b8f1cb5a9
--- /dev/null
+++ b/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventCardMessageBodyNotShared.tsx
@@ -0,0 +1,51 @@
+import styled from '@emotion/styled';
+import { IconLock } from 'twenty-ui/display';
+
+const StyledEmailBodyNotSharedContainer = styled.div`
+ align-items: center;
+ background: ${({ theme }) => theme.background.transparent.lighter};
+ border: 1px solid ${({ theme }) => theme.border.color.light};
+ border-radius: ${({ theme }) => theme.spacing(1)};
+ display: flex;
+ flex-direction: column;
+ gap: ${({ theme }) => theme.spacing(3)};
+
+ height: 80px;
+ justify-content: center;
+
+ color: ${({ theme }) => theme.font.color.light};
+ font-size: ${({ theme }) => theme.font.size.sm};
+ font-weight: ${({ theme }) => theme.font.weight.medium};
+ width: 100%;
+`;
+
+const StyledEmailBodyNotSharedIconContainer = styled.div`
+ display: flex;
+ width: ${({ theme }) => theme.icon.size.sm}px;
+ height: ${({ theme }) => theme.icon.size.sm}px;
+ justify-content: center;
+ align-items: center;
+`;
+
+const StyledEmailBodyNotShared = styled.div`
+ align-items: center;
+ display: flex;
+ gap: ${({ theme }) => theme.spacing(1)};
+`;
+
+export const EventCardMessageBodyNotShared = ({
+ notSharedByFullName,
+}: {
+ notSharedByFullName: string;
+}) => {
+ return (
+
+
+
+
+
+ Not shared by {notSharedByFullName}
+
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventCardMessageForbidden.tsx b/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventCardMessageForbidden.tsx
new file mode 100644
index 000000000..60e658036
--- /dev/null
+++ b/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventCardMessageForbidden.tsx
@@ -0,0 +1,43 @@
+import { EventCardMessageBodyNotShared } from '@/activities/timeline-activities/rows/message/components/EventCardMessageBodyNotShared';
+import styled from '@emotion/styled';
+
+const StyledEventCardMessageContainer = styled.div`
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+`;
+
+const StyledEmailContent = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: ${({ theme }) => theme.spacing(4)};
+ justify-content: center;
+ width: 100%;
+`;
+
+const StyledEmailTitle = styled.div`
+ color: ${({ theme }) => theme.font.color.primary};
+ font-weight: ${({ theme }) => theme.font.weight.medium};
+ display: flex;
+ flex-direction: column;
+ margin-top: ${({ theme }) => theme.spacing(2)};
+`;
+
+export const EventCardMessageForbidden = ({
+ notSharedByFullName,
+}: {
+ notSharedByFullName: string;
+}) => {
+ return (
+
+
+
+ Subject not shared
+
+
+
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventCardMessageNotShared.tsx b/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventCardMessageNotShared.tsx
deleted file mode 100644
index 18ae476e8..000000000
--- a/packages/twenty-front/src/modules/activities/timeline-activities/rows/message/components/EventCardMessageNotShared.tsx
+++ /dev/null
@@ -1,86 +0,0 @@
-import styled from '@emotion/styled';
-import { IconLock } from 'twenty-ui/display';
-
-const StyledEventCardMessageContainer = styled.div`
- display: flex;
- flex-direction: column;
-`;
-
-const StyledEmailContent = styled.div`
- display: flex;
- flex-direction: column;
- gap: ${({ theme }) => theme.spacing(4)};
- justify-content: center;
-`;
-
-const StyledEmailTop = styled.div`
- display: flex;
- flex-direction: column;
- gap: ${({ theme }) => theme.spacing(2)};
-`;
-
-const StyledEmailTitle = styled.div`
- color: ${({ theme }) => theme.font.color.primary};
- font-weight: ${({ theme }) => theme.font.weight.medium};
- display: flex;
-`;
-
-const StyledEmailBodyNotShareContainer = styled.div`
- align-items: center;
- align-self: stretch;
- background: ${({ theme }) => theme.background.transparent.lighter};
- border: 1px solid ${({ theme }) => theme.border.color.light};
- border-radius: ${({ theme }) => theme.spacing(1)};
- display: flex;
- flex-direction: column;
- gap: ${({ theme }) => theme.spacing(3)};
-
- height: 80px;
- justify-content: center;
- padding: 0 ${({ theme }) => theme.spacing(1)};
-
- color: ${({ theme }) => theme.font.color.light};
- font-size: ${({ theme }) => theme.font.size.sm};
- font-weight: ${({ theme }) => theme.font.weight.medium};
-`;
-
-const StyledEmailBodyNotSharedIconContainer = styled.div`
- display: flex;
- width: 14px;
- height: 14px;
- justify-content: center;
- align-items: center;
-`;
-
-const StyledEmailBodyNotShare = styled.div`
- align-items: center;
- display: flex;
- gap: ${({ theme }) => theme.spacing(1)};
- padding: 0 ${({ theme }) => theme.spacing(1)};
-`;
-
-export const EventCardMessageNotShared = ({
- sharedByFullName,
-}: {
- sharedByFullName: string;
-}) => {
- return (
-
-
-
-
- Subject not shared
-
-
-
-
-
-
-
- Not shared by {sharedByFullName}
-
-
-
-
- );
-};
diff --git a/packages/twenty-server/src/engine/core-modules/messaging/services/timeline-messaging.service.ts b/packages/twenty-server/src/engine/core-modules/messaging/services/timeline-messaging.service.ts
index cc1d15e4e..993f1df97 100644
--- a/packages/twenty-server/src/engine/core-modules/messaging/services/timeline-messaging.service.ts
+++ b/packages/twenty-server/src/engine/core-modules/messaging/services/timeline-messaging.service.ts
@@ -222,7 +222,7 @@ export class TimelineMessagingService {
const visibilityValues = Object.values(MessageChannelVisibility);
- const threadVisibilityByThreadIdForWhichWorkspaceMemberIsNotInParticipants:
+ const threadVisibilityByThreadIdForWhichWorkspaceMemberIsNotOwner:
| {
[key: string]: MessageChannelVisibility;
}
@@ -247,10 +247,10 @@ export class TimelineMessagingService {
const threadVisibilityByThreadId: {
[key: string]: MessageChannelVisibility;
} = messageThreadIds.reduce((threadVisibilityAcc, messageThreadId) => {
- // If the workspace member is not in the participants of the thread, use the visibility value from the query
+ // If the workspace member is not the owner of the thread, use the visibility value from the query
threadVisibilityAcc[messageThreadId] =
threadIdsWithoutWorkspaceMember.includes(messageThreadId)
- ? (threadVisibilityByThreadIdForWhichWorkspaceMemberIsNotInParticipants?.[
+ ? (threadVisibilityByThreadIdForWhichWorkspaceMemberIsNotOwner?.[
messageThreadId
] ?? MessageChannelVisibility.METADATA)
: MessageChannelVisibility.SHARE_EVERYTHING;
diff --git a/packages/twenty-server/src/engine/core-modules/messaging/utils/format-threads.util.ts b/packages/twenty-server/src/engine/core-modules/messaging/utils/format-threads.util.ts
index a141cbca1..230e1420f 100644
--- a/packages/twenty-server/src/engine/core-modules/messaging/utils/format-threads.util.ts
+++ b/packages/twenty-server/src/engine/core-modules/messaging/utils/format-threads.util.ts
@@ -1,3 +1,5 @@
+import { FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED } from 'twenty-shared/constants';
+
import { TimelineThread } from 'src/engine/core-modules/messaging/dtos/timeline-thread.dto';
import { extractParticipantSummary } from 'src/engine/core-modules/messaging/utils/extract-participant-summary.util';
import { MessageChannelVisibility } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
@@ -19,10 +21,23 @@ export const formatThreads = (
[key: string]: MessageChannelVisibility;
},
): TimelineThread[] => {
- return threads.map((thread) => ({
- ...thread,
- ...extractParticipantSummary(threadParticipantsByThreadId[thread.id]),
- visibility: threadVisibilityByThreadId[thread.id],
- read: true,
- }));
+ return threads.map((thread) => {
+ const visibility = threadVisibilityByThreadId[thread.id];
+
+ return {
+ ...thread,
+ subject:
+ visibility === MessageChannelVisibility.SHARE_EVERYTHING ||
+ visibility === MessageChannelVisibility.SUBJECT
+ ? thread.subject
+ : FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED,
+ lastMessageBody:
+ visibility === MessageChannelVisibility.SHARE_EVERYTHING
+ ? thread.lastMessageBody
+ : FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED,
+ ...extractParticipantSummary(threadParticipantsByThreadId[thread.id]),
+ visibility,
+ read: true,
+ };
+ });
};
diff --git a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts
deleted file mode 100644
index e4b68f726..000000000
--- a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { BadRequestException, NotFoundException, Scope } from '@nestjs/common';
-
-import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
-import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
-
-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 { 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({
- key: `calendarEvent.findMany`,
- scope: Scope.REQUEST,
-})
-export class CalendarEventFindManyPreQueryHook
- implements WorkspaceQueryHookInstance
-{
- constructor(
- private readonly twentyORMManager: TwentyORMManager,
- private readonly canAccessCalendarEventsService: CanAccessCalendarEventsService,
- ) {}
-
- async execute(
- authContext: AuthContext,
- objectName: string,
- payload: FindManyResolverArgs,
- ): Promise {
- if (!payload?.filter?.id?.eq) {
- throw new BadRequestException('id filter is required');
- }
-
- if (!authContext.user?.id) {
- throw new BadRequestException('User id is required');
- }
-
- const calendarChannelEventAssociationRepository =
- await this.twentyORMManager.getRepository(
- 'calendarChannelEventAssociation',
- );
-
- const calendarChannelCalendarEventAssociations =
- await calendarChannelEventAssociationRepository.find({
- where: {
- calendarEventId: payload?.filter?.id?.eq,
- },
- relations: ['calendarChannel.connectedAccount'],
- });
-
- if (calendarChannelCalendarEventAssociations.length === 0) {
- throw new NotFoundException();
- }
-
- await this.canAccessCalendarEventsService.canAccessCalendarEvents(
- authContext.user.id,
- authContext.workspace.id,
- calendarChannelCalendarEventAssociations,
- );
-
- return payload;
- }
-}
diff --git a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts
deleted file mode 100644
index 359721b9b..000000000
--- a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { BadRequestException, NotFoundException, Scope } from '@nestjs/common';
-
-import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
-import { FindOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
-
-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 { 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({
- key: `calendarEvent.findOne`,
- scope: Scope.REQUEST,
-})
-export class CalendarEventFindOnePreQueryHook
- implements WorkspaceQueryHookInstance
-{
- constructor(
- private readonly twentyORMManager: TwentyORMManager,
- private readonly canAccessCalendarEventsService: CanAccessCalendarEventsService,
- ) {}
-
- async execute(
- authContext: AuthContext,
- objectName: string,
- payload: FindOneResolverArgs,
- ): Promise {
- if (!payload?.filter?.id?.eq) {
- throw new BadRequestException('id filter is required');
- }
-
- if (!authContext.user?.id) {
- throw new BadRequestException('User id is required');
- }
-
- const calendarChannelEventAssociationRepository =
- await this.twentyORMManager.getRepository(
- 'calendarChannelEventAssociation',
- );
-
- const calendarChannelCalendarEventAssociations =
- await calendarChannelEventAssociationRepository.find({
- where: {
- calendarEventId: payload?.filter?.id?.eq,
- },
- relations: ['calendarChannel', 'calendarChannel.connectedAccount'],
- });
-
- if (calendarChannelCalendarEventAssociations.length === 0) {
- throw new NotFoundException();
- }
-
- await this.canAccessCalendarEventsService.canAccessCalendarEvents(
- authContext.user.id,
- authContext.workspace.id,
- calendarChannelCalendarEventAssociations,
- );
-
- return payload;
- }
-}
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 4ff0e03aa..c19278fb3 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
@@ -28,7 +28,7 @@ export class ApplyCalendarEventsVisibilityRestrictionsService {
where: {
calendarEventId: In(calendarEvents.map((event) => event.id)),
},
- relations: ['calendarChannel', 'calendarChannel.connectedAccount'],
+ relations: ['calendarChannel'],
});
const connectedAccountRepository =
diff --git a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-events.service.ts b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-events.service.ts
deleted file mode 100644
index e58e3118e..000000000
--- a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-event/services/can-access-calendar-events.service.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { Injectable } from '@nestjs/common';
-
-import groupBy from 'lodash.groupby';
-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';
-import { CalendarChannelVisibility } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
-import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
-import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository';
-import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
-
-@Injectable()
-export class CanAccessCalendarEventsService {
- constructor(
- private readonly twentyORMManager: TwentyORMManager,
- @InjectObjectMetadataRepository(WorkspaceMemberWorkspaceEntity)
- private readonly workspaceMemberService: WorkspaceMemberRepository,
- ) {}
-
- public async canAccessCalendarEvents(
- userId: string,
- workspaceId: string,
- calendarChannelCalendarEventAssociations: CalendarChannelEventAssociationWorkspaceEntity[],
- ) {
- const calendarChannels = calendarChannelCalendarEventAssociations.map(
- (association) => association.calendarChannel,
- );
-
- const calendarChannelsGroupByVisibility = groupBy(
- calendarChannels,
- (channel) => channel.visibility,
- );
-
- if (
- calendarChannelsGroupByVisibility[
- CalendarChannelVisibility.SHARE_EVERYTHING
- ] ||
- calendarChannelsGroupByVisibility[CalendarChannelVisibility.METADATA]
- ) {
- return;
- }
-
- const currentWorkspaceMember =
- await this.workspaceMemberService.getByIdOrFail(userId, workspaceId);
-
- const connectedAccountRepository =
- await this.twentyORMManager.getRepository(
- 'connectedAccount',
- );
-
- const connectedAccounts = await connectedAccountRepository.find({
- select: ['id'],
- where: {
- calendarChannels: {
- id: In(calendarChannels.map((channel) => channel.id)),
- },
- accountOwnerId: currentWorkspaceMember.id,
- },
- });
-
- if (connectedAccounts.length > 0) {
- return;
- }
-
- throw new ForbiddenError('Calendar events not shared');
- }
-}
diff --git a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-query-hook.module.ts b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-query-hook.module.ts
index 1b21ef65d..727a85699 100644
--- a/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-query-hook.module.ts
+++ b/packages/twenty-server/src/modules/calendar/common/query-hooks/calendar-query-hook.module.ts
@@ -2,11 +2,8 @@ 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 { 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({
@@ -14,10 +11,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta
ObjectMetadataRepositoryModule.forFeature([WorkspaceMemberWorkspaceEntity]),
],
providers: [
- CanAccessCalendarEventsService,
ApplyCalendarEventsVisibilityRestrictionsService,
- CalendarEventFindOnePreQueryHook,
- CalendarEventFindManyPreQueryHook,
CalendarEventFindOnePostQueryHook,
CalendarEventFindManyPostQueryHook,
],
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
new file mode 100644
index 000000000..345e6dde0
--- /dev/null
+++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service.spec.ts
@@ -0,0 +1,269 @@
+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 { 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 { ApplyMessagesVisibilityRestrictionsService } from './apply-messages-visibility-restrictions.service';
+
+const createMockMessage = (
+ id: string,
+ subject: string,
+ text: string,
+): MessageWorkspaceEntity => ({
+ id,
+ subject,
+ text,
+ headerMessageId: '',
+ receivedAt: new Date('2024-03-20T10:00:00Z'),
+ messageThreadId: '',
+ messageThread: null,
+ messageChannelMessageAssociations: [],
+ messageParticipants: [],
+ deletedAt: null,
+ createdAt: '2024-03-20T09:00:00Z',
+ updatedAt: '2024-03-20T09:00:00Z',
+});
+
+describe('ApplyMessagesVisibilityRestrictionsService', () => {
+ let service: ApplyMessagesVisibilityRestrictionsService;
+
+ const mockMessageChannelMessageAssociationRepository = {
+ find: jest.fn(),
+ };
+
+ const mockConnectedAccountRepository = {
+ find: jest.fn(),
+ };
+
+ const mockTwentyORMManager = {
+ getRepository: jest.fn().mockImplementation((name) => {
+ if (name === 'messageChannelMessageAssociation') {
+ return mockMessageChannelMessageAssociationRepository;
+ }
+ if (name === 'connectedAccount') {
+ return mockConnectedAccountRepository;
+ }
+ }),
+ };
+
+ beforeEach(async () => {
+ const module: TestingModule = await Test.createTestingModule({
+ providers: [
+ ApplyMessagesVisibilityRestrictionsService,
+ {
+ provide: TwentyORMManager,
+ useValue: mockTwentyORMManager,
+ },
+ ],
+ }).compile();
+
+ service = module.get(
+ ApplyMessagesVisibilityRestrictionsService,
+ );
+
+ jest.clearAllMocks();
+ });
+
+ it('should return message without obfuscated subject and text if the visibility is SHARE_EVERYTHING', async () => {
+ const messages = [
+ createMockMessage('messageId', 'Test Subject', 'Test Message'),
+ ];
+
+ mockMessageChannelMessageAssociationRepository.find.mockResolvedValue([
+ {
+ messageId: 'messageId',
+ messageChannel: {
+ id: 'messageChannelId',
+ visibility: MessageChannelVisibility.SHARE_EVERYTHING,
+ },
+ },
+ ]);
+
+ const result = await service.applyMessagesVisibilityRestrictions(
+ 'workspace-member-id',
+ messages,
+ );
+
+ expect(result).toEqual(messages);
+ expect(
+ result.every(
+ (item) =>
+ item.subject === 'Test Subject' && item.text === 'Test Message',
+ ),
+ ).toBe(true);
+ expect(mockConnectedAccountRepository.find).not.toHaveBeenCalled();
+ });
+
+ it('should return message without obfuscated subject and with obfuscated text if the visibility is SUBJECT', async () => {
+ const messages = [
+ createMockMessage('messageId', 'Test Subject', 'Test Message'),
+ ];
+
+ mockMessageChannelMessageAssociationRepository.find.mockResolvedValue([
+ {
+ messageId: 'messageId',
+ messageChannel: {
+ id: 'messageChannelId',
+ visibility: MessageChannelVisibility.SUBJECT,
+ },
+ },
+ ]);
+
+ mockConnectedAccountRepository.find.mockResolvedValue([]);
+
+ const result = await service.applyMessagesVisibilityRestrictions(
+ 'workspace-member-id',
+ messages,
+ );
+
+ expect(result).toEqual([
+ {
+ ...messages[0],
+ text: FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED,
+ },
+ ]);
+ });
+
+ it('should return message with obfuscated subject and text if the visibility is METADATA', async () => {
+ const messages = [
+ createMockMessage('messageId', 'Test Subject', 'Test Message'),
+ ];
+
+ mockMessageChannelMessageAssociationRepository.find.mockResolvedValue([
+ {
+ messageId: 'messageId',
+ messageChannel: {
+ id: 'messageChannelId',
+ visibility: MessageChannelVisibility.METADATA,
+ },
+ },
+ ]);
+
+ mockConnectedAccountRepository.find.mockResolvedValue([]);
+
+ const result = await service.applyMessagesVisibilityRestrictions(
+ 'workspace-member-id',
+ messages,
+ );
+
+ expect(result).toEqual([
+ {
+ ...messages[0],
+ subject: FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED,
+ text: FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED,
+ },
+ ]);
+ });
+
+ it('should return message without obfuscated subject and text if the visibility is METADATA and the workspace member is the channel owner', async () => {
+ const messages = [
+ createMockMessage('messageId', 'Test Subject', 'Test Message'),
+ ];
+
+ mockMessageChannelMessageAssociationRepository.find.mockResolvedValue([
+ {
+ messageId: 'messageId',
+ messageChannel: {
+ id: 'messageChannelId',
+ visibility: MessageChannelVisibility.METADATA,
+ },
+ },
+ ]);
+
+ mockConnectedAccountRepository.find.mockResolvedValue([{ id: '1' }]);
+
+ const result = await service.applyMessagesVisibilityRestrictions(
+ 'workspace-member-id',
+ messages,
+ );
+
+ expect(result).toEqual(messages);
+ expect(
+ result.every(
+ (item) =>
+ item.subject === 'Test Subject' && item.text === 'Test Message',
+ ),
+ ).toBe(true);
+ });
+
+ it('should not return message if visibility is not SHARE_EVERYTHING, SUBJECT or METADATA and the workspace member is not the channel owner', async () => {
+ const messages = [
+ createMockMessage('messageId', 'Test Subject', 'Test Message'),
+ ];
+
+ mockMessageChannelMessageAssociationRepository.find.mockResolvedValue([
+ {
+ messageId: 'messageId',
+ messageChannel: {
+ id: 'messageChannelId',
+ },
+ },
+ ]);
+
+ mockConnectedAccountRepository.find.mockResolvedValue([]);
+
+ const result = await service.applyMessagesVisibilityRestrictions(
+ 'workspace-member-id',
+ messages,
+ );
+
+ expect(result).toEqual([]);
+ });
+
+ it('should return all messages with the right visibility', 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,
+ },
+ },
+ ]);
+
+ mockConnectedAccountRepository.find
+ .mockResolvedValueOnce([]) // request for message 3
+ .mockResolvedValueOnce([]); // request for message 2
+
+ const result = await service.applyMessagesVisibilityRestrictions(
+ 'workspace-member-id',
+ messages,
+ );
+
+ 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,
+ },
+ ]);
+ });
+});
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
new file mode 100644
index 000000000..e87e3857d
--- /dev/null
+++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service.ts
@@ -0,0 +1,98 @@
+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 { NotFoundError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
+import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
+import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
+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';
+
+@Injectable()
+export class ApplyMessagesVisibilityRestrictionsService {
+ constructor(private readonly twentyORMManager: TwentyORMManager) {}
+
+ public async applyMessagesVisibilityRestrictions(
+ workspaceMemberId: string,
+ messages: MessageWorkspaceEntity[],
+ ) {
+ const messageChannelMessageAssociationRepository =
+ await this.twentyORMManager.getRepository(
+ 'messageChannelMessageAssociation',
+ );
+
+ const messageChannelMessagesAssociations =
+ await messageChannelMessageAssociationRepository.find({
+ where: {
+ messageId: In(messages.map((message) => message.id)),
+ },
+ relations: ['messageChannel'],
+ });
+
+ const connectedAccountRepository =
+ await this.twentyORMManager.getRepository(
+ 'connectedAccount',
+ );
+
+ for (let i = messages.length - 1; i >= 0; i--) {
+ const messageChannelMessageAssociations =
+ messageChannelMessagesAssociations.filter(
+ (association) => association.messageId === messages[i].id,
+ );
+
+ const messageChannels = messageChannelMessageAssociations
+ .map((association) => association.messageChannel)
+ .filter(
+ (channel): channel is NonNullable => channel !== null,
+ );
+
+ if (messageChannels.length === 0) {
+ throw new NotFoundError('Associated message channels not found');
+ }
+
+ const messageChannelsGroupByVisibility = groupBy(
+ messageChannels,
+ (channel) => channel.visibility,
+ );
+
+ if (
+ messageChannelsGroupByVisibility[
+ MessageChannelVisibility.SHARE_EVERYTHING
+ ]
+ ) {
+ continue;
+ }
+
+ const connectedAccounts = await connectedAccountRepository.find({
+ select: ['id'],
+ where: {
+ messageChannels: {
+ id: In(messageChannels.map((channel) => channel.id)),
+ },
+ accountOwnerId: workspaceMemberId,
+ },
+ });
+
+ if (connectedAccounts.length > 0) {
+ continue;
+ }
+ if (messageChannelsGroupByVisibility[MessageChannelVisibility.SUBJECT]) {
+ messages[i].text = FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED;
+ continue;
+ }
+
+ if (messageChannelsGroupByVisibility[MessageChannelVisibility.METADATA]) {
+ messages[i].subject = FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED;
+ messages[i].text = FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED;
+ continue;
+ }
+
+ messages.splice(i, 1);
+ }
+
+ return messages;
+ }
+}
diff --git a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/can-access-message-thread.service.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/can-access-message-thread.service.ts
deleted file mode 100644
index 19fdb153f..000000000
--- a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/can-access-message-thread.service.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { ForbiddenException } from '@nestjs/common';
-
-import { In } from 'typeorm';
-
-import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
-import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
-import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
-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 { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository';
-import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
-
-export class CanAccessMessageThreadService {
- constructor(
- @InjectObjectMetadataRepository(WorkspaceMemberWorkspaceEntity)
- private readonly workspaceMemberRepository: WorkspaceMemberRepository,
- private readonly twentyORMManager: TwentyORMManager,
- ) {}
-
- public async canAccessMessageThread(
- userId: string,
- workspaceId: string,
- messageChannelMessageAssociations: MessageChannelMessageAssociationWorkspaceEntity[],
- ) {
- const messageChannelIds = messageChannelMessageAssociations.map(
- (association) => association.messageChannelId,
- );
-
- const currentWorkspaceMember =
- await this.workspaceMemberRepository.getByIdOrFail(userId, workspaceId);
-
- const connectedAccountRepository =
- await this.twentyORMManager.getRepository(
- 'connectedAccount',
- );
-
- const connectedAccounts = await connectedAccountRepository.find({
- select: {
- id: true,
- },
- where: [
- {
- messageChannels: {
- id: In(messageChannelIds),
- visibility: MessageChannelVisibility.SHARE_EVERYTHING,
- },
- },
- {
- messageChannels: {
- id: In(messageChannelIds),
- },
- accountOwnerId: currentWorkspaceMember.id,
- },
- ],
- take: 1,
- });
-
- if (connectedAccounts.length === 0) {
- throw new ForbiddenException();
- }
- }
-}
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
new file mode 100644
index 000000000..63b3bcc4a
--- /dev/null
+++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.post-query.hook.ts
@@ -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 { 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';
+
+@WorkspaceQueryHook({
+ key: `message.findMany`,
+ type: WorkspaceQueryHookType.PostHook,
+})
+export class MessageFindManyPostQueryHook
+ implements WorkspaceQueryPostHookInstance
+{
+ constructor(
+ private readonly applyMessagesVisibilityRestrictionsService: ApplyMessagesVisibilityRestrictionsService,
+ ) {}
+
+ async execute(
+ authContext: AuthContext,
+ _objectName: string,
+ payload: MessageWorkspaceEntity[],
+ ): Promise {
+ if (!authContext.workspaceMemberId) {
+ throw new UserInputError('Workspace member id is required');
+ }
+
+ await this.applyMessagesVisibilityRestrictionsService.applyMessagesVisibilityRestrictions(
+ authContext.workspaceMemberId,
+ payload,
+ );
+ }
+}
diff --git a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook.ts
deleted file mode 100644
index 14fa417cf..000000000
--- a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import { BadRequestException, NotFoundException } from '@nestjs/common';
-
-import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
-import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
-
-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 { CanAccessMessageThreadService } from 'src/modules/messaging/common/query-hooks/message/can-access-message-thread.service';
-import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
-
-@WorkspaceQueryHook(`message.findMany`)
-export class MessageFindManyPreQueryHook implements WorkspaceQueryHookInstance {
- constructor(
- private readonly canAccessMessageThreadService: CanAccessMessageThreadService,
- private readonly twentyORMManager: TwentyORMManager,
- ) {}
-
- async execute(
- authContext: AuthContext,
- objectName: string,
- payload: FindManyResolverArgs,
- ): Promise {
- if (!payload?.filter?.messageThreadId?.eq) {
- throw new BadRequestException('messageThreadId filter is required');
- }
-
- if (!authContext.user?.id) {
- throw new BadRequestException('User id is required');
- }
-
- const messageChannelMessageAssociationRepository =
- await this.twentyORMManager.getRepository(
- 'messageChannelMessageAssociation',
- );
-
- const messageChannelMessageAssociations =
- await messageChannelMessageAssociationRepository.find({
- where: {
- message: {
- messageThreadId: payload.filter.messageThreadId.eq,
- },
- },
- });
-
- if (messageChannelMessageAssociations.length === 0) {
- throw new NotFoundException();
- }
-
- await this.canAccessMessageThreadService.canAccessMessageThread(
- authContext.user.id,
- authContext.workspace.id,
- messageChannelMessageAssociations,
- );
-
- return payload;
- }
-}
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
new file mode 100644
index 000000000..33e345503
--- /dev/null
+++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.post-query.hook.ts
@@ -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 { 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';
+
+@WorkspaceQueryHook({
+ key: `message.findOne`,
+ type: WorkspaceQueryHookType.PostHook,
+})
+export class MessageFindOnePostQueryHook
+ implements WorkspaceQueryPostHookInstance
+{
+ constructor(
+ private readonly applyMessagesVisibilityRestrictionsService: ApplyMessagesVisibilityRestrictionsService,
+ ) {}
+
+ async execute(
+ authContext: AuthContext,
+ _objectName: string,
+ payload: MessageWorkspaceEntity[],
+ ): Promise {
+ if (!authContext.workspaceMemberId) {
+ throw new UserInputError('Workspace member id is required');
+ }
+
+ await this.applyMessagesVisibilityRestrictionsService.applyMessagesVisibilityRestrictions(
+ authContext.workspaceMemberId,
+ payload,
+ );
+ }
+}
diff --git a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook.ts
deleted file mode 100644
index f06f4b09f..000000000
--- a/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-vars */
-import { NotFoundException } from '@nestjs/common';
-
-import { WorkspaceQueryHookInstance } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/interfaces/workspace-query-hook.interface';
-import { FindOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
-
-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 { CanAccessMessageThreadService } from 'src/modules/messaging/common/query-hooks/message/can-access-message-thread.service';
-import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
-
-@WorkspaceQueryHook(`message.findOne`)
-export class MessageFindOnePreQueryHook implements WorkspaceQueryHookInstance {
- constructor(
- private readonly canAccessMessageThreadService: CanAccessMessageThreadService,
- private readonly twentyORMManager: TwentyORMManager,
- ) {}
-
- async execute(
- authContext: AuthContext,
- objectName: string,
- payload: FindOneResolverArgs,
- ): Promise {
- if (!authContext.user?.id) {
- throw new NotFoundException('User id is required');
- }
-
- const messageChannelMessageAssociationRepository =
- await this.twentyORMManager.getRepository(
- 'messageChannelMessageAssociation',
- );
-
- const messageChannelMessageAssociations =
- await messageChannelMessageAssociationRepository.find({
- where: {
- messageId: payload?.filter?.id?.eq,
- },
- });
-
- if (messageChannelMessageAssociations.length === 0) {
- throw new NotFoundException();
- }
-
- await this.canAccessMessageThreadService.canAccessMessageThread(
- authContext.user.id,
- authContext.workspace.id,
- messageChannelMessageAssociations,
- );
-
- return payload;
- }
-}
diff --git a/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts
index 1222865f6..99f703b19 100644
--- a/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts
+++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts
@@ -1,9 +1,9 @@
import { Module } from '@nestjs/common';
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
-import { CanAccessMessageThreadService } from 'src/modules/messaging/common/query-hooks/message/can-access-message-thread.service';
-import { MessageFindManyPreQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook';
-import { MessageFindOnePreQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook';
+import { ApplyMessagesVisibilityRestrictionsService } from 'src/modules/messaging/common/query-hooks/message/apply-messages-visibility-restrictions.service';
+import { MessageFindManyPostQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-many.post-query.hook';
+import { MessageFindOnePostQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-one.post-query.hook';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
@Module({
@@ -11,9 +11,9 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta
ObjectMetadataRepositoryModule.forFeature([WorkspaceMemberWorkspaceEntity]),
],
providers: [
- CanAccessMessageThreadService,
- MessageFindOnePreQueryHook,
- MessageFindManyPreQueryHook,
+ ApplyMessagesVisibilityRestrictionsService,
+ MessageFindOnePostQueryHook,
+ MessageFindManyPostQueryHook,
],
})
export class MessagingQueryHookModule {}