Compare commits

..

55 Commits

Author SHA1 Message Date
5084cb7296 Merge pull request #4077 from NginxProxyManager/develop
v2.12.1
2024-10-17 09:49:07 +10:00
2f9e062718 bump version 2024-10-17 09:05:25 +10:00
edbed1af90 Adds tests for settings endpoints
and reenables dns cert test
and fixes problems with schema
2024-10-17 08:48:47 +10:00
8497022e41 Merge pull request #4076 from Nephiel/4074-fix-1
All checks were successful
Close stale issues and PRs / stale (push) Successful in 5s
Fix schema validation errors
2024-10-17 07:07:05 +10:00
fa2c814fcb Fix schema validation in Default Site
Should solve error `data/value must match exactly one schema in oneOf` when setting the Default Site to 404 or 444. #4074
2024-10-16 19:09:14 +00:00
d96a3987c0 Fix forward_scheme validation in Redirection Host
Should solve error `data/forward_scheme must be equal to one of the allowed values` when configuring a Redirection Host with scheme set to `auto`. #4074
2024-10-16 19:04:50 +00:00
e677bfa2e8 Merge pull request #4073 from NginxProxyManager/develop
v2.12.0
2024-10-16 15:41:55 +10:00
fe2d8895d6 Cypress test for http and dns cert provision 2024-10-16 14:53:57 +10:00
5bdc05878f Fix issues with certbot command when using LE_SERVER 2024-10-16 11:23:58 +10:00
929ac3bd7c Adds env var to set certbot acme server
this is required for test suite to use dns certbot request
without talking to live or staging letsencrypt servers or
production level dns providers. This is a backwards port
from the v3 branch and opens the door for a full certificate
cypress test
2024-10-16 11:06:29 +10:00
f48e1b46a8 Updated swagger cypress package,
which works with proxies
2024-10-16 08:32:49 +10:00
351ba8dacd More tests for certificates, fixed schema problems 2024-10-16 08:32:49 +10:00
3b89d5f380 Merge pull request #4068 from Hadatko/fixWedosParamDescription
All checks were successful
Close stale issues and PRs / stale (push) Successful in 5s
fixed wedos password description
2024-10-15 10:23:33 +10:00
e5aa880ec4 fixed wedos password description
Signed-off-by: Dusan Cervenka <cervenka.dusan@gmail.com>
2024-10-15 01:58:15 +02:00
7322d35bd7 Fix CI
All checks were successful
Close stale issues and PRs / stale (push) Successful in 4s
2024-10-14 07:39:50 +10:00
81b89185f2 Squid ci fixes
All checks were successful
Close stale issues and PRs / stale (push) Successful in 4s
2024-10-13 22:15:18 +10:00
f2bb8f2b3d Squid ci fixes 2024-10-13 22:04:07 +10:00
b01817bc7f Adds squid to dev/CI stacks
- for testing forwarded ip address later
2024-10-13 21:54:58 +10:00
5aeb99b856 Version bump
All checks were successful
Close stale issues and PRs / stale (push) Successful in 4s
2024-10-11 15:28:24 +10:00
e7e4003d15 Merge pull request #4053 from NginxProxyManager/master
Master
2024-10-11 15:26:06 +10:00
78f3e7281b Merge pull request #4015 from NginxProxyManager/dependabot/npm_and_yarn/backend/express-4.20.0
Bump express from 4.19.2 to 4.20.0 in /backend
2024-10-11 15:18:36 +10:00
c9d97aff38 Merge pull request #4052 from NginxProxyManager/dependabot/npm_and_yarn/test/braces-3.0.3
Bump braces from 3.0.2 to 3.0.3 in /test
2024-10-11 15:18:15 +10:00
9813071e76 Merge pull request #3864 from ROSEBikesGmbH/egobude-add-edge-dns-by-akamai
Add Edge DNS by Akamai
2024-10-11 14:16:39 +10:00
d7a7fa3496 Merge pull request #3907 from rockenstein-AG/develop
Add rockenstein AG DNS Plugin
2024-10-11 14:14:49 +10:00
2e72f253a0 Merge pull request #3910 from rafaelncarvalho/patch-1
Update Bootstrap to 3.4.1
2024-10-11 14:14:20 +10:00
ac47eab23b Merge pull request #3942 from cqhtyi/patch-1
Update nginx-proxy-manager
2024-10-11 14:13:31 +10:00
0bfa6c9d4f Merge pull request #3973 from ddshd/proxy-add-set
Add set directives for proxied paths to keep nginx from crashing if upstream is down
2024-10-11 14:08:39 +10:00
f71de7474d Bump express from 4.19.2 to 4.20.0 in /backend
Bumps [express](https://github.com/expressjs/express) from 4.19.2 to 4.20.0.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.20.0)

---
updated-dependencies:
- dependency-name: express
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-11 04:06:52 +00:00
3a2617e6bf Bump braces from 3.0.2 to 3.0.3 in /test
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-11 04:06:40 +00:00
6c6722464d Merge pull request #4051 from NginxProxyManager/dependabot/npm_and_yarn/frontend/elliptic-6.5.7
Bump elliptic from 6.5.4 to 6.5.7 in /frontend
2024-10-11 14:05:42 +10:00
02a7b43932 Merge pull request #3991 from nlynzaad/develop_mysql2
swap mysql library and knex client for mysql2
2024-10-11 14:05:26 +10:00
42a5bb6af3 Merge pull request #3988 from vggscqq/patch-1
Added active24 DNS provider
2024-10-11 14:04:41 +10:00
a08d18bdb2 Remove broken script 2024-10-11 14:04:24 +10:00
d2d104b723 Merge pull request #4020 from RafaelSchridi/develop
Add mijn.host dns plugin
2024-10-11 13:27:57 +10:00
e0352ecc48 Merge pull request #4016 from NginxProxyManager/dependabot/npm_and_yarn/backend/body-parser-1.20.3
Bump body-parser from 1.20.2 to 1.20.3 in /backend
2024-10-11 13:27:14 +10:00
4e035f285d Update deps in docs 2024-10-11 13:26:00 +10:00
b046bb3229 Merge pull request #4044 from mokkin/patch-1
version is obsolete now
2024-10-11 13:24:24 +10:00
304899e604 Bump elliptic from 6.5.4 to 6.5.7 in /frontend
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.4 to 6.5.7.
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.4...v6.5.7)

---
updated-dependencies:
- dependency-name: elliptic
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-11 03:22:32 +00:00
e525b5470e Merge pull request #4018 from NginxProxyManager/dependabot/npm_and_yarn/docs/rollup-4.22.4
Bump rollup from 4.17.2 to 4.22.4 in /docs
2024-10-11 13:22:21 +10:00
aacb2302bf Merge pull request #4049 from NginxProxyManager/cve-fixes
CVE fixes and other API work
2024-10-11 13:21:28 +10:00
d21403ca1e Move docker login in pipeline 2024-10-11 12:57:40 +10:00
c39d5433bc Fix CVE-2024-46256 and CVE-2024-46257
- Schema validate against bad domain characters
- Integration test for CVE POC examples
- Cypress rewrite of plugins for file upload
2024-10-11 11:31:57 +10:00
6f7963ee08 version is obsolete now 2024-10-09 23:47:07 +02:00
a8f1f7f017 Add mijn.host dns plugin 2024-09-25 22:37:13 +02:00
e401095707 Bump rollup from 4.17.2 to 4.22.4 in /docs
Bumps [rollup](https://github.com/rollup/rollup) from 4.17.2 to 4.22.4.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.17.2...v4.22.4)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-24 00:54:26 +00:00
d69cb26157 Bump body-parser from 1.20.2 to 1.20.3 in /backend
Bumps [body-parser](https://github.com/expressjs/body-parser) from 1.20.2 to 1.20.3.
- [Release notes](https://github.com/expressjs/body-parser/releases)
- [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/body-parser/compare/1.20.2...1.20.3)

---
updated-dependencies:
- dependency-name: body-parser
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-21 08:52:30 +00:00
48a9f5f9db swop mysql library and knex client for mysql2 2024-09-10 23:08:02 +02:00
ca9eeb5118 Added quotation around TOKEN variable. Made Active24 start from capital letter in UI 2024-09-09 11:53:16 +02:00
a03009056c Added active24 DNS provider 2024-09-09 11:06:47 +02:00
554d1ff2b6 Add set directives for proxies to keep from crashing if upstream is down 2024-09-04 00:07:43 -04:00
0042726477 Update nginx-proxy-manager
Fix Nginx not restarting correctly.
2024-08-20 15:36:21 +08:00
ed5d87b021 Update Bootstrap to 3.4.1
Fixes:

CVE-2018-20676
CVE-2019-8331
CVE-2018-20677
CVE-2018-14042
CVE-2016-10735
CVE-2018-14040
2024-08-01 17:09:33 -03:00
894cd25534 Add "rockenstein" as dns provider 2024-07-31 11:04:20 +02:00
4446e2f760 Add Edge DNS by Akamai
Add Edge DNS by Akamai
2024-07-09 11:22:54 +02:00
35d7a3a407 Merge pull request #3847 from NginxProxyManager/develop
v2.11.3
2024-07-01 21:37:42 +10:00
67 changed files with 1988 additions and 842 deletions

View File

@ -1 +1 @@
2.11.3
2.12.1

31
Jenkinsfile vendored
View File

@ -56,6 +56,13 @@ pipeline {
sh 'sed -i -E "s/(version-)[0-9]+\\.[0-9]+\\.[0-9]+(-green)/\\1${BUILD_VERSION}\\2/" README.md'
}
}
stage('Docker Login') {
steps {
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
sh 'docker login -u "${duser}" -p "${dpass}"'
}
}
}
}
}
stage('Builds') {
@ -120,6 +127,11 @@ pipeline {
junit 'test/results/junit/*'
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
}
unstable {
dir(path: 'testing/results') {
archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml')
}
}
}
}
stage('Test Mysql') {
@ -148,6 +160,11 @@ pipeline {
junit 'test/results/junit/*'
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
}
unstable {
dir(path: 'testing/results') {
archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml')
}
}
}
}
stage('MultiArch Build') {
@ -157,10 +174,7 @@ pipeline {
}
}
steps {
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
sh 'docker login -u "${duser}" -p "${dpass}"'
sh "./scripts/buildx --push ${buildxPushTags}"
}
sh "./scripts/buildx --push ${buildxPushTags}"
}
}
stage('Docs / Comment') {
@ -200,20 +214,13 @@ pipeline {
always {
sh 'echo Reverting ownership'
sh 'docker run --rm -v "$(pwd):/data" jc21/ci-tools chown -R "$(id -u):$(id -g)" /data'
}
success {
juxtapose event: 'success'
sh 'figlet "SUCCESS"'
printResult(true)
}
failure {
archiveArtifacts(artifacts: 'debug/**/*.*', allowEmptyArchive: true)
juxtapose event: 'failure'
sh 'figlet "FAILURE"'
}
unstable {
archiveArtifacts(artifacts: 'debug/**/*.*', allowEmptyArchive: true)
juxtapose event: 'unstable'
sh 'figlet "UNSTABLE"'
}
}
}

View File

@ -1,7 +1,7 @@
<p align="center">
<img src="https://nginxproxymanager.com/github.png">
<br><br>
<img src="https://img.shields.io/badge/version-2.11.3-green.svg?style=for-the-badge">
<img src="https://img.shields.io/badge/version-2.12.1-green.svg?style=for-the-badge">
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
</a>

View File

