diff --git a/Dockerfile b/Dockerfile
index 03381839..1d71c0ac 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -9,11 +9,6 @@ RUN apk add nodejs
LABEL maintainer="fehguy"
ENV API_KEY "**None**"
-ENV OAUTH_CLIENT_ID "**None**"
-ENV OAUTH_CLIENT_SECRET "**None**"
-ENV OAUTH_REALM "**None**"
-ENV OAUTH_APP_NAME "**None**"
-ENV OAUTH_ADDITIONAL_PARAMS "**None**"
ENV SWAGGER_JSON "/app/swagger.json"
ENV PORT 8080
ENV BASE_URL ""
diff --git a/docker/configurator/helpers.js b/docker/configurator/helpers.js
new file mode 100644
index 00000000..c72479d6
--- /dev/null
+++ b/docker/configurator/helpers.js
@@ -0,0 +1,13 @@
+module.exports.indent = function indent(str, len, fromLine = 0) {
+
+ return str
+ .split("\n")
+ .map((line, i) => {
+ if (i + 1 >= fromLine) {
+ return `${Array(len + 1).join(" ")}${line}`
+ } else {
+ return line
+ }
+ })
+ .join("\n")
+}
\ No newline at end of file
diff --git a/docker/configurator/index.js b/docker/configurator/index.js
index 38567fcd..1144d03b 100755
--- a/docker/configurator/index.js
+++ b/docker/configurator/index.js
@@ -2,7 +2,8 @@ const fs = require("fs")
const path = require("path")
const translator = require("./translator")
-const configSchema = require("./variables")
+const oauthBlockBuilder = require("./oauth")
+const indent = require("./helpers").indent
const START_MARKER = "// Begin Swagger UI call region"
const END_MARKER = "// End Swagger UI call region"
@@ -22,19 +23,7 @@ fs.writeFileSync(targetPath, `${beforeStartMarkerContent}
const ui = SwaggerUIBundle({
${indent(translator(process.env, { injectBaseConfig: true }), 8, 2)}
})
+
+ ${indent(oauthBlockBuilder(process.env), 6, 2)}
${END_MARKER}
-${afterEndMarkerContent}`)
-
-function indent(str, len, fromLine) {
-
- return str
- .split("\n")
- .map((line, i) => {
- if(i + 1 >= fromLine) {
- return `${Array(len + 1).join(" ")}${line}`
- } else {
- return line
- }
- })
- .join("\n")
-}
\ No newline at end of file
+${afterEndMarkerContent}`)
\ No newline at end of file
diff --git a/docker/configurator/oauth.js b/docker/configurator/oauth.js
new file mode 100644
index 00000000..93fed5ba
--- /dev/null
+++ b/docker/configurator/oauth.js
@@ -0,0 +1,43 @@
+const translator = require("./translator")
+const indent = require("./helpers").indent
+
+const oauthBlockSchema = {
+ OAUTH_CLIENT_ID: {
+ type: "string",
+ name: "clientId"
+ },
+ OAUTH_CLIENT_SECRET: {
+ type: "string",
+ name: "clientSecret",
+ onFound: () => console.warn("Swagger UI warning: don't use `OAUTH_CLIENT_SECRET` in production!")
+ },
+ OAUTH_REALM: {
+ type: "string",
+ name: "realm"
+ },
+ OAUTH_APP_NAME: {
+ type: "string",
+ name: "appName"
+ },
+ OAUTH_SCOPE_SEPARATOR: {
+ type: "string",
+ name: "scopeSeparator"
+ },
+ OAUTH_ADDITIONAL_PARAMS: {
+ type: "object",
+ name: "additionalQueryStringParams"
+ }
+}
+
+module.exports = function oauthBlockBuilder(env) {
+ const translatorResult = translator(env, { schema: oauthBlockSchema })
+
+ if(translatorResult) {
+ return (
+ `ui.initOAuth({
+${indent(translatorResult, 2)}
+})`)
+ }
+
+ return ``
+}
\ No newline at end of file
diff --git a/docker/configurator/translator.js b/docker/configurator/translator.js
index 06167553..1671672e 100644
--- a/docker/configurator/translator.js
+++ b/docker/configurator/translator.js
@@ -55,6 +55,10 @@ function objectToKeyValueString(env, { injectBaseConfig = false, schema = config
if(!varSchema) return
+ if(varSchema.onFound) {
+ varSchema.onFound()
+ }
+
const storageContents = valueStorage[varSchema.name]
if(storageContents) {
diff --git a/docker/run.sh b/docker/run.sh
index 7ea77b3e..e5551315 100644
--- a/docker/run.sh
+++ b/docker/run.sh
@@ -28,13 +28,6 @@ if [ "${BASE_URL}" ]; then
fi
replace_in_index myApiKeyXXXX123456789 $API_KEY
-replace_or_delete_in_index your-client-id $OAUTH_CLIENT_ID
-replace_or_delete_in_index your-client-secret-if-required $OAUTH_CLIENT_SECRET
-replace_or_delete_in_index your-realms $OAUTH_REALM
-replace_or_delete_in_index your-app-name $OAUTH_APP_NAME
-if [ "$OAUTH_ADDITIONAL_PARAMS" != "**None**" ]; then
- replace_in_index "additionalQueryStringParams: {}" "additionalQueryStringParams: {$OAUTH_ADDITIONAL_PARAMS}"
-fi
if [[ -f $SWAGGER_JSON ]]; then
cp -s $SWAGGER_JSON $NGINX_ROOT
diff --git a/docs/usage/configuration.md b/docs/usage/configuration.md
index 8345d80a..cea3f2cd 100644
--- a/docs/usage/configuration.md
+++ b/docs/usage/configuration.md
@@ -81,9 +81,11 @@ Parameter name | Docker variable | Description
### Instance methods
-Parameter name | Docker variable | Description
+**💡 Take note! These are methods, not parameters**.
+
+Method name | Docker variable | Description
--- | --- | -----
-`initOAuth` | _Unavailable_ | `(configObj) => void`. Provide Swagger-UI with information about your OAuth server - see the OAuth2 documentation for more information.
+`initOAuth` | [_See `oauth2.md`_](./oauth2.md) | `(configObj) => void`. Provide Swagger-UI with information about your OAuth server - see the OAuth2 documentation for more information.
`preauthorizeBasic` | _Unavailable_ | `(authDefinitionKey, username, password) => action`. Programmatically set values for a Basic authorization scheme.
`preauthorizeApiKey` | _Unavailable_ | `(authDefinitionKey, apiKeyValue) => action`. Programmatically set values for an API key authorization scheme.
diff --git a/docs/usage/oauth2.md b/docs/usage/oauth2.md
index 3289ae95..4918374c 100644
--- a/docs/usage/oauth2.md
+++ b/docs/usage/oauth2.md
@@ -1,15 +1,15 @@
# OAuth2 configuration
You can configure OAuth2 authorization by calling the `initOAuth` method.
-Config Name | Description
---- | ---
-clientId | Default clientId. MUST be a string
-clientSecret | **🚨 Never use this parameter in your production environemnt. It exposes cruicial security information. This feature is intended for dev/test environments only. 🚨**
Default clientSecret. MUST be a string
-realm | realm query parameter (for oauth1) added to `authorizationUrl` and `tokenUrl`. MUST be a string
-appName | application name, displayed in authorization popup. MUST be a string
-scopeSeparator | scope separator for passing scopes, encoded before calling, default value is a space (encoded value `%20`). MUST be a string
-additionalQueryStringParams | Additional query parameters added to `authorizationUrl` and `tokenUrl`. MUST be an object
-useBasicAuthenticationWithAccessCodeGrant | Only activated for the `accessCode` flow. During the `authorization_code` request to the `tokenUrl`, pass the [Client Password](https://tools.ietf.org/html/rfc6749#section-2.3.1) using the HTTP Basic Authentication scheme (`Authorization` header with `Basic base64encode(client_id + client_secret)`). The default is `false`
+Property name | Docker variable | Description
+--- | --- | ------
+clientId | `OAUTH_CLIENT_ID` | Default clientId. MUST be a string
+clientSecret | `OAUTH_CLIENT_SECRET` | **🚨 Never use this parameter in your production environemnt. It exposes cruicial security information. This feature is intended for dev/test environments only. 🚨**
Default clientSecret. MUST be a string
+realm | `OAUTH_REALM` |realm query parameter (for oauth1) added to `authorizationUrl` and `tokenUrl`. MUST be a string
+appName | `OAUTH_APP_NAME` |application name, displayed in authorization popup. MUST be a string
+scopeSeparator | `OAUTH_SCOPE_SEPARATOR` |scope separator for passing scopes, encoded before calling, default value is a space (encoded value `%20`). MUST be a string
+additionalQueryStringParams | `OAUTH_ADDITIONAL_PARAMS` |Additional query parameters added to `authorizationUrl` and `tokenUrl`. MUST be an object
+useBasicAuthenticationWithAccessCodeGrant | _Unavailable_ |Only activated for the `accessCode` flow. During the `authorization_code` request to the `tokenUrl`, pass the [Client Password](https://tools.ietf.org/html/rfc6749#section-2.3.1) using the HTTP Basic Authentication scheme (`Authorization` header with `Basic base64encode(client_id + client_secret)`). The default is `false`
```javascript
const ui = SwaggerUI({...})
diff --git a/test/docker/oauth.js b/test/docker/oauth.js
new file mode 100644
index 00000000..3a6ffc3d
--- /dev/null
+++ b/test/docker/oauth.js
@@ -0,0 +1,58 @@
+const expect = require("expect")
+const oauthBlockBuilder = require("../../docker/configurator/oauth")
+const dedent = require("dedent")
+
+describe("docker: env translator - oauth block", function() {
+ it("should omit the block if there are no valid keys", function () {
+ const input = {}
+
+ expect(oauthBlockBuilder(input)).toEqual(``)
+ })
+ it("should omit the block if there are no valid keys", function () {
+ const input = {
+ NOT_A_VALID_KEY: "asdf1234"
+ }
+
+ expect(oauthBlockBuilder(input)).toEqual(``)
+ })
+ it("should generate a block from empty values", function() {
+ const input = {
+ OAUTH_CLIENT_ID: ``,
+ OAUTH_CLIENT_SECRET: ``,
+ OAUTH_REALM: ``,
+ OAUTH_APP_NAME: ``,
+ OAUTH_SCOPE_SEPARATOR: "",
+ OAUTH_ADDITIONAL_PARAMS: ``,
+ }
+
+ expect(oauthBlockBuilder(input)).toEqual(dedent(`
+ ui.initOAuth({
+ clientId: "",
+ clientSecret: "",
+ realm: "",
+ appName: "",
+ scopeSeparator: "",
+ additionalQueryStringParams: undefined,
+ })`))
+ })
+ it("should generate a full block", function() {
+ const input = {
+ OAUTH_CLIENT_ID: `myId`,
+ OAUTH_CLIENT_SECRET: `mySecret`,
+ OAUTH_REALM: `myRealm`,
+ OAUTH_APP_NAME: `myAppName`,
+ OAUTH_SCOPE_SEPARATOR: "%21",
+ OAUTH_ADDITIONAL_PARAMS: `{ "a": 1234, "b": "stuff" }`,
+ }
+
+ expect(oauthBlockBuilder(input)).toEqual(dedent(`
+ ui.initOAuth({
+ clientId: "myId",
+ clientSecret: "mySecret",
+ realm: "myRealm",
+ appName: "myAppName",
+ scopeSeparator: "%21",
+ additionalQueryStringParams: { "a": 1234, "b": "stuff" },
+ })`))
+ })
+})
\ No newline at end of file
diff --git a/test/docker/translator.js b/test/docker/translator.js
index 887c8fc1..bf7597e7 100644
--- a/test/docker/translator.js
+++ b/test/docker/translator.js
@@ -3,18 +3,43 @@ const translator = require("../../docker/configurator/translator")
const dedent = require("dedent")
describe("docker: env translator", function() {
- it("should generate an empty baseline config", function() {
- const input = {}
+ describe("fundamentals", function() {
+ it("should generate an empty baseline config", function () {
+ const input = {}
- expect(translator(input)).toEqual(``)
+ expect(translator(input)).toEqual(``)
+ })
+
+ it("should call an onFound callback", function () {
+ const input = {
+ MY_THING: "hey"
+ }
+
+ const onFoundSpy = expect.createSpy()
+
+ const schema = {
+ MY_THING: {
+ type: "string",
+ name: "myThing",
+ onFound: onFoundSpy
+ }
+ }
+
+ const res = translator(input, {
+ schema
+ })
+ expect(res).toEqual(`myThing: "hey",`)
+ expect(onFoundSpy.calls.length).toEqual(1)
+
+ })
})
+ describe("Swagger UI configuration", function() {
+ it("should generate a base config including the base content", function () {
+ const input = {}
- it("should generate a base config including the base content", function() {
- const input = {}
-
- expect(translator(input, {
- injectBaseConfig: true
- })).toEqual(dedent(`
+ expect(translator(input, {
+ injectBaseConfig: true
+ })).toEqual(dedent(`
url: "https://petstore.swagger.io/v2/swagger.json",
"dom_id": "#swagger-ui",
deepLinking: true,
@@ -27,121 +52,121 @@ describe("docker: env translator", function() {
],
layout: "StandaloneLayout",
`))
- })
+ })
- it("should ignore an unknown config", function() {
- const input = {
- ASDF1234: "wow hello"
- }
+ it("should ignore an unknown config", function () {
+ const input = {
+ ASDF1234: "wow hello"
+ }
- expect(translator(input)).toEqual(dedent(``))
- })
+ expect(translator(input)).toEqual(dedent(``))
+ })
- it("should generate a string config", function() {
- const input = {
- URL: "http://petstore.swagger.io/v2/swagger.json",
- FILTER: ""
- }
+ it("should generate a string config", function () {
+ const input = {
+ URL: "http://petstore.swagger.io/v2/swagger.json",
+ FILTER: ""
+ }
- expect(translator(input)).toEqual(dedent(`
+ expect(translator(input)).toEqual(dedent(`
url: "http://petstore.swagger.io/v2/swagger.json",
filter: "",`
- ).trim())
- })
+ ).trim())
+ })
- it("should generate a boolean config", function() {
- const input = {
- DEEP_LINKING: "true",
- SHOW_EXTENSIONS: "false",
- SHOW_COMMON_EXTENSIONS: ""
- }
+ it("should generate a boolean config", function () {
+ const input = {
+ DEEP_LINKING: "true",
+ SHOW_EXTENSIONS: "false",
+ SHOW_COMMON_EXTENSIONS: ""
+ }
- expect(translator(input)).toEqual(dedent(`
+ expect(translator(input)).toEqual(dedent(`
deepLinking: true,
showExtensions: false,
showCommonExtensions: undefined,`
- ))
- })
+ ))
+ })
- it("should generate an object config", function() {
- const input = {
- SPEC: `{ swagger: "2.0" }`
- }
+ it("should generate an object config", function () {
+ const input = {
+ SPEC: `{ swagger: "2.0" }`
+ }
- expect(translator(input)).toEqual(dedent(`
+ expect(translator(input)).toEqual(dedent(`
spec: { swagger: "2.0" },`
).trim())
- })
+ })
- it("should generate an array config", function() {
- const input = {
- URLS: `["/one", "/two"]`,
- SUPPORTED_SUBMIT_METHODS: ""
- }
+ it("should generate an array config", function () {
+ const input = {
+ URLS: `["/one", "/two"]`,
+ SUPPORTED_SUBMIT_METHODS: ""
+ }
- expect(translator(input)).toEqual(dedent(`
+ expect(translator(input)).toEqual(dedent(`
urls: ["/one", "/two"],
supportedSubmitMethods: undefined,`
).trim())
- })
+ })
- it("should properly escape key names when necessary", function () {
- const input = {
- URLS: `["/one", "/two"]`,
- URLS_PRIMARY_NAME: "one",
- }
+ it("should properly escape key names when necessary", function () {
+ const input = {
+ URLS: `["/one", "/two"]`,
+ URLS_PRIMARY_NAME: "one",
+ }
- expect(translator(input)).toEqual(dedent(`
+ expect(translator(input)).toEqual(dedent(`
urls: ["/one", "/two"],
"urls.primaryName": "one",`
).trim())
- })
+ })
- it("should disregard a legacy variable in favor of a regular one", function() {
- const input = {
- // Order is important to this test... legacy vars should be
- // superseded regardless of what is fed in first.
- API_URL: "/old.json",
- URL: "/swagger.json",
- URLS: `["/one", "/two"]`,
- API_URLS: `["/three", "/four"]`,
- }
+ it("should disregard a legacy variable in favor of a regular one", function () {
+ const input = {
+ // Order is important to this test... legacy vars should be
+ // superseded regardless of what is fed in first.
+ API_URL: "/old.json",
+ URL: "/swagger.json",
+ URLS: `["/one", "/two"]`,
+ API_URLS: `["/three", "/four"]`,
+ }
- expect(translator(input)).toEqual(dedent(`
+ expect(translator(input)).toEqual(dedent(`
url: "/swagger.json",
urls: ["/one", "/two"],`
).trim())
- })
+ })
- it("should generate a full config k:v string", function() {
- const input = {
- API_URL: "/old.yaml",
- API_URLS: `["/old", "/older"]`,
- CONFIG_URL: "/wow",
- DOM_ID: "#swagger_ui",
- SPEC: `{ swagger: "2.0" }`,
- URL: "/swagger.json",
- URLS: `["/one", "/two"]`,
- URLS_PRIMARY_NAME: "one",
- LAYOUT: "BaseLayout",
- DEEP_LINKING: "false",
- DISPLAY_OPERATION_ID: "true",
- DEFAULT_MODELS_EXPAND_DEPTH: "0",
- DEFAULT_MODEL_EXPAND_DEPTH: "1",
- DEFAULT_MODEL_RENDERING: "example",
- DISPLAY_REQUEST_DURATION: "true",
- DOC_EXPANSION: "full",
- FILTER: "wowee",
- MAX_DISPLAYED_TAGS: "4",
- SHOW_EXTENSIONS: "true",
- SHOW_COMMON_EXTENSIONS: "false",
- OAUTH2_REDIRECT_URL: "http://google.com/",
- SHOW_MUTATED_REQUEST: "true",
- SUPPORTED_SUBMIT_METHODS: `["get", "post"]`,
- VALIDATOR_URL: "http://smartbear.com/"
- }
+ it("should generate a full config k:v string", function () {
+ const input = {
+ API_URL: "/old.yaml",
+ API_URLS: `["/old", "/older"]`,
+ CONFIG_URL: "/wow",
+ DOM_ID: "#swagger_ui",
+ SPEC: `{ swagger: "2.0" }`,
+ URL: "/swagger.json",
+ URLS: `["/one", "/two"]`,
+ URLS_PRIMARY_NAME: "one",
+ LAYOUT: "BaseLayout",
+ DEEP_LINKING: "false",
+ DISPLAY_OPERATION_ID: "true",
+ DEFAULT_MODELS_EXPAND_DEPTH: "0",
+ DEFAULT_MODEL_EXPAND_DEPTH: "1",
+ DEFAULT_MODEL_RENDERING: "example",
+ DISPLAY_REQUEST_DURATION: "true",
+ DOC_EXPANSION: "full",
+ FILTER: "wowee",
+ MAX_DISPLAYED_TAGS: "4",
+ SHOW_EXTENSIONS: "true",
+ SHOW_COMMON_EXTENSIONS: "false",
+ OAUTH2_REDIRECT_URL: "http://google.com/",
+ SHOW_MUTATED_REQUEST: "true",
+ SUPPORTED_SUBMIT_METHODS: `["get", "post"]`,
+ VALIDATOR_URL: "http://smartbear.com/"
+ }
- expect(translator(input)).toEqual(dedent(`
+ expect(translator(input)).toEqual(dedent(`
configUrl: "/wow",
"dom_id": "#swagger_ui",
spec: { swagger: "2.0" },
@@ -165,37 +190,37 @@ describe("docker: env translator", function() {
supportedSubmitMethods: ["get", "post"],
validatorUrl: "http://smartbear.com/",`
).trim())
- })
+ })
- it("should generate a full config k:v string including base config", function() {
- const input = {
- API_URL: "/old.yaml",
- API_URLS: `["/old", "/older"]`,
- CONFIG_URL: "/wow",
- DOM_ID: "#swagger_ui",
- SPEC: `{ swagger: "2.0" }`,
- URL: "/swagger.json",
- URLS: `["/one", "/two"]`,
- URLS_PRIMARY_NAME: "one",
- LAYOUT: "BaseLayout",
- DEEP_LINKING: "false",
- DISPLAY_OPERATION_ID: "true",
- DEFAULT_MODELS_EXPAND_DEPTH: "0",
- DEFAULT_MODEL_EXPAND_DEPTH: "1",
- DEFAULT_MODEL_RENDERING: "example",
- DISPLAY_REQUEST_DURATION: "true",
- DOC_EXPANSION: "full",
- FILTER: "wowee",
- MAX_DISPLAYED_TAGS: "4",
- SHOW_EXTENSIONS: "true",
- SHOW_COMMON_EXTENSIONS: "false",
- OAUTH2_REDIRECT_URL: "http://google.com/",
- SHOW_MUTATED_REQUEST: "true",
- SUPPORTED_SUBMIT_METHODS: `["get", "post"]`,
- VALIDATOR_URL: "http://smartbear.com/"
- }
+ it("should generate a full config k:v string including base config", function () {
+ const input = {
+ API_URL: "/old.yaml",
+ API_URLS: `["/old", "/older"]`,
+ CONFIG_URL: "/wow",
+ DOM_ID: "#swagger_ui",
+ SPEC: `{ swagger: "2.0" }`,
+ URL: "/swagger.json",
+ URLS: `["/one", "/two"]`,
+ URLS_PRIMARY_NAME: "one",
+ LAYOUT: "BaseLayout",
+ DEEP_LINKING: "false",
+ DISPLAY_OPERATION_ID: "true",
+ DEFAULT_MODELS_EXPAND_DEPTH: "0",
+ DEFAULT_MODEL_EXPAND_DEPTH: "1",
+ DEFAULT_MODEL_RENDERING: "example",
+ DISPLAY_REQUEST_DURATION: "true",
+ DOC_EXPANSION: "full",
+ FILTER: "wowee",
+ MAX_DISPLAYED_TAGS: "4",
+ SHOW_EXTENSIONS: "true",
+ SHOW_COMMON_EXTENSIONS: "false",
+ OAUTH2_REDIRECT_URL: "http://google.com/",
+ SHOW_MUTATED_REQUEST: "true",
+ SUPPORTED_SUBMIT_METHODS: `["get", "post"]`,
+ VALIDATOR_URL: "http://smartbear.com/"
+ }
- expect(translator(input, { injectBaseConfig: true })).toEqual(dedent(`
+ expect(translator(input, { injectBaseConfig: true })).toEqual(dedent(`
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
@@ -226,5 +251,6 @@ describe("docker: env translator", function() {
supportedSubmitMethods: ["get", "post"],
validatorUrl: "http://smartbear.com/",`
).trim())
+ })
})
})
\ No newline at end of file