fix(api): enhance logic

This commit is contained in:
yassinedorbozgithub
2025-06-12 17:41:20 +01:00
parent 3fe1cc4f28
commit 99f0f0eb2f
7 changed files with 48 additions and 66 deletions

View File

@@ -91,7 +91,7 @@ describe('CategoryController', () => {
{
provide: BlockService,
useValue: {
findOne: jest.fn(),
findOneAndPopulate: jest.fn(),
},
},
],

View File

@@ -11,7 +11,6 @@ import { InjectModel } from '@nestjs/mongoose';
import { Document, Model, Query } from 'mongoose';
import { BaseRepository, DeleteResult } from '@/utils/generics/base-repository';
import { getCriteriaIds } from '@/utils/helpers/criteria';
import { TFilterQuery } from '@/utils/types/filter.types';
import { CategoryDto } from '../dto/category.dto';
@@ -25,14 +24,11 @@ export class CategoryRepository extends BaseRepository<
never,
CategoryDto
> {
private readonly blockService: BlockService;
constructor(
@InjectModel(Category.name) readonly model: Model<Category>,
@Optional() blockService?: BlockService,
@Optional() private readonly blockService?: BlockService,
) {
super(model, Category);
this.blockService = blockService!;
}
/**
@@ -43,7 +39,7 @@ export class CategoryRepository extends BaseRepository<
* @param criteria - The filter criteria for finding blocks to delete.
*/
async preDelete(
query: Query<
_query: Query<
DeleteResult,
Document<Category, any, any>,
unknown,
@@ -52,19 +48,18 @@ export class CategoryRepository extends BaseRepository<
>,
criteria: TFilterQuery<Category>,
) {
criteria = query.getQuery();
const ids = getCriteriaIds(criteria);
for (const id of ids) {
const associatedBlocks = await this.blockService.findOne({
category: id,
if (criteria._id) {
const block = await this.blockService?.findOneAndPopulate({
category: criteria._id,
});
if (associatedBlocks) {
const category = await this.findOne({ _id: id });
if (block) {
throw new ForbiddenException(
`Category ${category?.label || id} has blocks associated with it`,
`Category ${block.category?.label} has at least one associated block`,
);
}
} else {
throw new Error('Attempted to delete category using unknown criteria');
}
}
}

View File

@@ -21,7 +21,6 @@ import { PluginType } from '@/plugins/types';
import { SettingService } from '@/setting/services/setting.service';
import { FALLBACK_DEFAULT_NLU_PENALTY_FACTOR } from '@/utils/constants/nlp';
import { BaseService } from '@/utils/generics/base-service';
import { getCriteriaIds } from '@/utils/helpers/criteria';
import { getRandomElement } from '@/utils/helpers/safeRandom';
import { TFilterQuery } from '@/utils/types/filter.types';
@@ -786,20 +785,23 @@ export class BlockService extends BaseService<
*/
@OnEvent('hook:label:preDelete')
async handleLabelDelete(_query: unknown, criteria: TFilterQuery<Label>) {
const ids = getCriteriaIds(criteria);
await this.getRepository().model.updateMany(
{
$or: [
{ trigger_labels: { $in: ids } },
{ assign_labels: { $in: ids } },
],
},
{
$pull: {
trigger_labels: { $in: ids },
assign_labels: { $in: ids },
if (criteria._id) {
await this.getRepository().model.updateMany(
{
$or: [
{ trigger_labels: criteria._id },
{ assign_labels: criteria._id },
],
},
},
);
{
$pull: {
trigger_labels: criteria._id,
assign_labels: criteria._id,
},
},
);
} else {
throw new Error('Attempted to delete label using unknown criteria');
}
}
}

View File

@@ -24,7 +24,6 @@ import {
} from '@/attachment/types';
import { config } from '@/config';
import { BaseService } from '@/utils/generics/base-service';
import { getCriteriaIds } from '@/utils/helpers/criteria';
import { TFilterQuery } from '@/utils/types/filter.types';
import {
SocketGet,
@@ -274,10 +273,13 @@ export class SubscriberService extends BaseService<
_query: unknown,
criteria: TFilterQuery<Label>,
): Promise<void> {
const ids = getCriteriaIds(criteria);
await this.getRepository().model.updateMany(
{ labels: { $in: ids } },
{ $pull: { labels: { $in: ids } } },
);
if (criteria._id) {
await this.getRepository().model.updateMany(
{ labels: criteria._id },
{ $pull: { labels: criteria._id } },
);
} else {
throw new Error('Attempted to delete label using unknown criteria');
}
}
}

View File

@@ -52,14 +52,15 @@ export class ContentTypeRepository extends BaseRepository<
>,
criteria: TFilterQuery<ContentType>,
) {
const entityId: string = criteria._id as string;
const associatedBlocks = await this.blockService?.findOne({
'options.content.entity': entityId,
});
if (associatedBlocks) {
throw new ForbiddenException(`Content type have blocks associated to it`);
}
if (criteria._id) {
const associatedBlock = await this.blockService?.findOne({
'options.content.entity': criteria._id,
});
if (associatedBlock) {
throw new ForbiddenException(
'Content type have blocks associated to it',
);
}
await this.contentModel.deleteMany({ entity: criteria._id });
} else {
throw new Error(

View File

@@ -24,6 +24,7 @@ import { PageQueryDto } from '@/utils/pagination/pagination-query.dto';
import { TFilterQuery } from '@/utils/types/filter.types';
import { TNlpSampleDto } from '../dto/nlp-sample.dto';
import { NlpSampleEntity } from '../schemas/nlp-sample-entity.schema';
import {
NLP_SAMPLE_POPULATE,
NlpSample,
@@ -44,6 +45,8 @@ export class NlpSampleRepository extends BaseRepository<
> {
constructor(
@InjectModel(NlpSample.name) readonly model: Model<NlpSample>,
@InjectModel(NlpSampleEntity.name)
private readonly nlpSampleEntityModel: Model<NlpSampleEntity>,
private readonly nlpSampleEntityRepository: NlpSampleEntityRepository,
) {
super(model, NlpSample, NLP_SAMPLE_POPULATE, NlpSampleFull);
@@ -310,7 +313,7 @@ export class NlpSampleRepository extends BaseRepository<
criteria: TFilterQuery<NlpSample>,
) {
if (criteria._id) {
await this.nlpSampleEntityRepository.deleteMany({
await this.nlpSampleEntityModel.deleteMany({
sample: criteria._id,
});
} else {

View File

@@ -1,21 +0,0 @@
/*
* Copyright © 2025 Hexastack. All rights reserved.
*
* Licensed under the GNU Affero General Public License v3.0 (AGPLv3) with the following additional terms:
* 1. The name "Hexabot" is a trademark of Hexastack. You may not use this name in derivative works without express written permission.
* 2. All derivative works must include clear attribution to the original creator and software, Hexastack and Hexabot, in a prominent location (e.g., in the software's "About" section, documentation, and README file).
*/
import { FilterQuery } from 'mongoose';
export const getCriteriaIds = <T extends { _id: string }>({
_id,
}: FilterQuery<T>) => {
return Array.isArray(_id?.$in)
? _id.$in
: Array.isArray(_id)
? _id
: _id
? [_id]
: [];
};