src/api/v2/projects/assets/assets.validator.tsmodified
import { NextFunction, Request, Response } from "express";
import { LoggerFactory } from "../../../../util/logger";
import { validateProjectId, validateUuidAndThrow, validateString, validatePagingQueryParam } from "../../common.validator";
import { createInvalidRequestApiError, createRequestNotAcceptableAPIError } from "../../../../util/errorFormatter";
import { PagingQueryParam } from "../../../../models/ingress";

const logger = LoggerFactory("AssetsValidator");

export const validateListAssetsRequest = (req: Request, res: Response, next: NextFunction) => {
    if (!validateProjectId(logger, req.params.projectId, res)) return;
    const paging: PagingQueryParam = req.query;
    if (!validatePagingQueryParam(logger, paging, res)) return;
    next();
};

export const validateAssetIdParam = (req: Request, res: Response, next: NextFunction) => {
    if (!validateProjectId(logger, req.params.projectId, res)) return;
    if (!validateUuidAndThrow(logger, "assetId", req.params.assetId, res)) return;
    next();
};

export const validateCreateRequest = (req: Request, res: Response, next: NextFunction) => {
    if (!validateProjectId(logger, req.params.projectId, res)) return;
    const { name, assetTypeId } = req.body;
    if (!validateString(logger, "name", name, res)) return;
    if (!validateUuidAndThrow(logger, "assetTypeId", assetTypeId, res)) return;
    next();
};

// Partial update: only the scalar Asset fields listed here may be updated. Any
// other field is rejected. Per the PAPI-3631 scope only `name` is patchable;
// relational fields (AssetTypeId, ParentAssetId) are out of scope.
const PATCHABLE_FIELDS = new Set<string>(["name"]);

export const validatePatchAssetRequest = (req: Request, res: Response, next: NextFunction) => {
    if (!validateProjectId(logger, req.params.projectId, res)) return;
    if (!validateUuidAndThrow(logger, "assetId", req.params.assetId, res)) return;

    const body = req.body ?? {};
    const providedFields = Object.keys(body);

    if (providedFields.length === 0) {
        return res.status(400).json(createInvalidRequestApiError("No valid fields provided for PATCH operation."));
    }

    for (const key of providedFields) {
        if (!PATCHABLE_FIELDS.has(key)) {
            return res.status(406).send(createRequestNotAcceptableAPIError(`Field '${key}' is not allowed`));
        }
    }

    // Partial update: only validate the fields actually supplied.
    if ("name" in body && !validateString(logger, "name", body.name, res)) return;

    next();
};