src/api/v2/projects/assets/assets.routes.tsmodified
import express from "express";
import { Authorities } from "../../../auth/authorities.types";
import { hasRolesOrProjectAccess } from "../../../../middleware/authorisation";
import {
    listAssets,
    getAsset,
    createAsset,
    patchAsset,
} from "./assets.controller";
import {
    validateAssetIdParam,
    validateCreateRequest,
    validateListAssetsRequest,
    validatePatchAssetRequest,
} from "./assets.validator";

const router = express.Router({ mergeParams: true });

/**
 * @swagger
 * /api/v2/projects/{projectId}/assets:
 *   get:
 *     summary: List all assets for a project.
 *     tags: [Assets]
 *     description: Returns a paginated list of assets. Advance to the next page by passing the `lastFetchedIndexId` from the previous response.
 *     parameters:
 *       - in: path
 *         name: projectId
 *         required: true
 *         schema:
 *           type: string
 *           format: uuid
 *       - in: query
 *         name: lastFetchedIndexId
 *         required: false
 *         schema:
 *           type: integer
 *         description: The last fetched index id from the previous page. Omit for the first page.
 *       - in: query
 *         name: size
 *         required: false
 *         schema:
 *           type: integer
 *         description: The maximum number of assets to fetch.
 *     responses:
 *       200:
 *         description: Paginated list of assets.
 *         content:
 *           application/json:
 *             schema:
 *               allOf:
 *                 - $ref: "#/components/schemas/PaginationEnvelope"
 *                 - type: object
 *                   properties:
 *                     records:
 *                       type: array
 *                       items:
 *                         $ref: "#/components/schemas/Asset"
 *       400:
 *         description: Invalid request.
 *       401:
 *         description: Unauthorized.
 *       404:
 *         description: Project not found.
 *       500:
 *         description: Server error.
 */
router.get("", validateListAssetsRequest, hasRolesOrProjectAccess([Authorities.INTERNAL_ROLE], [Authorities.PROJECT_VIEW]), listAssets);

/**
 * @swagger
 * /api/v2/projects/{projectId}/assets/{assetId}:
 *   get:
 *     summary: Get an asset by ID.
 *     tags: [Assets]
 *     parameters:
 *       - in: path
 *         name: projectId
 *         required: true
 *         schema:
 *           type: string
 *           format: uuid
 *       - in: path
 *         name: assetId
 *         required: true
 *         schema:
 *           type: string
 *           format: uuid
 *     responses:
 *       200:
 *         description: Asset details.
 *         content:
 *           application/json:
 *             schema:
 *               $ref: "#/components/schemas/Asset"
 *       400:
 *         description: Invalid request.
 *       401:
 *         description: Unauthorized.
 *       404:
 *         description: Not found.
 *       500:
 *         description: Server error.
 */
router.get("/:assetId", validateAssetIdParam, hasRolesOrProjectAccess([Authorities.INTERNAL_ROLE], [Authorities.PROJECT_VIEW]), getAsset);

/**
 * @swagger
 * /api/v2/projects/{projectId}/assets:
 *   post:
 *     summary: Create an asset.
 *     tags: [Assets]
 *     parameters:
 *       - in: path
 *         name: projectId
 *         required: true
 *         schema:
 *           type: string
 *           format: uuid
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required: [name, assetTypeId]
 *             properties:
 *               name:
 *                 type: string
 *                 description: Name of the asset.
 *               assetTypeId:
 *                 type: string
 *                 format: uuid
 *                 description: ID of the asset type to associate with this asset.
 *             example:
 *               name: "Chiller Unit 1"
 *               assetTypeId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
 *     responses:
 *       201:
 *         description: Asset created.
 *         content:
 *           application/json:
 *             schema:
 *               $ref: "#/components/schemas/Asset"
 *       400:
 *         description: Invalid request.
 *       401:
 *         description: Unauthorized.
 *       404:
 *         description: Project or asset type not found.
 *       500:
 *         description: Server error.
 */
router.post("", validateCreateRequest, hasRolesOrProjectAccess([Authorities.INTERNAL_ROLE], [Authorities.PROJECT_EDIT]), createAsset);

/**
 * @swagger
 * /api/v2/projects/{projectId}/assets/{assetId}:
 *   patch:
 *     summary: Partially update an asset.
 *     tags: [Assets]
 *     description: >
 *       Partially updates an asset: only the fields present in the request body are
 *       updated. The only patchable field is `name`. Any other field is rejected.
 *     parameters:
 *       - in: path
 *         name: projectId
 *         required: true
 *         schema:
 *           type: string
 *           format: uuid
 *       - in: path
 *         name: assetId
 *         required: true
 *         schema:
 *           type: string
 *           format: uuid
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             properties:
 *               name:
 *                 type: string
 *                 description: New name for the asset.
 *             example:
 *               name: "Chiller Unit 2"
 *     responses:
 *       200:
 *         description: Updated asset.
 *         content:
 *           application/json:
 *             schema:
 *               $ref: "#/components/schemas/Asset"
 *       400:
 *         description: Invalid request (e.g. empty body or blank name).
 *       401:
 *         description: Unauthorized.
 *       404:
 *         description: Project or asset not found.
 *       406:
 *         description: A non-patchable field was supplied.
 *       500:
 *         description: Server error.
 */
router.patch("/:assetId", validatePatchAssetRequest, hasRolesOrProjectAccess([Authorities.INTERNAL_ROLE], [Authorities.PROJECT_EDIT]), patchAsset);

export default router;