// @ts-check
/**
* Credential controllers (contract envelope).
* @import {ExpressRequestAuthorized, ExpressResponse} from '../../types.js'
*/
import { sendOk, sendErrorFrom } from '../../utils/apiEnvelope.js';
import * as service from './service.js';
/**
* @swagger
* /api/project/credential:
* get:
* summary: List credentials (SSH keys for Git hosts)
* description: |
* Lists all credentials of the organization the caller can see. Returns
* the public key and host metadata — never the private key (which lives
* in Vault).
* tags:
* - Project Credentials
* security:
* - bearerAuth: []
* responses:
* 200:
* description: List of credentials
* content:
* application/json:
* schema:
* $ref: './credential.swagger.yaml#/components/schemas/SuccessResponse'
* put:
* summary: Create a credential (automatically generates an ed25519 SSH key pair)
* description: |
* Generates a new ed25519 key pair and persists it entirely in Vault at
* `orgas/data/{orgId}/credentials/{UID}/{name}`. The returned credentialsRef
* (`{UID}/{name}`) is stored on repository shares. The public key must be
* registered at the Git host (deploy key / user key) to allow access.
* tags:
* - Project Credentials
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* $ref: './credential.swagger.yaml#/components/schemas/CredentialCreateBody'
* responses:
* 200:
* description: Credential created
* content:
* application/json:
* schema:
* $ref: './credential.swagger.yaml#/components/schemas/SuccessResponse'
* 422:
* description: Invalid name/host or credential already exists
* content:
* application/json:
* schema:
* $ref: './credential.swagger.yaml#/components/schemas/ErrorResponse'
* 500:
* description: Vault write failed
* content:
* application/json:
* schema:
* $ref: './credential.swagger.yaml#/components/schemas/ErrorResponse'
*/
/**
* @swagger
* /api/project/credential/hostkey:
* get:
* summary: Scan SSH host keys of a Git host
* description: |
* Runs `ssh-keyscan` on the backend and returns the ed25519 host keys of
* the given Git host as known_hosts lines. Used by the credential forms
* to auto-fill the `hostKey` field after the URL is entered. The host key
* is the server identity of the Git host (for StrictHostKeyChecking) —
* not the credential key pair.
* tags:
* - Project Credentials
* security:
* - bearerAuth: []
* parameters:
* - in: query
* name: host
* required: true
* schema:
* type: string
* description: Hostname, optionally with `:port` (e.g. `git.commtool.org` or `git.commtool.org:2222`)
* responses:
* 200:
* description: Host keys found
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* type: boolean
* example: true
* result:
* type: object
* properties:
* host:
* type: string
* keys:
* type: array
* items:
* type: string
* example: "git.commtool.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA..."
* 422:
* description: Invalid host parameter
* 502:
* description: Host unreachable or scan failed
*/
/**
* GET /project/credential/hostkey?host=...
* @param {ExpressRequestAuthorized} req
* @param {ExpressResponse} res
*/
export const scanHostKey = async (req, res) => {
try {
const result = await service.scanHostKey(req.query.host);
sendOk(res, result);
} catch (e) {
sendErrorFrom(res, e);
}
};
/**
* PUT /project/credential
* @param {ExpressRequestAuthorized} req
* @param {ExpressResponse} res
*/
export const putCredential = async (req, res) => {
try {
const result = await service.createCredential(req);
sendOk(res, result.result);
} catch (e) {
sendErrorFrom(res, e);
}
};
/**
* GET /project/credential
* @param {ExpressRequestAuthorized} req
* @param {ExpressResponse} res
*/
export const listCredentials = async (req, res) => {
try {
const result = await service.listCredentials(req);
sendOk(res, result.result);
} catch (e) {
sendErrorFrom(res, e);
}
};
/**
* @swagger
* /api/project/credential/{ref}:
* get:
* summary: Get a credential
* description: |
* Returns metadata + public key, never the private key. `ref` is the
* URL-encoded credentialsRef `{UID}/{name}`.
* tags:
* - Project Credentials
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: ref
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Credential
* content:
* application/json:
* schema:
* $ref: './credential.swagger.yaml#/components/schemas/SuccessResponse'
* 404:
* description: Credential not found
* content:
* application/json:
* schema:
* $ref: './credential.swagger.yaml#/components/schemas/ErrorResponse'
* delete:
* summary: Delete a credential
* description: Removes the Vault secret.
* tags:
* - Project Credentials
* security:
* - bearerAuth: []
* parameters:
* - in: path
* name: ref
* required: true
* schema:
* type: string
* responses:
* 200:
* description: Credential deleted
* content:
* application/json:
* schema:
* $ref: './credential.swagger.yaml#/components/schemas/SuccessResponse'
*/
/**
* GET /project/credential/:ref
* @param {ExpressRequestAuthorized} req
* @param {ExpressResponse} res
*/
export const getCredential = async (req, res) => {
try {
const result = await service.getCredential(req, req.params.ref);
sendOk(res, result.result);
} catch (e) {
sendErrorFrom(res, e);
}
};
/**
* DELETE /project/credential/:ref
* @param {ExpressRequestAuthorized} req
* @param {ExpressResponse} res
*/
export const deleteCredential = async (req, res) => {
try {
const result = await service.deleteCredential(req, req.params.ref);
sendOk(res, result.result);
} catch (e) {
sendErrorFrom(res, e);
}
};