mirror of
https://github.com/BobbyWibowo/lolisafe.git
synced 2024-12-12 23:46:22 +00:00
feat: swagger-ui, work in progress
This commit is contained in:
parent
93dc820368
commit
d4e41e3586
@ -93,7 +93,7 @@ module.exports = {
|
||||
as any changes in said directory will be detected live.
|
||||
You may even add or remove pages while lolisafe is running.
|
||||
*/
|
||||
pages: ['home', 'auth', 'dashboard', 'faq'],
|
||||
pages: ['home', 'auth', 'dashboard', 'faq', 'apidocs'],
|
||||
|
||||
/*
|
||||
This will load public/libs/cookieconsent/cookieconsent.min.{css,js} on homepage (configured from home.js).
|
||||
|
@ -8,8 +8,8 @@ const utils = require('./utilsController')
|
||||
const ClientError = require('./utils/ClientError')
|
||||
const config = require('./../config')
|
||||
|
||||
// Don't forget to update min/max length of text inputs in auth.njk
|
||||
// when changing these values.
|
||||
// Don't forget to update min/max length of text inputs in views/auth.njk,
|
||||
// and OpenAPI spec in routes/api.js when changing these values.
|
||||
const self = {
|
||||
user: {
|
||||
min: 4,
|
||||
|
@ -48,7 +48,9 @@ self.higher = (user, target) => {
|
||||
self.mapPermissions = user => {
|
||||
const map = {}
|
||||
Object.keys(self.permissions).forEach(group => {
|
||||
map[group] = self.is(user, group)
|
||||
if (self.is(user, group)) {
|
||||
map[group] = self.is(user, group)
|
||||
}
|
||||
})
|
||||
return map
|
||||
}
|
||||
|
14
gulpfile.js
14
gulpfile.js
@ -140,9 +140,17 @@ gulp.task('build:js', () => {
|
||||
.pipe(gulp.dest(dist))
|
||||
})
|
||||
|
||||
gulp.task('build', gulp.parallel('build:sass', 'build:css', 'build:fontello', 'build:js'))
|
||||
gulp.task('build:openapi-spec', cb => {
|
||||
exec('node ./scripts/build-openapi-spec.js', (error, stdout, stderr) => {
|
||||
if (stdout) process.stdout.write(stdout)
|
||||
if (stderr) process.stderr.write(stderr)
|
||||
cb(error)
|
||||
})
|
||||
})
|
||||
|
||||
/** TASKS: VERSION STRINGS */
|
||||
gulp.task('build', gulp.parallel('build:sass', 'build:css', 'build:fontello', 'build:js', 'build:openapi-spec'))
|
||||
|
||||
/** TASKS: EXEC */
|
||||
|
||||
gulp.task('exec:bump-versions', cb => {
|
||||
exec('node ./scripts/bump-versions.js 1', (error, stdout, stderr) => {
|
||||
@ -192,6 +200,7 @@ gulp.task('nodemon', cb => {
|
||||
watch: [
|
||||
'controllers/',
|
||||
'routes/',
|
||||
'scripts/build-openapi-spec.js',
|
||||
'views/_globals.njk',
|
||||
'views/_layout.njk',
|
||||
'views/album.njk',
|
||||
@ -200,6 +209,7 @@ gulp.task('nodemon', cb => {
|
||||
'lolisafe.js'
|
||||
],
|
||||
ext: 'js',
|
||||
tasks: ['build:openapi-spec'],
|
||||
done: cb
|
||||
})
|
||||
})
|
||||
|
@ -86,7 +86,8 @@
|
||||
"postcss": "~8.4.16",
|
||||
"postcss-preset-env": "~7.8.1",
|
||||
"stylelint": "~14.11.0",
|
||||
"stylelint-config-standard-scss": "~5.0.0"
|
||||
"stylelint-config-standard-scss": "~5.0.0",
|
||||
"swagger-jsdoc": "~6.2.5"
|
||||
},
|
||||
"volta": {
|
||||
"node": "16.17.0",
|
||||
|
BIN
public/libs/swagger-ui/favicon-16x16.png
Normal file
BIN
public/libs/swagger-ui/favicon-16x16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 665 B |
BIN
public/libs/swagger-ui/favicon-32x32.png
Normal file
BIN
public/libs/swagger-ui/favicon-32x32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 628 B |
16
public/libs/swagger-ui/index.css
Normal file
16
public/libs/swagger-ui/index.css
Normal file
@ -0,0 +1,16 @@
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
overflow: -moz-scrollbars-vertical;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background: #fafafa;
|
||||
}
|
79
public/libs/swagger-ui/oauth2-redirect.html
Normal file
79
public/libs/swagger-ui/oauth2-redirect.html
Normal file
@ -0,0 +1,79 @@
|
||||
<!doctype html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<title>Swagger UI: OAuth2 Redirect</title>
|
||||
</head>
|
||||
<body>
|
||||
<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).replace('?', '&');
|
||||
} 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.schema.get("flow") === "authorization_code"
|
||||
) && !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. The 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();
|
||||
}
|
||||
|
||||
if (document.readyState !== 'loading') {
|
||||
run();
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
run();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
3
public/libs/swagger-ui/swagger-ui-bundle.js
Normal file
3
public/libs/swagger-ui/swagger-ui-bundle.js
Normal file
File diff suppressed because one or more lines are too long
1
public/libs/swagger-ui/swagger-ui-bundle.js.map
Normal file
1
public/libs/swagger-ui/swagger-ui-bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
1
public/libs/swagger-ui/swagger-ui-es-bundle-core.js.map
Normal file
1
public/libs/swagger-ui/swagger-ui-es-bundle-core.js.map
Normal file
File diff suppressed because one or more lines are too long
3
public/libs/swagger-ui/swagger-ui-es-bundle.js
Normal file
3
public/libs/swagger-ui/swagger-ui-es-bundle.js
Normal file
File diff suppressed because one or more lines are too long
1
public/libs/swagger-ui/swagger-ui-es-bundle.js.map
Normal file
1
public/libs/swagger-ui/swagger-ui-es-bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
3
public/libs/swagger-ui/swagger-ui-standalone-preset.js
Normal file
3
public/libs/swagger-ui/swagger-ui-standalone-preset.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
4
public/libs/swagger-ui/swagger-ui.css
Normal file
4
public/libs/swagger-ui/swagger-ui.css
Normal file
File diff suppressed because one or more lines are too long
1
public/libs/swagger-ui/swagger-ui.css.map
Normal file
1
public/libs/swagger-ui/swagger-ui.css.map
Normal file
File diff suppressed because one or more lines are too long
2
public/libs/swagger-ui/swagger-ui.js
Normal file
2
public/libs/swagger-ui/swagger-ui.js
Normal file
File diff suppressed because one or more lines are too long
1
public/libs/swagger-ui/swagger-ui.js.map
Normal file
1
public/libs/swagger-ui/swagger-ui.js.map
Normal file
File diff suppressed because one or more lines are too long
877
public/openapi.json
Normal file
877
public/openapi.json
Normal file
@ -0,0 +1,877 @@
|
||||
{
|
||||
"openapi": "3.0.0",
|
||||
"info": {
|
||||
"title": "lolisafe",
|
||||
"version": "3.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"/api/check": {
|
||||
"get": {
|
||||
"summary": "Get server's partial config",
|
||||
"description": "This only contains the necessary config to customize the homepage uploader's behavior.",
|
||||
"tags": [
|
||||
"General"
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"private",
|
||||
"enableUserAccounts",
|
||||
"maxSize",
|
||||
"chunkSize",
|
||||
"fileIdentifierLength",
|
||||
"stripTags"
|
||||
],
|
||||
"properties": {
|
||||
"private": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enableUserAccounts": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"maxSize": {
|
||||
"type": "string"
|
||||
},
|
||||
"chunkSize": {
|
||||
"type": "object"
|
||||
},
|
||||
"fileIdentifierLength": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"min": {
|
||||
"type": "number"
|
||||
},
|
||||
"max": {
|
||||
"type": "number"
|
||||
},
|
||||
"default": {
|
||||
"type": "number"
|
||||
},
|
||||
"force": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"stripTags": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
},
|
||||
"temporaryUploadAges": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"defaultTemporaryUploadAge": {
|
||||
"type": "number"
|
||||
},
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"$ref": "#/components/responses/ServerError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/login": {
|
||||
"post": {
|
||||
"summary": "Verify user credentials and get token",
|
||||
"tags": [
|
||||
"Auth"
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/UsernamePassword"
|
||||
},
|
||||
"example": {
|
||||
"username": "",
|
||||
"password": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/components/responses/AuthSuccessful"
|
||||
},
|
||||
"400": {
|
||||
"$ref": "#/components/responses/BadRequest"
|
||||
},
|
||||
"403": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
},
|
||||
"example": {
|
||||
"success": false,
|
||||
"description": "Wrong credentials."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"$ref": "#/components/responses/ServerError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/register": {
|
||||
"post": {
|
||||
"summary": "Register a user",
|
||||
"tags": [
|
||||
"Auth"
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/UsernamePassword"
|
||||
},
|
||||
"example": {
|
||||
"username": "",
|
||||
"password": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/components/responses/AuthSuccessful"
|
||||
},
|
||||
"400": {
|
||||
"$ref": "#/components/responses/BadRequest"
|
||||
},
|
||||
"403": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
},
|
||||
"example": {
|
||||
"success": false,
|
||||
"description": "Registration is currently disabled."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"$ref": "#/components/responses/ServerError"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/password/change": {
|
||||
"post": {
|
||||
"summary": "Change user's password",
|
||||
"tags": [
|
||||
"Auth"
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"password"
|
||||
],
|
||||
"properties": {
|
||||
"password": {
|
||||
"$ref": "#/components/schemas/Password"
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"password": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/components/responses/Success"
|
||||
},
|
||||
"400": {
|
||||
"$ref": "#/components/responses/BadRequest"
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
},
|
||||
"500": {
|
||||
"$ref": "#/components/responses/ServerError"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"token": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/users": {
|
||||
"get": {
|
||||
"summary": "Get users at page 1",
|
||||
"description": "Requires admin permission.",
|
||||
"tags": [
|
||||
"Users",
|
||||
"Administration"
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/components/responses/UsersResponse"
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
},
|
||||
"500": {
|
||||
"$ref": "#/components/responses/ServerError"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"token": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/users/{page}": {
|
||||
"get": {
|
||||
"summary": "Get users at page N",
|
||||
"description": "Requires admin permission. This allows negative value to navigate backwards.",
|
||||
"tags": [
|
||||
"Users",
|
||||
"Administration"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "page",
|
||||
"schema": {
|
||||
"type": "number"
|
||||
},
|
||||
"required": true,
|
||||
"description": "Page of users to get."
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/components/responses/UsersResponse"
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
},
|
||||
"500": {
|
||||
"$ref": "#/components/responses/ServerError"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"token": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/users/create": {
|
||||
"post": {
|
||||
"summary": "Create a new user",
|
||||
"description": "Requires admin permission. If password is omitted, server will generate a random one.",
|
||||
"tags": [
|
||||
"Users",
|
||||
"Administration"
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"username",
|
||||
"group"
|
||||
],
|
||||
"properties": {
|
||||
"username": {
|
||||
"$ref": "#/components/schemas/Username"
|
||||
},
|
||||
"password": {
|
||||
"$ref": "#/components/schemas/Password"
|
||||
},
|
||||
"group": {
|
||||
"$ref": "#/components/schemas/Usergroup"
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"username": "",
|
||||
"password": "",
|
||||
"group": "user"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"success",
|
||||
"username",
|
||||
"password",
|
||||
"group"
|
||||
],
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"username": {
|
||||
"$ref": "#/components/schemas/Username"
|
||||
},
|
||||
"password": {
|
||||
"$ref": "#/components/schemas/Password"
|
||||
},
|
||||
"group": {
|
||||
"$ref": "#/components/schemas/Usergroup"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
},
|
||||
"500": {
|
||||
"$ref": "#/components/responses/ServerError"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"token": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/users/delete": {
|
||||
"post": {
|
||||
"summary": "Delete a user",
|
||||
"description": "Requires admin permission.",
|
||||
"tags": [
|
||||
"Users",
|
||||
"Administration"
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/components/schemas/UserID"
|
||||
},
|
||||
"purge": {
|
||||
"description": "Whether to purge the user's uploaded files as well.",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"id": 69420,
|
||||
"purge": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/components/responses/Success"
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
},
|
||||
"500": {
|
||||
"$ref": "#/components/responses/ServerError"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"token": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/users/disable": {
|
||||
"post": {
|
||||
"summary": "Disable a user",
|
||||
"description": "Requires admin permission.",
|
||||
"tags": [
|
||||
"Users",
|
||||
"Administration"
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/components/schemas/UserID"
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"id": 69420
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"success",
|
||||
"update"
|
||||
],
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"update": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"enabled"
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Whether user is enabled or not.",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"success": true,
|
||||
"update": {
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
},
|
||||
"500": {
|
||||
"$ref": "#/components/responses/ServerError"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"token": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/users/edit": {
|
||||
"post": {
|
||||
"summary": "Edit a user",
|
||||
"description": "Requires admin permission.",
|
||||
"tags": [
|
||||
"Users",
|
||||
"Administration"
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/components/schemas/UserID"
|
||||
},
|
||||
"username": {
|
||||
"$ref": "#/components/schemas/Username"
|
||||
},
|
||||
"group": {
|
||||
"$ref": "#/components/schemas/Usergroup"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Whether to enable or disable user.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"resetPassword": {
|
||||
"description": "Whether to reset user's password with a randomly generated one.",
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"id": 69420,
|
||||
"username": "",
|
||||
"group": "user",
|
||||
"enabled": true,
|
||||
"resetPassword": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"success",
|
||||
"update"
|
||||
],
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"update": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"username": {
|
||||
"$ref": "#/components/schemas/Username"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Whether user is enabled or not.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"permission": {
|
||||
"description": "Numeric permission according to selected usergroup.",
|
||||
"type": "number"
|
||||
},
|
||||
"password": {
|
||||
"$ref": "#/components/schemas/Password"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/components/responses/Unauthorized"
|
||||
},
|
||||
"500": {
|
||||
"$ref": "#/components/responses/ServerError"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"token": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"Username": {
|
||||
"type": "string",
|
||||
"minLength": 4,
|
||||
"maxLength": 32
|
||||
},
|
||||
"Password": {
|
||||
"type": "string",
|
||||
"format": "password",
|
||||
"minLength": 6,
|
||||
"maxLength": 64
|
||||
},
|
||||
"Result": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"success"
|
||||
],
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Error": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"success",
|
||||
"description"
|
||||
],
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"code": {
|
||||
"description": "Helper error code. Currently very sparsely used.",
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
},
|
||||
"UsernamePassword": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"username",
|
||||
"password"
|
||||
],
|
||||
"properties": {
|
||||
"username": {
|
||||
"$ref": "#/components/schemas/Username"
|
||||
},
|
||||
"password": {
|
||||
"$ref": "#/components/schemas/Password"
|
||||
}
|
||||
}
|
||||
},
|
||||
"UserID": {
|
||||
"description": "User's numerical ID in database.",
|
||||
"type": "number"
|
||||
},
|
||||
"User": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"id",
|
||||
"username",
|
||||
"enabled",
|
||||
"timestamp",
|
||||
"registration",
|
||||
"groups",
|
||||
"uploads",
|
||||
"usage"
|
||||
],
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/components/schemas/UserID"
|
||||
},
|
||||
"username": {
|
||||
"$ref": "#/components/schemas/Username"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "Whether user is enabled or not.",
|
||||
"type": "boolean",
|
||||
"nullable": true
|
||||
},
|
||||
"timestamp": {
|
||||
"description": "Timestamp of user's last token update.",
|
||||
"type": "number",
|
||||
"nullable": true
|
||||
},
|
||||
"registration": {
|
||||
"description": "Timestamp of user's registration date.",
|
||||
"type": "number",
|
||||
"nullable": true
|
||||
},
|
||||
"groups": {
|
||||
"description": "Usergroup(s) information.",
|
||||
"type": "object"
|
||||
},
|
||||
"uploads": {
|
||||
"description": "Amount of uploads associated to this user.",
|
||||
"type": "number"
|
||||
},
|
||||
"usage": {
|
||||
"description": "Amount of disk used by this user in bytes.",
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Usergroup": {
|
||||
"description": "Usergroup name.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"Success": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Result"
|
||||
},
|
||||
"example": {
|
||||
"success": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"BadRequest": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
},
|
||||
"example": {
|
||||
"success": false,
|
||||
"description": "Bad request."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Unauthorized": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
},
|
||||
"example": {
|
||||
"success": false,
|
||||
"description": "Invalid token.",
|
||||
"code": 10001
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ServerError": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Error"
|
||||
},
|
||||
"example": {
|
||||
"success": false,
|
||||
"description": "An unexpected error occurred. Try again?"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"AuthSuccessful": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"success",
|
||||
"token"
|
||||
],
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"token": {
|
||||
"description": "Token that can be used for user authentication in other API routes.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"success": true,
|
||||
"token": "YOUR_TOKEN_HERE"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"UsersResponse": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"success",
|
||||
"users",
|
||||
"usersPerPage",
|
||||
"count"
|
||||
],
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"users": {
|
||||
"description": "Array of users.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/User"
|
||||
}
|
||||
},
|
||||
"usersPerPage": {
|
||||
"description": "Users per page for pagination.",
|
||||
"type": "number"
|
||||
},
|
||||
"count": {
|
||||
"description": "Total users in database.",
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securitySchemes": {
|
||||
"token": {
|
||||
"type": "apiKey",
|
||||
"name": "token",
|
||||
"in": "header"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "General",
|
||||
"description": "General routes"
|
||||
},
|
||||
{
|
||||
"name": "Uploads",
|
||||
"description": "Uploads routes"
|
||||
},
|
||||
{
|
||||
"name": "Auth",
|
||||
"description": "Auth routes"
|
||||
},
|
||||
{
|
||||
"name": "Users",
|
||||
"description": "Users routes"
|
||||
},
|
||||
{
|
||||
"name": "Album",
|
||||
"description": "Albums routes"
|
||||
},
|
||||
{
|
||||
"name": "Moderation",
|
||||
"description": "Moderation routes"
|
||||
},
|
||||
{
|
||||
"name": "Administration",
|
||||
"description": "Administration routes"
|
||||
}
|
||||
]
|
||||
}
|
612
routes/api.js
612
routes/api.js
@ -7,6 +7,150 @@ const upload = require('./../controllers/uploadController')
|
||||
const utils = require('./../controllers/utilsController')
|
||||
const config = require('./../config')
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* components:
|
||||
* schemas:
|
||||
* Username:
|
||||
* type: string
|
||||
* minLength: 4
|
||||
* maxLength: 32
|
||||
* Password:
|
||||
* type: string
|
||||
* format: password
|
||||
* minLength: 6
|
||||
* maxLength: 64
|
||||
* Result:
|
||||
* type: object
|
||||
* required:
|
||||
* - success
|
||||
* properties:
|
||||
* success:
|
||||
* type: boolean
|
||||
* Error:
|
||||
* type: object
|
||||
* required:
|
||||
* - success
|
||||
* - description
|
||||
* properties:
|
||||
* success:
|
||||
* type: boolean
|
||||
* description:
|
||||
* type: string
|
||||
* code:
|
||||
* description: Helper error code. Currently very sparsely used.
|
||||
* type: number
|
||||
* responses:
|
||||
* Success:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: "#/components/schemas/Result"
|
||||
* example:
|
||||
* success: true
|
||||
* BadRequest:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: "#/components/schemas/Error"
|
||||
* example:
|
||||
* success: false
|
||||
* description: Bad request.
|
||||
* Unauthorized:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: "#/components/schemas/Error"
|
||||
* example:
|
||||
* success: false
|
||||
* description: Invalid token.
|
||||
* code: 10001
|
||||
* ServerError:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: "#/components/schemas/Error"
|
||||
* example:
|
||||
* success: false
|
||||
* description: An unexpected error occurred. Try again?
|
||||
* securitySchemes:
|
||||
* token:
|
||||
* type: apiKey
|
||||
* name: token
|
||||
* in: header
|
||||
* tags:
|
||||
* - name: General
|
||||
* description: General routes
|
||||
* - name: Uploads
|
||||
* description: Uploads routes
|
||||
* - name: Auth
|
||||
* description: Auth routes
|
||||
* - name: Users
|
||||
* description: Users routes
|
||||
* - name: Album
|
||||
* description: Albums routes
|
||||
* - name: Moderation
|
||||
* description: Moderation routes
|
||||
* - name: Administration
|
||||
* description: Administration routes
|
||||
*/
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /api/check:
|
||||
* get:
|
||||
* summary: Get server's partial config
|
||||
* description: This only contains the necessary config to customize the homepage uploader's behavior.
|
||||
* tags:
|
||||
* - General
|
||||
* responses:
|
||||
* 200:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - private
|
||||
* - enableUserAccounts
|
||||
* - maxSize
|
||||
* - chunkSize
|
||||
* - fileIdentifierLength
|
||||
* - stripTags
|
||||
* properties:
|
||||
* private:
|
||||
* type: boolean
|
||||
* enableUserAccounts:
|
||||
* type: boolean
|
||||
* maxSize:
|
||||
* type: string
|
||||
* chunkSize:
|
||||
* type: object
|
||||
* fileIdentifierLength:
|
||||
* type: object
|
||||
* properties:
|
||||
* min:
|
||||
* type: number
|
||||
* max:
|
||||
* type: number
|
||||
* default:
|
||||
* type: number
|
||||
* force:
|
||||
* type: boolean
|
||||
* stripTags:
|
||||
* oneOf:
|
||||
* - type: object
|
||||
* - type: boolean
|
||||
* temporaryUploadAges:
|
||||
* type: array
|
||||
* items:
|
||||
* type: number
|
||||
* defaultTemporaryUploadAge:
|
||||
* type: number
|
||||
* version:
|
||||
* type: string
|
||||
* 500:
|
||||
* $ref: "#/components/responses/ServerError"
|
||||
*/
|
||||
routes.get('/check', async (req, res) => {
|
||||
const obj = {
|
||||
private: config.private,
|
||||
@ -23,22 +167,488 @@ routes.get('/check', async (req, res) => {
|
||||
if (utils.clientVersion) {
|
||||
obj.version = utils.clientVersion
|
||||
}
|
||||
|
||||
return res.json(obj)
|
||||
})
|
||||
|
||||
/** ./controllers/authController.js */
|
||||
/**
|
||||
* @openapi
|
||||
* components:
|
||||
* schemas:
|
||||
* UsernamePassword:
|
||||
* type: object
|
||||
* required:
|
||||
* - username
|
||||
* - password
|
||||
* properties:
|
||||
* username:
|
||||
* $ref: "#/components/schemas/Username"
|
||||
* password:
|
||||
* $ref: "#/components/schemas/Password"
|
||||
* responses:
|
||||
* AuthSuccessful:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - success
|
||||
* - token
|
||||
* properties:
|
||||
* success:
|
||||
* type: boolean
|
||||
* token:
|
||||
* description: Token that can be used for user authentication in other API routes.
|
||||
* type: string
|
||||
* example:
|
||||
* success: true
|
||||
* token: YOUR_TOKEN_HERE
|
||||
*/
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /api/login:
|
||||
* post:
|
||||
* summary: Verify user credentials and get token
|
||||
* tags:
|
||||
* - Auth
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: "#/components/schemas/UsernamePassword"
|
||||
* example:
|
||||
* username: ""
|
||||
* password: ""
|
||||
* responses:
|
||||
* 200:
|
||||
* $ref: "#/components/responses/AuthSuccessful"
|
||||
* 400:
|
||||
* $ref: "#/components/responses/BadRequest"
|
||||
* 403:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: "#/components/schemas/Error"
|
||||
* example:
|
||||
* success: false
|
||||
* description: Wrong credentials.
|
||||
* 500:
|
||||
* $ref: "#/components/responses/ServerError"
|
||||
*/
|
||||
routes.post('/login', utils.assertJSON, auth.verify)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /api/register:
|
||||
* post:
|
||||
* summary: Register a user
|
||||
* tags:
|
||||
* - Auth
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: "#/components/schemas/UsernamePassword"
|
||||
* example:
|
||||
* username: ""
|
||||
* password: ""
|
||||
* responses:
|
||||
* 200:
|
||||
* $ref: "#/components/responses/AuthSuccessful"
|
||||
* 400:
|
||||
* $ref: "#/components/responses/BadRequest"
|
||||
* 403:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: "#/components/schemas/Error"
|
||||
* example:
|
||||
* success: false
|
||||
* description: Registration is currently disabled.
|
||||
* 500:
|
||||
* $ref: "#/components/responses/ServerError"
|
||||
*/
|
||||
routes.post('/register', utils.assertJSON, auth.register)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /api/password/change:
|
||||
* post:
|
||||
* summary: Change user's password
|
||||
* tags:
|
||||
* - Auth
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - password
|
||||
* properties:
|
||||
* password:
|
||||
* $ref: "#/components/schemas/Password"
|
||||
* example:
|
||||
* password: ""
|
||||
* responses:
|
||||
* 200:
|
||||
* $ref: "#/components/responses/Success"
|
||||
* 400:
|
||||
* $ref: "#/components/responses/BadRequest"
|
||||
* 403:
|
||||
* $ref: "#/components/responses/Unauthorized"
|
||||
* 500:
|
||||
* $ref: "#/components/responses/ServerError"
|
||||
* security:
|
||||
* - token: []
|
||||
*/
|
||||
routes.post('/password/change', [auth.requireUser, utils.assertJSON], auth.changePassword)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* components:
|
||||
* schemas:
|
||||
* UserID:
|
||||
* description: User's numerical ID in database.
|
||||
* type: number
|
||||
* User:
|
||||
* type: object
|
||||
* required:
|
||||
* - id
|
||||
* - username
|
||||
* - enabled
|
||||
* - timestamp
|
||||
* - registration
|
||||
* - groups
|
||||
* - uploads
|
||||
* - usage
|
||||
* properties:
|
||||
* id:
|
||||
* $ref: "#/components/schemas/UserID"
|
||||
* username:
|
||||
* $ref: "#/components/schemas/Username"
|
||||
* enabled:
|
||||
* description: Whether user is enabled or not.
|
||||
* type: boolean
|
||||
* nullable: true
|
||||
* timestamp:
|
||||
* description: Timestamp of user's last token update.
|
||||
* type: number
|
||||
* nullable: true
|
||||
* registration:
|
||||
* description: Timestamp of user's registration date.
|
||||
* type: number
|
||||
* nullable: true
|
||||
* groups:
|
||||
* description: Usergroup(s) information.
|
||||
* type: object
|
||||
* uploads:
|
||||
* description: Amount of uploads associated to this user.
|
||||
* type: number
|
||||
* usage:
|
||||
* description: Amount of disk used by this user in bytes.
|
||||
* type: number
|
||||
* Usergroup:
|
||||
* description: Usergroup name.
|
||||
* type: string
|
||||
* responses:
|
||||
* UsersResponse:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - success
|
||||
* - users
|
||||
* - usersPerPage
|
||||
* - count
|
||||
* properties:
|
||||
* success:
|
||||
* type: boolean
|
||||
* users:
|
||||
* description: Array of users.
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: "#/components/schemas/User"
|
||||
* usersPerPage:
|
||||
* description: Users per page for pagination.
|
||||
* type: number
|
||||
* count:
|
||||
* description: Total users in database.
|
||||
* type: number
|
||||
*/
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /api/users:
|
||||
* get:
|
||||
* summary: Get users at page 1
|
||||
* description: Requires admin permission.
|
||||
* tags:
|
||||
* - Users
|
||||
* - Administration
|
||||
* responses:
|
||||
* 200:
|
||||
* $ref: "#/components/responses/UsersResponse"
|
||||
* 403:
|
||||
* $ref: "#/components/responses/Unauthorized"
|
||||
* 500:
|
||||
* $ref: "#/components/responses/ServerError"
|
||||
* security:
|
||||
* - token: []
|
||||
*/
|
||||
routes.get('/users', auth.requireUser, auth.listUsers)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /api/users/{page}:
|
||||
* get:
|
||||
* summary: Get users at page N
|
||||
* description: Requires admin permission. This allows negative value to navigate backwards.
|
||||
* tags:
|
||||
* - Users
|
||||
* - Administration
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: page
|
||||
* schema:
|
||||
* type: number
|
||||
* required: true
|
||||
* description: Page of users to get.
|
||||
* responses:
|
||||
* 200:
|
||||
* $ref: "#/components/responses/UsersResponse"
|
||||
* 403:
|
||||
* $ref: "#/components/responses/Unauthorized"
|
||||
* 500:
|
||||
* $ref: "#/components/responses/ServerError"
|
||||
* security:
|
||||
* - token: []
|
||||
*/
|
||||
routes.get('/users/:page', auth.requireUser, auth.listUsers)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /api/users/create:
|
||||
* post:
|
||||
* summary: Create a new user
|
||||
* description: Requires admin permission. If password is omitted, server will generate a random one.
|
||||
* tags:
|
||||
* - Users
|
||||
* - Administration
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - username
|
||||
* - group
|
||||
* properties:
|
||||
* username:
|
||||
* $ref: "#/components/schemas/Username"
|
||||
* password:
|
||||
* $ref: "#/components/schemas/Password"
|
||||
* group:
|
||||
* $ref: "#/components/schemas/Usergroup"
|
||||
* example:
|
||||
* username: ""
|
||||
* password: ""
|
||||
* group: user
|
||||
* responses:
|
||||
* 200:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - success
|
||||
* - username
|
||||
* - password
|
||||
* - group
|
||||
* properties:
|
||||
* success:
|
||||
* type: boolean
|
||||
* username:
|
||||
* $ref: "#/components/schemas/Username"
|
||||
* password:
|
||||
* $ref: "#/components/schemas/Password"
|
||||
* group:
|
||||
* $ref: "#/components/schemas/Usergroup"
|
||||
* 403:
|
||||
* $ref: "#/components/responses/Unauthorized"
|
||||
* 500:
|
||||
* $ref: "#/components/responses/ServerError"
|
||||
* security:
|
||||
* - token: []
|
||||
*/
|
||||
routes.post('/users/create', [auth.requireUser, utils.assertJSON], auth.createUser)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /api/users/delete:
|
||||
* post:
|
||||
* summary: Delete a user
|
||||
* description: Requires admin permission.
|
||||
* tags:
|
||||
* - Users
|
||||
* - Administration
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - id
|
||||
* properties:
|
||||
* id:
|
||||
* $ref: "#/components/schemas/UserID"
|
||||
* purge:
|
||||
* description: Whether to purge the user's uploaded files as well.
|
||||
* type: boolean
|
||||
* example:
|
||||
* id: 69420
|
||||
* purge: false
|
||||
* responses:
|
||||
* 200:
|
||||
* $ref: "#/components/responses/Success"
|
||||
* 403:
|
||||
* $ref: "#/components/responses/Unauthorized"
|
||||
* 500:
|
||||
* $ref: "#/components/responses/ServerError"
|
||||
* security:
|
||||
* - token: []
|
||||
*/
|
||||
routes.post('/users/delete', [auth.requireUser, utils.assertJSON], auth.deleteUser)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /api/users/disable:
|
||||
* post:
|
||||
* summary: Disable a user
|
||||
* description: Requires admin permission.
|
||||
* tags:
|
||||
* - Users
|
||||
* - Administration
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - id
|
||||
* properties:
|
||||
* id:
|
||||
* $ref: "#/components/schemas/UserID"
|
||||
* example:
|
||||
* id: 69420
|
||||
* responses:
|
||||
* 200:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - success
|
||||
* - update
|
||||
* properties:
|
||||
* success:
|
||||
* type: boolean
|
||||
* update:
|
||||
* type: object
|
||||
* required:
|
||||
* - enabled
|
||||
* properties:
|
||||
* enabled:
|
||||
* description: Whether user is enabled or not.
|
||||
* type: boolean
|
||||
* example:
|
||||
* success: true
|
||||
* update:
|
||||
* enabled: false
|
||||
* 403:
|
||||
* $ref: "#/components/responses/Unauthorized"
|
||||
* 500:
|
||||
* $ref: "#/components/responses/ServerError"
|
||||
* security:
|
||||
* - token: []
|
||||
*/
|
||||
routes.post('/users/disable', [auth.requireUser, utils.assertJSON], auth.disableUser)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /api/users/edit:
|
||||
* post:
|
||||
* summary: Edit a user
|
||||
* description: Requires admin permission.
|
||||
* tags:
|
||||
* - Users
|
||||
* - Administration
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - id
|
||||
* properties:
|
||||
* id:
|
||||
* $ref: "#/components/schemas/UserID"
|
||||
* username:
|
||||
* $ref: "#/components/schemas/Username"
|
||||
* group:
|
||||
* $ref: "#/components/schemas/Usergroup"
|
||||
* enabled:
|
||||
* description: Whether to enable or disable user.
|
||||
* type: boolean
|
||||
* resetPassword:
|
||||
* description: Whether to reset user's password with a randomly generated one.
|
||||
* type: boolean
|
||||
* example:
|
||||
* id: 69420
|
||||
* username: ""
|
||||
* group: user
|
||||
* enabled: true
|
||||
* resetPassword: false
|
||||
* responses:
|
||||
* 200:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - success
|
||||
* - update
|
||||
* properties:
|
||||
* success:
|
||||
* type: boolean
|
||||
* update:
|
||||
* type: object
|
||||
* properties:
|
||||
* username:
|
||||
* $ref: "#/components/schemas/Username"
|
||||
* enabled:
|
||||
* description: Whether user is enabled or not.
|
||||
* type: boolean
|
||||
* permission:
|
||||
* description: Numeric permission according to selected usergroup.
|
||||
* type: number
|
||||
* password:
|
||||
* $ref: "#/components/schemas/Password"
|
||||
* 403:
|
||||
* $ref: "#/components/responses/Unauthorized"
|
||||
* 500:
|
||||
* $ref: "#/components/responses/ServerError"
|
||||
* security:
|
||||
* - token: []
|
||||
*/
|
||||
routes.post('/users/edit', [auth.requireUser, utils.assertJSON], auth.editUser)
|
||||
|
||||
/** ./controllers/uploadController.js */
|
||||
|
54
scripts/build-openapi-spec.js
Normal file
54
scripts/build-openapi-spec.js
Normal file
@ -0,0 +1,54 @@
|
||||
const { promisify } = require('util')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const swaggerJsdoc = require('swagger-jsdoc')
|
||||
|
||||
const self = {
|
||||
dest: './public/openapi.json',
|
||||
options: {
|
||||
failOnErrors: true,
|
||||
definition: {
|
||||
openapi: '3.0.0',
|
||||
info: {
|
||||
title: 'lolisafe',
|
||||
version: '3.0.0'
|
||||
}
|
||||
},
|
||||
apis: ['./routes/*.js']
|
||||
},
|
||||
// This is a parallel of utilsController.js->stripIndents().
|
||||
// Added here so that this script won't have to import the said controller.
|
||||
stripIndents: string => {
|
||||
if (!string) return
|
||||
const result = string.replace(/^[^\S\n]+/gm, '')
|
||||
const match = result.match(/^[^\S\n]*(?=\S)/gm)
|
||||
const indent = match && Math.min(...match.map(el => el.length))
|
||||
if (indent) {
|
||||
const regexp = new RegExp(`^.{${indent}}`, 'gm')
|
||||
return result.replace(regexp, '')
|
||||
}
|
||||
return result
|
||||
},
|
||||
access: promisify(fs.access),
|
||||
writeFile: promisify(fs.writeFile)
|
||||
}
|
||||
|
||||
;(async () => {
|
||||
const openapiSpecification = swaggerJsdoc(self.options)
|
||||
|
||||
// logger.inspect(openapiSpecification)
|
||||
|
||||
const file = path.resolve(self.dest)
|
||||
|
||||
// Stringify OpenAPI specification
|
||||
const stringified = JSON.stringify(openapiSpecification, null, 2) + '\n'
|
||||
|
||||
// Write to file
|
||||
await self.writeFile(file, stringified)
|
||||
// console.log(`Successfully written OpenAPI specification to ${self.dest}.`)
|
||||
})()
|
||||
.then(() => process.exit(0))
|
||||
.catch(error => {
|
||||
console.error(error)
|
||||
process.exit(1)
|
||||
})
|
1266
src/css/apidocs.scss
Normal file
1266
src/css/apidocs.scss
Normal file
File diff suppressed because it is too large
Load Diff
25
src/js/apidocs.js
Normal file
25
src/js/apidocs.js
Normal file
@ -0,0 +1,25 @@
|
||||
/* global SwaggerUIBundle, SwaggerUIStandalonePreset */
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const mainScript = document.querySelector('#mainScript')
|
||||
const name = mainScript && mainScript.dataset.name
|
||||
? mainScript.dataset.name
|
||||
: 'lolisafe'
|
||||
|
||||
window.ui = SwaggerUIBundle({
|
||||
urls: [
|
||||
// Expects openapi.json to be publicly accessible via GET /openapi.json route
|
||||
{ url: 'openapi.json', name }
|
||||
],
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
plugins: [
|
||||
SwaggerUIBundle.plugins.DownloadUrl
|
||||
],
|
||||
layout: 'StandaloneLayout'
|
||||
})
|
||||
})
|
46
views/apidocs.njk
Normal file
46
views/apidocs.njk
Normal file
@ -0,0 +1,46 @@
|
||||
{%- import '_globals.njk' as globals with context -%}
|
||||
|
||||
{# Set root domain here to inherit values from config file #}
|
||||
{%- set root = utils.conf.homeDomain or utils.conf.domain -%}
|
||||
|
||||
{% set metaTitle = "API Docs" %}
|
||||
{% set metaUrl = '/api-docs' %}
|
||||
|
||||
{%- set title -%}
|
||||
{%- if metaTitle -%}
|
||||
{{ metaTitle + ' | ' + globals.name }}
|
||||
{%- else -%}
|
||||
{{ globals.name + ' – ' + globals.motto }}
|
||||
{%- endif %}
|
||||
{%- endset -%}
|
||||
|
||||
{%- set url = root + (metaUrl or '') -%}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>{{ title }}</title>
|
||||
|
||||
<!-- Stylesheets -->
|
||||
<link rel="stylesheet" type="text/css" href="libs/swagger-ui/swagger-ui.css{{ versions[3] }}">
|
||||
<link rel="stylesheet" type="text/css" href="libs/swagger-ui/index.css{{ versions[3] }}">
|
||||
<link rel="stylesheet" type="text/css" href="css/apidocs.css{{ versions[1] }}">
|
||||
|
||||
<!-- Icons, configs, etcetera -->
|
||||
<link rel="icon" type="image/png" href="{{ root }}/libs/swagger-ui/favicon-32x32.png{{ versions[2] }}" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="{{ root }}/libs/swagger-ui/favicon-16x16.png{{ versions[2] }}" sizes="16x16">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Swagger UI container -->
|
||||
<div id="swagger-ui"></div>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="libs/swagger-ui/swagger-ui-bundle.js{{ versions[3] }}" charset="utf-8"></script>
|
||||
<script src="libs/swagger-ui/swagger-ui-standalone-preset.js{{ versions[3] }}" charset="utf-8"></script>
|
||||
{# We assign an ID for this so that the script can find out its own data tags #}
|
||||
<script id="mainScript" src="js/apidocs.js{{ versions[1] }}" data-name="{{ name }}" charset="utf-8"></script>
|
||||
</body>
|
||||
</html>
|
132
yarn.lock
132
yarn.lock
@ -2,6 +2,38 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@apidevtools/json-schema-ref-parser@^9.0.6":
|
||||
version "9.0.9"
|
||||
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b"
|
||||
integrity sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==
|
||||
dependencies:
|
||||
"@jsdevtools/ono" "^7.1.3"
|
||||
"@types/json-schema" "^7.0.6"
|
||||
call-me-maybe "^1.0.1"
|
||||
js-yaml "^4.1.0"
|
||||
|
||||
"@apidevtools/openapi-schemas@^2.0.4":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz#9fa08017fb59d80538812f03fc7cac5992caaa17"
|
||||
integrity sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==
|
||||
|
||||
"@apidevtools/swagger-methods@^3.0.2":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz#b789a362e055b0340d04712eafe7027ddc1ac267"
|
||||
integrity sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==
|
||||
|
||||
"@apidevtools/swagger-parser@10.0.2":
|
||||
version "10.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@apidevtools/swagger-parser/-/swagger-parser-10.0.2.tgz#f4145afb7c3a3bafe0376f003b5c3bdeae17a952"
|
||||
integrity sha512-JFxcEyp8RlNHgBCE98nwuTkZT6eNFPc1aosWV6wPcQph72TSEEu1k3baJD4/x1qznU+JiDdz8F5pTwabZh+Dhg==
|
||||
dependencies:
|
||||
"@apidevtools/json-schema-ref-parser" "^9.0.6"
|
||||
"@apidevtools/openapi-schemas" "^2.0.4"
|
||||
"@apidevtools/swagger-methods" "^3.0.2"
|
||||
"@jsdevtools/ono" "^7.1.3"
|
||||
call-me-maybe "^1.0.1"
|
||||
z-schema "^4.2.3"
|
||||
|
||||
"@babel/code-frame@^7.0.0":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a"
|
||||
@ -251,6 +283,11 @@
|
||||
"@jridgewell/resolve-uri" "^3.0.3"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@jsdevtools/ono@^7.1.3":
|
||||
version "7.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796"
|
||||
integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==
|
||||
|
||||
"@mapbox/node-pre-gyp@^1.0.0":
|
||||
version "1.0.9"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz#09a8781a3a036151cdebbe8719d6f8b25d4058bc"
|
||||
@ -372,7 +409,7 @@
|
||||
"@types/qs" "*"
|
||||
"@types/serve-static" "*"
|
||||
|
||||
"@types/json-schema@*":
|
||||
"@types/json-schema@*", "@types/json-schema@^7.0.6":
|
||||
version "7.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
|
||||
integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
|
||||
@ -1068,6 +1105,11 @@ call-bind@^1.0.0, call-bind@^1.0.2:
|
||||
function-bind "^1.1.1"
|
||||
get-intrinsic "^1.0.2"
|
||||
|
||||
call-me-maybe@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
|
||||
integrity sha512-wCyFsDQkKPwwF8BDwOiWNx/9K45L/hvggQiDbve+viMNMQnWhrlYIuBk09offfwCRtCO9P6XwUttufzU11WCVw==
|
||||
|
||||
callsites@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||
@ -1308,7 +1350,12 @@ colors@^1.2.1:
|
||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
|
||||
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
|
||||
|
||||
commander@^2.20.0:
|
||||
commander@6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.0.tgz#b990bfb8ac030aedc6d11bc04d1488ffef56db75"
|
||||
integrity sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==
|
||||
|
||||
commander@^2.20.0, commander@^2.7.1:
|
||||
version "2.20.3"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||
@ -1704,6 +1751,13 @@ dir-glob@^3.0.1:
|
||||
dependencies:
|
||||
path-type "^4.0.0"
|
||||
|
||||
doctrine@3.0.0, doctrine@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
|
||||
integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
|
||||
doctrine@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
|
||||
@ -1711,13 +1765,6 @@ doctrine@^2.1.0:
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
|
||||
doctrine@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
|
||||
integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
|
||||
dom-serializer@^1.0.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30"
|
||||
@ -2643,6 +2690,18 @@ glob-watcher@^5.0.3:
|
||||
normalize-path "^3.0.0"
|
||||
object.defaults "^1.1.0"
|
||||
|
||||
glob@7.1.6:
|
||||
version "7.1.6"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
||||
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.1.1, glob@^7.1.3:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
|
||||
@ -3669,6 +3728,16 @@ lodash.clonedeep@^4.3.2:
|
||||
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
|
||||
integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==
|
||||
|
||||
lodash.get@^4.4.2:
|
||||
version "4.4.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
|
||||
integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==
|
||||
|
||||
lodash.isequal@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
|
||||
|
||||
lodash.memoize@4.1.2, lodash.memoize@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
||||
@ -3679,6 +3748,11 @@ lodash.merge@^4.6.2:
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||
|
||||
lodash.mergewith@^4.6.2:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55"
|
||||
integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==
|
||||
|
||||
lodash.truncate@^4.4.2:
|
||||
version "4.4.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
||||
@ -5941,6 +6015,25 @@ svgo@^2.7.0:
|
||||
picocolors "^1.0.0"
|
||||
stable "^0.1.8"
|
||||
|
||||
swagger-jsdoc@~6.2.5:
|
||||
version "6.2.5"
|
||||
resolved "https://registry.yarnpkg.com/swagger-jsdoc/-/swagger-jsdoc-6.2.5.tgz#65bffa142276436b2b131255f59a6b55384a0e8e"
|
||||
integrity sha512-l+cdsKS2y+QDhrH1TJSUiE0y9XKuf5xaGSatjf0hR/wjTlMpO8WfubBK9d/nASdbHPMtj9iJZLBH2ogBEhL7Sw==
|
||||
dependencies:
|
||||
commander "6.2.0"
|
||||
doctrine "3.0.0"
|
||||
glob "7.1.6"
|
||||
lodash.mergewith "^4.6.2"
|
||||
swagger-parser "10.0.2"
|
||||
yaml "2.0.0-1"
|
||||
|
||||
swagger-parser@10.0.2:
|
||||
version "10.0.2"
|
||||
resolved "https://registry.yarnpkg.com/swagger-parser/-/swagger-parser-10.0.2.tgz#d7f18faa09c9c145e938977c9bd6c3435998b667"
|
||||
integrity sha512-9jHkHM+QXyLGFLk1DkXBwV+4HyNm0Za3b8/zk/+mjr8jgOSiqm3FOTHBSDsBjtn9scdL+8eWcHdupp2NLM8tDw==
|
||||
dependencies:
|
||||
"@apidevtools/swagger-parser" "10.0.2"
|
||||
|
||||
systeminformation@~5.12.6:
|
||||
version "5.12.6"
|
||||
resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.12.6.tgz#b75d7aaf9f5da32439fc633d2be9eb741691d200"
|
||||
@ -6336,6 +6429,11 @@ validate-npm-package-license@^3.0.1:
|
||||
spdx-correct "^3.0.0"
|
||||
spdx-expression-parse "^3.0.0"
|
||||
|
||||
validator@^13.6.0:
|
||||
version "13.7.0"
|
||||
resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857"
|
||||
integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==
|
||||
|
||||
value-or-function@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813"
|
||||
@ -6492,6 +6590,11 @@ yallist@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yaml@2.0.0-1:
|
||||
version "2.0.0-1"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.0.0-1.tgz#8c3029b3ee2028306d5bcf396980623115ff8d18"
|
||||
integrity sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==
|
||||
|
||||
yaml@^1.10.0, yaml@^1.10.2:
|
||||
version "1.10.2"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||
@ -6538,3 +6641,14 @@ yocto-queue@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||
|
||||
z-schema@^4.2.3:
|
||||
version "4.2.4"
|
||||
resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-4.2.4.tgz#73102a49512179b12a8ec50b1daa676b984da6e4"
|
||||
integrity sha512-YvBeW5RGNeNzKOUJs3rTL4+9rpcvHXt5I051FJbOcitV8bl40pEfcG0Q+dWSwS0/BIYrMZ/9HHoqLllMkFhD0w==
|
||||
dependencies:
|
||||
lodash.get "^4.4.2"
|
||||
lodash.isequal "^4.5.0"
|
||||
validator "^13.6.0"
|
||||
optionalDependencies:
|
||||
commander "^2.7.1"
|
||||
|
Loading…
Reference in New Issue
Block a user