mirror of
https://github.com/hexastack/hexabot
synced 2025-06-26 18:27:28 +00:00
fix(api): enhance logic
This commit is contained in:
@@ -91,7 +91,7 @@ describe('CategoryController', () => {
|
||||
{
|
||||
provide: BlockService,
|
||||
useValue: {
|
||||
findOne: jest.fn(),
|
||||
findOneAndPopulate: jest.fn(),
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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]
|
||||
: [];
|
||||
};
|
||||
Reference in New Issue
Block a user