@ -1,6 +1,6 @@
{
"database": {
"engine": "mysql",
"engine": "mysql2",
"host": "db",
"name": "npm",
"user": "npm",

View File

@ -3,27 +3,29 @@ const fs = require('fs');
const https = require('https');
const tempWrite = require('temp-write');
const moment = require('moment');
const archiver = require('archiver');
const path = require('path');
const { isArray } = require('lodash');
const logger = require('../logger').ssl;
const config = require('../lib/config');
const error = require('../lib/error');
const utils = require('../lib/utils');
const certbot = require('../lib/certbot');
const certificateModel = require('../models/certificate');
const tokenModel = require('../models/token');
const dnsPlugins = require('../global/certbot-dns-plugins.json');
const internalAuditLog = require('./audit-log');
const internalNginx = require('./nginx');
const internalHost = require('./host');
const certbot = require('../lib/certbot');
const archiver = require('archiver');
const path = require('path');
const { isArray } = require('lodash');
const letsencryptStaging = config.useLetsencryptStaging();
const letsencryptServer = config.useLetsencryptServer();
const letsencryptConfig = '/etc/letsencrypt.ini';
const certbotCommand = 'certbot';
function omissions() {
return ['is_deleted'];
return ['is_deleted', 'owner.is_deleted'];
}
const internalCertificate = {
@ -207,6 +209,7 @@ const internalCertificate = {
.patchAndFetchById(certificate.id, {
expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss')
})
.then(utils.omitRow(omissions()))
.then((saved_row) => {
// Add cert data for audit log
saved_row.meta = _.assign({}, saved_row.meta, {
@ -730,29 +733,29 @@ const internalCertificate = {
return utils.exec('openssl x509 -in ' + certificate_file + ' -subject -noout')
.then((result) => {
// Examples:
// subject=CN = *.jc21.com
// subject=CN = something.example.com
const regex = /(?:subject=)?[^=]+=\s+(\S+)/gim;
const match = regex.exec(result);
if (typeof match[1] === 'undefined') {
throw new error.ValidationError('Could not determine subject from certificate: ' + result);
if (match && typeof match[1] !== 'undefined') {
certData['cn'] = match[1];
}
certData['cn'] = match[1];
})
.then(() => {
return utils.exec('openssl x509 -in ' + certificate_file + ' -issuer -noout');
})
.then((result) => {
// Examples:
// issuer=C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
// issuer=C = US, O = Let's Encrypt, CN = E5
// issuer=O = NginxProxyManager, CN = NginxProxyManager Intermediate CA","O = NginxProxyManager, CN = NginxProxyManager Intermediate CA
const regex = /^(?:issuer=)?(.*)$/gim;
const match = regex.exec(result);
if (typeof match[1] === 'undefined') {
throw new error.ValidationError('Could not determine issuer from certificate: ' + result);
if (match && typeof match[1] !== 'undefined') {
certData['issuer'] = match[1];
}
certData['issuer'] = match[1];
})
.then(() => {
return utils.exec('openssl x509 -in ' + certificate_file + ' -dates -noout');
@ -827,17 +830,18 @@ const internalCertificate = {
requestLetsEncryptSsl: (certificate) => {
logger.info('Requesting Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
const cmd = certbotCommand + ' certonly ' +
'--config "' + letsencryptConfig + '" ' +
const cmd = `${certbotCommand} certonly ` +
`--config '${letsencryptConfig}' ` +
'--work-dir "/tmp/letsencrypt-lib" ' +
'--logs-dir "/tmp/letsencrypt-log" ' +
'--cert-name "npm-' + certificate.id + '" ' +
`--cert-name "npm-${certificate.id}" ` +
'--agree-tos ' +
'--authenticator webroot ' +
'--email "' + certificate.meta.letsencrypt_email + '" ' +
`--email '${certificate.meta.letsencrypt_email}' ` +
'--preferred-challenges "dns,http" ' +
'--domains "' + certificate.domain_names.join(',') + '" ' +
(letsencryptStaging ? '--staging' : '');
`--domains "${certificate.domain_names.join(',')}" ` +
(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
logger.info('Command:', cmd);
@ -868,25 +872,26 @@ const internalCertificate = {
const hasConfigArg = certificate.meta.dns_provider !== 'route53';
let mainCmd = certbotCommand + ' certonly ' +
'--config "' + letsencryptConfig + '" ' +
`--config '${letsencryptConfig}' ` +
'--work-dir "/tmp/letsencrypt-lib" ' +
'--logs-dir "/tmp/letsencrypt-log" ' +
'--cert-name "npm-' + certificate.id + '" ' +
`--cert-name 'npm-${certificate.id}' ` +
'--agree-tos ' +
'--email "' + certificate.meta.letsencrypt_email + '" ' +
'--domains "' + certificate.domain_names.join(',') + '" ' +
'--authenticator ' + dnsPlugin.full_plugin_name + ' ' +
`--email '${certificate.meta.letsencrypt_email}' ` +
`--domains '${certificate.domain_names.join(',')}' ` +
`--authenticator '${dnsPlugin.full_plugin_name}' ` +
(
hasConfigArg
? '--' + dnsPlugin.full_plugin_name + '-credentials "' + credentialsLocation + '"'
? `--${dnsPlugin.full_plugin_name}-credentials '${credentialsLocation}' `
: ''
) +
(
certificate.meta.propagation_seconds !== undefined
? ' --' + dnsPlugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds
? `--${dnsPlugin.full_plugin_name}-propagation-seconds '${certificate.meta.propagation_seconds}' `
: ''
) +
(letsencryptStaging ? ' --staging' : '');
(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
// Prepend the path to the credentials file as an environment variable
if (certificate.meta.dns_provider === 'route53') {
@ -963,14 +968,15 @@ const internalCertificate = {
logger.info('Renewing Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
const cmd = certbotCommand + ' renew --force-renewal ' +
'--config "' + letsencryptConfig + '" ' +
`--config '${letsencryptConfig}' ` +
'--work-dir "/tmp/letsencrypt-lib" ' +
'--logs-dir "/tmp/letsencrypt-log" ' +
'--cert-name "npm-' + certificate.id + '" ' +
`--cert-name 'npm-${certificate.id}' ` +
'--preferred-challenges "dns,http" ' +
'--no-random-sleep-on-renew ' +
'--disable-hook-validation ' +
(letsencryptStaging ? '--staging' : '');
(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
logger.info('Command:', cmd);
@ -995,13 +1001,14 @@ const internalCertificate = {
logger.info(`Renewing Let'sEncrypt certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
let mainCmd = certbotCommand + ' renew --force-renewal ' +
'--config "' + letsencryptConfig + '" ' +
`--config "${letsencryptConfig}" ` +
'--work-dir "/tmp/letsencrypt-lib" ' +
'--logs-dir "/tmp/letsencrypt-log" ' +
'--cert-name "npm-' + certificate.id + '" ' +
`--cert-name 'npm-${certificate.id}' ` +
'--disable-hook-validation ' +
'--no-random-sleep-on-renew ' +
(letsencryptStaging ? ' --staging' : '');
(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
// Prepend the path to the credentials file as an environment variable
if (certificate.meta.dns_provider === 'route53') {
@ -1027,12 +1034,13 @@ const internalCertificate = {
logger.info('Revoking Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
const mainCmd = certbotCommand + ' revoke ' +
'--config "' + letsencryptConfig + '" ' +
`--config '${letsencryptConfig}' ` +
'--work-dir "/tmp/letsencrypt-lib" ' +
'--logs-dir "/tmp/letsencrypt-log" ' +
'--cert-path "/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' +
`--cert-path '/etc/letsencrypt/live/npm-${certificate.id}/fullchain.pem' ` +
'--delete-after-revoke ' +
(letsencryptStaging ? '--staging' : '');
(letsencryptServer !== null ? `--server '${letsencryptServer}' ` : '') +
(letsencryptStaging && letsencryptServer === null ? '--staging ' : '');
// Don't fail command if file does not exist
const delete_credentialsCmd = `rm -f '/etc/letsencrypt/credentials/credentials-${certificate.id}' || true`;

View File

@ -181,7 +181,9 @@ const internalNginx = {
* @param {Object} host
* @returns {Promise}
*/
generateConfig: (host_type, host) => {
generateConfig: (host_type, host_row) => {
// Prevent modifying the original object:
let host = JSON.parse(JSON.stringify(host_row));
const nice_host_type = internalNginx.getFileFriendlyHostType(host_type);
if (config.debug()) {

View File

@ -1,6 +1,6 @@
module.exports = {
development: {
client: 'mysql',
client: 'mysql2',
migrations: {
tableName: 'migrations',
stub: 'lib/migrate_template.js',
@ -9,7 +9,7 @@ module.exports = {
},
production: {
client: 'mysql',
client: 'mysql2',
migrations: {
tableName: 'migrations',
stub: 'lib/migrate_template.js',

View File

@ -34,7 +34,7 @@ const configure = () => {
logger.info('Using MySQL configuration');
instance = {
database: {
engine: 'mysql',
engine: 'mysql2',
host: envMysqlHost,
port: process.env.DB_MYSQL_PORT || 3306,
user: envMysqlUser,
@ -180,5 +180,15 @@ module.exports = {
*/
useLetsencryptStaging: function () {
return !!process.env.LE_STAGING;
},
/**
* @returns {string|null}
*/
useLetsencryptServer: function () {
if (process.env.LE_SERVER) {
return process.env.LE_SERVER;
}
return null;
}
};

View File

@ -9,9 +9,9 @@
"archiver": "^5.3.0",
"batchflow": "^0.4.0",
"bcrypt": "^5.0.0",
"body-parser": "^1.19.0",
"body-parser": "^1.20.3",
"compression": "^1.7.4",
"express": "^4.19.2",
"express": "^4.20.0",
"express-fileupload": "^1.1.9",
"gravatar": "^1.8.0",
"jsonwebtoken": "^9.0.0",
@ -19,7 +19,7 @@
"liquidjs": "10.6.1",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"mysql": "^2.18.1",
"mysql2": "^3.11.1",
"node-rsa": "^1.0.8",
"objection": "3.0.1",
"path": "^0.12.7",

View File

@ -76,7 +76,7 @@
"uniqueItems": true,
"items": {
"type": "string",
"pattern": "^(?:\\*\\.)?(?:[^.*]+\\.?)+[^.]$"
"pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$"
}
},
"enabled": {

View File

@ -24,22 +24,34 @@
"description": "Nice Name for the custom certificate"
},
"domain_names": {
"$ref": "../common.json#/properties/domain_names"
"description": "Domain Names separated by a comma",
"type": "array",
"maxItems": 100,
"uniqueItems": true,
"items": {
"type": "string",
"pattern": "^[^&| @!#%^();:/\\\\}{=+?<>,~`'\"]+$"
}
},
"expires_on": {
"description": "Date and time of expiration",
"readOnly": true,
"type": "string"
},
"owner": {
"$ref": "./user-object.json"
},
"meta": {
"type": "object",
"additionalProperties": false,
"properties": {
"letsencrypt_email": {
"type": "string"
"certificate": {
"type": "string",
"minLength": 1
},
"letsencrypt_agree": {
"type": "boolean"
"certificate_key": {
"type": "string",
"minLength": 1
},
"dns_challenge": {
"type": "boolean"
@ -50,13 +62,18 @@
"dns_provider_credentials": {
"type": "string"
},
"letsencrypt_agree": {
"type": "boolean"
},
"letsencrypt_certificate": {
"type": "object"
},
"letsencrypt_email": {
"type": "string"
},
"propagation_seconds": {
"anyOf": [
{
"type": "integer",
"minimum": 0
}
]
"type": "integer",
"minimum": 0
}
}
}

View File

@ -0,0 +1,9 @@
{
"type": "object",
"description": "Error",
"properties": {
"error": {
"$ref": "./error-object.json"
}
}
}

View File

@ -23,9 +23,7 @@
"locations",
"hsts_enabled",
"hsts_subdomains",
"certificate",
"use_default_location",
"ipv6"
"certificate"
],
"additionalProperties": false,
"properties": {
@ -151,12 +149,6 @@
"$ref": "./access-list-object.json"
}
]
},
"use_default_location": {
"type": "boolean"
},
"ipv6": {
"type": "boolean"
}
}
}

View File

@ -28,7 +28,7 @@
},
"forward_scheme": {
"type": "string",
"enum": ["http", "https"]
"enum": ["auto", "http", "https"]
},
"forward_domain_name": {
"description": "Domain Name",

View File

@ -25,7 +25,7 @@
"value": {
"description": "Value in almost any form",
"example": "congratulations",
"oneOf": [
"anyOf": [
{
"type": "string",
"minLength": 1
@ -46,7 +46,10 @@
},
"meta": {
"description": "Extra metadata",
"example": {},
"example": {
"redirect": "http://example.com",
"html": "<h1>404</h1>"
},
"type": "object"
}
}

View File

@ -55,6 +55,25 @@
"certificate_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1n9j9C5Bes1nd\nqACDckERauxXVNKCnUlUM1buGBx1xc+j2e2Ar23wUJJuWBY18VfT8yqfqVDktO2w\nrbmvZvLuPmXePOKbIKS+XXh+2NG9L5bDG9rwGFCRXnbQj+GWCdMfzx14+CR1IHge\nYz6Cv/Si2/LJPCh/CoBfM4hUQJON3lxAWrWBpdbZnKYMrxuPBRfW9OuzTbCVXToQ\noxRAHiOR9081Xn1WeoKr7kVBIa5UphlvWXa12w1YmUwJu7YndnJGIavLWeNCVc7Z\nEo+nS8Wr/4QWicatIWZXpVaEOPhRoeplQDxNWg5b/Q26rYoVd7PrCmRs7sVcH79X\nzGONeH1PAgMBAAECggEAANb3Wtwl07pCjRrMvc7WbC0xYIn82yu8/g2qtjkYUJcU\nia5lQbYN7RGCS85Oc/tkq48xQEG5JQWNH8b918jDEMTrFab0aUEyYcru1q9L8PL6\nYHaNgZSrMrDcHcS8h0QOXNRJT5jeGkiHJaTR0irvB526tqF3knbK9yW22KTfycUe\na0Z9voKn5xRk1DCbHi/nk2EpT7xnjeQeLFaTIRXbS68omkr4YGhwWm5OizoyEGZu\nW0Zum5BkQyMr6kor3wdxOTG97ske2rcyvvHi+ErnwL0xBv0qY0Dhe8DpuXpDezqw\no72yY8h31Fu84i7sAj24YuE5Df8DozItFXQpkgbQ6QKBgQDPrufhvIFm2S/MzBdW\nH8JxY7CJlJPyxOvc1NIl9RczQGAQR90kx52cgIcuIGEG6/wJ/xnGfMmW40F0DnQ+\nN+oLgB9SFxeLkRb7s9Z/8N3uIN8JJFYcerEOiRQeN2BXEEWJ7bUThNtsVrAcKoUh\nELsDmnHW/3V+GKwhd0vpk842+wKBgQDf4PGLG9PTE5tlAoyHFodJRd2RhTJQkwsU\nMDNjLJ+KecLv+Nl+QiJhoflG1ccqtSFlBSCG067CDQ5LV0xm3mLJ7pfJoMgjcq31\nqjEmX4Ls91GuVOPtbwst3yFKjsHaSoKB5fBvWRcKFpBUezM7Qcw2JP3+dQT+bQIq\ncMTkRWDSvQKBgQDOdCQFDjxg/lR7NQOZ1PaZe61aBz5P3pxNqa7ClvMaOsuEQ7w9\nvMYcdtRq8TsjA2JImbSI0TIg8gb2FQxPcYwTJKl+FICOeIwtaSg5hTtJZpnxX5LO\nutTaC0DZjNkTk5RdOdWA8tihyUdGqKoxJY2TVmwGe2rUEDjFB++J4inkEwKBgB6V\ng0nmtkxanFrzOzFlMXwgEEHF+Xaqb9QFNa/xs6XeNnREAapO7JV75Cr6H2hFMFe1\nmJjyqCgYUoCWX3iaHtLJRnEkBtNY4kzyQB6m46LtsnnnXO/dwKA2oDyoPfFNRoDq\nYatEd3JIXNU9s2T/+x7WdOBjKhh72dTkbPFmTPDdAoGAU6rlPBevqOFdObYxdPq8\nEQWu44xqky3Mf5sBpOwtu6rqCYuziLiN7K4sjN5GD5mb1cEU+oS92ZiNcUQ7MFXk\n8yTYZ7U0VcXyAcpYreWwE8thmb0BohJBr+Mp3wLTx32x0HKdO6vpUa0d35LUTUmM\nRrKmPK/msHKK/sVHiL+NFqo=\n-----END PRIVATE KEY-----\n"
}
}
},
"schema": {
"type": "object",
"additionalProperties": false,
"required": ["certificate", "certificate_key"],
"properties": {
"certificate": {
"type": "string",
"minLength": 1
},
"certificate_key": {
"type": "string",
"minLength": 1
},
"intermediate_certificate": {
"type": "string",
"minLength": 1
}
}
}
}
}

View File

@ -72,6 +72,26 @@
}
}
}
},
"400": {
"description": "400 response",
"content": {
"application/json": {
"examples": {
"default": {
"value": {
"error": {
"code": 400,
"message": "Domains are invalid"
}
}
}
},
"schema": {
"$ref": "../../../components/error.json"
}
}
}
}
}
}

View File

@ -50,6 +50,42 @@
"certificate_key": true
}
}
},
"schema": {
"type": "object",
"additionalProperties": false,
"required": ["certificate", "certificate_key"],
"properties": {
"certificate": {
"type": "object",
"additionalProperties": false,
"required": ["cn", "issuer", "dates"],
"properties": {
"cn": {
"type": "string"
},
"issuer": {
"type": "string"
},
"dates": {
"type": "object",
"additionalProperties": false,
"required": ["from", "to"],
"properties": {
"from": {
"type": "integer"
},
"to": {
"type": "integer"
}
}
}
}
},
"certificate_key": {
"type": "boolean"
}
}
}
}
}
@ -67,6 +103,9 @@
}
}
}
},
"schema": {
"$ref": "../../../../components/error.json"
}
}
}

View File

@ -50,7 +50,7 @@
}
},
"schema": {
"$ref": "../../../../../components/error-object.json"
"$ref": "../../../../../components/error.json"
}
}
}

