Selaa lähdekoodia

Openapi Schema improvements

- Return proper booleans in api responses
- Update jsonschemavalidation to latest draft
Jamie Curnow 1 vuosi sitten
vanhempi
sitoutus
4572b205c9
69 muutettua tiedostoa jossa 844 lisäystä ja 2057 poistoa
  1. 0 1456
      backend/doc/api.swagger.json
  2. 1 1
      backend/internal/proxy-host.js
  3. 3 10
      backend/lib/access.js
  4. 0 1
      backend/lib/access/permissions.json
  5. 0 1
      backend/lib/access/roles.json
  6. 18 0
      backend/lib/helpers.js
  7. 9 8
      backend/lib/validator/api.js
  8. 8 7
      backend/lib/validator/index.js
  9. 17 0
      backend/models/access_list.js
  10. 20 5
      backend/models/auth.js
  11. 19 4
      backend/models/certificate.js
  12. 16 0
      backend/models/dead_host.js
  13. 23 0
      backend/models/proxy_host.js
  14. 19 0
      backend/models/redirection_host.js
  15. 21 4
      backend/models/stream.js
  16. 16 0
      backend/models/user.js
  17. 7 3
      backend/package.json
  18. 2 2
      backend/routes/audit-log.js
  19. 4 4
      backend/routes/nginx/access_lists.js
  20. 4 4
      backend/routes/nginx/certificates.js
  21. 4 4
      backend/routes/nginx/dead_hosts.js
  22. 4 4
      backend/routes/nginx/proxy_hosts.js
  23. 4 4
      backend/routes/nginx/redirection_hosts.js
  24. 4 4
      backend/routes/nginx/streams.js
  25. 4 4
      backend/routes/users.js
  26. 3 16
      backend/schema/common.json
  27. 4 4
      backend/schema/components/access-list-object.json
  28. 5 5
      backend/schema/components/audit-log-object.json
  29. 7 9
      backend/schema/components/certificate-object.json
  30. 11 11
      backend/schema/components/dead-host-object.json
  31. 30 16
      backend/schema/components/proxy-host-object.json
  32. 12 12
      backend/schema/components/redirection-host-object.json
  33. 5 5
      backend/schema/components/stream-object.json
  34. 3 5
      backend/schema/components/user-object.json
  35. 2 2
      backend/schema/paths/nginx/access-lists/get.json
  36. 1 1
      backend/schema/paths/nginx/access-lists/listID/get.json
  37. 4 4
      backend/schema/paths/nginx/access-lists/listID/put.json
  38. 4 4
      backend/schema/paths/nginx/access-lists/post.json
  39. 1 1
      backend/schema/paths/nginx/certificates/certID/renew/post.json
  40. 1 1
      backend/schema/paths/nginx/certificates/post.json
  41. 5 5
      backend/schema/paths/nginx/dead-hosts/get.json
  42. 5 5
      backend/schema/paths/nginx/dead-hosts/hostID/get.json
  43. 7 7
      backend/schema/paths/nginx/dead-hosts/hostID/put.json
  44. 7 7
      backend/schema/paths/nginx/dead-hosts/post.json
  45. 8 8
      backend/schema/paths/nginx/proxy-hosts/get.json
  46. 8 8
      backend/schema/paths/nginx/proxy-hosts/hostID/get.json
  47. 10 10
      backend/schema/paths/nginx/proxy-hosts/hostID/put.json
  48. 10 10
      backend/schema/paths/nginx/proxy-hosts/post.json
  49. 7 7
      backend/schema/paths/nginx/redirection-hosts/get.json
  50. 7 7
      backend/schema/paths/nginx/redirection-hosts/hostID/get.json
  51. 9 9
      backend/schema/paths/nginx/redirection-hosts/hostID/put.json
  52. 9 9
      backend/schema/paths/nginx/redirection-hosts/post.json
  53. 3 3
      backend/schema/paths/nginx/streams/get.json
  54. 5 5
      backend/schema/paths/nginx/streams/post.json
  55. 3 3
      backend/schema/paths/nginx/streams/streamID/get.json
  56. 10 10
      backend/schema/paths/nginx/streams/streamID/put.json
  57. 2 2
      backend/schema/paths/users/get.json
  58. 1 1
      backend/schema/paths/users/post.json
  59. 1 1
      backend/schema/paths/users/userID/get.json
  60. 1 1
      backend/schema/paths/users/userID/login/post.json
  61. 1 1
      backend/schema/paths/users/userID/put.json
  62. 1 1
      backend/schema/swagger.json
  63. 16 0
      backend/validate-schema.js
  64. 58 22
      backend/yarn.lock
  65. 1 1
      test/cypress/e2e/api/Health.cy.js
  66. 1 1
      test/cypress/e2e/api/Hosts.cy.js
  67. 2 7
      test/cypress/plugins/backendApi/logger.js
  68. 8 9
      test/package.json
  69. 318 271
      test/yarn.lock

+ 0 - 1456
backend/doc/api.swagger.json

