Source: RouterProject/project/controller.js

// @ts-check
/**
 * Project controllers (contract envelope).
 * @import {ExpressRequestAuthorized, ExpressResponse} from '../../types.js'
 */

import { sendOk, sendErrorFrom } from '../../utils/apiEnvelope.js';
import { hasActionPermission } from '../../utils/actionPermissions.js';
import { paginateList } from '../../utils/paginateList.js';
import * as service from './service.js';

/**
 * @swagger
 * /api/project/project/capabilities:
 *   get:
 *     summary: Capabilities of the caller (server-calculated)
 *     description: |
 *       Returns the capabilities of the currently authenticated user in the
 *       organization scope. Capabilities are always calculated server-side
 *       from job action rights — never from a client-supplied role or value.
 *       Currently exposes `projectCreate` (job action right `project.create`).
 *     tags:
 *       - Projects
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Capabilities
 *         content:
 *           application/json:
 *             schema:
 *               type: object
 *               properties:
 *                 success:
 *                   type: boolean
 *                 result:
 *                   $ref: './project.swagger.yaml#/components/schemas/ProjectCapabilities'
 *       403:
 *         description: Not authorized
 */
/**
 * GET /project/project/capabilities
 * @param {ExpressRequestAuthorized} req
 * @param {ExpressResponse} res
 */
export const getProjectCapabilities = async (req, res) => {
    try {
        const projectCreate = await hasActionPermission(req, 'project.create');
        sendOk(res, { projectCreate });
    } catch (e) {
        sendErrorFrom(res, e);
    }
};

/**
 * @swagger
 * /api/project/project/{group}:
 *   put:
 *     summary: Create a project under a group
 *     description: |
 *       Creates a project in the current organization under the given group
 *       (`:group`). Requires the job action right `project.create` and change
 *       rights on the group. The creator receives admin on the new project.
 *     tags:
 *       - Projects
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: group
 *         required: true
 *         schema:
 *           type: string
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: './project.swagger.yaml#/components/schemas/ProjectCreateBody'
 *     responses:
 *       200:
 *         description: Project created
 *         content:
 *           application/json:
 *             schema:
 *               $ref: './project.swagger.yaml#/components/schemas/SuccessResponse'
 *       403:
 *         description: No project.create job action permission
 *         content:
 *           application/json:
 *             schema:
 *               $ref: './project.swagger.yaml#/components/schemas/ErrorResponse'
 *       422:
 *         description: Validation failed
 *         content:
 *           application/json:
 *             schema:
 *               $ref: './project.swagger.yaml#/components/schemas/ErrorResponse'
 */
/**
 * PUT /project/project/:group
 * @param {ExpressRequestAuthorized} req
 * @param {ExpressResponse} res
 */
export const putProject = async (req, res) => {
    try {
        const result = await service.createProject(req);
        sendOk(res, result.result);
    } catch (e) {
        sendErrorFrom(res, e);
    }
};

/**
 * @swagger
 * /api/project/project:
 *   get:
 *     summary: List projects
 *     description: |
 *       Lists all projects of the organization the caller can see
 *       (visible | changeable | admin). Admins and bots see all projects.
 *       Optional `group_uid` query filter restricts the listing to the projects
 *       of one owner group.
 *     tags:
 *       - Projects
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: query
 *         name: group_uid
 *         required: false
 *         schema:
 *           type: string
 *     responses:
 *       200:
 *         description: List of projects
 *         content:
 *           application/json:
 *             schema:
 *               $ref: './project.swagger.yaml#/components/schemas/SuccessResponse'
 *       403:
 *         description: Not authorized
 *         content:
 *           application/json:
 *             schema:
 *               $ref: './project.swagger.yaml#/components/schemas/ErrorResponse'
 */
/**
 * GET /project/project
 * @param {ExpressRequestAuthorized} req
 * @param {ExpressResponse} res
 */
export const listProjects = async (req, res) => {
    try {
        if (req.query.__page) {
            const result = await paginateList(req, async () => service.getListing(req.session, req.query));
            sendOk(res, result);
            return;
        }
        const result = await service.getListing(req.session, req.query);
        sendOk(res, result);
    } catch (e) {
        sendErrorFrom(res, e);
    }
};

/**
 * @swagger
 * /api/project/project/{UID}:
 *   get:
 *     summary: Get a project
 *     description: Requires at least `visible` on the project.
 *     tags:
 *       - Projects
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: UID
 *         required: true
 *         schema:
 *           type: string
 *     responses:
 *       200:
 *         description: Project
 *         content:
 *           application/json:
 *             schema:
 *               $ref: './project.swagger.yaml#/components/schemas/SuccessResponse'
 *       403:
 *         description: Not accessible
 *         content:
 *           application/json:
 *             schema:
 *               $ref: './project.swagger.yaml#/components/schemas/ErrorResponse'
 *       404:
 *         description: Project not found in this organization
 *         content:
 *           application/json:
 *             schema:
 *               $ref: './project.swagger.yaml#/components/schemas/ErrorResponse'
 */
/**
 * GET /project/project/:UID
 * @param {ExpressRequestAuthorized} req
 * @param {ExpressResponse} res
 */
export const getProject = async (req, res) => {
    try {
        const result = await service.getProject(req, req.params.UID);
        sendOk(res, result.result);
    } catch (e) {
        sendErrorFrom(res, e);
    }
};

/**
 * @swagger
 * /api/project/project/{UID}:
 *   post:
 *     summary: Update project metadata
 *     description: Requires `admin` on the project. Only supplied fields are changed.
 *     tags:
 *       - Projects
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: UID
 *         required: true
 *         schema:
 *           type: string
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: './project.swagger.yaml#/components/schemas/ProjectUpdateBody'
 *     responses:
 *       200:
 *         description: Project updated
 *         content:
 *           application/json:
 *             schema:
 *               $ref: './project.swagger.yaml#/components/schemas/SuccessResponse'
 *       403:
 *         description: Not changeable
 *         content:
 *           application/json:
 *             schema:
 *               $ref: './project.swagger.yaml#/components/schemas/ErrorResponse'
 *   delete:
 *     summary: Delete a project
 *     description: |
 *       Requires `admin` on the project. Removes the project, its memberA/member
 *       links (owner group, owner user and share links) in one transaction;
 *       orphaned shares (no remaining links) are deleted with it. Publishes
 *       remove events for the project and removed shares.
 *     tags:
 *       - Projects
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: UID
 *         required: true
 *         schema:
 *           type: string
 *     responses:
 *       200:
 *         description: Project deleted
 *         content:
 *           application/json:
 *             schema:
 *               $ref: './project.swagger.yaml#/components/schemas/SuccessResponse'
 *       403:
 *         description: Not changeable
 *         content:
 *           application/json:
 *             schema:
 *               $ref: './project.swagger.yaml#/components/schemas/ErrorResponse'
 */
/**
 * POST /project/project/:UID
 * @param {ExpressRequestAuthorized} req
 * @param {ExpressResponse} res
 */
export const updateProject = async (req, res) => {
    try {
        const result = await service.updateProject(req, req.params.UID);
        sendOk(res, result.result);
    } catch (e) {
        sendErrorFrom(res, e);
    }
};

/**
 * DELETE /project/project/:UID
 * @param {ExpressRequestAuthorized} req
 * @param {ExpressResponse} res
 */
export const deleteProject = async (req, res) => {
    try {
        const result = await service.deleteProject(req, req.params.UID);
        sendOk(res, result.result);
    } catch (e) {
        sendErrorFrom(res, e);
    }
};