feat: Add ability to expose Swagger specification (#1577)

This commit is contained in:
Hannes
2026-03-11 11:39:42 +01:00
committed by GitHub
parent 7604a31a74
commit bb907d62e4
8 changed files with 48 additions and 0 deletions
+3
View File
@@ -51,6 +51,9 @@ services:
# will be sent through this proxy if set. # will be sent through this proxy if set.
# - OUTGOING_PROXY=http://proxy:3128 # - OUTGOING_PROXY=http://proxy:3128
# Set to true to expose the Swagger specification at /swagger.json
# - SWAGGER_EXPOSED=false
# - S3_ENDPOINT= # - S3_ENDPOINT=
# - S3_REGION= # - S3_REGION=
# - S3_ACCESS_KEY_ID= # - S3_ACCESS_KEY_ID=
+3
View File
@@ -65,6 +65,9 @@ services:
# which you can control via OUTGOING_BLOCKED_* and OUTGOING_ALLOWED_* below. # which you can control via OUTGOING_BLOCKED_* and OUTGOING_ALLOWED_* below.
# - OUTGOING_PROXY=http://proxy:3128 # - OUTGOING_PROXY=http://proxy:3128
# Set to true to expose the Swagger specification at /swagger.json
# - SWAGGER_EXPOSED=false
# - S3_ENDPOINT= # - S3_ENDPOINT=
# - S3_REGION= # - S3_REGION=
# - S3_ACCESS_KEY_ID= # - S3_ACCESS_KEY_ID=
+3
View File
@@ -42,6 +42,9 @@ SECRET_KEY=notsecretkey
# will be sent through this proxy if set. # will be sent through this proxy if set.
# OUTGOING_PROXY=http://proxy:3128 # OUTGOING_PROXY=http://proxy:3128
# Set to true to expose the Swagger specification at /swagger.json
# SWAGGER_EXPOSED=false
# S3_ENDPOINT= # S3_ENDPOINT=
# S3_REGION= # S3_REGION=
# S3_ACCESS_KEY_ID= # S3_ACCESS_KEY_ID=
+28
View File
@@ -0,0 +1,28 @@
/*!
* Copyright (c) 2024 PLANKA Software GmbH
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
*/
const fs = require('fs');
const path = require('path');
const SWAGGER_PATH = path.join(sails.config.appPath, 'swagger.json');
module.exports = {
async fn() {
if (!sails.config.custom.swaggerExposed) {
return this.res.notFound();
}
let specification;
try {
const content = fs.readFileSync(SWAGGER_PATH, 'utf8');
specification = JSON.parse(content);
} catch (error) {
sails.log.warn('swagger.json not found, run "npm run swagger:generate" to create it');
return this.res.notFound();
}
return specification;
},
};
+7
View File
@@ -2,6 +2,10 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
// eslint-disable-next-line import/no-extraneous-dependencies // eslint-disable-next-line import/no-extraneous-dependencies
const ignore = require('ignore'); const ignore = require('ignore');
// eslint-disable-next-line import/no-extraneous-dependencies
const swaggerJsdoc = require('swagger-jsdoc');
const swaggerConfig = require('./config/swagger');
const OUT_DIR = 'dist'; const OUT_DIR = 'dist';
@@ -37,6 +41,9 @@ const build = (src, dest) => {
fs.copyFileSync(srcPath, destPath); fs.copyFileSync(srcPath, destPath);
} }
} }
const specification = swaggerJsdoc(swaggerConfig);
fs.writeFileSync(path.join(dest, 'swagger.json'), JSON.stringify(specification, null, 2));
}; };
build('./', OUT_DIR); build('./', OUT_DIR);
+1
View File
@@ -64,6 +64,7 @@ module.exports.custom = {
showDetailedAuthErrors: process.env.SHOW_DETAILED_AUTH_ERRORS === 'true', showDetailedAuthErrors: process.env.SHOW_DETAILED_AUTH_ERRORS === 'true',
outgoingProxy: process.env.OUTGOING_PROXY, outgoingProxy: process.env.OUTGOING_PROXY,
swaggerExposed: process.env.SWAGGER_EXPOSED === 'true',
s3Endpoint: process.env.S3_ENDPOINT, s3Endpoint: process.env.S3_ENDPOINT,
s3Region: process.env.S3_REGION, s3Region: process.env.S3_REGION,
+1
View File
@@ -44,6 +44,7 @@ module.exports.policies = {
'_internal/update-config': ['is-authenticated', 'is-internal'], '_internal/update-config': ['is-authenticated', 'is-internal'],
'swagger/show': true,
'bootstrap/show': true, 'bootstrap/show': true,
'terms/show': true, 'terms/show': true,
'access-tokens/create': true, 'access-tokens/create': true,
+2
View File
@@ -235,6 +235,8 @@ module.exports.routes = {
'PATCH /api/_internal/config': '_internal/update-config', 'PATCH /api/_internal/config': '_internal/update-config',
'GET /swagger.json': 'swagger/show',
'GET /favicons/*': { 'GET /favicons/*': {
fn: protectedStaticDirServer('/favicons', () => sails.config.custom.faviconsPathSegment), fn: protectedStaticDirServer('/favicons', () => sails.config.custom.faviconsPathSegment),
skipAssets: false, skipAssets: false,