mirror of
https://github.com/Unleash/unleash.git
synced 2025-09-15 17:50:48 +02:00
feat: First draft of admin Open API specification (OAS) (#652)
Co-authored-by: Ivar Conradi Østhus <ivarconr@gmail.com>
This commit is contained in:
parent
abc93d55da
commit
c7c2f17bd0
18
.github/workflows/readme.yaml
vendored
Normal file
18
.github/workflows/readme.yaml
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
name: Sync OAS to ReadMe
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- main
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: readmeio/github-readme-sync@v2
|
||||||
|
with:
|
||||||
|
readme-oas-key: oDf7vsdkbfuFmj6M7E5W98QcmyBnLpmM:5fc4b9a323e95041cd0a08fb
|
||||||
|
|
||||||
|
# OPTIONAL CONFIG, use if necessary
|
||||||
|
# oas-file-path: './swagger.json'
|
||||||
|
# api-version: 'v1.0.0'
|
BIN
docs/api/oas/favicon-16x16.png
Normal file
BIN
docs/api/oas/favicon-16x16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 665 B |
BIN
docs/api/oas/favicon-32x32.png
Normal file
BIN
docs/api/oas/favicon-32x32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 628 B |
76
docs/api/oas/index.html
Normal file
76
docs/api/oas/index.html
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<!-- HTML for static distribution bundle build -->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Unleash Open API</title>
|
||||||
|
<link rel="stylesheet" href="theme-material.css">
|
||||||
|
<!-- Material design styles from ostranme.github.io/swagger-ui-themes
|
||||||
|
Original follows
|
||||||
|
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" > -->
|
||||||
|
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
||||||
|
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
||||||
|
<style>
|
||||||
|
html
|
||||||
|
{
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: -moz-scrollbars-vertical;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*:before,
|
||||||
|
*:after
|
||||||
|
{
|
||||||
|
box-sizing: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
body
|
||||||
|
{
|
||||||
|
margin:0;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topbar-wrapper img {
|
||||||
|
content: url(https://unleash.github.io/img/logo-inverted.png);
|
||||||
|
}
|
||||||
|
|
||||||
|
.swagger-ui .topbar .download-url-wrapper .download-url-button {
|
||||||
|
background-color: #3f51b5 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swagger-ui .topbar .download-url-wrapper input[type=text] {
|
||||||
|
border-color: #3f51b5 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="swagger-ui"></div>
|
||||||
|
|
||||||
|
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
|
||||||
|
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
|
||||||
|
<script>
|
||||||
|
window.onload = function() {
|
||||||
|
// Begin Swagger UI call region
|
||||||
|
const ui = SwaggerUIBundle({
|
||||||
|
url: "openapi.yaml",
|
||||||
|
dom_id: '#swagger-ui',
|
||||||
|
defaultModelsExpandDepth: -1,
|
||||||
|
deepLinking: true,
|
||||||
|
presets: [
|
||||||
|
SwaggerUIBundle.presets.apis,
|
||||||
|
SwaggerUIStandalonePreset
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
SwaggerUIBundle.plugins.DownloadUrl
|
||||||
|
],
|
||||||
|
layout: "StandaloneLayout"
|
||||||
|
})
|
||||||
|
// End Swagger UI call region
|
||||||
|
|
||||||
|
window.ui = ui
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
74
docs/api/oas/oauth2-redirect.html
Normal file
74
docs/api/oas/oauth2-redirect.html
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<title>Swagger UI: OAuth2 Redirect</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
<script>
|
||||||
|
'use strict';
|
||||||
|
function run () {
|
||||||
|
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||||
|
var sentState = oauth2.state;
|
||||||
|
var redirectUrl = oauth2.redirectUrl;
|
||||||
|
var isValid, qp, arr;
|
||||||
|
|
||||||
|
if (/code|token|error/.test(window.location.hash)) {
|
||||||
|
qp = window.location.hash.substring(1);
|
||||||
|
} else {
|
||||||
|
qp = location.search.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
arr = qp.split("&")
|
||||||
|
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';})
|
||||||
|
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
||||||
|
function (key, value) {
|
||||||
|
return key === "" ? value : decodeURIComponent(value)
|
||||||
|
}
|
||||||
|
) : {}
|
||||||
|
|
||||||
|
isValid = qp.state === sentState
|
||||||
|
|
||||||
|
if ((
|
||||||
|
oauth2.auth.schema.get("flow") === "accessCode"||
|
||||||
|
oauth2.auth.schema.get("flow") === "authorizationCode"
|
||||||
|
) && !oauth2.auth.code) {
|
||||||
|
if (!isValid) {
|
||||||
|
oauth2.errCb({
|
||||||
|
authId: oauth2.auth.name,
|
||||||
|
source: "auth",
|
||||||
|
level: "warning",
|
||||||
|
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qp.code) {
|
||||||
|
delete oauth2.state;
|
||||||
|
oauth2.auth.code = qp.code;
|
||||||
|
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
||||||
|
} else {
|
||||||
|
let oauthErrorMsg
|
||||||
|
if (qp.error) {
|
||||||
|
oauthErrorMsg = "["+qp.error+"]: " +
|
||||||
|
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
||||||
|
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
oauth2.errCb({
|
||||||
|
authId: oauth2.auth.name,
|
||||||
|
source: "auth",
|
||||||
|
level: "error",
|
||||||
|
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
||||||
|
}
|
||||||
|
window.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('DOMContentLoaded', function () {
|
||||||
|
run();
|
||||||
|
});
|
||||||
|
</script>
|
1335
docs/api/oas/openapi.yaml
Normal file
1335
docs/api/oas/openapi.yaml
Normal file
File diff suppressed because it is too large
Load Diff
24
docs/api/oas/redoc.html
Normal file
24
docs/api/oas/redoc.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>ReDoc</title>
|
||||||
|
<!-- needed for adaptive design -->
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
ReDoc doesn't change outer page styles
|
||||||
|
-->
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<redoc spec-url='openapi.yaml'></redoc>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
|
||||||
|
</body>
|
||||||
|
</html>
|
3
docs/api/oas/swagger-ui-bundle.js
Normal file
3
docs/api/oas/swagger-ui-bundle.js
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/oas/swagger-ui-bundle.js.map
Normal file
1
docs/api/oas/swagger-ui-bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
3
docs/api/oas/swagger-ui-es-bundle-core.js
Normal file
3
docs/api/oas/swagger-ui-es-bundle-core.js
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/oas/swagger-ui-es-bundle-core.js.map
Normal file
1
docs/api/oas/swagger-ui-es-bundle-core.js.map
Normal file
File diff suppressed because one or more lines are too long
3
docs/api/oas/swagger-ui-es-bundle.js
Normal file
3
docs/api/oas/swagger-ui-es-bundle.js
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/oas/swagger-ui-es-bundle.js.map
Normal file
1
docs/api/oas/swagger-ui-es-bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
3
docs/api/oas/swagger-ui-standalone-preset.js
Normal file
3
docs/api/oas/swagger-ui-standalone-preset.js
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/oas/swagger-ui-standalone-preset.js.map
Normal file
1
docs/api/oas/swagger-ui-standalone-preset.js.map
Normal file
File diff suppressed because one or more lines are too long
4
docs/api/oas/swagger-ui.css
Normal file
4
docs/api/oas/swagger-ui.css
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/oas/swagger-ui.css.map
Normal file
1
docs/api/oas/swagger-ui.css.map
Normal file
File diff suppressed because one or more lines are too long
3
docs/api/oas/swagger-ui.js
Normal file
3
docs/api/oas/swagger-ui.js
Normal file
File diff suppressed because one or more lines are too long
1
docs/api/oas/swagger-ui.js.map
Normal file
1
docs/api/oas/swagger-ui.js.map
Normal file
File diff suppressed because one or more lines are too long
1676
docs/api/oas/swagger.json
Normal file
1676
docs/api/oas/swagger.json
Normal file
File diff suppressed because it is too large
Load Diff
1719
docs/api/oas/theme-material.css
Normal file
1719
docs/api/oas/theme-material.css
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,43 +5,90 @@ title: Getting Started
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
You will need **Node.js** >= 12 and a **PostgreSQL** >= 10 database instance to be able to run Unleash.
|
You will need:
|
||||||
|
|
||||||
When starting Unleash you must specify a database URI (can be set as environment variable DATABASE_URL) which includes a username and password, that have rights to migrate the database.
|
- [**Node.js**](https://nodejs.org/en/download/) (version 12 or later)
|
||||||
|
- [**PostgreSQL**](https://www.postgresql.org/download/) (version 10 or later)
|
||||||
|
- [Create an unleash user and database](./developer-guide.md).
|
||||||
|
|
||||||
On startup _Unleash_ will perform necessary migrations if needed.
|
## Start Unleash server
|
||||||
|
|
||||||
## Start Unleash
|
Whichever option you choose to start Unleash, you must specify a database URI (it can be set in the environment variable DATABASE_URL).
|
||||||
|
|
||||||
### 1. The simplest way to get started:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm install unleash-server -g
|
|
||||||
$ unleash -d postgres://unleash_user:password@localhost:5432/unleash -p 4242
|
|
||||||
|
|
||||||
|
Once the server has started, you will see the message:
|
||||||
|
```
|
||||||
Unleash started on http://localhost:4242
|
Unleash started on http://localhost:4242
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Or programmatically:
|
### Option one - from a terminal/bash shell
|
||||||
|
|
||||||
You can also depend on unleash
|
```
|
||||||
|
npm install unleash-server -g
|
||||||
```js
|
unleash -d postgres://unleash_user:password@localhost:5432/unleash -p 4242
|
||||||
const unleash = require('unleash-server');
|
|
||||||
|
|
||||||
unleash
|
|
||||||
.start({
|
|
||||||
databaseUrl: 'postgres://unleash_user:password@localhost:5432/unleash',
|
|
||||||
port: 4242,
|
|
||||||
})
|
|
||||||
.then(unleash => {
|
|
||||||
console.log(
|
|
||||||
`Unleash started on http://localhost:${unleash.app.get('port')}`,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Available unleash options include:
|
### Option two - from Node.js
|
||||||
|
|
||||||
|
1. Create a new folder/directory on your development computer.
|
||||||
|
2. From a terminal/bash shell, install the dependencies:
|
||||||
|
|
||||||
|
```
|
||||||
|
npm init
|
||||||
|
npm install unleash-server --save
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Create a file called *server.js*, paste the following into it and save.
|
||||||
|
```js
|
||||||
|
const unleash = require('unleash-server');
|
||||||
|
|
||||||
|
unleash
|
||||||
|
.start({
|
||||||
|
databaseUrl: 'postgres://unleash_user:password@localhost:5432/unleash',
|
||||||
|
port: 4242,
|
||||||
|
})
|
||||||
|
.then(unleash => {
|
||||||
|
console.log(
|
||||||
|
`Unleash started on http://localhost:${unleash.app.get('port')}`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Run *server.js*:
|
||||||
|
```
|
||||||
|
node server.js
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option three - use Docker
|
||||||
|
|
||||||
|
Launch the [Unleash server Docker image](https://hub.docker.com/r/unleashorg/unleash-server/).
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run -d -e DATABASE_URL=postgres://user:pass@10.200.221.11:5432/unleash unleashorg/unleash-server
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test your server and create a sample API call
|
||||||
|
|
||||||
|
Once the Unleash server has started, go to [localhost:4242](http://localhost:4242) in your browser. If you see a list of example feature toggles, try modifying one of them with [curl](https://curl.se/) from a terminal/bash shell:
|
||||||
|
|
||||||
|
~~~
|
||||||
|
curl --location --request PUT 'http://localhost:4242/api/admin/features/Feature.A' --header 'Content-Type: application/json' --data-raw '{\
|
||||||
|
"name": "Feature.A",\
|
||||||
|
"description": "Dolor sit amet.",\
|
||||||
|
"type": "release",\
|
||||||
|
"enabled": false,\
|
||||||
|
"stale": false,\
|
||||||
|
"strategies": [\
|
||||||
|
{\
|
||||||
|
"name": "default",\
|
||||||
|
"parameters": {}\
|
||||||
|
}\
|
||||||
|
]\
|
||||||
|
}'\
|
||||||
|
~~~
|
||||||
|
<!-- The following doesn't seem to fit the 'remit' of Getting started'. it would be a better fit in the developer section of the documentation -->
|
||||||
|
## Unleash server options
|
||||||
|
|
||||||
|
Available Unleash options include:
|
||||||
|
|
||||||
- **db** - The database configuration object taking the following properties:
|
- **db** - The database configuration object taking the following properties:
|
||||||
- _user_ - the database username (`DATABASE_USERNAME`)
|
- _user_ - the database username (`DATABASE_USERNAME`)
|
||||||
@ -70,9 +117,9 @@ Available unleash options include:
|
|||||||
- **baseUriPath** (string) - use to register a base path for all routes on the application. For example `/my/unleash/base` (note the starting /). Defaults to `/`. Can also be configured through the environment variable `BASE_URI_PATH`.
|
- **baseUriPath** (string) - use to register a base path for all routes on the application. For example `/my/unleash/base` (note the starting /). Defaults to `/`. Can also be configured through the environment variable `BASE_URI_PATH`.
|
||||||
- **secureHeaders** (boolean) - use this to enable security headers (HSTS, CSP, etc) when serving Unleash from HTTPS. Can also be configured through the environment variable `SECURE_HEADERS`.
|
- **secureHeaders** (boolean) - use this to enable security headers (HSTS, CSP, etc) when serving Unleash from HTTPS. Can also be configured through the environment variable `SECURE_HEADERS`.
|
||||||
|
|
||||||
#### Disabling Auto-Start
|
### Disabling Auto-Start
|
||||||
|
|
||||||
If you're using unleash as part of a larger express app, you can disable the automatic server start by calling `server.create`. It takes the same options as `sevrer.start`, but will not begin listening for connections.
|
If you're using Unleash as part of a larger express app, you can disable the automatic server start by calling `server.create`. It takes the same options as `sevrer.start`, but will not begin listening for connections.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const unleash = require('unleash-server');
|
const unleash = require('unleash-server');
|
||||||
@ -89,17 +136,9 @@ unleash
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Docker
|
|
||||||
|
|
||||||
You can also use the [hosted docker image](https://hub.docker.com/r/unleashorg/unleash-server/) to start the Unleash server
|
|
||||||
|
|
||||||
```sh
|
|
||||||
docker run -d -e DATABASE_URL=postgres://user:pass@10.200.221.11:5432/unleash unleashorg/unleash-server
|
|
||||||
```
|
|
||||||
|
|
||||||
## Securing Unleash
|
## Securing Unleash
|
||||||
|
|
||||||
Unleash also have extension points where you can integrate Unleash with your authentication provider (OAuth 2.0). Read more about [securing unleash](./securing-unleash.md).
|
You can integrate Unleash with your authentication provider (OAuth 2.0). Read more about [securing unleash](./securing-unleash.md).
|
||||||
|
|
||||||
## How do I configure the log output?
|
## How do I configure the log output?
|
||||||
|
|
||||||
|
@ -43,6 +43,10 @@ module.exports = function(config) {
|
|||||||
app.use(baseUriPath, express.static(config.publicFolder));
|
app.use(baseUriPath, express.static(config.publicFolder));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.enableOAS) {
|
||||||
|
app.use(`${baseUriPath}/oas`, express.static('docs/api/oas'));
|
||||||
|
}
|
||||||
|
|
||||||
if (config.adminAuthentication === 'unsecure') {
|
if (config.adminAuthentication === 'unsecure') {
|
||||||
simpleAuthentication(baseUriPath, app);
|
simpleAuthentication(baseUriPath, app);
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@ function defaultOptions() {
|
|||||||
headersTimeout: 61 * 1000,
|
headersTimeout: 61 * 1000,
|
||||||
version,
|
version,
|
||||||
secureHeaders: process.env.SECURE_HEADERS || false,
|
secureHeaders: process.env.SECURE_HEADERS || false,
|
||||||
|
enableOAS: process.env.ENABLE_OAS || false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,4 +12,5 @@ unleash.start({
|
|||||||
ssl: false,
|
ssl: false,
|
||||||
},
|
},
|
||||||
enableRequestLogger: true,
|
enableRequestLogger: true,
|
||||||
|
enableOAS: true,
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user