View File

@ -50,7 +50,7 @@
}
},
"schema": {
"$ref": "../../../../../components/error-object.json"
"$ref": "../../../../../components/error.json"
}
}
}

View File

@ -94,9 +94,7 @@
"avatar": "",
"roles": ["admin"]
},
"certificate": null,
"use_default_location": true,
"ipv6": true
"certificate": null
}
}
},

View File

@ -79,9 +79,7 @@
"nickname": "Admin",
"avatar": "",
"roles": ["admin"]
},
"use_default_location": true,
"ipv6": true
}
}
}
},

View File

@ -50,7 +50,7 @@
}
},
"schema": {
"$ref": "../../../../../components/error-object.json"
"$ref": "../../../../../components/error.json"
}
}
}

View File

@ -50,7 +50,7 @@
}
},
"schema": {
"$ref": "../../../../../components/error-object.json"
"$ref": "../../../../../components/error.json"
}
}
}

View File

@ -129,9 +129,7 @@
"roles": ["admin"]
},
"certificate": null,
"access_list": null,
"use_default_location": true,
"ipv6": true
"access_list": null
}
}
},

View File

@ -114,9 +114,7 @@
"avatar": "//www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?default=mm",
"roles": ["admin"]
},
"access_list": null,
"use_default_location": true,
"ipv6": true
"access_list": null
}
}
},

View File

@ -50,7 +50,7 @@
}
},
"schema": {
"$ref": "../../../../../components/error-object.json"
"$ref": "../../../../../components/error.json"
}
}
}

View File

@ -50,7 +50,7 @@
}
},
"schema": {
"$ref": "../../../../../components/error-object.json"
"$ref": "../../../../../components/error.json"
}
}
}

View File

@ -114,9 +114,7 @@
"avatar": "",
"roles": ["admin"]
},
"certificate": null,
"use_default_location": true,
"ipv6": true
"certificate": null
}
}
},

View File

@ -99,9 +99,7 @@
"nickname": "Admin",
"avatar": "",
"roles": ["admin"]
},
"use_default_location": true,
"ipv6": true
}
}
}
},

View File

@ -50,7 +50,7 @@
}
},
"schema": {
"$ref": "../../../../../components/error-object.json"
"$ref": "../../../../../components/error.json"
}
}
}

View File

@ -50,7 +50,7 @@
}
},
"schema": {
"$ref": "../../../../../components/error-object.json"
"$ref": "../../../../../components/error.json"
}
}
}

View File

@ -129,9 +129,7 @@
"roles": ["admin"]
},
"certificate": null,
"access_list": null,
"use_default_location": true,
"ipv6": true
"access_list": null
}
}
},

View File

@ -13,7 +13,8 @@
"name": "settingID",
"schema": {
"type": "string",
"minLength": 1
"minLength": 1,
"enum": ["default-site"]
},
"required": true,
"description": "Setting ID",
@ -31,10 +32,21 @@
"minProperties": 1,
"properties": {
"value": {
"$ref": "../../../components/setting-object.json#/properties/value"
"type": "string",
"minLength": 1,
"enum": ["congratulations", "404", "444", "redirect", "html"]
},
"meta": {
"$ref": "../../../components/setting-object.json#/properties/meta"
"type": "object",
"additionalProperties": false,
"properties": {
"redirect": {
"type": "string"
},
"html": {
"type": "string"
}
}
}
}
}

View File

@ -6,7 +6,12 @@
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }};
set $proxy_forward_scheme {{ forward_scheme }};
set $proxy_server "{{ forward_host }}";
set $proxy_port {{ forward_port }};
proxy_pass $proxy_forward_scheme://$proxy_server:$proxy_port{{ forward_path }};
{% include "_access.conf" %}
{% include "_assets.conf" %}

View File

