Repository: BRIKEV/express-jsdoc-swagger
Pull request #18 (2020-06-02 22:15:22)

Security schemes
This PR contains:
  - security section.
  - securitySchemes within components with the name of each security scheme.


Patch:
diff --git a/examples/README.md b/examples/README.md
index 5ceec19..4cfc573 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -7,6 +7,7 @@ This page will includes some examples on how to use this package.
 - components - WIP
 - request body - WIP
 - [parameters](https://github.com/BRIKEV/express-jsdoc-swagger/tree/master/examples/parameters)
+- [security](https://github.com/BRIKEV/express-jsdoc-swagger/tree/master/examples/security)
 - albumAPI - WIP
 
 
diff --git a/examples/package.json b/examples/package.json
index 8a6035d..b0359bf 100644
--- a/examples/package.json
+++ b/examples/package.json
@@ -11,7 +11,8 @@
     "responses:simple": "node responses/simple.js",
     "responses:multiple": "node responses/multiple.js",
     "responses:components": "node responses/components.js",
-    "responses:full-example": "node responses/full-example.js"
+    "responses:full-example": "node responses/full-example.js",
+    "security:basic-auth": "node security/basic-auth.js"
   },
   "keywords": [],
   "author": "",
diff --git a/examples/security/basic-auth.js b/examples/security/basic-auth.js
new file mode 100644
index 0000000..03255e8
--- /dev/null
+++ b/examples/security/basic-auth.js
@@ -0,0 +1,36 @@
+const express = require('express');
+
+const logger = require('../utils/logger');
+const expressJSDocSwagger = require('../..');
+
+const options = {
+  info: {
+    version: '1.0.0',
+    title: 'Albums store',
+    license: {
+      name: 'MIT',
+    },
+  },
+  security: {
+    BasicAuth: {
+      type: 'http',
+      scheme: 'basic',
+    },
+  },
+  file: './basic-auth.js',
+  baseDir: __dirname,
+};
+
+const app = express();
+const port = 3000;
+
+expressJSDocSwagger(app)(options);
+
+/**
+ * GET /api/v1
+ * @summary This is the summary or description of the endpoint
+ * @return {string} 200 - success response
+ */
+app.get('/api/v1', (req, res) => res.send('Hello World!'));
+
+app.listen(port, () => logger.info(`Example app listening at http://localhost:${port}`));
diff --git a/index.js b/index.js
index cd87ec0..8fadcd6 100644
--- a/index.js
+++ b/index.js
@@ -7,6 +7,7 @@ const getOnlyComments = require('./consumers/getOnlyComments');
 const jsdocInfo = require('./consumers/jsdocInfo');
 const {
   getBasicInfo,
+  getSecuritySchemes,
   getPaths,
   getComponents,
   getTags,
@@ -34,10 +35,12 @@ const expressJSDocSwagger = app => {
       openapi: '3.0.0',
       info: options.info,
       servers: options.servers,
+      security: options.security,
     };
 
     debug('Getting basic swagger info');
     swaggerObject = getBasicInfo(swaggerObject);
+    swaggerObject = getSecuritySchemes(swaggerObject);
     debug(`SwaggerObject with basic info ${JSON.stringify(swaggerObject)}`);
 
     globFilesMatches(options.baseDir, options.file)
@@ -49,7 +52,7 @@ const expressJSDocSwagger = app => {
         swaggerObject = getComponents(swaggerObject, data);
         swaggerObject = getTags(swaggerObject, data);
       })
-      .catch(err => console.log(err));
+      .catch(console.log);
 
 
     app.use('/api-docs', (req, res, next) => {
diff --git a/transforms/components/index.js b/transforms/components/index.js
index 1ffc7cf..ccda444 100644
--- a/transforms/components/index.js
+++ b/transforms/components/index.js
@@ -52,6 +52,7 @@ const parseComponents = (swaggerObject = {}, components = []) => {
   return {
     ...swaggerObject,
     components: {
+      ...swaggerObject.components,
       schemas: componentSchema,
     },
   };
diff --git a/transforms/index.js b/transforms/index.js
index 6c6a1d5..ebfdbd7 100644
--- a/transforms/index.js
+++ b/transforms/index.js
@@ -1,4 +1,5 @@
 const getBasicInfo = require('./basic');
+const getSecuritySchemes = require('./security');
 const getPaths = require('./paths');
 const getComponents = require('./components');
 const getTags = require('./tags');
@@ -8,4 +9,5 @@ module.exports = {
   getPaths,
   getComponents,
   getTags,
+  getSecuritySchemes,
 };
diff --git a/transforms/security/index.js b/transforms/security/index.js
new file mode 100644
index 0000000..3ac90be
--- /dev/null
+++ b/transforms/security/index.js
@@ -0,0 +1,20 @@
+
+const formatSecurity = securitySchemes => {
+  const securityTypes = Object.keys(securitySchemes);
+  return securityTypes.map(type => ({ [type]: [] }));
+};
+
+const parseSecuritySchemas = (swaggerObject = {}) => {
+  const { security } = swaggerObject;
+  const updatedSwaggerObject = {
+    ...swaggerObject,
+    ...(security ? { security: formatSecurity(security) } : {}),
+    components: {
+      ...swaggerObject.components,
+      ...(security ? { securitySchemes: security } : {}),
+    },
+  };
+  return updatedSwaggerObject;
+};
+
+module.exports = parseSecuritySchemas;


Test patch:
diff --git a/test/transforms/security/index.test.js b/test/transforms/security/index.test.js
new file mode 100644
index 0000000..820b8a2
--- /dev/null
+++ b/test/transforms/security/index.test.js
@@ -0,0 +1,105 @@
+const parseSecuritySchemas = require('../../../transforms/security');
+
+describe('Transform security schemas', () => {
+  it('Should return a empty object with not securitySchemes', () => {
+    const input = undefined;
+    const expected = {
+      components: {},
+    };
+    const result = parseSecuritySchemas(input);
+    expect(result).toEqual(expected);
+  });
+
+  it('Should return a empty components object with not securitySchemes when security was not set', () => {
+    const input = {
+      info: {
+        version: '1.0.0',
+        title: 'Albums store',
+        license: {
+          name: 'MIT',
+        },
+      },
+    };
+    const expected = {
+      info: {
+        version: '1.0.0',
+        title: 'Albums store',
+        license: {
+          name: 'MIT',
+        },
+      },
+      components: {},
+    };
+    const result = parseSecuritySchemas(input);
+    expect(result).toEqual(expected);
+  });
+
+  it('Should return a security array and securitySchemes within components field', () => {
+    const input = {
+      security: {
+        BasicAuth: {
+          type: 'http',
+          scheme: 'basic',
+        },
+      },
+    };
+    const expected = {
+      security: [
+        {
+          BasicAuth: [],
+        },
+      ],
+      components: {
+        securitySchemes: {
+          BasicAuth: {
+            type: 'http',
+            scheme: 'basic',
+          },
+        },
+      },
+    };
+    const result = parseSecuritySchemas(input);
+    expect(result).toEqual(expected);
+  });
+
+  it('Should return a security array and securitySchemes, both with each security type', () => {
+    const input = {
+      security: {
+        BasicAuth: {
+          type: 'http',
+          scheme: 'basic',
+        },
+        bearerAuth: {
+          type: 'http',
+          scheme: 'bearer',
+          bearerFormat: 'JWT',
+        },
+      },
+    };
+    const expected = {
+      security: [
+        {
+          BasicAuth: [],
+        },
+        {
+          bearerAuth: [],
+        },
+      ],
+      components: {
+        securitySchemes: {
+          BasicAuth: {
+            type: 'http',
+            scheme: 'basic',
+          },
+          bearerAuth: {
+            type: 'http',
+            scheme: 'bearer',
+            bearerFormat: 'JWT',
+          },
+        },
+      },
+    };
+    const result = parseSecuritySchemas(input);
+    expect(result).toEqual(expected);
+  });
+});