Remove connected account feature flag (#19286)
Co-authored-by: martmull <martmull@hotmail.fr> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions <github-actions@twenty.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
+1
-1
@@ -1,8 +1,8 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { MessageChannelVisibility } from 'twenty-shared/types';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { TimelineThreadParticipantDTO } from 'src/engine/core-modules/messaging/dtos/timeline-thread-participant.dto';
|
||||
import { MessageChannelVisibility } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||
|
||||
@ObjectType('TimelineThread')
|
||||
export class TimelineThreadDTO {
|
||||
|
||||
+107
-25
@@ -1,19 +1,32 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { MessageParticipantRole } from 'twenty-shared/types';
|
||||
import { In } from 'typeorm';
|
||||
import {
|
||||
MessageChannelVisibility,
|
||||
MessageParticipantRole,
|
||||
} from 'twenty-shared/types';
|
||||
import { In, type Repository } from 'typeorm';
|
||||
|
||||
import { type TimelineThreadDTO } from 'src/engine/core-modules/messaging/dtos/timeline-thread.dto';
|
||||
import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { ConnectedAccountEntity } from 'src/engine/metadata-modules/connected-account/entities/connected-account.entity';
|
||||
import { MessageChannelEntity } from 'src/engine/metadata-modules/message-channel/entities/message-channel.entity';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
|
||||
import { MessageChannelVisibility } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||
import { type MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
|
||||
import { type MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity';
|
||||
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
|
||||
@Injectable()
|
||||
export class TimelineMessagingService {
|
||||
constructor(
|
||||
private readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
|
||||
@InjectRepository(MessageChannelEntity)
|
||||
private readonly messageChannelRepository: Repository<MessageChannelEntity>,
|
||||
@InjectRepository(ConnectedAccountEntity)
|
||||
private readonly connectedAccountRepository: Repository<ConnectedAccountEntity>,
|
||||
@InjectRepository(UserWorkspaceEntity)
|
||||
private readonly userWorkspaceRepository: Repository<UserWorkspaceEntity>,
|
||||
) {}
|
||||
|
||||
public async getAndCountMessageThreads(
|
||||
@@ -212,57 +225,126 @@ export class TimelineMessagingService {
|
||||
|
||||
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
|
||||
async () => {
|
||||
const workspaceMemberRepository =
|
||||
await this.globalWorkspaceOrmManager.getRepository<WorkspaceMemberWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workspaceMember',
|
||||
{ shouldBypassPermissionChecks: true },
|
||||
);
|
||||
|
||||
const currentMember = await workspaceMemberRepository.findOne({
|
||||
where: { id: workspaceMemberId },
|
||||
select: { userId: true },
|
||||
});
|
||||
|
||||
if (!currentMember) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const currentUserWorkspace = await this.userWorkspaceRepository.findOne(
|
||||
{
|
||||
where: { userId: currentMember.userId, workspaceId },
|
||||
select: { id: true },
|
||||
},
|
||||
);
|
||||
|
||||
if (!currentUserWorkspace) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const currentUserWorkspaceId = currentUserWorkspace.id;
|
||||
|
||||
const messageThreadRepository =
|
||||
await this.globalWorkspaceOrmManager.getRepository<MessageThreadWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'messageThread',
|
||||
);
|
||||
|
||||
const threadVisibility = await messageThreadRepository
|
||||
const threadChannelRows = await messageThreadRepository
|
||||
.createQueryBuilder()
|
||||
.select('messageThread.id', 'id')
|
||||
.addSelect('messageChannel.visibility', 'visibility')
|
||||
.addSelect('connectedAccount.accountOwnerId', 'accountOwnerId')
|
||||
.addSelect(
|
||||
'messageChannelMessageAssociation.messageChannelId',
|
||||
'messageChannelId',
|
||||
)
|
||||
.leftJoin('messageThread.messages', 'message')
|
||||
.leftJoin(
|
||||
'message.messageChannelMessageAssociations',
|
||||
'messageChannelMessageAssociation',
|
||||
)
|
||||
.leftJoin(
|
||||
'messageChannelMessageAssociation.messageChannel',
|
||||
'messageChannel',
|
||||
)
|
||||
.leftJoin('messageChannel.connectedAccount', 'connectedAccount')
|
||||
.where('messageThread.id = ANY(:messageThreadIds)', {
|
||||
messageThreadIds: messageThreadIds,
|
||||
messageThreadIds,
|
||||
})
|
||||
.getRawMany();
|
||||
.getRawMany<{ id: string; messageChannelId: string | null }>();
|
||||
|
||||
const allMessageChannelIds = [
|
||||
...new Set(
|
||||
threadChannelRows
|
||||
.map((row) => row.messageChannelId)
|
||||
.filter((id): id is string => id !== null && id !== undefined),
|
||||
),
|
||||
];
|
||||
|
||||
if (allMessageChannelIds.length === 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const messageChannels = await this.messageChannelRepository.find({
|
||||
where: { id: In(allMessageChannelIds), workspaceId },
|
||||
select: { id: true, visibility: true, connectedAccountId: true },
|
||||
});
|
||||
|
||||
const allConnectedAccountIds = [
|
||||
...new Set(
|
||||
messageChannels.map((channel) => channel.connectedAccountId),
|
||||
),
|
||||
];
|
||||
|
||||
const ownedAccountIds = new Set(
|
||||
(
|
||||
await this.connectedAccountRepository.find({
|
||||
where: {
|
||||
id: In(allConnectedAccountIds),
|
||||
userWorkspaceId: currentUserWorkspaceId,
|
||||
},
|
||||
select: { id: true },
|
||||
})
|
||||
).map((account) => account.id),
|
||||
);
|
||||
|
||||
const channelVisibilityMap = new Map(
|
||||
messageChannels.map((channel) => [
|
||||
channel.id,
|
||||
ownedAccountIds.has(channel.connectedAccountId)
|
||||
? MessageChannelVisibility.SHARE_EVERYTHING
|
||||
: channel.visibility,
|
||||
]),
|
||||
);
|
||||
|
||||
const visibilityValues = Object.values(MessageChannelVisibility);
|
||||
|
||||
const threadVisibilityByThreadId: {
|
||||
[key: string]: MessageChannelVisibility;
|
||||
} = threadVisibility.reduce((threadVisibilityAcc, threadVisibility) => {
|
||||
if (threadVisibility.accountOwnerId === workspaceMemberId) {
|
||||
threadVisibilityAcc[threadVisibility.id] =
|
||||
MessageChannelVisibility.SHARE_EVERYTHING;
|
||||
} = {};
|
||||
|
||||
return threadVisibilityAcc;
|
||||
}
|
||||
for (const { id: threadId, messageChannelId } of threadChannelRows) {
|
||||
if (!messageChannelId) continue;
|
||||
|
||||
threadVisibilityAcc[threadVisibility.id] =
|
||||
const channelVisibility = channelVisibilityMap.get(messageChannelId);
|
||||
|
||||
if (!channelVisibility) continue;
|
||||
|
||||
threadVisibilityByThreadId[threadId] =
|
||||
visibilityValues[
|
||||
Math.max(
|
||||
visibilityValues.indexOf(threadVisibility.visibility),
|
||||
visibilityValues.indexOf(channelVisibility),
|
||||
visibilityValues.indexOf(
|
||||
threadVisibilityAcc[threadVisibility.id] ??
|
||||
threadVisibilityByThreadId[threadId] ??
|
||||
MessageChannelVisibility.METADATA,
|
||||
),
|
||||
)
|
||||
];
|
||||
|
||||
return threadVisibilityAcc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
return threadVisibilityByThreadId;
|
||||
},
|
||||
|
||||
+10
-1
@@ -1,13 +1,17 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { GetMessagesService } from 'src/engine/core-modules/messaging/services/get-messages.service';
|
||||
import { TimelineMessagingService } from 'src/engine/core-modules/messaging/services/timeline-messaging.service';
|
||||
import { TimelineMessagingResolver } from 'src/engine/core-modules/messaging/timeline-messaging.resolver';
|
||||
import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { UserModule } from 'src/engine/core-modules/user/user.module';
|
||||
import { ConnectedAccountEntity } from 'src/engine/metadata-modules/connected-account/entities/connected-account.entity';
|
||||
import { MessageChannelEntity } from 'src/engine/metadata-modules/message-channel/entities/message-channel.entity';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
import { ConnectedAccountModule } from 'src/modules/connected-account/connected-account.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -16,6 +20,11 @@ import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permi
|
||||
ConnectedAccountModule,
|
||||
FeatureFlagModule,
|
||||
PermissionsModule,
|
||||
TypeOrmModule.forFeature([
|
||||
MessageChannelEntity,
|
||||
ConnectedAccountEntity,
|
||||
UserWorkspaceEntity,
|
||||
]),
|
||||
],
|
||||
exports: [],
|
||||
providers: [
|
||||
|
||||
+1
-1
@@ -1,9 +1,9 @@
|
||||
import { FIELD_RESTRICTED_ADDITIONAL_PERMISSIONS_REQUIRED } from 'twenty-shared/constants';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { MessageChannelVisibility } from 'twenty-shared/types';
|
||||
import { type TimelineThreadDTO } 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';
|
||||
import { type MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
|
||||
|
||||
export const formatThreads = (
|
||||
|
||||
Reference in New Issue
Block a user