@ -412,6 +412,11 @@ async@^3.2.0:
resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
aws-ssl-profiles@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz#157dd77e9f19b1d123678e93f120e6f193022641"
integrity sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
@ -435,11 +440,6 @@ bcrypt@^5.0.0:
node-addon-api "^3.0.0"
node-pre-gyp "0.15.0"
bignumber.js@9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075"
integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==
binary-extensions@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9"
@ -459,10 +459,10 @@ blueimp-md5@^2.16.0:
resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.17.0.tgz#f4fcac088b115f7b4045f19f5da59e9d01b1bb96"
integrity sha512-x5PKJHY5rHQYaADj6NwPUR2QRCUVSggPzrUKkeENpj871o9l9IefJbO2jkT5UvYykeOK9dx0VmkIo6dZ+vThYw==
body-parser@1.20.2, body-parser@^1.19.0:
version "1.20.2"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd"
integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==
body-parser@1.20.3, body-parser@^1.20.3:
version "1.20.3"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6"
integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==
dependencies:
bytes "3.1.2"
content-type "~1.0.5"
@ -472,7 +472,7 @@ body-parser@1.20.2, body-parser@^1.19.0:
http-errors "2.0.0"
iconv-lite "0.4.24"
on-finished "2.4.1"
qs "6.11.0"
qs "6.13.0"
raw-body "2.5.2"
type-is "~1.6.18"
unpipe "1.0.0"
@ -910,6 +910,11 @@ delegates@^1.0.0:
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
denque@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1"
integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==
depd@2.0.0, depd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
@ -988,6 +993,11 @@ encodeurl@~1.0.2:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
encodeurl@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
encoding@^0.1.12:
version "0.1.13"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
@ -1185,37 +1195,37 @@ express-fileupload@^1.1.9:
dependencies:
busboy "^0.3.1"
express@^4.19.2:
version "4.19.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465"
integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==
express@^4.20.0:
version "4.20.0"
resolved "https://registry.yarnpkg.com/express/-/express-4.20.0.tgz#f1d08e591fcec770c07be4767af8eb9bcfd67c48"
integrity sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw==
dependencies:
accepts "~1.3.8"
array-flatten "1.1.1"
body-parser "1.20.2"
body-parser "1.20.3"
content-disposition "0.5.4"
content-type "~1.0.4"
cookie "0.6.0"
cookie-signature "1.0.6"
debug "2.6.9"
depd "2.0.0"
encodeurl "~1.0.2"
encodeurl "~2.0.0"
escape-html "~1.0.3"
etag "~1.8.1"
finalhandler "1.2.0"
fresh "0.5.2"
http-errors "2.0.0"
merge-descriptors "1.0.1"
merge-descriptors "1.0.3"
methods "~1.1.2"
on-finished "2.4.1"
parseurl "~1.3.3"
path-to-regexp "0.1.7"
path-to-regexp "0.1.10"
proxy-addr "~2.0.7"
qs "6.11.0"
range-parser "~1.2.1"
safe-buffer "5.2.1"
send "0.18.0"
serve-static "1.15.0"
send "0.19.0"
serve-static "1.16.0"
setprototypeof "1.2.0"
statuses "2.0.1"
type-is "~1.6.18"
@ -1411,6 +1421,13 @@ gauge@~2.7.3:
strip-ansi "^3.0.1"
wide-align "^1.1.0"
generate-function@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f"
integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==
dependencies:
is-property "^1.0.2"
get-caller-file@^2.0.1:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
@ -1655,7 +1672,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.4:
dependencies:
safer-buffer ">= 2.1.2 < 3"
iconv-lite@^0.6.2:
iconv-lite@^0.6.2, iconv-lite@^0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
@ -1858,6 +1875,11 @@ is-path-inside@^3.0.3:
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
is-property@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
integrity sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==
is-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3"
@ -2078,6 +2100,11 @@ lodash@^4.17.21:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
long@^5.2.1:
version "5.2.3"
resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1"
integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==
lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
@ -2095,6 +2122,16 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
lru-cache@^7.14.1:
version "7.18.3"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89"
integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==
lru-cache@^8.0.0:
version "8.0.5"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-8.0.5.tgz#983fe337f3e176667f8e567cfcce7cb064ea214e"
integrity sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==
make-dir@^3.0.0, make-dir@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
@ -2129,10 +2166,10 @@ media-typer@0.3.0:
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
merge-descriptors@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
merge-descriptors@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5"
integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==
methods@~1.1.2:
version "1.1.2"
@ -2298,15 +2335,27 @@ ms@2.1.3, ms@^2.0.0:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
mysql@^2.18.1:
version "2.18.1"
resolved "https://registry.yarnpkg.com/mysql/-/mysql-2.18.1.tgz#2254143855c5a8c73825e4522baf2ea021766717"
integrity sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==
mysql2@^3.11.1:
version "3.11.1"
resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-3.11.1.tgz#edfb856e2176fcf43d2cc066dd4959e9fc76ea85"
integrity sha512-Oc8Zffd0gpIJnJ/NOMp6IiiJJDdWc7nmWpS+UE3K9feTpYia8XkbgL6EaOJYz52f6+2pAoC0eAQqUzal4lnNGQ==
dependencies:
bignumber.js "9.0.0"
readable-stream "2.3.7"
safe-buffer "5.1.2"
sqlstring "2.3.1"
aws-ssl-profiles "^1.1.1"
denque "^2.1.0"
generate-function "^2.3.1"
iconv-lite "^0.6.3"
long "^5.2.1"
lru-cache "^8.0.0"
named-placeholders "^1.1.3"
seq-queue "^0.0.5"
sqlstring "^2.3.2"
named-placeholders@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/named-placeholders/-/named-placeholders-1.1.3.tgz#df595799a36654da55dda6152ba7a137ad1d9351"
integrity sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==
dependencies:
lru-cache "^7.14.1"
natural-compare@^1.4.0:
version "1.4.0"
@ -2673,10 +2722,10 @@ path-parse@^1.0.7:
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
path-to-regexp@0.1.10:
version "0.1.10"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b"
integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==
path@^0.12.7:
version "0.12.7"
@ -2792,6 +2841,13 @@ qs@6.11.0:
dependencies:
side-channel "^1.0.4"
qs@6.13.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==
dependencies:
side-channel "^1.0.6"
querystring@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
@ -2827,7 +2883,7 @@ rc@^1.2.7, rc@^1.2.8:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
readable-stream@2.3.7, readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6:
readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
@ -3019,10 +3075,34 @@ send@0.18.0:
range-parser "~1.2.1"
statuses "2.0.1"
serve-static@1.15.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
send@0.19.0:
version "0.19.0"
resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8"
integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==
dependencies:
debug "2.6.9"
depd "2.0.0"
destroy "1.2.0"
encodeurl "~1.0.2"
escape-html "~1.0.3"
etag "~1.8.1"
fresh "0.5.2"
http-errors "2.0.0"
mime "1.6.0"
ms "2.1.3"
on-finished "2.4.1"
range-parser "~1.2.1"
statuses "2.0.1"
seq-queue@^0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e"
integrity sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==
serve-static@1.16.0:
version "1.16.0"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.0.tgz#2bf4ed49f8af311b519c46f272bf6ac3baf38a92"
integrity sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA==
dependencies:
encodeurl "~1.0.2"
escape-html "~1.0.3"
@ -3063,7 +3143,7 @@ shebang-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
side-channel@^1.0.4:
side-channel@^1.0.4, side-channel@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2"
integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==
@ -3130,10 +3210,10 @@ sqlite3@5.1.6:
optionalDependencies:
node-gyp "8.x"
sqlstring@2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.1.tgz#475393ff9e91479aea62dcaf0ca3d14983a7fb40"
integrity sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=
sqlstring@^2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.3.tgz#2ddc21f03bce2c387ed60680e739922c65751d0c"
integrity sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==
ssri@^8.0.0, ssri@^8.0.1:
version "8.0.1"

View File

@ -3,6 +3,8 @@
# This file assumes that the frontend has been built using ./scripts/frontend-build
FROM nginxproxymanager/testca AS testca
FROM letsencrypt/pebble AS pebbleca
FROM nginxproxymanager/nginx-full:certbot-node
ARG TARGETPLATFORM
@ -45,6 +47,8 @@ RUN yarn install \
# add late to limit cache-busting by modifications
COPY docker/rootfs /
COPY --from=pebbleca /test/certs/pebble.minica.pem /etc/ssl/certs/pebble.minica.pem
COPY --from=testca /home/step/certs/root_ca.crt /etc/ssl/certs/NginxProxyManager.crt
# Remove frontend service not required for prod, dev nginx config as well
RUN rm -rf /etc/s6-overlay/s6-rc.d/user/contents.d/frontend /etc/nginx/conf.d/dev.conf \

View File

