feat: secure custom field value routing
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { CreateCustomFieldValueDto, UpdateCustomFieldValueDto } from '../shared/dto/custom-field.dto';
|
||||
import {
|
||||
CreateCustomFieldValueDto,
|
||||
UpdateCustomFieldValueDto,
|
||||
CustomFieldEntityType,
|
||||
} from '../shared/dto/custom-field.dto';
|
||||
|
||||
@Injectable()
|
||||
export class CustomFieldsService {
|
||||
@@ -17,9 +21,99 @@ export class CustomFieldsService {
|
||||
}
|
||||
|
||||
// Trouver toutes les valeurs de champs personnalisés pour une entité
|
||||
async findCustomFieldValuesByEntity(entityType: string, entityId: string) {
|
||||
private getCustomFieldValueKey(entityType: CustomFieldEntityType) {
|
||||
switch (entityType) {
|
||||
case CustomFieldEntityType.MACHINE:
|
||||
return 'machineId' as const;
|
||||
case CustomFieldEntityType.COMPOSANT:
|
||||
return 'composantId' as const;
|
||||
case CustomFieldEntityType.PIECE:
|
||||
return 'pieceId' as const;
|
||||
default:
|
||||
throw new BadRequestException('Type d\'entité de champ personnalisé invalide.');
|
||||
}
|
||||
}
|
||||
|
||||
private async resolveEntityContext(entityType: CustomFieldEntityType, entityId: string) {
|
||||
switch (entityType) {
|
||||
case CustomFieldEntityType.MACHINE: {
|
||||
const machine = await this.prisma.machine.findUnique({
|
||||
where: { id: entityId },
|
||||
select: { typeMachineId: true },
|
||||
});
|
||||
|
||||
if (!machine) {
|
||||
throw new NotFoundException('Machine introuvable.');
|
||||
}
|
||||
|
||||
if (!machine.typeMachineId) {
|
||||
throw new BadRequestException(
|
||||
'La machine ne possède pas de type associé pour les champs personnalisés.',
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
typeId: machine.typeMachineId,
|
||||
customFieldTypeField: 'typeMachineId' as const,
|
||||
valueKey: 'machineId' as const,
|
||||
};
|
||||
}
|
||||
case CustomFieldEntityType.COMPOSANT: {
|
||||
const composant = await this.prisma.composant.findUnique({
|
||||
where: { id: entityId },
|
||||
select: { typeComposantId: true },
|
||||
});
|
||||
|
||||
if (!composant) {
|
||||
throw new NotFoundException('Composant introuvable.');
|
||||
}
|
||||
|
||||
if (!composant.typeComposantId) {
|
||||
throw new BadRequestException(
|
||||
'Le composant ne possède pas de type associé pour les champs personnalisés.',
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
typeId: composant.typeComposantId,
|
||||
customFieldTypeField: 'typeComposantId' as const,
|
||||
valueKey: 'composantId' as const,
|
||||
};
|
||||
}
|
||||
case CustomFieldEntityType.PIECE: {
|
||||
const piece = await this.prisma.piece.findUnique({
|
||||
where: { id: entityId },
|
||||
select: { typePieceId: true },
|
||||
});
|
||||
|
||||
if (!piece) {
|
||||
throw new NotFoundException('Pièce introuvable.');
|
||||
}
|
||||
|
||||
if (!piece.typePieceId) {
|
||||
throw new BadRequestException(
|
||||
'La pièce ne possède pas de type associé pour les champs personnalisés.',
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
typeId: piece.typePieceId,
|
||||
customFieldTypeField: 'typePieceId' as const,
|
||||
valueKey: 'pieceId' as const,
|
||||
};
|
||||
}
|
||||
default:
|
||||
throw new BadRequestException('Type d\'entité de champ personnalisé invalide.');
|
||||
}
|
||||
}
|
||||
|
||||
async findCustomFieldValuesByEntity(
|
||||
entityType: CustomFieldEntityType,
|
||||
entityId: string,
|
||||
) {
|
||||
const key = this.getCustomFieldValueKey(entityType);
|
||||
const whereClause = {
|
||||
[entityType + 'Id']: entityId,
|
||||
[key]: entityId,
|
||||
};
|
||||
|
||||
return this.prisma.customFieldValue.findMany({
|
||||
@@ -59,12 +153,35 @@ export class CustomFieldsService {
|
||||
}
|
||||
|
||||
// Créer ou mettre à jour une valeur de champ personnalisé
|
||||
async upsertCustomFieldValue(customFieldId: string, entityType: string, entityId: string, value: string) {
|
||||
async upsertCustomFieldValue(
|
||||
customFieldId: string,
|
||||
entityType: CustomFieldEntityType,
|
||||
entityId: string,
|
||||
value: string,
|
||||
) {
|
||||
const { typeId, customFieldTypeField, valueKey } = await this.resolveEntityContext(
|
||||
entityType,
|
||||
entityId,
|
||||
);
|
||||
|
||||
const allowedCustomField = await this.prisma.customField.findFirst({
|
||||
where: {
|
||||
id: customFieldId,
|
||||
[customFieldTypeField]: typeId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!allowedCustomField) {
|
||||
throw new BadRequestException(
|
||||
'Le champ personnalisé n\'est pas autorisé pour cette entité.',
|
||||
);
|
||||
}
|
||||
|
||||
// D'abord, essayer de trouver une valeur existante
|
||||
const existingValue = await this.prisma.customFieldValue.findFirst({
|
||||
where: {
|
||||
customFieldId,
|
||||
[entityType + 'Id']: entityId,
|
||||
[valueKey]: entityId,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -83,7 +200,7 @@ export class CustomFieldsService {
|
||||
data: {
|
||||
customFieldId,
|
||||
value,
|
||||
[entityType + 'Id']: entityId,
|
||||
[valueKey]: entityId,
|
||||
},
|
||||
include: {
|
||||
customField: true,
|
||||
@@ -91,4 +208,4 @@ export class CustomFieldsService {
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user