POC timeline activity (#5697)

TODO: 
- remove WorkspaceIsNotAuditLogged decorators on activity/activityTarget
to log task/note creations
- handle attachments
-  fix css and remove unnecessary styled components or duplicates
This commit is contained in:
Weiko
2024-06-11 18:53:28 +02:00
committed by GitHub
parent 64b8e4ec4d
commit be96c68416
60 changed files with 2134 additions and 443 deletions

View File

@ -0,0 +1,64 @@
import { ForbiddenException } from '@nestjs/common';
import groupBy from 'lodash.groupby';
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
import { MessageChannelWorkspaceEntity } 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(MessageChannelWorkspaceEntity)
private readonly messageChannelService: MessageChannelRepository,
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
private readonly connectedAccountRepository: ConnectedAccountRepository,
@InjectObjectMetadataRepository(WorkspaceMemberWorkspaceEntity)
private readonly workspaceMemberRepository: WorkspaceMemberRepository,
) {}
public async canAccessMessageThread(
userId: string,
workspaceId: string,
messageChannelMessageAssociations: any[],
) {
const messageChannels = await this.messageChannelService.getByIds(
messageChannelMessageAssociations.map(
(association) => association.messageChannelId,
),
workspaceId,
);
const messageChannelsGroupByVisibility = groupBy(
messageChannels,
(channel) => channel.visibility,
);
if (messageChannelsGroupByVisibility.share_everything) {
return;
}
const currentWorkspaceMember =
await this.workspaceMemberRepository.getByIdOrFail(userId, workspaceId);
const messageChannelsConnectedAccounts =
await this.connectedAccountRepository.getByIds(
messageChannels.map((channel) => channel.connectedAccountId),
workspaceId,
);
const messageChannelsWorkspaceMemberIds =
messageChannelsConnectedAccounts.map(
(connectedAccount) => connectedAccount.accountOwnerId,
);
if (messageChannelsWorkspaceMemberIds.includes(currentWorkspaceMember.id)) {
return;
}
throw new ForbiddenException();
}
}

View File

@ -1,24 +1,16 @@
import {
BadRequestException,
ForbiddenException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import groupBy from 'lodash.groupby';
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 { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository';
import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository';
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
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';
import { CanAccessMessageThreadService } from 'src/modules/messaging/common/query-hooks/message/can-access-message-thread.service';
import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository';
import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository';
import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
@Injectable()
export class MessageFindManyPreQueryHook implements WorkspacePreQueryHook {
@ -27,12 +19,7 @@ export class MessageFindManyPreQueryHook implements WorkspacePreQueryHook {
MessageChannelMessageAssociationWorkspaceEntity,
)
private readonly messageChannelMessageAssociationService: MessageChannelMessageAssociationRepository,
@InjectObjectMetadataRepository(MessageChannelWorkspaceEntity)
private readonly messageChannelService: MessageChannelRepository,
@InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity)
private readonly connectedAccountRepository: ConnectedAccountRepository,
@InjectObjectMetadataRepository(WorkspaceMemberWorkspaceEntity)
private readonly workspaceMemberRepository: WorkspaceMemberRepository,
private readonly canAccessMessageThreadService: CanAccessMessageThreadService,
) {}
async execute(
@ -54,52 +41,10 @@ export class MessageFindManyPreQueryHook implements WorkspacePreQueryHook {
throw new NotFoundException();
}
await this.canAccessMessageThread(
await this.canAccessMessageThreadService.canAccessMessageThread(
userId,
workspaceId,
messageChannelMessageAssociations,
);
}
private async canAccessMessageThread(
userId: string,
workspaceId: string,
messageChannelMessageAssociations: any[],
) {
const messageChannels = await this.messageChannelService.getByIds(
messageChannelMessageAssociations.map(
(association) => association.messageChannelId,
),
workspaceId,
);
const messageChannelsGroupByVisibility = groupBy(
messageChannels,
(channel) => channel.visibility,
);
if (messageChannelsGroupByVisibility.SHARE_EVERYTHING) {
return;
}
const currentWorkspaceMember =
await this.workspaceMemberRepository.getByIdOrFail(userId, workspaceId);
const messageChannelsConnectedAccounts =
await this.connectedAccountRepository.getByIds(
messageChannels.map((channel) => channel.connectedAccountId),
workspaceId,
);
const messageChannelsWorkspaceMemberIds =
messageChannelsConnectedAccounts.map(
(connectedAccount) => connectedAccount.accountOwnerId,
);
if (messageChannelsWorkspaceMemberIds.includes(currentWorkspaceMember.id)) {
return;
}
throw new ForbiddenException();
}
}

View File

@ -1,16 +1,43 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { Injectable, MethodNotAllowedException } from '@nestjs/common';
import { 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 { CanAccessMessageThreadService } from 'src/modules/messaging/common/query-hooks/message/can-access-message-thread.service';
import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository';
import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
@Injectable()
export class MessageFindOnePreQueryHook implements WorkspacePreQueryHook {
constructor(
@InjectObjectMetadataRepository(
MessageChannelMessageAssociationWorkspaceEntity,
)
private readonly messageChannelMessageAssociationService: MessageChannelMessageAssociationRepository,
private readonly canAccessMessageThreadService: CanAccessMessageThreadService,
) {}
async execute(
_userId: string,
_workspaceId: string,
_payload: FindOneResolverArgs,
userId: string,
workspaceId: string,
payload: FindOneResolverArgs,
): Promise<void> {
throw new MethodNotAllowedException('Method not allowed.');
const messageChannelMessageAssociations =
await this.messageChannelMessageAssociationService.getByMessageIds(
[payload?.filter?.id?.eq],
workspaceId,
);
if (messageChannelMessageAssociations.length === 0) {
throw new NotFoundException();
}
await this.canAccessMessageThreadService.canAccessMessageThread(
userId,
workspaceId,
messageChannelMessageAssociations,
);
}
}

View File

@ -3,6 +3,7 @@ import { Module } from '@nestjs/common';
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
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 { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
@ -18,6 +19,7 @@ import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/stan
]),
],
providers: [
CanAccessMessageThreadService,
{
provide: MessageFindOnePreQueryHook.name,
useClass: MessageFindOnePreQueryHook,