@ -1,7 +1,10 @@
FROM nginxproxymanager/testca AS testca
FROM letsencrypt/pebble AS pebbleca
FROM nginxproxymanager/nginx-full:certbot-node
LABEL maintainer="Jamie Curnow <jc@jc21.com>"
# See: https://github.com/just-containers/s6-overlay/blob/master/README.md
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
ENV SUPPRESS_NO_CONFIG_WARNING=1 \
S6_BEHAVIOUR_IF_STAGE2_FAILS=1 \
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
@ -17,17 +20,20 @@ RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
&& rm -rf /var/lib/apt/lists/*
# Task
RUN cd /usr \
&& curl -sL https://taskfile.dev/install.sh | sh \
&& cd /root
WORKDIR /usr
RUN curl -sL https://taskfile.dev/install.sh | sh
WORKDIR /root
COPY rootfs /
RUN rm -f /etc/nginx/conf.d/production.conf
RUN chmod 644 /etc/logrotate.d/nginx-proxy-manager
# s6 overlay
COPY scripts/install-s6 /tmp/install-s6
RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6
RUN rm -f /etc/nginx/conf.d/production.conf \
&& chmod 644 /etc/logrotate.d/nginx-proxy-manager \
&& /tmp/install-s6 "${TARGETPLATFORM}" \
&& rm -f /tmp/install-s6
# Certs for testing purposes
COPY --from=pebbleca /test/certs/pebble.minica.pem /etc/ssl/certs/pebble.minica.pem
COPY --from=testca /home/step/certs/root_ca.crt /etc/ssl/certs/NginxProxyManager.crt
EXPOSE 80 81 443
ENTRYPOINT [ "/init" ]

92
docker/dev/squid.conf Normal file
View File

@ -0,0 +1,92 @@
# WELCOME TO SQUID 6.6
# ----------------------------
#
# This is the documentation for the Squid configuration file.
# This documentation can also be found online at:
# http://www.squid-cache.org/Doc/config/
#
# You may wish to look at the Squid home page and wiki for the
# FAQ and other documentation:
# http://www.squid-cache.org/
# https://wiki.squid-cache.org/SquidFaq
# https://wiki.squid-cache.org/ConfigExamples
#
# Example rule allowing access from your local networks.
# Adapt to list your (internal) IP networks from where browsing
# should be allowed
acl localnet src 0.0.0.1-0.255.255.255 # RFC 1122 "this" network (LAN)
acl localnet src 10.0.0.0/8 # RFC 1918 local private network (LAN)
acl localnet src 100.64.0.0/10 # RFC 6598 shared address space (CGN)
acl localnet src 169.254.0.0/16 # RFC 3927 link-local (directly plugged) machines
acl localnet src 172.0.0.0/8
acl localnet src 192.168.0.0/16 # RFC 1918 local private network (LAN)
acl localnet src fc00::/7 # RFC 4193 local private network range
acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 81
acl Safe_ports port 443 # https
#
# Recommended minimum Access Permission configuration:
#
# Deny requests to certain unsafe ports
http_access deny !Safe_ports
# Deny CONNECT to other than secure SSL ports
http_access deny CONNECT !SSL_ports
# Only allow cachemgr access from localhost
http_access allow localhost manager
http_access deny manager
# This default configuration only allows localhost requests because a more
# permissive Squid installation could introduce new attack vectors into the
# network by proxying external TCP connections to unprotected services.
http_access allow localhost
# The two deny rules below are unnecessary in this default configuration
# because they are followed by a "deny all" rule. However, they may become
# critically important when you start allowing external requests below them.
# Protect web applications running on the same server as Squid. They often
# assume that only local users can access them at "localhost" ports.
http_access deny to_localhost
# Protect cloud servers that provide local users with sensitive info about
# their server via certain well-known link-local (a.k.a. APIPA) addresses.
http_access deny to_linklocal
#
# INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
#
include /etc/squid/conf.d/*.conf
# For example, to allow access from your local networks, you may uncomment the
# following rule (and/or add rules that match your definition of "local"):
# http_access allow localnet
# And finally deny all other access to this proxy
http_access deny all
# Squid normally listens to port 3128
http_port 3128
# Leave coredumps in the first cache dir
coredump_dir /var/spool/squid
#
# Add any of your own refresh_pattern entries above these.
#
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern \/(Packages|Sources)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
refresh_pattern \/Release(|\.gpg)$ 0 0% 0 refresh-ims
refresh_pattern \/InRelease$ 0 0% 0 refresh-ims
refresh_pattern \/(Translation-.*)(|\.bz2|\.gz|\.xz)$ 0 0% 0 refresh-ims
# example pattern for deb packages
#refresh_pattern (\.deb|\.udeb)$ 129600 100% 129600
refresh_pattern . 0 20% 4320

View File

@ -9,6 +9,9 @@ services:
environment:
DEBUG: 'true'
FORCE_COLOR: 1
# Required for DNS Certificate provisioning in CI
LE_SERVER: 'https://ca.internal/acme/acme/directory'
REQUESTS_CA_BUNDLE: '/etc/ssl/certs/NginxProxyManager.crt'
volumes:
- 'npm_data_ci:/data'
- 'npm_le_ci:/etc/letsencrypt'
@ -91,14 +94,25 @@ services:
context: ../
dockerfile: test/cypress/Dockerfile
environment:
CYPRESS_baseUrl: 'http://fullstack:81'
HTTP_PROXY: 'squid:3128'
HTTPS_PROXY: 'squid:3128'
volumes:
- 'cypress_logs:/results'
- './dev/resolv.conf:/etc/resolv.conf:ro'
- '/etc/localtime:/etc/localtime:ro'
command: cypress run --browser chrome --config-file=cypress/config/ci.js
networks:
- fulltest
squid:
image: ubuntu/squid
volumes:
- './dev/squid.conf:/etc/squid/squid.conf:ro'
- './dev/resolv.conf:/etc/resolv.conf:ro'
- '/etc/localtime:/etc/localtime:ro'
networks:
- fulltest
volumes:
cypress_logs:
npm_data_ci:

View File

@ -1,7 +1,7 @@
# WARNING: This is a DEVELOPMENT docker-compose file, it should not be used for production.
services:
npm:
fullstack:
image: nginxproxymanager:dev
container_name: npm_core
build:
@ -12,7 +12,11 @@ services:
- 3081:81
- 3443:443
networks:
- nginx_proxy_manager
nginx_proxy_manager:
aliases:
- website1.example.com
- website2.example.com
- website3.example.com
environment:
PUID: 1000
PGID: 1000
@ -29,12 +33,20 @@ services:
DB_MYSQL_NAME: 'npm'
# DB_SQLITE_FILE: "/data/database.sqlite"
# DISABLE_IPV6: "true"
# Required for DNS Certificate provisioning testing:
LE_SERVER: 'https://ca.internal/acme/acme/directory'
REQUESTS_CA_BUNDLE: '/etc/ssl/certs/NginxProxyManager.crt'
volumes:
- npm_data:/data
- le_data:/etc/letsencrypt
- './dev/resolv.conf:/etc/resolv.conf:ro'
- ../backend:/app
- ../frontend:/app/frontend
- ../global:/app/global
healthcheck:
test: ["CMD", "/usr/bin/check-health"]
interval: 10s
timeout: 3s
depends_on:
- db
working_dir: /app
@ -54,6 +66,23 @@ services:
volumes:
- db_data:/var/lib/mysql
stepca:
image: jc21/testca
volumes:
- './dev/resolv.conf:/etc/resolv.conf:ro'
- '/etc/localtime:/etc/localtime:ro'
networks:
nginx_proxy_manager:
aliases:
- ca.internal
dnsrouter:
image: jc21/dnsrouter
volumes:
- ./dev/dnsrouter-config.json.tmp:/dnsrouter-config.json:ro
networks:
- nginx_proxy_manager
swagger:
image: swaggerapi/swagger-ui:latest
container_name: npm_swagger
@ -63,7 +92,77 @@ services:
URL: "http://npm:81/api/schema"
PORT: '80'
depends_on:
- npm
- fullstack
squid:
image: ubuntu/squid
container_name: npm_squid
volumes:
- './dev/squid.conf:/etc/squid/squid.conf:ro'
- './dev/resolv.conf:/etc/resolv.conf:ro'
- '/etc/localtime:/etc/localtime:ro'
networks:
- nginx_proxy_manager
ports:
- 8128:3128
pdns:
image: pschiffe/pdns-mysql
volumes:
- '/etc/localtime:/etc/localtime:ro'
environment:
PDNS_master: 'yes'
PDNS_api: 'yes'
PDNS_api_key: 'npm'
PDNS_webserver: 'yes'
PDNS_webserver_address: '0.0.0.0'
PDNS_webserver_password: 'npm'
PDNS_webserver-allow-from: '127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8'
PDNS_version_string: 'anonymous'
PDNS_default_ttl: 1500
PDNS_allow_axfr_ips: '127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8'
PDNS_gmysql_host: pdns-db
PDNS_gmysql_port: 3306
PDNS_gmysql_user: pdns
PDNS_gmysql_password: pdns
PDNS_gmysql_dbname: pdns
depends_on:
- pdns-db
networks:
nginx_proxy_manager:
aliases:
- ns1.pdns
- ns2.pdns
pdns-db:
image: mariadb
environment:
MYSQL_ROOT_PASSWORD: 'pdns'
MYSQL_DATABASE: 'pdns'
MYSQL_USER: 'pdns'
MYSQL_PASSWORD: 'pdns'
volumes:
- 'pdns_mysql:/var/lib/mysql'
- '/etc/localtime:/etc/localtime:ro'
- './dev/pdns-db.sql:/docker-entrypoint-initdb.d/01_init.sql:ro'
networks:
- nginx_proxy_manager
cypress:
image: "npm_dev_cypress"
build:
context: ../
dockerfile: test/cypress/Dockerfile
environment:
HTTP_PROXY: 'squid:3128'
HTTPS_PROXY: 'squid:3128'
volumes:
- '../test/results:/results'
- './dev/resolv.conf:/etc/resolv.conf:ro'
- '/etc/localtime:/etc/localtime:ro'
command: cypress run --browser chrome --config-file=cypress/config/ci.js
networks:
- nginx_proxy_manager
volumes:
npm_data:
@ -72,6 +171,8 @@ volumes:
name: npm_le_data
db_data:
name: npm_db_data
pdns_mysql:
name: npm_pdns_mysql
networks:
nginx_proxy_manager:

View File

@ -8,7 +8,7 @@
compress
sharedscripts
postrotate
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
kill -USR1 `cat /run/nginx/nginx.pid 2>/dev/null` 2>/dev/null || true
endscript
}
@ -22,6 +22,6 @@
compress
sharedscripts
postrotate
/bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
kill -USR1 `cat /run/nginx/nginx.pid 2>/dev/null` 2>/dev/null || true
endscript
}
}

View File

@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Default Site</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<style>
.jumbotron { margin-top: 50px; }
</style>

View File

@ -5,7 +5,7 @@
"preview": "vitepress preview"
},
"devDependencies": {
"vitepress": "^1.1.4"
"vitepress": "^1.4.0"
},
"dependencies": {}
}

View File

@ -62,7 +62,6 @@ I won't go in to too much detail here but here are the basics for someone new to
2. Create a docker-compose.yml file similar to this:
```yml
version: '3.8'
services:
app:
image: 'jc21/nginx-proxy-manager:latest'

File diff suppressed because it is too large Load Diff

View File

@ -2648,9 +2648,9 @@ electron-to-chromium@^1.3.47:
integrity sha512-67V62Z4CFOiAtox+o+tosGfVk0QX4DJgH609tjT8QymbJZVAI/jWnAthnr8c5hnRNziIRwkc9EMQYejiVz3/9Q==
elliptic@^6.5.3, elliptic@^6.5.4:
version "6.5.4"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
version "6.5.7"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b"
integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==
dependencies:
bn.js "^4.11.9"
brorand "^1.1.0"

View File

@ -7,6 +7,14 @@
"credentials": "dns_acmedns_api_url = http://acmedns-server/\ndns_acmedns_registration_file = /data/acme-registration.json",
"full_plugin_name": "dns-acmedns"
},
"active24":{
"name": "Active24",
"package_name": "certbot-dns-active24",
"version": "~=1.5.1",
"dependencies": "",
"credentials": "dns_active24_token=\"TOKEN\"",
"full_plugin_name": "dns-active24"
},
"aliyun": {
"name": "Aliyun",
"package_name": "certbot-dns-aliyun",
@ -319,6 +327,14 @@
"credentials": "dns_luadns_email = user@example.com\ndns_luadns_token = 0123456789abcdef0123456789abcdef",
"full_plugin_name": "dns-luadns"
},
"mijnhost": {
"name": "mijn.host",
"package_name": "certbot-dns-mijn-host",
"version": "~=0.0.4",
"dependencies": "",
"credentials": "dns-mijn-host-credentials = /etc/letsencrypt/mijnhost-credentials.ini",
"full_plugin_name": "dns-mijn-host"
},
"namecheap": {
"name": "Namecheap",
"package_name": "certbot-dns-namecheap",
@ -407,6 +423,14 @@
"credentials": "# Target DNS server\ndns_rfc2136_server = 192.0.2.1\n# Target DNS port\ndns_rfc2136_port = 53\n# TSIG key name\ndns_rfc2136_name = keyname.\n# TSIG key secret\ndns_rfc2136_secret = 4q4wM/2I180UXoMyN4INVhJNi8V9BCV+jMw2mXgZw/CSuxUT8C7NKKFs AmKd7ak51vWKgSl12ib86oQRPkpDjg==\n# TSIG key algorithm\ndns_rfc2136_algorithm = HMAC-SHA512",
"full_plugin_name": "dns-rfc2136"
},
"rockenstein": {
"name": "rockenstein AG",
"package_name": "certbot-dns-rockenstein",
"version": "~=1.0.0",
"dependencies": "",
"credentials": "dns_rockenstein_token=<token>",
"full_plugin_name": "dns-rockenstein"
},
"route53": {
"name": "Route 53 (Amazon)",
"package_name": "certbot-dns-route53",
@ -468,7 +492,15 @@
"package_name": "certbot-dns-wedos",
"version": "~=2.2",
"dependencies": "",
"credentials": "dns_wedos_user = <wedos_registration>\ndns_wedos_auth = <wapi_sha256_password>",
"credentials": "dns_wedos_user = <wedos_registration>\ndns_wedos_auth = <wapi_password>",
"full_plugin_name": "dns-wedos"
},
"edgedns": {
"name": "Akamai Edge DNS",
"package_name": "certbot-plugin-edgedns",
"version": "~=0.1.0",
"dependencies": "",
"credentials": "edgedns_client_secret = as3d1asd5d1a32sdfsdfs2d1asd5=\nedgedns_host = sdflskjdf-dfsdfsdf-sdfsdfsdf.luna.akamaiapis.net\nedgedns_access_token = kjdsi3-34rfsdfsdf-234234fsdfsdf\nedgedns_client_token = dkfjdf-342fsdfsd-23fsdfsdfsdf",
"full_plugin_name": "edgedns"
}
}

View File

@ -15,3 +15,13 @@ COMPOSE_PROJECT_NAME="npmdev"
COMPOSE_FILE="docker/docker-compose.dev.yml"
export COMPOSE_FILE COMPOSE_PROJECT_NAME
# $1: container_name
get_container_ip () {
local container_name=$1
local container
local ip
container=$(docker-compose ps --all -q "${container_name}" | tail -n1)
ip=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$container")
echo "$ip"
}

View File

@ -65,7 +65,7 @@ rm -rf "${LOCAL_RESOLVE}"
printf "nameserver %s\noptions ndots:0" "${DNSROUTER_IP}" > "${LOCAL_RESOLVE}"
# bring up all remaining containers, except cypress!
docker-compose up -d --remove-orphans stepca
docker-compose up -d --remove-orphans stepca squid
docker-compose pull db-mysql || true # ok to fail
docker-compose up -d --remove-orphans --pull=never fullstack

View File

@ -6,8 +6,8 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Ensure docker-compose exists
if hash docker-compose 2>/dev/null; then
cd "${DIR}/.."
echo -e "${BLUE} ${CYAN}Testing Dev Stack ...${RESET}"
docker-compose exec -T npm bash -c "cd /app && task test"
rm -rf "$DIR/../test/results"
docker-compose up --build cypress
else
echo -e "${RED} docker-compose command is not available${RESET}"
fi

View File

@ -7,8 +7,43 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if hash docker-compose 2>/dev/null; then
cd "${DIR}/.."
echo -e "${BLUE} ${CYAN}Starting Dev Stack ...${RESET}"
echo -e "${BLUE} $(docker-compose config)${RESET}"
docker-compose up -d --remove-orphans --force-recreate --build
# Bring up a stack, in steps so we can inject IPs everywhere
docker-compose up -d pdns pdns-db
PDNS_IP=$(get_container_ip "pdns")
echo -e "${BLUE} ${YELLOW}PDNS IP is ${PDNS_IP}${RESET}"
# adjust the dnsrouter config
LOCAL_DNSROUTER_CONFIG="$DIR/../docker/dev/dnsrouter-config.json"
rm -rf "$LOCAL_DNSROUTER_CONFIG.tmp"
# IMPORTANT: changes to dnsrouter-config.json will affect this line:
jq --arg a "$PDNS_IP" '.servers[0].upstreams[1].upstream = $a' "$LOCAL_DNSROUTER_CONFIG" > "$LOCAL_DNSROUTER_CONFIG.tmp"
docker-compose up -d dnsrouter
DNSROUTER_IP=$(get_container_ip "dnsrouter")
echo -e "${BLUE} ${YELLOW}DNS Router IP is ${DNSROUTER_IP}"
if [ "${DNSROUTER_IP:-}" = "" ]; then
echo -e "${RED} ERROR: DNS Router IP is not set${RESET}"
exit 1
fi
# mount the resolver
LOCAL_RESOLVE="$DIR/../docker/dev/resolv.conf"
rm -rf "${LOCAL_RESOLVE}"
printf "nameserver %s\noptions ndots:0" "${DNSROUTER_IP}" > "${LOCAL_RESOLVE}"
# bring up all remaining containers, except cypress!
docker-compose up -d --remove-orphans stepca squid
docker-compose pull db
docker-compose up -d --remove-orphans --pull=never fullstack
docker-compose up -d --remove-orphans swagger
# docker-compose up -d --remove-orphans --force-recreate --build
# wait for main container to be healthy
bash "$DIR/wait-healthy" "$(docker-compose ps --all -q fullstack)" 120
echo ""
echo -e "${CYAN}Admin UI: http://127.0.0.1:3081${RESET}"

View File

@ -15,8 +15,8 @@ module.exports = defineConfig({
return require("../plugins/index.js")(on, config);
},
env: {
swaggerBase: '{{baseUrl}}/api/schema',
swaggerBase: '{{baseUrl}}/api/schema?ts=' + Date.now(),
},
baseUrl: 'http://localhost:1234',
baseUrl: 'http://fullstack:81',
}
});

View File

@ -1,22 +0,0 @@
const { defineConfig } = require('cypress');
module.exports = defineConfig({
requestTimeout: 30000,
defaultCommandTimeout: 20000,
reporter: 'cypress-multi-reporters',
reporterOptions: {
configFile: 'multi-reporter.json'
},
video: false,
videosFolder: 'results/videos',
screenshotsFolder: 'results/screenshots',
e2e: {
setupNodeEvents(on, config) {
return require("../plugins/index.js")(on, config);
},
env: {
swaggerBase: '{{baseUrl}}/api/schema',
},
baseUrl: 'http://localhost:1234',
}
});

View File

@ -0,0 +1,99 @@
/// <reference types="cypress" />
describe('Certificates endpoints', () => {
let token;
let certID;
before(() => {
cy.getToken().then((tok) => {
token = tok;
});
});
it('Validate custom certificate', function() {
cy.task('backendApiPostFiles', {
token: token,
path: '/api/nginx/certificates/validate',
files: {
certificate: 'test.example.com.pem',
certificate_key: 'test.example.com-key.pem',
},
}).then((data) => {
cy.validateSwaggerSchema('post', 200, '/nginx/certificates/validate', data);
expect(data).to.have.property('certificate');
expect(data).to.have.property('certificate_key');
});
});
it('Custom certificate lifecycle', function() {
// Create custom cert
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/certificates',
data: {
provider: "other",
nice_name: "Test Certificate",
},
}).then((data) => {
cy.validateSwaggerSchema('post', 201, '/nginx/certificates', data);
expect(data).to.have.property('id');
certID = data.id;
// Upload files
cy.task('backendApiPostFiles', {
token: token,
path: `/api/nginx/certificates/${certID}/upload`,
files: {
certificate: 'test.example.com.pem',
certificate_key: 'test.example.com-key.pem',
},
}).then((data) => {
cy.validateSwaggerSchema('post', 200, '/nginx/certificates/{certID}/upload', data);
expect(data).to.have.property('certificate');
expect(data).to.have.property('certificate_key');
// Get all certs
cy.task('backendApiGet', {
token: token,
path: '/api/nginx/certificates?expand=owner'
}).then((data) => {
cy.validateSwaggerSchema('get', 200, '/nginx/certificates', data);
expect(data.length).to.be.greaterThan(0);
// Delete cert
cy.task('backendApiDelete', {
token: token,
path: `/api/nginx/certificates/${certID}`
}).then((data) => {
cy.validateSwaggerSchema('delete', 200, '/nginx/certificates/{certID}', data);
expect(data).to.be.equal(true);
});
});
});
});
});
it('Request Certificate - CVE-2024-46256/CVE-2024-46257', function() {
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/certificates',
data: {
domain_names: ['test.com"||echo hello-world||\\\\n test.com"'],
meta: {
dns_challenge: false,
letsencrypt_agree: true,
letsencrypt_email: 'admin@example.com',
},
provider: 'letsencrypt',
},
returnOnError: true,
}).then((data) => {
cy.validateSwaggerSchema('post', 400, '/nginx/certificates', data);
expect(data).to.have.property('error');
expect(data.error).to.have.property('message');
expect(data.error).to.have.property('code');
expect(data.error.code).to.equal(400);
expect(data.error.message).to.contain('data/domain_names/0 must match pattern');
});
});
});

View File

@ -0,0 +1,62 @@
/// <reference types="cypress" />
describe('Full Certificate Provisions', () => {
let token;
before(() => {
cy.getToken().then((tok) => {
token = tok;
});
});
it('Should be able to create new http certificate', function() {
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/certificates',
data: {
domain_names: [
'website1.example.com'
],
meta: {
letsencrypt_email: 'admin@example.com',
letsencrypt_agree: true,
dns_challenge: false
},
provider: 'letsencrypt'
}
}).then((data) => {
cy.validateSwaggerSchema('post', 201, '/nginx/certificates', data);
expect(data).to.have.property('id');
expect(data.id).to.be.greaterThan(0);
expect(data.provider).to.be.equal('letsencrypt');
});
});
it('Should be able to create new DNS certificate with Powerdns', function() {
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/certificates',
data: {
domain_names: [
'website2.example.com'
],
meta: {
letsencrypt_email: "admin@example.com",
dns_challenge: true,
dns_provider: 'powerdns',
dns_provider_credentials: 'dns_powerdns_api_url = http://ns1.pdns:8081\r\ndns_powerdns_api_key = npm',
letsencrypt_agree: true,
propagation_seconds: 5,
},
provider: 'letsencrypt'
}
}).then((data) => {
cy.validateSwaggerSchema('post', 201, '/nginx/certificates', data);
expect(data).to.have.property('id');
expect(data.id).to.be.greaterThan(0);
expect(data.provider).to.be.equal('letsencrypt');
expect(data.meta.dns_provider).to.be.equal('powerdns');
});
});
});

View File

@ -1,4 +1,4 @@
/// <reference types="Cypress" />
/// <reference types="cypress" />
describe('Basic API checks', () => {
it('Should return a valid health payload', function () {
@ -12,7 +12,7 @@ describe('Basic API checks', () => {
it('Should return a valid schema payload', function () {
cy.task('backendApiGet', {
path: '/api/schema',
path: '/api/schema?ts=' + Date.now(),
}).then((data) => {
expect(data.openapi).to.be.equal('3.1.0');
});

View File

@ -1,6 +1,6 @@
/// <reference types="Cypress" />
/// <reference types="cypress" />
describe('Hosts endpoints', () => {
describe('Proxy Hosts endpoints', () => {
let token;
before(() => {

View File

@ -0,0 +1,124 @@
/// <reference types="cypress" />
describe('Settings endpoints', () => {
let token;
before(() => {
cy.getToken().then((tok) => {
token = tok;
});
});
it('Get all settings', function() {
cy.task('backendApiGet', {
token: token,
path: '/api/settings',
}).then((data) => {
cy.validateSwaggerSchema('get', 200, '/settings', data);
expect(data.length).to.be.greaterThan(0);
});
});
it('Get default-site setting', function() {
cy.task('backendApiGet', {
token: token,
path: '/api/settings/default-site',
}).then((data) => {
cy.validateSwaggerSchema('get', 200, '/settings/{settingID}', data);
expect(data).to.have.property('id');
expect(data.id).to.be.equal('default-site');
});
});
it('Default Site congratulations', function() {
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
data: {
value: 'congratulations',
},
}).then((data) => {
cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data);
expect(data).to.have.property('id');
expect(data.id).to.be.equal('default-site');
expect(data).to.have.property('value');
expect(data.value).to.be.equal('congratulations');
});
});
it('Default Site 404', function() {
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
data: {
value: '404',
},
}).then((data) => {
cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data);
expect(data).to.have.property('id');
expect(data.id).to.be.equal('default-site');
expect(data).to.have.property('value');
expect(data.value).to.be.equal('404');
});
});
it('Default Site 444', function() {
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
data: {
value: '444',
},
}).then((data) => {
cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data);
expect(data).to.have.property('id');
expect(data.id).to.be.equal('default-site');
expect(data).to.have.property('value');
expect(data.value).to.be.equal('444');
});
});
it('Default Site redirect', function() {
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
data: {
value: 'redirect',
meta: {
redirect: 'https://www.google.com',
},
},
}).then((data) => {
cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data);
expect(data).to.have.property('id');
expect(data.id).to.be.equal('default-site');
expect(data).to.have.property('value');
expect(data.value).to.be.equal('redirect');
expect(data).to.have.property('meta');
expect(data.meta).to.have.property('redirect');
expect(data.meta.redirect).to.be.equal('https://www.google.com');
});
});
it('Default Site html', function() {
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
data: {
value: 'html',
meta: {
html: '<p>hello world</p>'
},
},
}).then((data) => {
cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data);
expect(data).to.have.property('id');
expect(data.id).to.be.equal('default-site');
expect(data).to.have.property('value');
expect(data.value).to.be.equal('html');
expect(data).to.have.property('meta');
expect(data.meta).to.have.property('html');
expect(data.meta.html).to.be.equal('<p>hello world</p>');
});
});
});

View File

@ -1,4 +1,4 @@
/// <reference types="Cypress" />
/// <reference types="cypress" />
describe('Users endpoints', () => {
let token;

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1n9j9C5Bes1nd
qACDckERauxXVNKCnUlUM1buGBx1xc+j2e2Ar23wUJJuWBY18VfT8yqfqVDktO2w
rbmvZvLuPmXePOKbIKS+XXh+2NG9L5bDG9rwGFCRXnbQj+GWCdMfzx14+CR1IHge
Yz6Cv/Si2/LJPCh/CoBfM4hUQJON3lxAWrWBpdbZnKYMrxuPBRfW9OuzTbCVXToQ
oxRAHiOR9081Xn1WeoKr7kVBIa5UphlvWXa12w1YmUwJu7YndnJGIavLWeNCVc7Z
Eo+nS8Wr/4QWicatIWZXpVaEOPhRoeplQDxNWg5b/Q26rYoVd7PrCmRs7sVcH79X
zGONeH1PAgMBAAECggEAANb3Wtwl07pCjRrMvc7WbC0xYIn82yu8/g2qtjkYUJcU
ia5lQbYN7RGCS85Oc/tkq48xQEG5JQWNH8b918jDEMTrFab0aUEyYcru1q9L8PL6
YHaNgZSrMrDcHcS8h0QOXNRJT5jeGkiHJaTR0irvB526tqF3knbK9yW22KTfycUe
a0Z9voKn5xRk1DCbHi/nk2EpT7xnjeQeLFaTIRXbS68omkr4YGhwWm5OizoyEGZu
W0Zum5BkQyMr6kor3wdxOTG97ske2rcyvvHi+ErnwL0xBv0qY0Dhe8DpuXpDezqw
o72yY8h31Fu84i7sAj24YuE5Df8DozItFXQpkgbQ6QKBgQDPrufhvIFm2S/MzBdW
H8JxY7CJlJPyxOvc1NIl9RczQGAQR90kx52cgIcuIGEG6/wJ/xnGfMmW40F0DnQ+
N+oLgB9SFxeLkRb7s9Z/8N3uIN8JJFYcerEOiRQeN2BXEEWJ7bUThNtsVrAcKoUh
ELsDmnHW/3V+GKwhd0vpk842+wKBgQDf4PGLG9PTE5tlAoyHFodJRd2RhTJQkwsU
MDNjLJ+KecLv+Nl+QiJhoflG1ccqtSFlBSCG067CDQ5LV0xm3mLJ7pfJoMgjcq31
qjEmX4Ls91GuVOPtbwst3yFKjsHaSoKB5fBvWRcKFpBUezM7Qcw2JP3+dQT+bQIq
cMTkRWDSvQKBgQDOdCQFDjxg/lR7NQOZ1PaZe61aBz5P3pxNqa7ClvMaOsuEQ7w9
vMYcdtRq8TsjA2JImbSI0TIg8gb2FQxPcYwTJKl+FICOeIwtaSg5hTtJZpnxX5LO
utTaC0DZjNkTk5RdOdWA8tihyUdGqKoxJY2TVmwGe2rUEDjFB++J4inkEwKBgB6V
g0nmtkxanFrzOzFlMXwgEEHF+Xaqb9QFNa/xs6XeNnREAapO7JV75Cr6H2hFMFe1
mJjyqCgYUoCWX3iaHtLJRnEkBtNY4kzyQB6m46LtsnnnXO/dwKA2oDyoPfFNRoDq
YatEd3JIXNU9s2T/+x7WdOBjKhh72dTkbPFmTPDdAoGAU6rlPBevqOFdObYxdPq8
EQWu44xqky3Mf5sBpOwtu6rqCYuziLiN7K4sjN5GD5mb1cEU+oS92ZiNcUQ7MFXk
8yTYZ7U0VcXyAcpYreWwE8thmb0BohJBr+Mp3wLTx32x0HKdO6vpUa0d35LUTUmM
RrKmPK/msHKK/sVHiL+NFqo=
-----END PRIVATE KEY-----

View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEYDCCAsigAwIBAgIRAPoSC0hvitb26ODMlsH6YbowDQYJKoZIhvcNAQELBQAw
gZExHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTEzMDEGA1UECwwqamN1
cm5vd0BKYW1pZXMtTGFwdG9wLmxvY2FsIChKYW1pZSBDdXJub3cpMTowOAYDVQQD
DDFta2NlcnQgamN1cm5vd0BKYW1pZXMtTGFwdG9wLmxvY2FsIChKYW1pZSBDdXJu
b3cpMB4XDTI0MTAwOTA3MjIxN1oXDTI3MDEwOTA3MjIxN1owXjEnMCUGA1UEChMe
bWtjZXJ0IGRldmVsb3BtZW50IGNlcnRpZmljYXRlMTMwMQYDVQQLDCpqY3Vybm93
QEphbWllcy1MYXB0b3AubG9jYWwgKEphbWllIEN1cm5vdykwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQC1n9j9C5Bes1ndqACDckERauxXVNKCnUlUM1bu
GBx1xc+j2e2Ar23wUJJuWBY18VfT8yqfqVDktO2wrbmvZvLuPmXePOKbIKS+XXh+
2NG9L5bDG9rwGFCRXnbQj+GWCdMfzx14+CR1IHgeYz6Cv/Si2/LJPCh/CoBfM4hU
QJON3lxAWrWBpdbZnKYMrxuPBRfW9OuzTbCVXToQoxRAHiOR9081Xn1WeoKr7kVB
Ia5UphlvWXa12w1YmUwJu7YndnJGIavLWeNCVc7ZEo+nS8Wr/4QWicatIWZXpVaE
OPhRoeplQDxNWg5b/Q26rYoVd7PrCmRs7sVcH79XzGONeH1PAgMBAAGjZTBjMA4G
A1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAfBgNVHSMEGDAWgBSB
/vfmBUd4W7CvyEMl7YpMVQs8vTAbBgNVHREEFDASghB0ZXN0LmV4YW1wbGUuY29t
MA0GCSqGSIb3DQEBCwUAA4IBgQASwON/jPAHzcARSenY0ZGY1m5OVTYoQ/JWH0oy
l8SyFCQFEXt7UHDD/eTtLT0vMyc190nP57P8lTnZGf7hSinZz1B1d6V4cmzxpk0s
VXZT+irL6bJVJoMBHRpllKAhGULIo33baTrWFKA0oBuWx4AevSWKcLW5j87kEawn
ATCuMQ1I3ifR1mSlB7X8fb+vF+571q0NGuB3a42j6rdtXJ6SmH4+9B4qO0sfHDNt
IImpLCH/tycDpcYrGSCn1QrekFG1bSEh+Bb9i8rqMDSDsYrTFPZTuOQ3EtjGni9u
m+rEP3OyJg+md8c+0LVP7/UU4QWWnw3/Wolo5kSCxE8vNTFqi4GhVbdLnUtcIdTV
XxuR6cKyW87Snj1a0nG76ZLclt/akxDhtzqeV60BO0p8pmiev8frp+E94wFNYCmp
1cr3CnMEGRaficLSDFC6EBENzlZW2BQT6OMIV+g0NBgSyQe39s2zcdEl5+SzDVuw
hp8bJUp/QN7pnOVCDbjTQ+HVMXw=
-----END CERTIFICATE-----

View File

@ -1,9 +1,14 @@
const logger = require('./logger');
const restler = require('@jc21/restler');
const axios = require('axios').default;
const BackendApi = function(config, token) {
this.config = config;
this.token = token;
this.axios = axios.create({
baseURL: config.baseUrl,
timeout: 90000,
});
};
/**
@ -14,129 +19,114 @@ BackendApi.prototype.setToken = function(token) {
};
/**
* @param {bool} returnOnError
*/
BackendApi.prototype._prepareOptions = function(returnOnError) {
let options = {
headers: {
Accept: 'application/json'
}
}
if (this.token) {
options.headers.Authorization = 'Bearer ' + this.token;
}
if (returnOnError) {
options.validateStatus = function () {
return true;
}
}
return options;
};
/**
* @param {*} response
* @param {function} resolve
* @param {function} reject
* @param {bool} returnOnError
*/
BackendApi.prototype._handleResponse = function(response, resolve, reject, returnOnError) {
logger('Response data:', response.data);
if (!returnOnError && typeof response.data === 'object' && typeof response.data.error === 'object') {
if (typeof response.data === 'object' && typeof response.data.error === 'object' && typeof response.data.error.message !== 'undefined') {
reject(new Error(response.data.error.code + ': ' + response.data.error.message));
} else {
reject(new Error('Error ' + response.status));
}
} else {
resolve(response.data);
}
};
/**
* @param {*} err
* @param {function} resolve
* @param {function} reject
* @param {bool} returnOnError
*/
BackendApi.prototype._handleError = function(err, resolve, reject, returnOnError) {
logger('Axios Error:', err);
if (returnOnError) {
resolve(typeof err.response.data !== 'undefined' ? err.response.data : err);
} else {
reject(err);
}
};
/**
* @param {string} method
* @param {string} path
* @param {bool} [returnOnError]
* @param {*} [data]
* @returns {Promise<object>}
*/
BackendApi.prototype.get = function(path, returnOnError) {
BackendApi.prototype.request = function (method, path, returnOnError, data) {
logger(method.toUpperCase(), path);
const options = this._prepareOptions(returnOnError);
return new Promise((resolve, reject) => {
let headers = {
Accept: 'application/json'
};
if (this.token) {
headers.Authorization = 'Bearer ' + this.token;
let opts = {
method: method,
url: path,
...options
}
if (data !== undefined && data !== null) {
opts.data = data;
}
logger('GET ', this.config.baseUrl + path);
restler
.get(this.config.baseUrl + path, {
headers: headers,
this.axios(opts)
.then((response) => {
this._handleResponse(response, resolve, reject, returnOnError);
})
.on('complete', function(data, response) {
logger('Response data:', data);
if (!returnOnError && data instanceof Error) {
reject(data);
} else if (!returnOnError && response.statusCode != 200) {
if (typeof data === 'object' && typeof data.error === 'object' && typeof data.error.message !== 'undefined') {
reject(new Error(data.error.code + ': ' + data.error.message));
} else {
reject(new Error('Error ' + response.statusCode));
}
} else {
resolve(data);
}
.catch((err) => {
this._handleError(err, resolve, reject, returnOnError);
});
});
};
/**
* @param {string} path
* @param {form} form
* @param {bool} [returnOnError]
* @returns {Promise<object>}
*/
BackendApi.prototype.delete = function(path, returnOnError) {
BackendApi.prototype.postForm = function (path, form, returnOnError) {
logger('POST', this.config.baseUrl + path);
const options = this._prepareOptions(returnOnError);
return new Promise((resolve, reject) => {
let headers = {
Accept: 'application/json'
};
if (this.token) {
headers.Authorization = 'Bearer ' + this.token;
const opts = {
...options,
...form.getHeaders(),
}
logger('DELETE ', this.config.baseUrl + path);
restler
.del(this.config.baseUrl + path, {
headers: headers,
this.axios.post(path, form, opts)
.then((response) => {
this._handleResponse(response, resolve, reject, returnOnError);
})
.on('complete', function(data, response) {
logger('Response data:', data);
if (!returnOnError && data instanceof Error) {
reject(data);
} else if (!returnOnError && response.statusCode != 200) {
if (typeof data === 'object' && typeof data.error === 'object' && typeof data.error.message !== 'undefined') {
reject(new Error(data.error.code + ': ' + data.error.message));
} else {
reject(new Error('Error ' + response.statusCode));
}
} else {
resolve(data);
}
.catch((err) => {
this._handleError(err, resolve, reject, returnOnError);
});
});
};
/**
* @param {string} path
* @param {object} data
* @param {bool} [returnOnError]
* @returns {Promise<object>}
*/
BackendApi.prototype.postJson = function(path, data, returnOnError) {
logger('POST ', this.config.baseUrl + path);
return this._putPostJson('postJson', path, data, returnOnError);
};
/**
* @param {string} path
* @param {object} data
* @param {bool} [returnOnError]
* @returns {Promise<object>}
*/
BackendApi.prototype.putJson = function(path, data, returnOnError) {
logger('PUT ', this.config.baseUrl + path);
return this._putPostJson('putJson', path, data, returnOnError);
};
/**
* @param {string} path
* @param {object} data
* @param {bool} [returnOnError]
* @returns {Promise<object>}
*/
BackendApi.prototype._putPostJson = function(fn, path, data, returnOnError) {
return new Promise((resolve, reject) => {
restler[fn](this.config.baseUrl + path, data, {
headers: {
Accept: 'application/json',
Authorization: 'Bearer ' + this.token,
},
}).on('complete', function(data, response) {
logger('Response data:', data);
if (!returnOnError && data instanceof Error) {
reject(data);
} else if (!returnOnError && (response.statusCode < 200 || response.statusCode >= 300)) {
if (typeof data === 'object' && typeof data.error === 'object' && typeof data.error.message !== 'undefined') {
reject(new Error(data.error.code + ': ' + data.error.message));
} else {
reject(new Error('Error ' + response.statusCode));
}
} else {
resolve(data);
}
});
});
};
module.exports = BackendApi;

View File

@ -1,8 +1,9 @@
const fs = require('fs');
const FormData = require('form-data');
const logger = require('./logger');
const Client = require('./client');
module.exports = function (config) {
logger('Client Ready using', config.baseUrl);
return {
@ -17,7 +18,7 @@ module.exports = function (config) {
backendApiGet: (options) => {
const api = new Client(config);
api.setToken(options.token);
return api.get(options.path, options.returnOnError || false);
return api.request('get', options.path, options.returnOnError || false);
},
/**
@ -31,7 +32,26 @@ module.exports = function (config) {
backendApiPost: (options) => {
const api = new Client(config);
api.setToken(options.token);
return api.postJson(options.path, options.data, options.returnOnError || false);
return api.request('post', options.path, options.returnOnError || false, options.data);
},
/**
* @param {object} options
* @param {string} options.token JWT
* @param {string} options.path API path
* @param {object} options.files
* @param {bool} [options.returnOnError] If true, will return instead of throwing errors
* @returns {string}
*/
backendApiPostFiles: (options) => {
const api = new Client(config);
api.setToken(options.token);
const form = new FormData();
for (let [key, value] of Object.entries(options.files)) {
form.append(key, fs.createReadStream(config.fixturesFolder + '/' + value));
}
return api.postForm(options.path, form, options.returnOnError || false);
},
/**
@ -45,7 +65,7 @@ module.exports = function (config) {
backendApiPut: (options) => {
const api = new Client(config);
api.setToken(options.token);
return api.putJson(options.path, options.data, options.returnOnError || false);
return api.request('put', options.path, options.returnOnError || false, options.data);
},
/**
@ -58,7 +78,7 @@ module.exports = function (config) {
backendApiDelete: (options) => {
const api = new Client(config);
api.setToken(options.token);
return api.delete(options.path, options.returnOnError || false);
return api.request('delete', options.path, options.returnOnError || false);
}
};
};
};

View File

@ -1,4 +1,4 @@
const {SwaggerValidation} = require('@jc21/cypress-swagger-validation');
const { SwaggerValidation } = require('@jc21/cypress-swagger-validation');
module.exports = (on, config) => {
// Replace swaggerBase config var wildcard

View File

@ -1,11 +1,11 @@
{
"name": "test",
"name": "npm-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"@jc21/cypress-swagger-validation": "^0.2.6",
"@jc21/restler": "^3.4.0",
"@jc21/cypress-swagger-validation": "^0.3.1",
"axios": "^1.7.7",
"cypress": "^13.15.0",
"cypress-multi-reporters": "^1.6.4",
"cypress-wait-until": "^3.0.2",
@ -13,13 +13,14 @@
"eslint-plugin-align-assignments": "^1.1.2",
"eslint-plugin-chai-friendly": "^1.0.1",
"eslint-plugin-cypress": "^3.5.0",
"form-data": "^4.0.1",
"lodash": "^4.17.21",
"mocha": "^10.7.3",
"mocha-junit-reporter": "^2.2.1"
},
"scripts": {
"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}"
"cypress": "HTTP_PROXY=127.0.0.1:8128 HTTPS_PROXY=127.0.0.1:8128 cypress open --config-file=cypress/config/ci.js",
"cypress:headless": "HTTP_PROXY=127.0.0.1:8128 HTTPS_PROXY=127.0.0.1:8128 cypress run --config-file=cypress/config/ci.js"
},
"author": "",
"license": "ISC"

View File

@ -11,14 +11,13 @@
call-me-maybe "^1.0.1"
js-yaml "^3.13.1"
"@apidevtools/json-schema-ref-parser@9.0.9":
version "9.0.9"
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b"
integrity sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==
"@apidevtools/json-schema-ref-parser@^11.7.2":
version "11.7.2"
resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz#cdf3e0aded21492364a70e193b45b7cf4177f031"
integrity sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==
dependencies:
"@jsdevtools/ono" "^7.1.3"
"@types/json-schema" "^7.0.6"
call-me-maybe "^1.0.1"
"@types/json-schema" "^7.0.15"
js-yaml "^4.1.0"
"@apidevtools/openapi-schemas@^2.1.0":
@ -167,29 +166,20 @@
resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a"
integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==
"@jc21/cypress-swagger-validation@^0.2.6":
version "0.2.6"
resolved "https://registry.yarnpkg.com/@jc21/cypress-swagger-validation/-/cypress-swagger-validation-0.2.6.tgz#8b61f2413fa81cae6f8c2f33ecce5a6ded897030"
integrity sha512-8i8poTwi13e4BRKWpvmXFmqvEfQq3Kn9tunWhNYT7IQwiMeUVou+g1yh99QzuI501DBPtL2XEwjNukxTf5GiyQ==
"@jc21/cypress-swagger-validation@^0.3.1":
version "0.3.1"
resolved "https://registry.yarnpkg.com/@jc21/cypress-swagger-validation/-/cypress-swagger-validation-0.3.1.tgz#1cdd49850a20f876ed62149623f99988264751be"
integrity sha512-Vdt1gLfj8p0tJhA42Cfn43XBbsKocNfVCEVSwkn7RmZgWUyRKjqhBBRTVa9cKZTozyg8Co/yhBMsNyjmHFVXtQ==
dependencies:
"@apidevtools/json-schema-ref-parser" "^11.7.2"
"@apidevtools/swagger-parser" "^10.1.0"
ajv "^8.12.0"
ajv "^8.17.1"
axios "^1.7.7"
json-schema "^0.4.0"
json-schema-ref-parser "^9.0.6"
jsonpath "^1.1.1"
lodash "^4.17.21"
openapi-types "^12.1.3"
picocolors "^1.0.0"
"@jc21/restler@^3.4.0":
version "3.4.0"
resolved "https://registry.yarnpkg.com/@jc21/restler/-/restler-3.4.0.tgz#cfa214ddb9946a800c6fe472529f72b01e93c763"
integrity sha512-P1Nl2ifoQwqtxcqJKYHvxgPfckeIZWbVSYMlNAP+cL2KNk3U5eErPKt4xr5YLIQ+NarFsHMGH8+CBa00FKAGrw==
dependencies:
iconv-lite "0.2.11"
qs "1.2.0"
xml2js "0.4.0"
yaml "0.2.3"
picocolors "^1.1.0"
"@jsdevtools/ono@^7.1.3":
version "7.1.3"
@ -206,7 +196,7 @@
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
"@types/json-schema@^7.0.15", "@types/json-schema@^7.0.6":
"@types/json-schema@^7.0.15":
version "7.0.15"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
@ -271,7 +261,17 @@ ajv@^6.12.4:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
ajv@^8.12.0, ajv@^8.6.3:
ajv@^8.17.1:
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.3:
version "8.13.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.13.0.tgz#a3939eaec9fb80d217ddf0c3376948c023f28c91"
integrity sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==
@ -390,6 +390,15 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c"
integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==
axios@^1.7.7:
version "1.7.7"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f"
integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==
dependencies:
follow-redirects "^1.15.6"
form-data "^4.0.0"
proxy-from-env "^1.1.0"
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
@ -438,11 +447,11 @@ brace-expansion@^2.0.1:
balanced-match "^1.0.0"
braces@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
version "3.0.3"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
dependencies:
fill-range "^7.0.1"
fill-range "^7.1.1"
browser-stdout@^1.3.1:
version "1.3.1"
@ -506,11 +515,6 @@ chalk@^4.0.0, chalk@^4.1.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chalk@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385"
integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==
charenc@0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
@ -1049,6 +1053,11 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
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==
fd-slicer@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
@ -1070,10 +1079,10 @@ file-entry-cache@^8.0.0:
dependencies:
flat-cache "^4.0.0"
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
fill-range@^7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
dependencies:
to-regex-range "^5.0.1"
@ -1103,11 +1112,25 @@ flatted@^3.2.9:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
follow-redirects@^1.15.6:
version "1.15.9"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1"
integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
form-data@^4.0.0, form-data@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48"
integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
form-data@~4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
@ -1283,11 +1306,6 @@ human-signals@^1.1.1:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
iconv-lite@0.2.11:
version "0.2.11"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.2.11.tgz#1ce60a3a57864a292d1321ff4609ca4bb965adc8"
integrity sha1-HOYKOleGSiktEyH/RgnKS7llrcg=
ieee754@^1.1.13:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
@ -1450,13 +1468,6 @@ json-buffer@3.0.1:
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
json-schema-ref-parser@^9.0.6:
version "9.0.9"
resolved "https://registry.yarnpkg.com/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#66ea538e7450b12af342fa3d5b8458bc1e1e013f"
integrity sha512-qcP2lmGy+JUoQJ4DOQeLaZDqH9qSkeGCK3suKWxJXS82dg728Mn3j97azDMaOUmJAN4uCq91LdPx4K7E8F1a7Q==
dependencies:
"@apidevtools/json-schema-ref-parser" "9.0.9"
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"
@ -1812,10 +1823,10 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
picocolors@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1"
integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==
picocolors@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.0.tgz#5358b76a78cde483ba5cef6a9dc9671440b27d59"
integrity sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==
picomatch@^2.0.4:
version "2.2.2"
@ -1857,6 +1868,11 @@ proxy-from-env@1.0.0:
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee"
integrity sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==
proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
psl@^1.1.33:
version "1.9.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
@ -1875,11 +1891,6 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
qs@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-1.2.0.tgz#ed079be28682147e6fd9a34cc2b0c1e0ec6453ee"
integrity sha1-7Qeb4oaCFH5v2aNMwrDB4OxkU+4=
qs@6.13.0:
version "6.13.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
@ -1968,11 +1979,6 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sax@0.5.x:
version "0.5.8"
resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1"
integrity sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=
semver@^7.5.3:
version "7.6.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
@ -2309,34 +2315,16 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
xml2js@0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.0.tgz#124fc4114b4129c810800ecb2ac86cf25462cb9a"
integrity sha1-Ek/EEUtBKcgQgA7LKshs8lRiy5o=
dependencies:
sax "0.5.x"
xmlbuilder ">=0.4.2"
xml@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5"
integrity sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==
xmlbuilder@>=0.4.2:
version "13.0.2"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-13.0.2.tgz#02ae33614b6a047d1c32b5389c1fdacb2bce47a7"
integrity sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==
y18n@^5.0.5:
version "5.0.8"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
yaml@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-0.2.3.tgz#b5450e92e76ef36b5dd24e3660091ebaeef3e5c7"
integrity sha1-tUUOkudu82td0k42YAkeuu7z5cc=
yargs-parser@^20.2.2, yargs-parser@^20.2.9:
version "20.2.9"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"