4002 prevent user from creating twice the same blocklist item (#5213)
Closes #4002
This commit is contained in:
@ -21,33 +21,42 @@ const StyledLinkContainer = styled.div`
|
|||||||
|
|
||||||
type SettingsAccountsEmailsBlocklistInputProps = {
|
type SettingsAccountsEmailsBlocklistInputProps = {
|
||||||
updateBlockedEmailList: (email: string) => void;
|
updateBlockedEmailList: (email: string) => void;
|
||||||
|
blockedEmailOrDomainList: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const validationSchema = z
|
const validationSchema = (blockedEmailOrDomainList: string[]) =>
|
||||||
.object({
|
z
|
||||||
emailOrDomain: z
|
.object({
|
||||||
.string()
|
emailOrDomain: z
|
||||||
.trim()
|
.string()
|
||||||
.email('Invalid email or domain')
|
.trim()
|
||||||
.or(
|
.email('Invalid email or domain')
|
||||||
z
|
.or(
|
||||||
.string()
|
z
|
||||||
.refine(
|
.string()
|
||||||
(value) => value.startsWith('@') && isDomain(value.slice(1)),
|
.refine(
|
||||||
'Invalid email or domain',
|
(value) => value.startsWith('@') && isDomain(value.slice(1)),
|
||||||
),
|
'Invalid email or domain',
|
||||||
),
|
),
|
||||||
})
|
)
|
||||||
.required();
|
.refine(
|
||||||
|
(value) => !blockedEmailOrDomainList.includes(value),
|
||||||
|
'Email or domain is already in blocklist',
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.required();
|
||||||
|
|
||||||
type FormInput = z.infer<typeof validationSchema>;
|
type FormInput = {
|
||||||
|
emailOrDomain: string;
|
||||||
|
};
|
||||||
|
|
||||||
export const SettingsAccountsEmailsBlocklistInput = ({
|
export const SettingsAccountsEmailsBlocklistInput = ({
|
||||||
updateBlockedEmailList,
|
updateBlockedEmailList,
|
||||||
|
blockedEmailOrDomainList,
|
||||||
}: SettingsAccountsEmailsBlocklistInputProps) => {
|
}: SettingsAccountsEmailsBlocklistInputProps) => {
|
||||||
const { reset, handleSubmit, control, formState } = useForm<FormInput>({
|
const { reset, handleSubmit, control, formState } = useForm<FormInput>({
|
||||||
mode: 'onSubmit',
|
mode: 'onSubmit',
|
||||||
resolver: zodResolver(validationSchema),
|
resolver: zodResolver(validationSchema(blockedEmailOrDomainList)),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
emailOrDomain: '',
|
emailOrDomain: '',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -45,6 +45,7 @@ export const SettingsAccountsEmailsBlocklistSection = () => {
|
|||||||
description="Exclude the following people and domains from my email sync"
|
description="Exclude the following people and domains from my email sync"
|
||||||
/>
|
/>
|
||||||
<SettingsAccountsEmailsBlocklistInput
|
<SettingsAccountsEmailsBlocklistInput
|
||||||
|
blockedEmailOrDomainList={blocklist.map((item) => item.handle)}
|
||||||
updateBlockedEmailList={updateBlockedEmailList}
|
updateBlockedEmailList={updateBlockedEmailList}
|
||||||
/>
|
/>
|
||||||
<SettingsAccountsEmailsBlocklistTable
|
<SettingsAccountsEmailsBlocklistTable
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runne
|
|||||||
import { CalendarEventFindManyPreQueryHook } from 'src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook';
|
import { CalendarEventFindManyPreQueryHook } from 'src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook';
|
||||||
import { CalendarEventFindOnePreQueryHook } from 'src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook';
|
import { CalendarEventFindOnePreQueryHook } from 'src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook';
|
||||||
import { BlocklistCreateManyPreQueryHook } from 'src/modules/connected-account/query-hooks/blocklist/blocklist-create-many.pre-query.hook';
|
import { BlocklistCreateManyPreQueryHook } from 'src/modules/connected-account/query-hooks/blocklist/blocklist-create-many.pre-query.hook';
|
||||||
|
import { BlocklistUpdateManyPreQueryHook } from 'src/modules/connected-account/query-hooks/blocklist/blocklist-update-many.pre-query.hook';
|
||||||
|
import { BlocklistUpdateOnePreQueryHook } from 'src/modules/connected-account/query-hooks/blocklist/blocklist-update-one.pre-query.hook';
|
||||||
|
|
||||||
// TODO: move to a decorator
|
// TODO: move to a decorator
|
||||||
export const workspacePreQueryHooks: WorkspaceQueryHook = {
|
export const workspacePreQueryHooks: WorkspaceQueryHook = {
|
||||||
@ -17,5 +19,7 @@ export const workspacePreQueryHooks: WorkspaceQueryHook = {
|
|||||||
},
|
},
|
||||||
blocklist: {
|
blocklist: {
|
||||||
createMany: [BlocklistCreateManyPreQueryHook.name],
|
createMany: [BlocklistCreateManyPreQueryHook.name],
|
||||||
|
updateMany: [BlocklistUpdateManyPreQueryHook.name],
|
||||||
|
updateOne: [BlocklistUpdateOnePreQueryHook.name],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -328,6 +328,14 @@ export class WorkspaceQueryRunnerService {
|
|||||||
options,
|
options,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await this.workspacePreQueryHookService.executePreHooks(
|
||||||
|
userId,
|
||||||
|
workspaceId,
|
||||||
|
objectMetadataItem.nameSingular,
|
||||||
|
'updateOne',
|
||||||
|
args,
|
||||||
|
);
|
||||||
|
|
||||||
const result = await this.execute(query, workspaceId);
|
const result = await this.execute(query, workspaceId);
|
||||||
|
|
||||||
const parsedResults = (
|
const parsedResults = (
|
||||||
@ -363,7 +371,7 @@ export class WorkspaceQueryRunnerService {
|
|||||||
args: UpdateManyResolverArgs<Record>,
|
args: UpdateManyResolverArgs<Record>,
|
||||||
options: WorkspaceQueryRunnerOptions,
|
options: WorkspaceQueryRunnerOptions,
|
||||||
): Promise<Record[] | undefined> {
|
): Promise<Record[] | undefined> {
|
||||||
const { workspaceId, objectMetadataItem } = options;
|
const { userId, workspaceId, objectMetadataItem } = options;
|
||||||
|
|
||||||
assertMutationNotOnRemoteObject(objectMetadataItem);
|
assertMutationNotOnRemoteObject(objectMetadataItem);
|
||||||
assertIsValidUuid(args.data.id);
|
assertIsValidUuid(args.data.id);
|
||||||
@ -376,6 +384,14 @@ export class WorkspaceQueryRunnerService {
|
|||||||
atMost: maximumRecordAffected,
|
atMost: maximumRecordAffected,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await this.workspacePreQueryHookService.executePreHooks(
|
||||||
|
userId,
|
||||||
|
workspaceId,
|
||||||
|
objectMetadataItem.nameSingular,
|
||||||
|
'updateMany',
|
||||||
|
args,
|
||||||
|
);
|
||||||
|
|
||||||
const result = await this.execute(query, workspaceId);
|
const result = await this.execute(query, workspaceId);
|
||||||
|
|
||||||
const parsedResults = (
|
const parsedResults = (
|
||||||
|
|||||||
@ -1,46 +1,28 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
import z from 'zod';
|
|
||||||
|
|
||||||
import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface';
|
import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface';
|
||||||
import { CreateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
import { CreateManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||||
|
|
||||||
import { isDomain } from 'src/engine/utils/is-domain';
|
import {
|
||||||
import { BlocklistObjectMetadata } from 'src/modules/connected-account/standard-objects/blocklist.object-metadata';
|
BlocklistItem,
|
||||||
|
BlocklistValidationService,
|
||||||
|
} from 'src/modules/connected-account/services/blocklist/blocklist-validation.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BlocklistCreateManyPreQueryHook implements WorkspacePreQueryHook {
|
export class BlocklistCreateManyPreQueryHook implements WorkspacePreQueryHook {
|
||||||
constructor() {}
|
constructor(
|
||||||
|
private readonly blocklistValidationService: BlocklistValidationService,
|
||||||
|
) {}
|
||||||
|
|
||||||
async execute(
|
async execute(
|
||||||
userId: string,
|
userId: string,
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
payload: CreateManyResolverArgs<
|
payload: CreateManyResolverArgs<BlocklistItem>,
|
||||||
Omit<BlocklistObjectMetadata, 'createdAt' | 'updatedAt'> & {
|
|
||||||
createdAt: string;
|
|
||||||
updatedAt: string;
|
|
||||||
}
|
|
||||||
>,
|
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const emailOrDomainSchema = z
|
await this.blocklistValidationService.validateBlocklistForCreateMany(
|
||||||
.string()
|
payload,
|
||||||
.trim()
|
userId,
|
||||||
.email('Invalid email or domain')
|
workspaceId,
|
||||||
.or(
|
);
|
||||||
z
|
|
||||||
.string()
|
|
||||||
.refine(
|
|
||||||
(value) => value.startsWith('@') && isDomain(value.slice(1)),
|
|
||||||
'Invalid email or domain',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const { handle } of payload.data) {
|
|
||||||
if (!handle) {
|
|
||||||
throw new Error('Handle is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
emailOrDomainSchema.parse(handle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,12 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BlocklistUpdateManyPreQueryHook implements WorkspacePreQueryHook {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
async execute(): Promise<void> {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface';
|
||||||
|
import { UpdateOneResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BlocklistItem,
|
||||||
|
BlocklistValidationService,
|
||||||
|
} from 'src/modules/connected-account/services/blocklist/blocklist-validation.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BlocklistUpdateOnePreQueryHook implements WorkspacePreQueryHook {
|
||||||
|
constructor(
|
||||||
|
private readonly blocklistValidationService: BlocklistValidationService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
userId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
payload: UpdateOneResolverArgs<BlocklistItem>,
|
||||||
|
): Promise<void> {
|
||||||
|
await this.blocklistValidationService.validateBlocklistForUpdateOne(
|
||||||
|
payload,
|
||||||
|
userId,
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,14 +1,25 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { BlocklistCreateManyPreQueryHook } from 'src/modules/connected-account/query-hooks/blocklist/blocklist-create-many.pre-query.hook';
|
import { BlocklistCreateManyPreQueryHook } from 'src/modules/connected-account/query-hooks/blocklist/blocklist-create-many.pre-query.hook';
|
||||||
|
import { BlocklistUpdateManyPreQueryHook } from 'src/modules/connected-account/query-hooks/blocklist/blocklist-update-many.pre-query.hook';
|
||||||
|
import { BlocklistUpdateOnePreQueryHook } from 'src/modules/connected-account/query-hooks/blocklist/blocklist-update-one.pre-query.hook';
|
||||||
|
import { BlocklistValidationModule } from 'src/modules/connected-account/services/blocklist/blocklist-validation.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [],
|
imports: [BlocklistValidationModule],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
provide: BlocklistCreateManyPreQueryHook.name,
|
provide: BlocklistCreateManyPreQueryHook.name,
|
||||||
useClass: BlocklistCreateManyPreQueryHook,
|
useClass: BlocklistCreateManyPreQueryHook,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: BlocklistUpdateManyPreQueryHook.name,
|
||||||
|
useClass: BlocklistUpdateManyPreQueryHook,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: BlocklistUpdateOnePreQueryHook.name,
|
||||||
|
useClass: BlocklistUpdateOnePreQueryHook,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class ConnectedAccountQueryHookModule {}
|
export class ConnectedAccountQueryHookModule {}
|
||||||
|
|||||||
@ -50,4 +50,21 @@ export class BlocklistRepository {
|
|||||||
transactionManager,
|
transactionManager,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getByWorkspaceMemberIdAndHandle(
|
||||||
|
workspaceMemberId: string,
|
||||||
|
handle: string,
|
||||||
|
workspaceId: string,
|
||||||
|
transactionManager?: EntityManager,
|
||||||
|
): Promise<ObjectRecord<BlocklistObjectMetadata>[]> {
|
||||||
|
const dataSourceSchema =
|
||||||
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
|
|
||||||
|
return await this.workspaceDataSourceService.executeRawQuery(
|
||||||
|
`SELECT * FROM ${dataSourceSchema}."blocklist" WHERE "workspaceMemberId" = $1 AND "handle" = $2`,
|
||||||
|
[workspaceMemberId, handle],
|
||||||
|
workspaceId,
|
||||||
|
transactionManager,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { BlocklistValidationService } from 'src/modules/connected-account/services/blocklist/blocklist-validation.service';
|
||||||
|
import { BlocklistObjectMetadata } from 'src/modules/connected-account/standard-objects/blocklist.object-metadata';
|
||||||
|
import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
ObjectMetadataRepositoryModule.forFeature([
|
||||||
|
BlocklistObjectMetadata,
|
||||||
|
WorkspaceMemberObjectMetadata,
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
providers: [BlocklistValidationService],
|
||||||
|
exports: [BlocklistValidationService],
|
||||||
|
})
|
||||||
|
export class BlocklistValidationModule {}
|
||||||
@ -0,0 +1,146 @@
|
|||||||
|
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import {
|
||||||
|
CreateManyResolverArgs,
|
||||||
|
UpdateOneResolverArgs,
|
||||||
|
} 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 { isDomain } from 'src/engine/utils/is-domain';
|
||||||
|
import { BlocklistRepository } from 'src/modules/connected-account/repositories/blocklist.repository';
|
||||||
|
import { BlocklistObjectMetadata } from 'src/modules/connected-account/standard-objects/blocklist.object-metadata';
|
||||||
|
import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository';
|
||||||
|
import { WorkspaceMemberObjectMetadata } from 'src/modules/workspace-member/standard-objects/workspace-member.object-metadata';
|
||||||
|
|
||||||
|
export type BlocklistItem = Omit<
|
||||||
|
BlocklistObjectMetadata,
|
||||||
|
'createdAt' | 'updatedAt' | 'workspaceMember'
|
||||||
|
> & {
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
workspaceMemberId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BlocklistValidationService {
|
||||||
|
constructor(
|
||||||
|
@InjectObjectMetadataRepository(BlocklistObjectMetadata)
|
||||||
|
private readonly blocklistRepository: BlocklistRepository,
|
||||||
|
@InjectObjectMetadataRepository(WorkspaceMemberObjectMetadata)
|
||||||
|
private readonly workspaceMemberRepository: WorkspaceMemberRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public async validateBlocklistForCreateMany(
|
||||||
|
payload: CreateManyResolverArgs<BlocklistItem>,
|
||||||
|
userId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
) {
|
||||||
|
await this.validateSchema(payload.data);
|
||||||
|
await this.validateUniquenessForCreateMany(payload, userId, workspaceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async validateBlocklistForUpdateOne(
|
||||||
|
payload: UpdateOneResolverArgs<BlocklistItem>,
|
||||||
|
userId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
) {
|
||||||
|
if (payload.data.handle) {
|
||||||
|
await this.validateSchema([payload.data]);
|
||||||
|
}
|
||||||
|
await this.validateUniquenessForUpdateOne(payload, userId, workspaceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async validateSchema(blocklist: BlocklistItem[]) {
|
||||||
|
const emailOrDomainSchema = z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.email('Invalid email or domain')
|
||||||
|
.or(
|
||||||
|
z
|
||||||
|
.string()
|
||||||
|
.refine(
|
||||||
|
(value) => value.startsWith('@') && isDomain(value.slice(1)),
|
||||||
|
'Invalid email or domain',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const handle of blocklist.map((item) => item.handle)) {
|
||||||
|
if (!handle) {
|
||||||
|
throw new BadRequestException('Blocklist handle is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = emailOrDomainSchema.safeParse(handle);
|
||||||
|
|
||||||
|
if (!result.success) {
|
||||||
|
throw new BadRequestException(result.error.errors[0].message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async validateUniquenessForCreateMany(
|
||||||
|
payload: CreateManyResolverArgs<BlocklistItem>,
|
||||||
|
userId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
) {
|
||||||
|
const currentWorkspaceMember =
|
||||||
|
await this.workspaceMemberRepository.getByIdOrFail(userId, workspaceId);
|
||||||
|
|
||||||
|
const currentBlocklist =
|
||||||
|
await this.blocklistRepository.getByWorkspaceMemberId(
|
||||||
|
currentWorkspaceMember.id,
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const currentBlocklistHandles = currentBlocklist.map(
|
||||||
|
(blocklist) => blocklist.handle,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
payload.data.some((item) => currentBlocklistHandles.includes(item.handle))
|
||||||
|
) {
|
||||||
|
throw new BadRequestException('Blocklist handle already exists');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async validateUniquenessForUpdateOne(
|
||||||
|
payload: UpdateOneResolverArgs<BlocklistItem>,
|
||||||
|
userId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
) {
|
||||||
|
const existingRecord = await this.blocklistRepository.getById(
|
||||||
|
payload.id,
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!existingRecord) {
|
||||||
|
throw new BadRequestException('Blocklist item not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existingRecord.workspaceMemberId !== payload.data.workspaceMemberId) {
|
||||||
|
throw new BadRequestException('Workspace member cannot be updated');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existingRecord.handle === payload.data.handle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentWorkspaceMember =
|
||||||
|
await this.workspaceMemberRepository.getByIdOrFail(userId, workspaceId);
|
||||||
|
|
||||||
|
const currentBlocklist =
|
||||||
|
await this.blocklistRepository.getByWorkspaceMemberId(
|
||||||
|
currentWorkspaceMember.id,
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const currentBlocklistHandles = currentBlocklist
|
||||||
|
.filter((blocklist) => blocklist.id !== payload.id)
|
||||||
|
.map((blocklist) => blocklist.handle);
|
||||||
|
|
||||||
|
if (currentBlocklistHandles.includes(payload.data.handle)) {
|
||||||
|
throw new BadRequestException('Blocklist handle already exists');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -32,7 +32,7 @@ export class MessageFindManyPreQueryHook implements WorkspacePreQueryHook {
|
|||||||
@InjectObjectMetadataRepository(ConnectedAccountObjectMetadata)
|
@InjectObjectMetadataRepository(ConnectedAccountObjectMetadata)
|
||||||
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
private readonly connectedAccountRepository: ConnectedAccountRepository,
|
||||||
@InjectObjectMetadataRepository(WorkspaceMemberObjectMetadata)
|
@InjectObjectMetadataRepository(WorkspaceMemberObjectMetadata)
|
||||||
private readonly workspaceMemberService: WorkspaceMemberRepository,
|
private readonly workspaceMemberRepository: WorkspaceMemberRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(
|
async execute(
|
||||||
@ -83,7 +83,7 @@ export class MessageFindManyPreQueryHook implements WorkspacePreQueryHook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const currentWorkspaceMember =
|
const currentWorkspaceMember =
|
||||||
await this.workspaceMemberService.getByIdOrFail(userId, workspaceId);
|
await this.workspaceMemberRepository.getByIdOrFail(userId, workspaceId);
|
||||||
|
|
||||||
const messageChannelsConnectedAccounts =
|
const messageChannelsConnectedAccounts =
|
||||||
await this.connectedAccountRepository.getByIds(
|
await this.connectedAccountRepository.getByIds(
|
||||||
|
|||||||
Reference in New Issue
Block a user