@@ -1,1456 +0,0 @@
-{
-	"openapi": "3.0.0",
-	"info": {
-		"title": "Nginx Proxy Manager API",
-		"version": "2.x.x"
-	},
-	"servers": [
-		{
-			"url": "http://127.0.0.1:81/api"
-		}
-	],
-	"paths": {
-		"/": {
-			"get": {
-				"operationId": "health",
-				"summary": "Returns the API health status",
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": {
-											"status": "OK",
-											"version": {
-												"major": 2,
-												"minor": 1,
-												"revision": 0
-											}
-										}
-									}
-								},
-								"schema": {
-									"$ref": "#/components/schemas/HealthObject"
-								}
-							}
-						}
-					}
-				}
-			}
-		},
-		"/nginx/proxy-hosts": {
-			"get": {
-				"operationId": "getProxyHosts",
-				"summary": "Get all proxy hosts",
-				"tags": ["Proxy Hosts"],
-				"security": [
-					{
-						"BearerAuth": ["users"]
-					}
-				],
-				"parameters": [
-					{
-						"in": "query",
-						"name": "expand",
-						"description": "Expansions",
-						"schema": {
-							"type": "string",
-							"enum": ["access_list", "owner", "certificate"]
-						}
-					}
-				],
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": [
-											{
-												"id": 1,
-												"created_on": "2023-03-30T01:12:23.000Z",
-												"modified_on": "2023-03-30T02:15:40.000Z",
-												"owner_user_id": 1,
-												"domain_names": ["aasdasdad"],
-												"forward_host": "asdasd",
-												"forward_port": 80,
-												"access_list_id": 0,
-												"certificate_id": 0,
-												"ssl_forced": 0,
-												"caching_enabled": 0,
-												"block_exploits": 0,
-												"advanced_config": "sdfsdfsdf",
-												"meta": {
-													"letsencrypt_agree": false,
-													"dns_challenge": false,
-													"nginx_online": false,
-													"nginx_err": "Command failed: /usr/sbin/nginx -t -g \"error_log off;\"\nnginx: [emerg] unknown directive \"sdfsdfsdf\" in /data/nginx/proxy_host/1.conf:37\nnginx: configuration file /etc/nginx/nginx.conf test failed\n"
-												},
-												"allow_websocket_upgrade": 0,
-												"http2_support": 0,
-												"forward_scheme": "http",
-												"enabled": 1,
-												"locations": [],
-												"hsts_enabled": 0,
-												"hsts_subdomains": 0,
-												"owner": {
-													"id": 1,
-													"created_on": "2023-03-30T01:11:50.000Z",
-													"modified_on": "2023-03-30T01:11:50.000Z",
-													"is_deleted": 0,
-													"is_disabled": 0,
-													"email": "[email protected]",
-													"name": "Administrator",
-													"nickname": "Admin",
-													"avatar": "",
-													"roles": ["admin"]
-												},
-												"access_list": null,
-												"certificate": null
-											},
-											{
-												"id": 2,
-												"created_on": "2023-03-30T02:11:49.000Z",
-												"modified_on": "2023-03-30T02:11:49.000Z",
-												"owner_user_id": 1,
-												"domain_names": ["test.example.com"],
-												"forward_host": "1.1.1.1",
-												"forward_port": 80,
-												"access_list_id": 0,
-												"certificate_id": 0,
-												"ssl_forced": 0,
-												"caching_enabled": 0,
-												"block_exploits": 0,
-												"advanced_config": "",
-												"meta": {
-													"letsencrypt_agree": false,
-													"dns_challenge": false,
-													"nginx_online": true,
-													"nginx_err": null
-												},
-												"allow_websocket_upgrade": 0,
-												"http2_support": 0,
-												"forward_scheme": "http",
-												"enabled": 1,
-												"locations": [],
-												"hsts_enabled": 0,
-												"hsts_subdomains": 0,
-												"owner": {
-													"id": 1,
-													"created_on": "2023-03-30T01:11:50.000Z",
-													"modified_on": "2023-03-30T01:11:50.000Z",
-													"is_deleted": 0,
-													"is_disabled": 0,
-													"email": "[email protected]",
-													"name": "Administrator",
-													"nickname": "Admin",
-													"avatar": "",
-													"roles": ["admin"]
-												},
-												"access_list": null,
-												"certificate": null
-											}
-										]
-									}
-								},
-								"schema": {
-									"$ref": "#/components/schemas/ProxyHostsList"
-								}
-							}
-						}
-					}
-				}
-			},
-			"post": {
-				"operationId": "createProxyHost",
-				"summary": "Create a Proxy Host",
-				"tags": ["Proxy Hosts"],
-				"security": [
-					{
-						"BearerAuth": ["users"]
-					}
-				],
-				"parameters": [
-					{
-						"in": "body",
-						"name": "proxyhost",
-						"description": "Proxy Host Payload",
-						"required": true,
-						"schema": {
-							"$ref": "#/components/schemas/ProxyHostObject"
-						}
-					}
-				],
-				"responses": {
-					"201": {
-						"description": "201 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": {
-											"id": 3,
-											"created_on": "2023-03-30T02:31:27.000Z",
-											"modified_on": "2023-03-30T02:31:27.000Z",
-											"owner_user_id": 1,
-											"domain_names": ["test2.example.com"],
-											"forward_host": "1.1.1.1",
-											"forward_port": 80,
-											"access_list_id": 0,
-											"certificate_id": 0,
-											"ssl_forced": 0,
-											"caching_enabled": 0,
-											"block_exploits": 0,
-											"advanced_config": "",
-											"meta": {
-												"letsencrypt_agree": false,
-												"dns_challenge": false
-											},
-											"allow_websocket_upgrade": 0,
-											"http2_support": 0,
-											"forward_scheme": "http",
-											"enabled": 1,
-											"locations": [],
-											"hsts_enabled": 0,
-											"hsts_subdomains": 0,
-											"certificate": null,
-											"owner": {
-												"id": 1,
-												"created_on": "2023-03-30T01:11:50.000Z",
-												"modified_on": "2023-03-30T01:11:50.000Z",
-												"is_deleted": 0,
-												"is_disabled": 0,
-												"email": "[email protected]",
-												"name": "Administrator",
-												"nickname": "Admin",
-												"avatar": "",
-												"roles": ["admin"]
-											},
-											"access_list": null,
-											"use_default_location": true,
-											"ipv6": true
-										}
-									}
-								},
-								"schema": {
-									"$ref": "#/components/schemas/ProxyHostObject"
-								}
-							}
-						}
-					}
-				}
-			}
-		},
-		"/schema": {
-			"get": {
-				"operationId": "schema",
-				"responses": {
-					"200": {
-						"description": "200 response"
-					}
-				},
-				"summary": "Returns this swagger API schema"
-			}
-		},
-		"/tokens": {
-			"get": {
-				"operationId": "refreshToken",
-				"summary": "Refresh your access token",
-				"tags": ["Tokens"],
-				"security": [
-					{
-						"BearerAuth": ["tokens"]
-					}
-				],
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": {
-											"expires": 1566540510,
-											"token": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4"
-										}
-									}
-								},
-								"schema": {
-									"$ref": "#/components/schemas/TokenObject"
-								}
-							}
-						}
-					}
-				}
-			},
-			"post": {
-				"operationId": "requestToken",
-				"parameters": [
-					{
-						"description": "Credentials Payload",
-						"in": "body",
-						"name": "credentials",
-						"required": true,
-						"schema": {
-							"additionalProperties": false,
-							"properties": {
-								"identity": {
-									"minLength": 1,
-									"type": "string"
-								},
-								"scope": {
-									"minLength": 1,
-									"type": "string",
-									"enum": ["user"]
-								},
-								"secret": {
-									"minLength": 1,
-									"type": "string"
-								}
-							},
-							"required": ["identity", "secret"],
-							"type": "object"
-						}
-					}
-				],
-				"responses": {
-					"200": {
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": {
-											"result": {
-												"expires": 1566540510,
-												"token": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4"
-											}
-										}
-									}
-								},
-								"schema": {
-									"$ref": "#/components/schemas/TokenObject"
-								}
-							}
-						},
-						"description": "200 response"
-					}
-				},
-				"summary": "Request a new access token from credentials",
-				"tags": ["Tokens"]
-			}
-		},
-		"/settings": {
-			"get": {
-				"operationId": "getSettings",
-				"summary": "Get all settings",
-				"tags": ["Settings"],
-				"security": [
-					{
-						"BearerAuth": ["settings"]
-					}
-				],
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": [
-											{
-												"id": "default-site",
-												"name": "Default Site",
-												"description": "What to show when Nginx is hit with an unknown Host",
-												"value": "congratulations",
-												"meta": {}
-											}
-										]
-									}
-								},
-								"schema": {
-									"$ref": "#/components/schemas/SettingsList"
-								}
-							}
-						}
-					}
-				}
-			}
-		},
-		"/settings/{settingID}": {
-			"get": {
-				"operationId": "getSetting",
-				"summary": "Get a setting",
-				"tags": ["Settings"],
-				"security": [
-					{
-						"BearerAuth": ["settings"]
-					}
-				],
-				"parameters": [
-					{
-						"in": "path",
-						"name": "settingID",
-						"schema": {
-							"type": "string",
-							"minLength": 1
-						},
-						"required": true,
-						"description": "Setting ID",
-						"example": "default-site"
-					}
-				],
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": {
-											"id": "default-site",
-											"name": "Default Site",
-											"description": "What to show when Nginx is hit with an unknown Host",
-											"value": "congratulations",
-											"meta": {}
-										}
-									}
-								},
-								"schema": {
-									"$ref": "#/components/schemas/SettingObject"
-								}
-							}
-						}
-					}
-				}
-			},
-			"put": {
-				"operationId": "updateSetting",
-				"summary": "Update a setting",
-				"tags": ["Settings"],
-				"security": [
-					{
-						"BearerAuth": ["settings"]
-					}
-				],
-				"parameters": [
-					{
-						"in": "path",
-						"name": "settingID",
-						"schema": {
-							"type": "string",
-							"minLength": 1
-						},
-						"required": true,
-						"description": "Setting ID",
-						"example": "default-site"
-					},
-					{
-						"in": "body",
-						"name": "setting",
-						"description": "Setting Payload",
-						"required": true,
-						"schema": {
-							"$ref": "#/components/schemas/SettingObject"
-						}
-					}
-				],
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": {
-											"id": "default-site",
-											"name": "Default Site",
-											"description": "What to show when Nginx is hit with an unknown Host",
-											"value": "congratulations",
-											"meta": {}
-										}
-									}
-								},
-								"schema": {
-									"$ref": "#/components/schemas/SettingObject"
-								}
-							}
-						}
-					}
-				}
-			}
-		},
-		"/users": {
-			"get": {
-				"operationId": "getUsers",
-				"summary": "Get all users",
-				"tags": ["Users"],
-				"security": [
-					{
-						"BearerAuth": ["users"]
-					}
-				],
-				"parameters": [
-					{
-						"in": "query",
-						"name": "expand",
-						"description": "Expansions",
-						"schema": {
-							"type": "string",
-							"enum": ["permissions"]
-						}
-					}
-				],
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": [
-											{
-												"id": 1,
-												"created_on": "2020-01-30T09:36:08.000Z",
-												"modified_on": "2020-01-30T09:41:04.000Z",
-												"is_disabled": 0,
-												"email": "[email protected]",
-												"name": "Jamie Curnow",
-												"nickname": "James",
-												"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
-												"roles": ["admin"]
-											}
-										]
-									},
-									"withPermissions": {
-										"value": [
-											{
-												"id": 1,
-												"created_on": "2020-01-30T09:36:08.000Z",
-												"modified_on": "2020-01-30T09:41:04.000Z",
-												"is_disabled": 0,
-												"email": "[email protected]",
-												"name": "Jamie Curnow",
-												"nickname": "James",
-												"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
-												"roles": ["admin"],
-												"permissions": {
-													"visibility": "all",
-													"proxy_hosts": "manage",
-													"redirection_hosts": "manage",
-													"dead_hosts": "manage",
-													"streams": "manage",
-													"access_lists": "manage",
-													"certificates": "manage"
-												}
-											}
-										]
-									}
-								},
-								"schema": {
-									"$ref": "#/components/schemas/UsersList"
-								}
-							}
-						}
-					}
-				}
-			},
-			"post": {
-				"operationId": "createUser",
-				"summary": "Create a User",
-				"tags": ["Users"],
-				"security": [
-					{
-						"BearerAuth": ["users"]
-					}
-				],
-				"parameters": [
-					{
-						"in": "body",
-						"name": "user",
-						"description": "User Payload",
-						"required": true,
-						"schema": {
-							"$ref": "#/components/schemas/UserObject"
-						}
-					}
-				],
-				"responses": {
-					"201": {
-						"description": "201 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": {
-											"id": 2,
-											"created_on": "2020-01-30T09:36:08.000Z",
-											"modified_on": "2020-01-30T09:41:04.000Z",
-											"is_disabled": 0,
-											"email": "[email protected]",
-											"name": "Jamie Curnow",
-											"nickname": "James",
-											"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
-											"roles": ["admin"],
-											"permissions": {
-												"visibility": "all",
-												"proxy_hosts": "manage",
-												"redirection_hosts": "manage",
-												"dead_hosts": "manage",
-												"streams": "manage",
-												"access_lists": "manage",
-												"certificates": "manage"
-											}
-										}
-									}
-								},
-								"schema": {
-									"$ref": "#/components/schemas/UserObject"
-								}
-							}
-						}
-					}
-				}
-			}
-		},
-		"/users/{userID}": {
-			"get": {
-				"operationId": "getUser",
-				"summary": "Get a user",
-				"tags": ["Users"],
-				"security": [
-					{
-						"BearerAuth": ["users"]
-					}
-				],
-				"parameters": [
-					{
-						"in": "path",
-						"name": "userID",
-						"schema": {
-							"oneOf": [
-								{
-									"type": "string",
-									"pattern": "^me$"
-								},
-								{
-									"type": "integer",
-									"minimum": 1
-								}
-							]
-						},
-						"required": true,
-						"description": "User ID or 'me' for yourself",
-						"example": 1
-					}
-				],
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": {
-											"id": 1,
-											"created_on": "2020-01-30T09:36:08.000Z",
-											"modified_on": "2020-01-30T09:41:04.000Z",
-											"is_disabled": 0,
-											"email": "[email protected]",
-											"name": "Jamie Curnow",
-											"nickname": "James",
-											"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
-											"roles": ["admin"]
-										}
-									}
-								},
-								"schema": {
-									"$ref": "#/components/schemas/UserObject"
-								}
-							}
-						}
-					}
-				}
-			},
-			"put": {
-				"operationId": "updateUser",
-				"summary": "Update a User",
-				"tags": ["Users"],
-				"security": [
-					{
-						"BearerAuth": ["users"]
-					}
-				],
-				"parameters": [
-					{
-						"in": "path",
-						"name": "userID",
-						"schema": {
-							"oneOf": [
-								{
-									"type": "string",
-									"pattern": "^me$"
-								},
-								{
-									"type": "integer",
-									"minimum": 1
-								}
-							]
-						},
-						"required": true,
-						"description": "User ID or 'me' for yourself",
-						"example": 2
-					},
-					{
-						"in": "body",
-						"name": "user",
-						"description": "User Payload",
-						"required": true,
-						"schema": {
-							"$ref": "#/components/schemas/UserObject"
-						}
-					}
-				],
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": {
-											"id": 2,
-											"created_on": "2020-01-30T09:36:08.000Z",
-											"modified_on": "2020-01-30T09:41:04.000Z",
-											"is_disabled": 0,
-											"email": "[email protected]",
-											"name": "Jamie Curnow",
-											"nickname": "James",
-											"avatar": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm",
-											"roles": ["admin"]
-										}
-									}
-								},
-								"schema": {
-									"$ref": "#/components/schemas/UserObject"
-								}
-							}
-						}
-					}
-				}
-			},
-			"delete": {
-				"operationId": "deleteUser",
-				"summary": "Delete a User",
-				"tags": ["Users"],
-				"security": [
-					{
-						"BearerAuth": ["users"]
-					}
-				],
-				"parameters": [
-					{
-						"in": "path",
-						"name": "userID",
-						"schema": {
-							"type": "integer",
-							"minimum": 1
-						},
-						"required": true,
-						"description": "User ID",
-						"example": 2
-					}
-				],
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": true
-									}
-								},
-								"schema": {
-									"type": "boolean"
-								}
-							}
-						}
-					}
-				}
-			}
-		},
-		"/users/{userID}/auth": {
-			"put": {
-				"operationId": "updateUserAuth",
-				"summary": "Update a User's Authentication",
-				"tags": ["Users"],
-				"security": [
-					{
-						"BearerAuth": ["users"]
-					}
-				],
-				"parameters": [
-					{
-						"in": "path",
-						"name": "userID",
-						"schema": {
-							"oneOf": [
-								{
-									"type": "string",
-									"pattern": "^me$"
-								},
-								{
-									"type": "integer",
-									"minimum": 1
-								}
-							]
-						},
-						"required": true,
-						"description": "User ID or 'me' for yourself",
-						"example": 2
-					},
-					{
-						"in": "body",
-						"name": "user",
-						"description": "User Payload",
-						"required": true,
-						"schema": {
-							"$ref": "#/components/schemas/AuthObject"
-						}
-					}
-				],
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": true
-									}
-								},
-								"schema": {
-									"type": "boolean"
-								}
-							}
-						}
-					}
-				}
-			}
-		},
-		"/users/{userID}/permissions": {
-			"put": {
-				"operationId": "updateUserPermissions",
-				"summary": "Update a User's Permissions",
-				"tags": ["Users"],
-				"security": [
-					{
-						"BearerAuth": ["users"]
-					}
-				],
-				"parameters": [
-					{
-						"in": "path",
-						"name": "userID",
-						"schema": {
-							"type": "integer",
-							"minimum": 1
-						},
-						"required": true,
-						"description": "User ID",
-						"example": 2
-					},
-					{
-						"in": "body",
-						"name": "user",
-						"description": "Permissions Payload",
-						"required": true,
-						"schema": {
-							"$ref": "#/components/schemas/PermissionsObject"
-						}
-					}
-				],
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": true
-									}
-								},
-								"schema": {
-									"type": "boolean"
-								}
-							}
-						}
-					}
-				}
-			}
-		},
-		"/users/{userID}/login": {
-			"put": {
-				"operationId": "loginAsUser",
-				"summary": "Login as this user",
-				"tags": ["Users"],
-				"security": [
-					{
-						"BearerAuth": ["users"]
-					}
-				],
-				"parameters": [
-					{
-						"in": "path",
-						"name": "userID",
-						"schema": {
-							"type": "integer",
-							"minimum": 1
-						},
-						"required": true,
-						"description": "User ID",
-						"example": 2
-					}
-				],
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": {
-											"token": "eyJhbGciOiJSUzI1NiIsInR...16OjT8B3NLyXg",
-											"expires": "2020-01-31T10:56:23.239Z",
-											"user": {
-												"id": 1,
-												"created_on": "2020-01-30T10:43:44.000Z",
-												"modified_on": "2020-01-30T10:43:44.000Z",
-												"is_disabled": 0,
-												"email": "[email protected]",
-												"name": "Jamie Curnow",
-												"nickname": "James",
-												"avatar": "//www.gravatar.com/avatar/3c8d73f45fd8763f827b964c76e6032a?default=mm",
-												"roles": ["admin"]
-											}
-										}
-									}
-								},
-								"schema": {
-									"type": "object",
-									"description": "Login object",
-									"required": ["expires", "token", "user"],
-									"additionalProperties": false,
-									"properties": {
-										"expires": {
-											"description": "Token Expiry Unix Time",
-											"example": 1566540249,
-											"minimum": 1,
-											"type": "number"
-										},
-										"token": {
-											"description": "JWT Token",
-											"example": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4",
-											"type": "string"
-										},
-										"user": {
-											"$ref": "#/components/schemas/UserObject"
-										}
-									}
-								}
-							}
-						}
-					}
-				}
-			}
-		},
-		"/reports/hosts": {
-			"get": {
-				"operationId": "reportsHosts",
-				"summary": "Report on Host Statistics",
-				"tags": ["Reports"],
-				"security": [
-					{
-						"BearerAuth": ["reports"]
-					}
-				],
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": {
-											"proxy": 20,
-											"redirection": 1,
-											"stream": 0,
-											"dead": 1
-										}
-									}
-								},
-								"schema": {
-									"$ref": "#/components/schemas/HostReportObject"
-								}
-							}
-						}
-					}
-				}
-			}
-		},
-		"/audit-log": {
-			"get": {
-				"operationId": "getAuditLog",
-				"summary": "Get Audit Log",
-				"tags": ["Audit Log"],
-				"security": [
-					{
-						"BearerAuth": ["audit-log"]
-					}
-				],
-				"responses": {
-					"200": {
-						"description": "200 response",
-						"content": {
-							"application/json": {
-								"examples": {
-									"default": {
-										"value": {
-											"proxy": 20,
-											"redirection": 1,
-											"stream": 0,
-											"dead": 1
-										}
-									}
-								},
-								"schema": {
-									"$ref": "#/components/schemas/HostReportObject"
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-	},
-	"components": {
-		"securitySchemes": {
-			"BearerAuth": {
-				"type": "http",
-				"scheme": "bearer"
-			}
-		},
-		"schemas": {
-			"HealthObject": {
-				"type": "object",
-				"description": "Health object",
-				"additionalProperties": false,
-				"required": ["status", "version"],
-				"properties": {
-					"status": {
-						"type": "string",
-						"description": "Healthy",
-						"example": "OK"
-					},
-					"version": {
-						"type": "object",
-						"description": "The version object",
-						"example": {
-							"major": 2,
-							"minor": 0,
-							"revision": 0
-						},
-						"additionalProperties": false,
-						"required": ["major", "minor", "revision"],
-						"properties": {
-							"major": {
-								"type": "integer",
-								"minimum": 0
-							},
-							"minor": {
-								"type": "integer",
-								"minimum": 0
-							},
-							"revision": {
-								"type": "integer",
-								"minimum": 0
-							}
-						}
-					}
-				}
-			},
-			"TokenObject": {
-				"type": "object",
-				"description": "Token object",
-				"required": ["expires", "token"],
-				"additionalProperties": false,
-				"properties": {
-					"expires": {
-						"description": "Token Expiry Unix Time",
-						"example": 1566540249,
-						"minimum": 1,
-						"type": "number"
-					},
-					"token": {
-						"description": "JWT Token",
-						"example": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4",
-						"type": "string"
-					}
-				}
-			},
-			"ProxyHostObject": {
-				"type": "object",
-				"description": "Proxy Host object",
-				"required": [
-					"id",
-					"created_on",
-					"modified_on",
-					"owner_user_id",
-					"domain_names",
-					"forward_host",
-					"forward_port",
-					"access_list_id",
-					"certificate_id",
-					"ssl_forced",
-					"caching_enabled",
-					"block_exploits",
-					"advanced_config",
-					"meta",
-					"allow_websocket_upgrade",
-					"http2_support",
-					"forward_scheme",
-					"enabled",
-					"locations",
-					"hsts_enabled",
-					"hsts_subdomains",
-					"certificate",
-					"use_default_location",
-					"ipv6"
-				],
-				"additionalProperties": false,
-				"properties": {
-					"id": {
-						"type": "integer",
-						"description": "Proxy Host ID",
-						"minimum": 1,
-						"example": 1
-					},
-					"created_on": {
-						"type": "string",
-						"description": "Created Date",
-						"example": "2020-01-30T09:36:08.000Z"
-					},
-					"modified_on": {
-						"type": "string",
-						"description": "Modified Date",
-						"example": "2020-01-30T09:41:04.000Z"
-					},
-					"owner_user_id": {
-						"type": "integer",
-						"minimum": 1,
-						"example": 1
-					},
-					"domain_names": {
-						"type": "array",
-						"minItems": 1,
-						"items": {
-							"type": "string",
-							"minLength": 1
-						}
-					},
-					"forward_host": {
-						"type": "string",
-						"minLength": 1
-					},
-					"forward_port": {
-						"type": "integer",
-						"minimum": 1
-					},
-					"access_list_id": {
-						"type": "integer"
-					},
-					"certificate_id": {
-						"type": "integer"
-					},
-					"ssl_forced": {
-						"type": "integer"
-					},
-					"caching_enabled": {
-						"type": "integer"
-					},
-					"block_exploits": {
-						"type": "integer"
-					},
-					"advanced_config": {
-						"type": "string"
-					},
-					"meta": {
-						"type": "object"
-					},
-					"allow_websocket_upgrade": {
-						"type": "integer"
-					},
-					"http2_support": {
-						"type": "integer"
-					},
-					"forward_scheme": {
-						"type": "string"
-					},
-					"enabled": {
-						"type": "integer"
-					},
-					"locations": {
-						"type": "array"
-					},
-					"hsts_enabled": {
-						"type": "integer"
-					},
-					"hsts_subdomains": {
-						"type": "integer"
-					},
-					"certificate": {
-						"type": "object",
-						"nullable": true
-					},
-					"owner": {
-						"type": "object",
-						"nullable": true
-					},
-					"access_list": {
-						"type": "object",
-						"nullable": true
-					},
-					"use_default_location": {
-						"type": "boolean"
-					},
-					"ipv6": {
-						"type": "boolean"
-					}
-				}
-			},
-			"ProxyHostsList": {
-				"type": "array",
-				"description": "Proxyn Hosts list",
-				"items": {
-					"$ref": "#/components/schemas/ProxyHostObject"
-				}
-			},
-			"SettingObject": {
-				"type": "object",
-				"description": "Setting object",
-				"required": ["id", "name", "description", "value", "meta"],
-				"additionalProperties": false,
-				"properties": {
-					"id": {
-						"type": "string",
-						"description": "Setting ID",
-						"minLength": 1,
-						"example": "default-site"
-					},
-					"name": {
-						"type": "string",
-						"description": "Setting Display Name",
-						"minLength": 1,
-						"example": "Default Site"
-					},
-					"description": {
-						"type": "string",
-						"description": "Meaningful description",
-						"minLength": 1,
-						"example": "What to show when Nginx is hit with an unknown Host"
-					},
-					"value": {
-						"description": "Value in almost any form",
-						"example": "congratulations",
-						"oneOf": [
-							{
-								"type": "string",
-								"minLength": 1
-							},
-							{
-								"type": "integer"
-							},
-							{
-								"type": "object"
-							},
-							{
-								"type": "number"
-							},
-							{
-								"type": "array"
-							}
-						]
-					},
-					"meta": {
-						"description": "Extra metadata",
-						"example": {},
-						"type": "object"
-					}
-				}
-			},
-			"SettingsList": {
-				"type": "array",
-				"description": "Setting list",
-				"items": {
-					"$ref": "#/components/schemas/SettingObject"
-				}
-			},
-			"UserObject": {
-				"type": "object",
-				"description": "User object",
-				"required": ["id", "created_on", "modified_on", "is_disabled", "email", "name", "nickname", "avatar", "roles"],
-				"additionalProperties": false,
-				"properties": {
-					"id": {
-						"type": "integer",
-						"description": "User ID",
-						"minimum": 1,
-						"example": 1
-					},
-					"created_on": {
-						"type": "string",
-						"description": "Created Date",
-						"example": "2020-01-30T09:36:08.000Z"
-					},
-					"modified_on": {
-						"type": "string",
-						"description": "Modified Date",
-						"example": "2020-01-30T09:41:04.000Z"
-					},
-					"is_disabled": {
-						"type": "integer",
-						"minimum": 0,
-						"maximum": 1,
-						"description": "Is user Disabled (0 = false, 1 = true)",
-						"example": 0
-					},
-					"email": {
-						"type": "string",
-						"description": "Email",
-						"minLength": 3,
-						"example": "[email protected]"
-					},
-					"name": {
-						"type": "string",
-						"description": "Name",
-						"minLength": 1,
-						"example": "Jamie Curnow"
-					},
-					"nickname": {
-						"type": "string",
-						"description": "Nickname",
-						"example": "James"
-					},
-					"avatar": {
-						"type": "string",
-						"description": "Gravatar URL based on email, without scheme",
-						"example": "//www.gravatar.com/avatar/6193176330f8d38747f038c170ddb193?default=mm"
-					},
-					"roles": {
-						"description": "Roles applied",
-						"example": ["admin"],
-						"type": "array",
-						"items": {
-							"type": "string"
-						}
-					}
-				}
-			},
-			"UsersList": {
-				"type": "array",
-				"description": "User list",
-				"items": {
-					"$ref": "#/components/schemas/UserObject"
-				}
-			},
-			"AuthObject": {
-				"type": "object",
-				"description": "Authentication Object",
-				"required": ["type", "secret"],
-				"properties": {
-					"type": {
-						"type": "string",
-						"pattern": "^password$",
-						"example": "password"
-					},
-					"current": {
-						"type": "string",
-						"minLength": 1,
-						"maxLength": 64,
-						"example": "changeme"
-					},
-					"secret": {
-						"type": "string",
-						"minLength": 8,
-						"maxLength": 64,
-						"example": "mySuperN3wP@ssword!"
-					}
-				}
-			},
-			"PermissionsObject": {
-				"type": "object",
-				"properties": {
-					"visibility": {
-						"type": "string",
-						"description": "Visibility Type",
-						"enum": ["all", "user"]
-					},
-					"access_lists": {
-						"type": "string",
-						"description": "Access Lists Permissions",
-						"enum": ["hidden", "view", "manage"]
-					},
-					"dead_hosts": {
-						"type": "string",
-						"description": "404 Hosts Permissions",
-						"enum": ["hidden", "view", "manage"]
-					},
-					"proxy_hosts": {
-						"type": "string",
-						"description": "Proxy Hosts Permissions",
-						"enum": ["hidden", "view", "manage"]
-					},
-					"redirection_hosts": {
-						"type": "string",
-						"description": "Redirection Permissions",
-						"enum": ["hidden", "view", "manage"]
-					},
-					"streams": {
-						"type": "string",
-						"description": "Streams Permissions",
-						"enum": ["hidden", "view", "manage"]
-					},
-					"certificates": {
-						"type": "string",
-						"description": "Certificates Permissions",
-						"enum": ["hidden", "view", "manage"]
-					}
-				}
-			},
-			"HostReportObject": {
-				"type": "object",
-				"properties": {
-					"proxy": {
-						"type": "integer",
-						"description": "Proxy Hosts Count"
-					},
-					"redirection": {
-						"type": "integer",
-						"description": "Redirection Hosts Count"
-					},
-					"stream": {
-						"type": "integer",
-						"description": "Streams Count"
-					},
-					"dead": {
-						"type": "integer",
-						"description": "404 Hosts Count"
-					}
-				}
-			}
-		}
-	}
-}

+ 1 - 1
backend/internal/proxy-host.js

@@ -8,7 +8,7 @@ const internalAuditLog    = require('./audit-log');
 const internalCertificate = require('./certificate');
 
 function omissions () {
-	return ['is_deleted'];
+	return ['is_deleted', 'owner.is_deleted'];
 }
 
 const internalProxyHost = {

+ 3 - 10
backend/lib/access.js

@@ -10,7 +10,7 @@
 
 const _              = require('lodash');
 const logger         = require('../logger').access;
-const validator      = require('ajv');
+const Ajv            = require('ajv/dist/2020');
 const error          = require('./error');
 const userModel      = require('../models/user');
 const proxyHostModel = require('../models/proxy_host');
@@ -174,7 +174,6 @@ module.exports = function (token_string) {
 
 		let schema = {
 			$id:                  'objects',
-			$schema:              'http://json-schema.org/draft-07/schema#',
 			description:          'Actor Properties',
 			type:                 'object',
 			additionalProperties: false,
@@ -251,7 +250,7 @@ module.exports = function (token_string) {
 						// Initialised, token decoded ok
 						return this.getObjectSchema(permission)
 							.then((objectSchema) => {
-								let data_schema = {
+								const data_schema = {
 									[permission]: {
 										data:                         data,
 										scope:                        Token.get('scope'),
@@ -267,7 +266,6 @@ module.exports = function (token_string) {
 								};
 
 								let permissionSchema = {
-									$schema:              'http://json-schema.org/draft-07/schema#',
 									$async:               true,
 									$id:                  'permissions',
 									additionalProperties: false,
@@ -276,14 +274,9 @@ module.exports = function (token_string) {
 
 								permissionSchema.properties[permission] = require('./access/' + permission.replace(/:/gim, '-') + '.json');
 
-								// logger.info('objectSchema', JSON.stringify(objectSchema, null, 2));
-								// logger.info('permissionSchema', JSON.stringify(permissionSchema, null, 2));
-								// logger.info('data_schema', JSON.stringify(data_schema, null, 2));
-
-								let ajv = validator({
+								const ajv = new Ajv({
 									verbose:      true,
 									allErrors:    true,
-									format:       'full',
 									missingRefs:  'fail',
 									breakOnError: true,
 									coerceTypes:  true,

+ 0 - 1
backend/lib/access/permissions.json

@@ -1,5 +1,4 @@
 {
-	"$schema": "http://json-schema.org/draft-07/schema#",
 	"$id": "perms",
 	"definitions": {
 		"view": {

+ 0 - 1
backend/lib/access/roles.json

@@ -1,5 +1,4 @@
 {
-	"$schema": "http://json-schema.org/draft-07/schema#",
 	"$id": "roles",
 	"definitions": {
 		"admin": {

+ 18 - 0
backend/lib/helpers.js

@@ -27,6 +27,24 @@ module.exports = {
 		}
 
 		return null;
+	},
+
+	convertIntFieldsToBool: function (obj, fields) {
+		fields.forEach(function (field) {
+			if (typeof obj[field] !== 'undefined') {
+				obj[field] = obj[field] === 1;
+			}
+		});
+		return obj;
+	},
+
+	convertBoolFieldsToInt: function (obj, fields) {
+		fields.forEach(function (field) {
+			if (typeof obj[field] !== 'undefined') {
+				obj[field] = obj[field] ? 1 : 0;
+			}
+		});
+		return obj;
 	}
 
 };

+ 9 - 8
backend/lib/validator/api.js

@@ -1,11 +1,12 @@
+const Ajv   = require('ajv/dist/2020');
 const error = require('../error');
 
-const ajv = require('ajv')({
-	verbose:        true,
-	validateSchema: true,
-	allErrors:      false,
-	format:         'full',
-	coerceTypes:    true
+const ajv = new Ajv({
+	verbose:         true,
+	allErrors:       true,
+	allowUnionTypes: true,
+	strict:          false,
+	coerceTypes:     true,
 });
 
 /**
@@ -25,8 +26,8 @@ function apiValidator (schema, payload/*, description*/) {
 			return;
 		}
 
-		let validate = ajv.compile(schema);
-		let valid    = validate(payload);
+		const validate = ajv.compile(schema);
+		const valid    = validate(payload);
 
 		if (valid && !validate.errors) {
 			resolve(payload);

+ 8 - 7
backend/lib/validator/index.js

@@ -1,15 +1,17 @@
 const _                 = require('lodash');
+const Ajv               = require('ajv/dist/2020');
 const error             = require('../error');
 const commonDefinitions = require('../../schema/common.json');
 
 RegExp.prototype.toJSON = RegExp.prototype.toString;
 
-const ajv = require('ajv')({
-	verbose:     true,
-	allErrors:   true,
-	format:      'full',  // strict regexes for format checks
-	coerceTypes: true,
-	schemas:     [commonDefinitions]
+const ajv = new Ajv({
+	verbose:         true,
+	allErrors:       true,
+	allowUnionTypes: true,
+	coerceTypes:     true,
+	strict:          false,
+	schemas:         [commonDefinitions]
 });
 
 /**
@@ -38,7 +40,6 @@ function validator (schema, payload) {
 			}
 		}
 	});
-
 }
 
 module.exports = validator;

+ 17 - 0
backend/models/access_list.js

@@ -2,6 +2,7 @@
 // http://vincit.github.io/objection.js/
 
 const db               = require('../db');
+const helpers          = require('../lib/helpers');
 const Model            = require('objection').Model;
 const User             = require('./user');
 const AccessListAuth   = require('./access_list_auth');
@@ -10,6 +11,12 @@ const now              = require('./now_helper');
 
 Model.knex(db);
 
+const boolFields = [
+	'is_deleted',
+	'satisfy_any',
+	'pass_auth',
+];
+
 class AccessList extends Model {
 	$beforeInsert () {
 		this.created_on  = now();
@@ -25,6 +32,16 @@ class AccessList extends Model {
 		this.modified_on = now();
 	}
 
+	$parseDatabaseJson(json) {
+		json = super.$parseDatabaseJson(json);
+		return helpers.convertIntFieldsToBool(json, boolFields);
+	}
+
+	$formatDatabaseJson(json) {
+		json = helpers.convertBoolFieldsToInt(json, boolFields);
+		return super.$formatDatabaseJson(json);
+	}
+
 	static get name () {
 		return 'AccessList';
 	}

+ 20 - 5
backend/models/auth.js

@@ -1,14 +1,19 @@
 // Objection Docs:
 // http://vincit.github.io/objection.js/
 
-const bcrypt = require('bcrypt');
-const db     = require('../db');
-const Model  = require('objection').Model;
-const User   = require('./user');
-const now    = require('./now_helper');
+const bcrypt  = require('bcrypt');
+const db      = require('../db');
+const helpers = require('../lib/helpers');
+const Model   = require('objection').Model;
+const User    = require('./user');
+const now     = require('./now_helper');
 
 Model.knex(db);
 
+const boolFields = [
+	'is_deleted',
+];
+
 function encryptPassword () {
 	/* jshint -W040 */
 	let _this = this;
@@ -41,6 +46,16 @@ class Auth extends Model {
 		return encryptPassword.apply(this, queryContext);
 	}
 
+	$parseDatabaseJson(json) {
+		json = super.$parseDatabaseJson(json);
+		return helpers.convertIntFieldsToBool(json, boolFields);
+	}
+
+	$formatDatabaseJson(json) {
+		json = helpers.convertBoolFieldsToInt(json, boolFields);
+		return super.$formatDatabaseJson(json);
+	}
+
 	/**
 	 * Verify a plain password against the encrypted password
 	 *

+ 19 - 4
backend/models/certificate.js

@@ -1,13 +1,18 @@
 // Objection Docs:
 // http://vincit.github.io/objection.js/
 
-const db    = require('../db');
-const Model = require('objection').Model;
-const User  = require('./user');
-const now   = require('./now_helper');
+const db      = require('../db');
+const helpers = require('../lib/helpers');
+const Model   = require('objection').Model;
+const User    = require('./user');
+const now     = require('./now_helper');
 
 Model.knex(db);
 
+const boolFields = [
+	'is_deleted',
+];
+
 class Certificate extends Model {
 	$beforeInsert () {
 		this.created_on  = now();
@@ -40,6 +45,16 @@ class Certificate extends Model {
 		}
 	}
 
+	$parseDatabaseJson(json) {
+		json = super.$parseDatabaseJson(json);
+		return helpers.convertIntFieldsToBool(json, boolFields);
+	}
+
+	$formatDatabaseJson(json) {
+		json = helpers.convertBoolFieldsToInt(json, boolFields);
+		return super.$formatDatabaseJson(json);
+	}
+
 	static get name () {
 		return 'Certificate';
 	}

+ 16 - 0
backend/models/dead_host.js

@@ -2,6 +2,7 @@
 // http://vincit.github.io/objection.js/
 
 const db          = require('../db');
+const helpers     = require('../lib/helpers');
 const Model       = require('objection').Model;
 const User        = require('./user');
 const Certificate = require('./certificate');
@@ -9,6 +10,11 @@ const now         = require('./now_helper');
 
 Model.knex(db);
 
+const boolFields = [
+	'is_deleted',
+	'enabled',
+];
+
 class DeadHost extends Model {
 	$beforeInsert () {
 		this.created_on  = now();
@@ -36,6 +42,16 @@ class DeadHost extends Model {
 		}
 	}
 
+	$parseDatabaseJson(json) {
+		json = super.$parseDatabaseJson(json);
+		return helpers.convertIntFieldsToBool(json, boolFields);
+	}
+
+	$formatDatabaseJson(json) {
+		json = helpers.convertBoolFieldsToInt(json, boolFields);
+		return super.$formatDatabaseJson(json);
+	}
+
 	static get name () {
 		return 'DeadHost';
 	}

+ 23 - 0
backend/models/proxy_host.js

@@ -2,6 +2,7 @@
 // http://vincit.github.io/objection.js/
 
 const db          = require('../db');
+const helpers     = require('../lib/helpers');
 const Model       = require('objection').Model;
 const User        = require('./user');
 const AccessList  = require('./access_list');
@@ -10,6 +11,18 @@ const now         = require('./now_helper');
 
 Model.knex(db);
 
+const boolFields = [
+	'is_deleted',
+	'ssl_forced',
+	'caching_enabled',
+	'block_exploits',
+	'allow_websocket_upgrade',
+	'http2_support',
+	'enabled',
+	'hsts_enabled',
+	'hsts_subdomains',
+];
+
 class ProxyHost extends Model {
 	$beforeInsert () {
 		this.created_on  = now();
@@ -37,6 +50,16 @@ class ProxyHost extends Model {
 		}
 	}
 
+	$parseDatabaseJson(json) {
+		json = super.$parseDatabaseJson(json);
+		return helpers.convertIntFieldsToBool(json, boolFields);
+	}
+
+	$formatDatabaseJson(json) {
+		json = helpers.convertBoolFieldsToInt(json, boolFields);
+		return super.$formatDatabaseJson(json);
+	}
+
 	static get name () {
 		return 'ProxyHost';
 	}

+ 19 - 0
backend/models/redirection_host.js

@@ -3,6 +3,7 @@
 // http://vincit.github.io/objection.js/
 
 const db          = require('../db');
+const helpers     = require('../lib/helpers');
 const Model       = require('objection').Model;
 const User        = require('./user');
 const Certificate = require('./certificate');
@@ -10,6 +11,14 @@ const now         = require('./now_helper');
 
 Model.knex(db);
 
+const boolFields = [
+	'is_deleted',
+	'enabled',
+	'preserve_path',
+	'ssl_forced',
+	'block_exploits',
+];
+
 class RedirectionHost extends Model {
 	$beforeInsert () {
 		this.created_on  = now();
@@ -37,6 +46,16 @@ class RedirectionHost extends Model {
 		}
 	}
 
+	$parseDatabaseJson(json) {
+		json = super.$parseDatabaseJson(json);
+		return helpers.convertIntFieldsToBool(json, boolFields);
+	}
+
+	$formatDatabaseJson(json) {
+		json = helpers.convertBoolFieldsToInt(json, boolFields);
+		return super.$formatDatabaseJson(json);
+	}
+
 	static get name () {
 		return 'RedirectionHost';
 	}

+ 21 - 4
backend/models/stream.js

@@ -1,13 +1,20 @@
 // Objection Docs:
 // http://vincit.github.io/objection.js/
 
-const db    = require('../db');
-const Model = require('objection').Model;
-const User  = require('./user');
-const now   = require('./now_helper');
+const db      = require('../db');
+const helpers = require('../lib/helpers');
+const Model   = require('objection').Model;
+const User    = require('./user');
+const now     = require('./now_helper');
 
 Model.knex(db);
 
+const boolFields = [
+	'is_deleted',
+	'tcp_forwarding',
+	'udp_forwarding',
+];
+
 class Stream extends Model {
 	$beforeInsert () {
 		this.created_on  = now();
@@ -23,6 +30,16 @@ class Stream extends Model {
 		this.modified_on = now();
 	}
 
+	$parseDatabaseJson(json) {
+		json = super.$parseDatabaseJson(json);
+		return helpers.convertIntFieldsToBool(json, boolFields);
+	}
+
+	$formatDatabaseJson(json) {
+		json = helpers.convertBoolFieldsToInt(json, boolFields);
+		return super.$formatDatabaseJson(json);
+	}
+
 	static get name () {
 		return 'Stream';
 	}

+ 16 - 0
backend/models/user.js

@@ -2,12 +2,18 @@
 // http://vincit.github.io/objection.js/
 
 const db             = require('../db');
+const helpers        = require('../lib/helpers');
 const Model          = require('objection').Model;
 const UserPermission = require('./user_permission');
 const now            = require('./now_helper');
 
 Model.knex(db);
 
+const boolFields = [
+	'is_deleted',
+	'is_disabled',
+];
+
 class User extends Model {
 	$beforeInsert () {
 		this.created_on  = now();
@@ -23,6 +29,16 @@ class User extends Model {
 		this.modified_on = now();
 	}
 
+	$parseDatabaseJson(json) {
+		json = super.$parseDatabaseJson(json);
+		return helpers.convertIntFieldsToBool(json, boolFields);
+	}
+
+	$formatDatabaseJson(json) {
+		json = helpers.convertBoolFieldsToInt(json, boolFields);
+		return super.$formatDatabaseJson(json);
+	}
+
 	static get name () {
 		return 'User';
 	}

+ 7 - 3
backend/package.json

@@ -2,10 +2,10 @@
 	"name": "nginx-proxy-manager",
 	"version": "0.0.0",
 	"description": "A beautiful interface for creating Nginx endpoints",
-	"main": "js/index.js",
+	"main": "index.js",
 	"dependencies": {
 		"@apidevtools/json-schema-ref-parser": "^11.7.0",
-		"ajv": "^6.12.0",
+		"ajv": "^8.17.1",
 		"archiver": "^5.3.0",
 		"batchflow": "^0.4.0",
 		"bcrypt": "^5.0.0",
@@ -14,7 +14,6 @@
 		"express": "^4.19.2",
 		"express-fileupload": "^1.1.9",
 		"gravatar": "^1.8.0",
-		"json-schema-ref-parser": "^8.0.0",
 		"jsonwebtoken": "^9.0.0",
 		"knex": "2.4.2",
 		"liquidjs": "10.6.1",
@@ -35,9 +34,14 @@
 	"author": "Jamie Curnow <[email protected]>",
 	"license": "MIT",
 	"devDependencies": {
+		"@apidevtools/swagger-parser": "^10.1.0",
+		"chalk": "4.1.2",
 		"eslint": "^8.36.0",
 		"eslint-plugin-align-assignments": "^1.1.2",
 		"nodemon": "^2.0.2",
 		"prettier": "^2.0.4"
+	},
+	"scripts": {
+		"validate-schema": "node validate-schema.js"
 	}
 }

+ 2 - 2
backend/routes/audit-log.js

@@ -29,10 +29,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				},
 				query: {
-					$ref: 'common#/definitions/query'
+					$ref: 'common#/properties/query'
 				}
 			}
 		}, {

+ 4 - 4
backend/routes/nginx/access_lists.js

@@ -31,10 +31,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				},
 				query: {
-					$ref: 'common#/definitions/query'
+					$ref: 'common#/properties/query'
 				}
 			}
 		}, {
@@ -91,10 +91,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				list_id: {
-					$ref: 'common#/definitions/id'
+					$ref: 'common#/properties/id'
 				},
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				}
 			}
 		}, {

+ 4 - 4
backend/routes/nginx/certificates.js

@@ -32,10 +32,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				},
 				query: {
-					$ref: 'common#/definitions/query'
+					$ref: 'common#/properties/query'
 				}
 			}
 		}, {
@@ -124,10 +124,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				certificate_id: {
-					$ref: 'common#/definitions/id'
+					$ref: 'common#/properties/id'
 				},
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				}
 			}
 		}, {

+ 4 - 4
backend/routes/nginx/dead_hosts.js

@@ -31,10 +31,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				},
 				query: {
-					$ref: 'common#/definitions/query'
+					$ref: 'common#/properties/query'
 				}
 			}
 		}, {
@@ -91,10 +91,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				host_id: {
-					$ref: 'common#/definitions/id'
+					$ref: 'common#/properties/id'
 				},
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				}
 			}
 		}, {

+ 4 - 4
backend/routes/nginx/proxy_hosts.js

@@ -31,10 +31,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				},
 				query: {
-					$ref: 'common#/definitions/query'
+					$ref: 'common#/properties/query'
 				}
 			}
 		}, {
@@ -91,10 +91,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				host_id: {
-					$ref: 'common#/definitions/id'
+					$ref: 'common#/properties/id'
 				},
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				}
 			}
 		}, {

+ 4 - 4
backend/routes/nginx/redirection_hosts.js

@@ -31,10 +31,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				},
 				query: {
-					$ref: 'common#/definitions/query'
+					$ref: 'common#/properties/query'
 				}
 			}
 		}, {
@@ -91,10 +91,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				host_id: {
-					$ref: 'common#/definitions/id'
+					$ref: 'common#/properties/id'
 				},
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				}
 			}
 		}, {

+ 4 - 4
backend/routes/nginx/streams.js

@@ -31,10 +31,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				},
 				query: {
-					$ref: 'common#/definitions/query'
+					$ref: 'common#/properties/query'
 				}
 			}
 		}, {
@@ -91,10 +91,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				stream_id: {
-					$ref: 'common#/definitions/id'
+					$ref: 'common#/properties/id'
 				},
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				}
 			}
 		}, {

+ 4 - 4
backend/routes/users.js

@@ -32,10 +32,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				},
 				query: {
-					$ref: 'common#/definitions/query'
+					$ref: 'common#/properties/query'
 				}
 			}
 		}, {
@@ -97,10 +97,10 @@ router
 			additionalProperties: false,
 			properties:           {
 				user_id: {
-					$ref: 'common#/definitions/id'
+					$ref: 'common#/properties/id'
 				},
 				expand: {
-					$ref: 'common#/definitions/expand'
+					$ref: 'common#/properties/expand'
 				}
 			}
 		}, {

+ 3 - 16
backend/schema/common.json

@@ -1,10 +1,10 @@
 {
-	"$schema": "http://json-schema.org/draft-07/schema#",
+	"$schema": "https://json-schema.org/draft/2020-12/schema",
 	"$id": "common",
-	"definitions": {
+	"type": "object",
+	"properties": {
 		"id": {
 			"description": "Unique identifier",
-			"example": 123456,
 			"readOnly": true,
 			"type": "integer",
 			"minimum": 1
@@ -37,25 +37,21 @@
 		},
 		"created_on": {
 			"description": "Date and time of creation",
-			"format": "date-time",
 			"readOnly": true,
 			"type": "string"
 		},
 		"modified_on": {
 			"description": "Date and time of last update",
-			"format": "date-time",
 			"readOnly": true,
 			"type": "string"
 		},
 		"user_id": {
 			"description": "User ID",
-			"example": 1234,
 			"type": "integer",
 			"minimum": 1
 		},
 		"certificate_id": {
 			"description": "Certificate ID",
-			"example": 1234,
 			"anyOf": [
 				{
 					"type": "integer",
@@ -69,13 +65,11 @@
 		},
 		"access_list_id": {
 			"description": "Access List ID",
-			"example": 1234,
 			"type": "integer",
 			"minimum": 0
 		},
 		"domain_names": {
 			"description": "Domain Names separated by a comma",
-			"example": "*.jc21.com,blog.jc21.com",
 			"type": "array",
 			"minItems": 1,
 			"maxItems": 100,
@@ -87,22 +81,18 @@
 		},
 		"enabled": {
 			"description": "Is Enabled",
-			"example": true,
 			"type": "boolean"
 		},
 		"ssl_forced": {
 			"description": "Is SSL Forced",
-			"example": false,
 			"type": "boolean"
 		},
 		"hsts_enabled": {
 			"description": "Is HSTS Enabled",
-			"example": false,
 			"type": "boolean"
 		},
 		"hsts_subdomains": {
 			"description": "Is HSTS applicable to all subdomains",
-			"example": false,
 			"type": "boolean"
 		},
 		"ssl_provider": {
@@ -111,17 +101,14 @@
 		},
 		"http2_support": {
 			"description": "HTTP2 Protocol Support",
-			"example": false,
 			"type": "boolean"
 		},
 		"block_exploits": {
 			"description": "Should we block common exploits",
-			"example": true,
 			"type": "boolean"
 		},
 		"caching_enabled": {
 			"description": "Should we cache assets",
-			"example": true,
 			"type": "boolean"
 		}
 	}

+ 4 - 4
backend/schema/components/access-list-object.json

@@ -5,16 +5,16 @@
 	"additionalProperties": false,
 	"properties": {
 		"id": {
-			"$ref": "../common.json#/definitions/id"
+			"$ref": "../common.json#/properties/id"
 		},
 		"created_on": {
-			"$ref": "../common.json#/definitions/created_on"
+			"$ref": "../common.json#/properties/created_on"
 		},
 		"modified_on": {
-			"$ref": "../common.json#/definitions/modified_on"
+			"$ref": "../common.json#/properties/modified_on"
 		},
 		"owner_user_id": {
-			"$ref": "../common.json#/definitions/user_id"
+			"$ref": "../common.json#/properties/user_id"
 		},
 		"name": {
 			"type": "string",

+ 5 - 5
backend/schema/components/audit-log-object.json

@@ -5,22 +5,22 @@
 	"additionalProperties": false,
 	"properties": {
 		"id": {
-			"$ref": "../common.json#/definitions/id"
+			"$ref": "../common.json#/properties/id"
 		},
 		"created_on": {
-			"$ref": "../common.json#/definitions/created_on"
+			"$ref": "../common.json#/properties/created_on"
 		},
 		"modified_on": {
-			"$ref": "../common.json#/definitions/modified_on"
+			"$ref": "../common.json#/properties/modified_on"
 		},
 		"user_id": {
-			"$ref": "../common.json#/definitions/user_id"
+			"$ref": "../common.json#/properties/user_id"
 		},
 		"object_type": {
 			"type": "string"
 		},
 		"object_id": {
-			"$ref": "../common.json#/definitions/id"
+			"$ref": "../common.json#/properties/id"
 		},
 		"action": {
 			"type": "string"

+ 7 - 9
backend/schema/components/certificate-object.json

@@ -5,30 +5,29 @@
 	"additionalProperties": false,
 	"properties": {
 		"id": {
-			"$ref": "../common.json#/definitions/id"
+			"$ref": "../common.json#/properties/id"
 		},
 		"created_on": {
-			"$ref": "../common.json#/definitions/created_on"
+			"$ref": "../common.json#/properties/created_on"
 		},
 		"modified_on": {
-			"$ref": "../common.json#/definitions/modified_on"
+			"$ref": "../common.json#/properties/modified_on"
 		},
 		"owner_user_id": {
-			"$ref": "../common.json#/definitions/user_id"
+			"$ref": "../common.json#/properties/user_id"
 		},
 		"provider": {
-			"$ref": "../common.json#/definitions/ssl_provider"
+			"$ref": "../common.json#/properties/ssl_provider"
 		},
 		"nice_name": {
 			"type": "string",
 			"description": "Nice Name for the custom certificate"
 		},
 		"domain_names": {
-			"$ref": "../common.json#/definitions/domain_names"
+			"$ref": "../common.json#/properties/domain_names"
 		},
 		"expires_on": {
 			"description": "Date and time of expiration",
-			"format": "date-time",
 			"readOnly": true,
 			"type": "string"
 		},
@@ -37,8 +36,7 @@
 			"additionalProperties": false,
 			"properties": {
 				"letsencrypt_email": {
-					"type": "string",
-					"format": "email"
+					"type": "string"
 				},
 				"letsencrypt_agree": {
 					"type": "boolean"

+ 11 - 11
backend/schema/components/dead-host-object.json

@@ -5,40 +5,40 @@
 	"additionalProperties": false,
 	"properties": {
 		"id": {
-			"$ref": "../common.json#/definitions/id"
+			"$ref": "../common.json#/properties/id"
 		},
 		"created_on": {
-			"$ref": "../common.json#/definitions/created_on"
+			"$ref": "../common.json#/properties/created_on"
 		},
 		"modified_on": {
-			"$ref": "../common.json#/definitions/modified_on"
+			"$ref": "../common.json#/properties/modified_on"
 		},
 		"owner_user_id": {
-			"$ref": "../common.json#/definitions/user_id"
+			"$ref": "../common.json#/properties/user_id"
 		},
 		"domain_names": {
-			"$ref": "../common.json#/definitions/domain_names"
+			"$ref": "../common.json#/properties/domain_names"
 		},
 		"certificate_id": {
-			"$ref": "../common.json#/definitions/certificate_id"
+			"$ref": "../common.json#/properties/certificate_id"
 		},
 		"ssl_forced": {
-			"$ref": "../common.json#/definitions/ssl_forced"
+			"$ref": "../common.json#/properties/ssl_forced"
 		},
 		"hsts_enabled": {
-			"$ref": "../common.json#/definitions/hsts_enabled"
+			"$ref": "../common.json#/properties/hsts_enabled"
 		},
 		"hsts_subdomains": {
-			"$ref": "../common.json#/definitions/hsts_subdomains"
+			"$ref": "../common.json#/properties/hsts_subdomains"
 		},
 		"http2_support": {
-			"$ref": "../common.json#/definitions/http2_support"
+			"$ref": "../common.json#/properties/http2_support"
 		},
 		"advanced_config": {
 			"type": "string"
 		},
 		"enabled": {
-			"$ref": "../common.json#/definitions/enabled"
+			"$ref": "../common.json#/properties/enabled"
 		},
 		"meta": {
 			"type": "object"

+ 30 - 16
backend/schema/components/proxy-host-object.json

@@ -30,19 +30,19 @@
 	"additionalProperties": false,
 	"properties": {
 		"id": {
-			"$ref": "../common.json#/definitions/id"
+			"$ref": "../common.json#/properties/id"
 		},
 		"created_on": {
-			"$ref": "../common.json#/definitions/created_on"
+			"$ref": "../common.json#/properties/created_on"
 		},
 		"modified_on": {
-			"$ref": "../common.json#/definitions/modified_on"
+			"$ref": "../common.json#/properties/modified_on"
 		},
 		"owner_user_id": {
-			"$ref": "../common.json#/definitions/user_id"
+			"$ref": "../common.json#/properties/user_id"
 		},
 		"domain_names": {
-			"$ref": "../common.json#/definitions/domain_names"
+			"$ref": "../common.json#/properties/domain_names"
 		},
 		"forward_host": {
 			"type": "string",
@@ -55,19 +55,19 @@
 			"maximum": 65535
 		},
 		"access_list_id": {
-			"$ref": "../common.json#/definitions/access_list_id"
+			"$ref": "../common.json#/properties/access_list_id"
 		},
 		"certificate_id": {
-			"$ref": "../common.json#/definitions/certificate_id"
+			"$ref": "../common.json#/properties/certificate_id"
 		},
 		"ssl_forced": {
-			"$ref": "../common.json#/definitions/ssl_forced"
+			"$ref": "../common.json#/properties/ssl_forced"
 		},
 		"caching_enabled": {
-			"$ref": "../common.json#/definitions/caching_enabled"
+			"$ref": "../common.json#/properties/caching_enabled"
 		},
 		"block_exploits": {
-			"$ref": "../common.json#/definitions/block_exploits"
+			"$ref": "../common.json#/properties/block_exploits"
 		},
 		"advanced_config": {
 			"type": "string"
@@ -81,14 +81,14 @@
 			"type": "boolean"
 		},
 		"http2_support": {
-			"$ref": "../common.json#/definitions/http2_support"
+			"$ref": "../common.json#/properties/http2_support"
 		},
 		"forward_scheme": {
 			"type": "string",
 			"enum": ["http", "https"]
 		},
 		"enabled": {
-			"$ref": "../common.json#/definitions/enabled"
+			"$ref": "../common.json#/properties/enabled"
 		},
 		"locations": {
 			"type": "array",
@@ -124,19 +124,33 @@
 			}
 		},
 		"hsts_enabled": {
-			"$ref": "../common.json#/definitions/hsts_enabled"
+			"$ref": "../common.json#/properties/hsts_enabled"
 		},
 		"hsts_subdomains": {
-			"$ref": "../common.json#/definitions/hsts_subdomains"
+			"$ref": "../common.json#/properties/hsts_subdomains"
 		},
 		"certificate": {
-			"$ref": "./certificate-object.json"
+			"oneOf": [
+				{
+					"type": "null"
+				},
+				{
+					"$ref": "./certificate-object.json"
+				}
+			]
 		},
 		"owner": {
 			"$ref": "./user-object.json"
 		},
 		"access_list": {
-			"$ref": "./access-list-object.json"
+			"oneOf": [
+				{
+					"type": "null"
+				},
+				{
+					"$ref": "./access-list-object.json"
+				}
+			]
 		},
 		"use_default_location": {
 			"type": "boolean"

+ 12 - 12
backend/schema/components/redirection-host-object.json

@@ -5,19 +5,19 @@
 	"additionalProperties": false,
 	"properties": {
 		"id": {
-			"$ref": "../common.json#/definitions/id"
+			"$ref": "../common.json#/properties/id"
 		},
 		"created_on": {
-			"$ref": "../common.json#/definitions/created_on"
+			"$ref": "../common.json#/properties/created_on"
 		},
 		"modified_on": {
-			"$ref": "../common.json#/definitions/modified_on"
+			"$ref": "../common.json#/properties/modified_on"
 		},
 		"owner_user_id": {
-			"$ref": "../common.json#/definitions/user_id"
+			"$ref": "../common.json#/properties/user_id"
 		},
 		"domain_names": {
-			"$ref": "../common.json#/definitions/domain_names"
+			"$ref": "../common.json#/properties/domain_names"
 		},
 		"forward_http_code": {
 			"description": "Redirect HTTP Status Code",
@@ -42,28 +42,28 @@
 			"type": "boolean"
 		},
 		"certificate_id": {
-			"$ref": "../common.json#/definitions/certificate_id"
+			"$ref": "../common.json#/properties/certificate_id"
 		},
 		"ssl_forced": {
-			"$ref": "../common.json#/definitions/ssl_forced"
+			"$ref": "../common.json#/properties/ssl_forced"
 		},
 		"hsts_enabled": {
-			"$ref": "../common.json#/definitions/hsts_enabled"
+			"$ref": "../common.json#/properties/hsts_enabled"
 		},
 		"hsts_subdomains": {
-			"$ref": "../common.json#/definitions/hsts_subdomains"
+			"$ref": "../common.json#/properties/hsts_subdomains"
 		},
 		"http2_support": {
-			"$ref": "../common.json#/definitions/http2_support"
+			"$ref": "../common.json#/properties/http2_support"
 		},
 		"block_exploits": {
-			"$ref": "../common.json#/definitions/block_exploits"
+			"$ref": "../common.json#/properties/block_exploits"
 		},
 		"advanced_config": {
 			"type": "string"
 		},
 		"enabled": {
-			"$ref": "../common.json#/definitions/enabled"
+			"$ref": "../common.json#/properties/enabled"
 		},
 		"meta": {
 			"type": "object"

+ 5 - 5
backend/schema/components/stream-object.json

@@ -5,16 +5,16 @@
 	"additionalProperties": false,
 	"properties": {
 		"id": {
-			"$ref": "../common.json#/definitions/id"
+			"$ref": "../common.json#/properties/id"
 		},
 		"created_on": {
-			"$ref": "../common.json#/definitions/created_on"
+			"$ref": "../common.json#/properties/created_on"
 		},
 		"modified_on": {
-			"$ref": "../common.json#/definitions/modified_on"
+			"$ref": "../common.json#/properties/modified_on"
 		},
 		"owner_user_id": {
-			"$ref": "../common.json#/definitions/user_id"
+			"$ref": "../common.json#/properties/user_id"
 		},
 		"incoming_port": {
 			"type": "integer",
@@ -51,7 +51,7 @@
 			"type": "boolean"
 		},
 		"enabled": {
-			"$ref": "../common.json#/definitions/enabled"
+			"$ref": "../common.json#/properties/enabled"
 		},
 		"meta": {
 			"type": "object"

+ 3 - 5
backend/schema/components/user-object.json

@@ -21,11 +21,9 @@
 			"example": "2020-01-30T09:41:04.000Z"
 		},
 		"is_disabled": {
-			"type": "integer",
-			"minimum": 0,
-			"maximum": 1,
-			"description": "Is user Disabled (0 = false, 1 = true)",
-			"example": 0
+			"type": "boolean",
+			"description": "Is user Disabled",
+			"example": true
 		},
 		"email": {
 			"type": "string",

+ 2 - 2
backend/schema/paths/nginx/access-lists/get.json

@@ -33,8 +33,8 @@
 									"owner_user_id": 1,
 									"name": "test1234",
 									"meta": {},
-									"satisfy_any": 1,
-									"pass_auth": 0,
+									"satisfy_any": true,
+									"pass_auth": false,
 									"proxy_host_count": 0
 								}
 							]

+ 1 - 1
backend/schema/paths/nginx/access-lists/listID/get.json

@@ -30,7 +30,7 @@
 								"id": 1,
 								"created_on": "2020-01-30T09:36:08.000Z",
 								"modified_on": "2020-01-30T09:41:04.000Z",
-								"is_disabled": 0,
+								"is_disabled": false,
 								"email": "[email protected]",
 								"name": "Jamie Curnow",
 								"nickname": "James",

+ 4 - 4
backend/schema/paths/nginx/access-lists/listID/put.json

@@ -102,15 +102,15 @@
 								"owner_user_id": 1,
 								"name": "test123!!",
 								"meta": {},
-								"satisfy_any": 1,
-								"pass_auth": 0,
+								"satisfy_any": true,
+								"pass_auth": false,
 								"proxy_host_count": 0,
 								"owner": {
 									"id": 1,
 									"created_on": "2024-10-07T22:43:55.000Z",
 									"modified_on": "2024-10-08T12:52:54.000Z",
-									"is_deleted": 0,
-									"is_disabled": 0,
+									"is_deleted": false,
+									"is_disabled": false,
 									"email": "[email protected]",
 									"name": "Administrator",
 									"nickname": "some guy",

+ 4 - 4
backend/schema/paths/nginx/access-lists/post.json

@@ -93,15 +93,15 @@
 								"owner_user_id": 1,
 								"name": "test1234",
 								"meta": {},
-								"satisfy_any": 1,
-								"pass_auth": 0,
+								"satisfy_any": true,
+								"pass_auth": false,
 								"proxy_host_count": 0,
 								"owner": {
 									"id": 1,
 									"created_on": "2024-10-07T22:43:55.000Z",
 									"modified_on": "2024-10-08T12:52:54.000Z",
-									"is_deleted": 0,
-									"is_disabled": 0,
+									"is_deleted": false,
+									"is_disabled": false,
 									"email": "[email protected]",
 									"name": "Administrator",
 									"nickname": "some guy",

+ 1 - 1
backend/schema/paths/nginx/certificates/certID/renew/post.json

@@ -32,7 +32,7 @@
 								"id": 4,
 								"created_on": "2024-10-09T05:31:58.000Z",
 								"owner_user_id": 1,
-								"is_deleted": 0,
+								"is_deleted": false,
 								"provider": "letsencrypt",
 								"nice_name": "My Test Cert",
 								"domain_names": ["test.jc21.supernerd.pro"],

+ 1 - 1
backend/schema/paths/nginx/certificates/post.json

@@ -47,7 +47,7 @@
 								"id": 5,
 								"created_on": "2024-10-09 05:28:35",
 								"owner_user_id": 1,
-								"is_deleted": 0,
+								"is_deleted": false,
 								"provider": "letsencrypt",
 								"nice_name": "test.example.com",
 								"domain_names": ["test.example.com"],

+ 5 - 5
backend/schema/paths/nginx/dead-hosts/get.json

@@ -33,16 +33,16 @@
 									"owner_user_id": 1,
 									"domain_names": ["test.example.com"],
 									"certificate_id": 0,
-									"ssl_forced": 0,
+									"ssl_forced": false,
 									"advanced_config": "",
 									"meta": {
 										"nginx_online": true,
 										"nginx_err": null
 									},
-									"http2_support": 0,
-									"enabled": 1,
-									"hsts_enabled": 0,
-									"hsts_subdomains": 0
+									"http2_support": false,
+									"enabled": true,
+									"hsts_enabled": false,
+									"hsts_subdomains": false
 								}
 							]
 						}

+ 5 - 5
backend/schema/paths/nginx/dead-hosts/hostID/get.json

@@ -33,16 +33,16 @@
 								"owner_user_id": 1,
 								"domain_names": ["test.example.com"],
 								"certificate_id": 0,
-								"ssl_forced": 0,
+								"ssl_forced": false,
 								"advanced_config": "",
 								"meta": {
 									"nginx_online": true,
 									"nginx_err": null
 								},
-								"http2_support": 0,
-								"enabled": 1,
-								"hsts_enabled": 0,
-								"hsts_subdomains": 0
+								"http2_support": false,
+								"enabled": true,
+								"hsts_enabled": false,
+								"hsts_subdomains": false
 							}
 						}
 					},

+ 7 - 7
backend/schema/paths/nginx/dead-hosts/hostID/put.json

@@ -72,22 +72,22 @@
 								"owner_user_id": 1,
 								"domain_names": ["test.example.com"],
 								"certificate_id": 0,
-								"ssl_forced": 0,
+								"ssl_forced": false,
 								"advanced_config": "",
 								"meta": {
 									"nginx_online": true,
 									"nginx_err": null
 								},
-								"http2_support": 0,
-								"enabled": 1,
-								"hsts_enabled": 0,
-								"hsts_subdomains": 0,
+								"http2_support": false,
+								"enabled": true,
+								"hsts_enabled": false,
+								"hsts_subdomains": false,
 								"owner": {
 									"id": 1,
 									"created_on": "2024-10-09T00:59:56.000Z",
 									"modified_on": "2024-10-09T00:59:56.000Z",
-									"is_deleted": 0,
-									"is_disabled": 0,
+									"is_deleted": false,
+									"is_disabled": false,
 									"email": "[email protected]",
 									"name": "Administrator",
 									"nickname": "Admin",

+ 7 - 7
backend/schema/paths/nginx/dead-hosts/post.json

@@ -60,20 +60,20 @@
 								"owner_user_id": 1,
 								"domain_names": ["test.example.com"],
 								"certificate_id": 0,
-								"ssl_forced": 0,
+								"ssl_forced": false,
 								"advanced_config": "",
 								"meta": {},
-								"http2_support": 0,
-								"enabled": 1,
-								"hsts_enabled": 0,
-								"hsts_subdomains": 0,
+								"http2_support": false,
+								"enabled": true,
+								"hsts_enabled": false,
+								"hsts_subdomains": false,
 								"certificate": null,
 								"owner": {
 									"id": 1,
 									"created_on": "2024-10-09T00:59:56.000Z",
 									"modified_on": "2024-10-09T00:59:56.000Z",
-									"is_deleted": 0,
-									"is_disabled": 0,
+									"is_deleted": false,
+									"is_disabled": false,
 									"email": "[email protected]",
 									"name": "Administrator",
 									"nickname": "Admin",

+ 8 - 8
backend/schema/paths/nginx/proxy-hosts/get.json

@@ -36,21 +36,21 @@
 									"forward_port": 8989,
 									"access_list_id": 0,
 									"certificate_id": 0,
-									"ssl_forced": 0,
-									"caching_enabled": 0,
-									"block_exploits": 0,
+									"ssl_forced": false,
+									"caching_enabled": false,
+									"block_exploits": false,
 									"advanced_config": "",
 									"meta": {
 										"nginx_online": true,
 										"nginx_err": null
 									},
-									"allow_websocket_upgrade": 0,
-									"http2_support": 0,
+									"allow_websocket_upgrade": false,
+									"http2_support": false,
 									"forward_scheme": "http",
-									"enabled": 1,
+									"enabled": true,
 									"locations": null,
-									"hsts_enabled": 0,
-									"hsts_subdomains": 0
+									"hsts_enabled": false,
+									"hsts_subdomains": false
 								}
 							]
 						}

+ 8 - 8
backend/schema/paths/nginx/proxy-hosts/hostID/get.json

@@ -36,21 +36,21 @@
 								"forward_port": 8989,
 								"access_list_id": 0,
 								"certificate_id": 0,
-								"ssl_forced": 0,
-								"caching_enabled": 0,
-								"block_exploits": 0,
+								"ssl_forced": false,
+								"caching_enabled": false,
+								"block_exploits": false,
 								"advanced_config": "",
 								"meta": {
 									"nginx_online": true,
 									"nginx_err": null
 								},
-								"allow_websocket_upgrade": 0,
-								"http2_support": 0,
+								"allow_websocket_upgrade": false,
+								"http2_support": false,
 								"forward_scheme": "http",
-								"enabled": 1,
+								"enabled": true,
 								"locations": null,
-								"hsts_enabled": 0,
-								"hsts_subdomains": 0
+								"hsts_enabled": false,
+								"hsts_subdomains": false
 							}
 						}
 					},

+ 10 - 10
backend/schema/paths/nginx/proxy-hosts/hostID/put.json

@@ -102,26 +102,26 @@
 								"forward_port": 8989,
 								"access_list_id": 0,
 								"certificate_id": 0,
-								"ssl_forced": 0,
-								"caching_enabled": 0,
-								"block_exploits": 0,
+								"ssl_forced": false,
+								"caching_enabled": false,
+								"block_exploits": false,
 								"advanced_config": "",
 								"meta": {
 									"nginx_online": true,
 									"nginx_err": null
 								},
-								"allow_websocket_upgrade": 0,
-								"http2_support": 0,
+								"allow_websocket_upgrade": false,
+								"http2_support": false,
 								"forward_scheme": "http",
-								"enabled": 1,
-								"hsts_enabled": 0,
-								"hsts_subdomains": 0,
+								"enabled": true,
+								"hsts_enabled": false,
+								"hsts_subdomains": false,
 								"owner": {
 									"id": 1,
 									"created_on": "2024-10-07T22:43:55.000Z",
 									"modified_on": "2024-10-08T12:52:54.000Z",
-									"is_deleted": 0,
-									"is_disabled": 0,
+									"is_deleted": false,
+									"is_disabled": false,
 									"email": "[email protected]",
 									"name": "Administrator",
 									"nickname": "some guy",

+ 10 - 10
backend/schema/paths/nginx/proxy-hosts/post.json

@@ -90,24 +90,24 @@
 								"forward_port": 8989,
 								"access_list_id": 0,
 								"certificate_id": 0,
-								"ssl_forced": 0,
-								"caching_enabled": 0,
-								"block_exploits": 0,
+								"ssl_forced": false,
+								"caching_enabled": false,
+								"block_exploits": false,
 								"advanced_config": "",
 								"meta": {},
-								"allow_websocket_upgrade": 0,
-								"http2_support": 0,
+								"allow_websocket_upgrade": false,
+								"http2_support": false,
 								"forward_scheme": "http",
-								"enabled": 1,
-								"hsts_enabled": 0,
-								"hsts_subdomains": 0,
+								"enabled": true,
+								"hsts_enabled": false,
+								"hsts_subdomains": false,
 								"certificate": null,
 								"owner": {
 									"id": 1,
 									"created_on": "2024-10-07T22:43:55.000Z",
 									"modified_on": "2024-10-08T12:52:54.000Z",
-									"is_deleted": 0,
-									"is_disabled": 0,
+									"is_deleted": false,
+									"is_disabled": false,
 									"email": "[email protected]",
 									"name": "Administrator",
 									"nickname": "some guy",

+ 7 - 7
backend/schema/paths/nginx/redirection-hosts/get.json

@@ -33,19 +33,19 @@
 									"owner_user_id": 1,
 									"domain_names": ["test.example.com"],
 									"forward_domain_name": "something-else.com",
-									"preserve_path": 0,
+									"preserve_path": false,
 									"certificate_id": 0,
-									"ssl_forced": 0,
-									"block_exploits": 0,
+									"ssl_forced": false,
+									"block_exploits": false,
 									"advanced_config": "",
 									"meta": {
 										"nginx_online": true,
 										"nginx_err": null
 									},
-									"http2_support": 0,
-									"enabled": 1,
-									"hsts_enabled": 0,
-									"hsts_subdomains": 0,
+									"http2_support": false,
+									"enabled": true,
+									"hsts_enabled": false,
+									"hsts_subdomains": false,
 									"forward_scheme": "http",
 									"forward_http_code": 301
 								}

+ 7 - 7
backend/schema/paths/nginx/redirection-hosts/hostID/get.json

@@ -33,19 +33,19 @@
 								"owner_user_id": 1,
 								"domain_names": ["test.example.com"],
 								"forward_domain_name": "something-else.com",
-								"preserve_path": 0,
+								"preserve_path": false,
 								"certificate_id": 0,
-								"ssl_forced": 0,
-								"block_exploits": 0,
+								"ssl_forced": false,
+								"block_exploits": false,
 								"advanced_config": "",
 								"meta": {
 									"nginx_online": true,
 									"nginx_err": null
 								},
-								"http2_support": 0,
-								"enabled": 1,
-								"hsts_enabled": 0,
-								"hsts_subdomains": 0,
+								"http2_support": false,
+								"enabled": true,
+								"hsts_enabled": false,
+								"hsts_subdomains": false,
 								"forward_scheme": "http",
 								"forward_http_code": 301
 							}

+ 9 - 9
backend/schema/paths/nginx/redirection-hosts/hostID/put.json

@@ -87,27 +87,27 @@
 								"owner_user_id": 1,
 								"domain_names": ["test.example.com"],
 								"forward_domain_name": "something-else.com",
-								"preserve_path": 0,
+								"preserve_path": false,
 								"certificate_id": 0,
-								"ssl_forced": 0,
-								"block_exploits": 0,
+								"ssl_forced": false,
+								"block_exploits": false,
 								"advanced_config": "",
 								"meta": {
 									"nginx_online": true,
 									"nginx_err": null
 								},
-								"http2_support": 0,
-								"enabled": 1,
-								"hsts_enabled": 0,
-								"hsts_subdomains": 0,
+								"http2_support": false,
+								"enabled": true,
+								"hsts_enabled": false,
+								"hsts_subdomains": false,
 								"forward_scheme": "http",
 								"forward_http_code": 301,
 								"owner": {
 									"id": 1,
 									"created_on": "2024-10-09T00:59:56.000Z",
 									"modified_on": "2024-10-09T00:59:56.000Z",
-									"is_deleted": 0,
-									"is_disabled": 0,
+									"is_deleted": false,
+									"is_disabled": false,
 									"email": "[email protected]",
 									"name": "Administrator",
 									"nickname": "Admin",

+ 9 - 9
backend/schema/paths/nginx/redirection-hosts/post.json

@@ -75,16 +75,16 @@
 								"owner_user_id": 1,
 								"domain_names": ["test.example.com"],
 								"forward_domain_name": "something-else.com",
-								"preserve_path": 0,
+								"preserve_path": false,
 								"certificate_id": 0,
-								"ssl_forced": 0,
-								"block_exploits": 0,
+								"ssl_forced": false,
+								"block_exploits": false,
 								"advanced_config": "",
 								"meta": {},
-								"http2_support": 0,
-								"enabled": 1,
-								"hsts_enabled": 0,
-								"hsts_subdomains": 0,
+								"http2_support": false,
+								"enabled": true,
+								"hsts_enabled": false,
+								"hsts_subdomains": false,
 								"forward_scheme": "http",
 								"forward_http_code": 301,
 								"certificate": null,
@@ -92,8 +92,8 @@
 									"id": 1,
 									"created_on": "2024-10-09T00:59:56.000Z",
 									"modified_on": "2024-10-09T00:59:56.000Z",
-									"is_deleted": 0,
-									"is_disabled": 0,
+									"is_deleted": false,
+									"is_disabled": false,
 									"email": "[email protected]",
 									"name": "Administrator",
 									"nickname": "Admin",

+ 3 - 3
backend/schema/paths/nginx/streams/get.json

@@ -34,13 +34,13 @@
 									"incoming_port": 9090,
 									"forwarding_host": "router.internal",
 									"forwarding_port": 80,
-									"tcp_forwarding": 0,
-									"udp_forwarding": 0,
+									"tcp_forwarding": true,
+									"udp_forwarding": false,
 									"meta": {
 										"nginx_online": true,
 										"nginx_err": null
 									},
-									"enabled": 1
+									"enabled": true
 								}
 							]
 						}

+ 5 - 5
backend/schema/paths/nginx/streams/post.json

@@ -55,19 +55,19 @@
 								"incoming_port": 9090,
 								"forwarding_host": "router.internal",
 								"forwarding_port": 80,
-								"tcp_forwarding": 0,
-								"udp_forwarding": 0,
+								"tcp_forwarding": true,
+								"udp_forwarding": false,
 								"meta": {
 									"nginx_online": true,
 									"nginx_err": null
 								},
-								"enabled": 1,
+								"enabled": true,
 								"owner": {
 									"id": 1,
 									"created_on": "2024-10-09T02:33:16.000Z",
 									"modified_on": "2024-10-09T02:33:16.000Z",
-									"is_deleted": 0,
-									"is_disabled": 0,
+									"is_deleted": false,
+									"is_disabled": false,
 									"email": "[email protected]",
 									"name": "Administrator",
 									"nickname": "Admin",

+ 3 - 3
backend/schema/paths/nginx/streams/streamID/get.json

@@ -34,13 +34,13 @@
 								"incoming_port": 9090,
 								"forwarding_host": "router.internal",
 								"forwarding_port": 80,
-								"tcp_forwarding": 0,
-								"udp_forwarding": 0,
+								"tcp_forwarding": true,
+								"udp_forwarding": false,
 								"meta": {
 									"nginx_online": true,
 									"nginx_err": null
 								},
-								"enabled": 1
+								"enabled": true
 							}
 						}
 					},

+ 10 - 10
backend/schema/paths/nginx/streams/streamID/put.json

@@ -102,26 +102,26 @@
 								"forward_port": 8989,
 								"access_list_id": 0,
 								"certificate_id": 0,
-								"ssl_forced": 0,
-								"caching_enabled": 0,
-								"block_exploits": 0,
+								"ssl_forced": false,
+								"caching_enabled": false,
+								"block_exploits": false,
 								"advanced_config": "",
 								"meta": {
 									"nginx_online": true,
 									"nginx_err": null
 								},
-								"allow_websocket_upgrade": 0,
-								"http2_support": 0,
+								"allow_websocket_upgrade": false,
+								"http2_support": false,
 								"forward_scheme": "http",
-								"enabled": 1,
-								"hsts_enabled": 0,
-								"hsts_subdomains": 0,
+								"enabled": true,
+								"hsts_enabled": false,
+								"hsts_subdomains": false,
 								"owner": {
 									"id": 1,
 									"created_on": "2024-10-07T22:43:55.000Z",
 									"modified_on": "2024-10-08T12:52:54.000Z",
-									"is_deleted": 0,
-									"is_disabled": 0,
+									"is_deleted": false,
+									"is_disabled": false,
 									"email": "[email protected]",
 									"name": "Administrator",
 									"nickname": "some guy",

+ 2 - 2
backend/schema/paths/users/get.json

@@ -30,7 +30,7 @@
 									"id": 1,
 									"created_on": "2020-01-30T09:36:08.000Z",
 									"modified_on": "2020-01-30T09:41:04.000Z",
-									"is_disabled": 0,
+									"is_disabled": false,
 									"email": "[email protected]",
 									"name": "Jamie Curnow",
 									"nickname": "James",
@@ -45,7 +45,7 @@
 									"id": 1,
 									"created_on": "2020-01-30T09:36:08.000Z",
 									"modified_on": "2020-01-30T09:41:04.000Z",
-									"is_disabled": 0,
+									"is_disabled": false,
 									"email": "[email protected]",
 									"name": "Jamie Curnow",
 									"nickname": "James",

+ 1 - 1
backend/schema/paths/users/post.json

@@ -56,7 +56,7 @@
 								"id": 2,
 								"created_on": "2020-01-30T09:41:04.000Z",
 								"modified_on": "2020-01-30T09:41:04.000Z",
-								"is_disabled": 0,
+								"is_disabled": false,
 								"email": "[email protected]",
 								"name": "Jamie Curnow",
 								"nickname": "James",

+ 1 - 1
backend/schema/paths/users/userID/get.json

@@ -39,7 +39,7 @@
 								"id": 1,
 								"created_on": "2020-01-30T09:36:08.000Z",
 								"modified_on": "2020-01-30T09:41:04.000Z",
-								"is_disabled": 0,
+								"is_disabled": false,
 								"email": "[email protected]",
 								"name": "Jamie Curnow",
 								"nickname": "James",

+ 1 - 1
backend/schema/paths/users/userID/login/post.json

@@ -34,7 +34,7 @@
 									"id": 1,
 									"created_on": "2020-01-30T10:43:44.000Z",
 									"modified_on": "2020-01-30T10:43:44.000Z",
-									"is_disabled": 0,
+									"is_disabled": false,
 									"email": "[email protected]",
 									"name": "Jamie Curnow",
 									"nickname": "James",

+ 1 - 1
backend/schema/paths/users/userID/put.json

@@ -69,7 +69,7 @@
 								"id": 2,
 								"created_on": "2020-01-30T09:36:08.000Z",
 								"modified_on": "2020-01-30T09:41:04.000Z",
-								"is_disabled": 0,
+								"is_disabled": false,
 								"email": "[email protected]",
 								"name": "Jamie Curnow",
 								"nickname": "James",

+ 1 - 1
backend/schema/swagger.json

@@ -1,5 +1,5 @@
 {
-	"openapi": "3.0.0",
+	"openapi": "3.1.0",
 	"info": {
 		"title": "Nginx Proxy Manager API",
 		"version": "2.x.x"

+ 16 - 0
backend/validate-schema.js

@@ -0,0 +1,16 @@
+const SwaggerParser = require('@apidevtools/swagger-parser');
+const chalk         = require('chalk');
+const schema        = require('./schema');
+const log           = console.log;
+
+schema.getCompiledSchema().then(async (swaggerJSON) => {
+	try {
+		const api = await SwaggerParser.validate(swaggerJSON);
+		console.log('API name: %s, Version: %s', api.info.title, api.info.version);
+		log(chalk.green('❯ Schema is valid'));
+	} catch (e) {
+		console.error(e);
+		log(chalk.red('❯', e.message), '\n');
+		process.exit(1);
+	}
+});

+ 58 - 22
backend/yarn.lock

@@ -2,12 +2,12 @@
 # yarn lockfile v1
 
 
-"@apidevtools/json-schema-ref-parser@8.0.0":
-  version "8.0.0"
-  resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-8.0.0.tgz#9eb749499b3f8d919e90bb141e4b6f67aee4692d"
-  integrity sha512-n4YBtwQhdpLto1BaUCyAeflizmIbaloGShsPyRtFf5qdFJxfssj+GgLavczgKJFa3Bq+3St2CKcpRJdjtB4EBw==
+"@apidevtools/json-schema-ref-parser@9.0.6":
+  version "9.0.6"
+  resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz#5d9000a3ac1fd25404da886da6b266adcd99cf1c"
+  integrity sha512-M3YgsLjI0lZxvrpeGVk9Ap032W6TPQkH6pRAZz81Ac3WUNF79VQooAFnp8umjvVzUmD93NkogxEwbSce7qMsUg==
   dependencies:
-    "@jsdevtools/ono" "^7.1.0"
+    "@jsdevtools/ono" "^7.1.3"
     call-me-maybe "^1.0.1"
     js-yaml "^3.13.1"
 
@@ -20,6 +20,29 @@
     "@types/json-schema" "^7.0.15"
     js-yaml "^4.1.0"
 
+"@apidevtools/openapi-schemas@^2.1.0":
+  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.1.0":
+  version "10.1.0"
+  resolved "https://registry.yarnpkg.com/@apidevtools/swagger-parser/-/swagger-parser-10.1.0.tgz#a987d71e5be61feb623203be0c96e5985b192ab6"
+  integrity sha512-9Kt7EuS/7WbMAUv2gSziqjvxwDbFSg3Xeyfuj5laUODX8o/k/CpsAKiQ8W7/R88eXFTMbJYg6+7uAmOWNKmwnw==
+  dependencies:
+    "@apidevtools/json-schema-ref-parser" "9.0.6"
+    "@apidevtools/openapi-schemas" "^2.1.0"
+    "@apidevtools/swagger-methods" "^3.0.2"
+    "@jsdevtools/ono" "^7.1.3"
+    ajv "^8.6.3"
+    ajv-draft-04 "^1.0.0"
+    call-me-maybe "^1.0.1"
+
 "@eslint-community/eslint-utils@^4.2.0":
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz#a556790523a351b4e47e9d385f47265eaaf9780a"
@@ -76,7 +99,7 @@
   resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
   integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
 
-"@jsdevtools/ono@^7.1.0", "@jsdevtools/ono@^7.1.3":
+"@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==
@@ -207,7 +230,12 @@ aggregate-error@^3.0.0:
     clean-stack "^2.0.0"
     indent-string "^4.0.0"
 
-ajv@^6.10.0, ajv@^6.12.0, ajv@^6.12.4:
+ajv-draft-04@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8"
+  integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==
+
+ajv@^6.10.0, ajv@^6.12.4:
   version "6.12.6"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
   integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
@@ -217,6 +245,16 @@ ajv@^6.10.0, ajv@^6.12.0, ajv@^6.12.4:
     json-schema-traverse "^0.4.1"
     uri-js "^4.2.2"
 
+ajv@^8.17.1, ajv@^8.6.3:
+  version "8.17.1"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6"
+  integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==
+  dependencies:
+    fast-deep-equal "^3.1.3"
+    fast-uri "^3.0.1"
+    json-schema-traverse "^1.0.0"
+    require-from-string "^2.0.2"
+
 ajv@^8.6.2:
   version "8.12.0"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1"
@@ -566,6 +604,14 @@ camelcase@^5.0.0, camelcase@^5.3.1:
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
   integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
 
[email protected], chalk@^4.0.0:
+  version "4.1.2"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+  integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+  dependencies:
+    ansi-styles "^4.1.0"
+    supports-color "^7.1.0"
+
 chalk@^2.3.2:
   version "2.4.2"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
@@ -583,14 +629,6 @@ chalk@^3.0.0:
     ansi-styles "^4.1.0"
     supports-color "^7.1.0"
 
-chalk@^4.0.0:
-  version "4.1.2"
-  resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
-  integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
-  dependencies:
-    ansi-styles "^4.1.0"
-    supports-color "^7.1.0"
-
 chokidar@^3.2.2:
   version "3.4.1"
   resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.1.tgz#e905bdecf10eaa0a0b1db0c664481cc4cbc22ba1"
@@ -1199,6 +1237,11 @@ fast-levenshtein@^2.0.6:
   resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
   integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
 
+fast-uri@^3.0.1:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.2.tgz#d78b298cf70fd3b752fd951175a3da6a7b48f024"
+  integrity sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==
+
 fastq@^1.6.0:
   version "1.15.0"
   resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
@@ -1870,13 +1913,6 @@ json-parse-better-errors@^1.0.1:
   resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
   integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
 
-json-schema-ref-parser@^8.0.0:
-  version "8.0.0"
-  resolved "https://registry.yarnpkg.com/json-schema-ref-parser/-/json-schema-ref-parser-8.0.0.tgz#7c758fac2cf822c05e837abd0a13f8fa2c15ffd4"
-  integrity sha512-2P4icmNkZLrBr6oa5gSZaDSol/oaBHYkoP/8dsw63E54NnHGRhhiFuy9yFoxPuSm+uHKmeGxAAWMDF16SCHhcQ==
-  dependencies:
-    "@apidevtools/json-schema-ref-parser" "8.0.0"
-
 json-schema-traverse@^0.4.1:
   version "0.4.1"
   resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"

+ 1 - 1
test/cypress/e2e/api/Health.cy.js

@@ -14,7 +14,7 @@ describe('Basic API checks', () => {
 		cy.task('backendApiGet', {
 			path: '/api/schema',
 		}).then((data) => {
-			expect(data.openapi).to.be.equal('3.0.0');
+			expect(data.openapi).to.be.equal('3.1.0');
 		});
 	});
 });

+ 1 - 1
test/cypress/e2e/api/Hosts.cy.js

@@ -39,7 +39,7 @@ describe('Hosts endpoints', () => {
 			expect(data).to.have.property('id');
 			expect(data.id).to.be.greaterThan(0);
 			expect(data).to.have.property('enabled');
-			expect(data.enabled).to.be.greaterThan(0);
+			expect(data).to.have.property("enabled", true);
 			expect(data).to.have.property('meta');
 			expect(typeof data.meta.nginx_online).to.be.equal('undefined');
 		});

+ 2 - 7
test/cypress/plugins/backendApi/logger.js

@@ -1,12 +1,7 @@
 const _ = require("lodash");
-const chalk = require("chalk");
 
 module.exports = function() {
-	var arr = _.values(arguments);
-	arr.unshift(
-		chalk.blue.bold("[") +
-			chalk.yellow.bold("Backend API") +
-			chalk.blue.bold("]"),
-	);
+	let arr = _.values(arguments);
+	arr.unshift('[Backend API]');
 	console.log.apply(null, arr);
 };

+ 8 - 9
test/package.json

@@ -6,21 +6,20 @@
 	"dependencies": {
 		"@jc21/cypress-swagger-validation": "^0.2.6",
 		"@jc21/restler": "^3.4.0",
-		"chalk": "^4.1.0",
-		"cypress": "^13.9.0",
+		"cypress": "^13.15.0",
 		"cypress-multi-reporters": "^1.6.4",
-		"cypress-wait-until": "^3.0.1",
-		"eslint": "^9.3.0",
+		"cypress-wait-until": "^3.0.2",
+		"eslint": "^9.12.0",
 		"eslint-plugin-align-assignments": "^1.1.2",
-		"eslint-plugin-chai-friendly": "^0.7.4",
-		"eslint-plugin-cypress": "^3.2.0",
+		"eslint-plugin-chai-friendly": "^1.0.1",
+		"eslint-plugin-cypress": "^3.5.0",
 		"lodash": "^4.17.21",
-		"mocha": "^10.4.0",
+		"mocha": "^10.7.3",
 		"mocha-junit-reporter": "^2.2.1"
 	},
 	"scripts": {
-		"cypress": "cypress open --config-file=cypress/config/dev.json --config baseUrl=${BASE_URL:-http://127.0.0.1:3081}",
-		"cypress:headless": "cypress run --config-file=cypress/config/dev.json --config baseUrl=${BASE_URL:-http://127.0.0.1:3081}"
+		"cypress": "cypress open --config-file=cypress/config/dev.js --config baseUrl=${BASE_URL:-http://127.0.0.1:3081}",
+		"cypress:headless": "cypress run --config-file=cypress/config/dev.js --config baseUrl=${BASE_URL:-http://127.0.0.1:3081}"
 	},
 	"author": "",
 	"license": "ISC"

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 318 - 271
test/yarn.lock


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä