Compare commits

..

9 Commits

Author SHA1 Message Date
jc21
a262ad132b Merge branch 'develop' into stream-ssl 2025-01-07 07:59:51 +10:00
jbowring
e4c10131f0 Merge branch 'NginxProxyManager:develop' into stream-ssl 2024-12-02 21:29:22 +00:00
Joel Bowring
d3526debe6 Merge branch 'NginxProxyManager:develop' into stream-ssl 2024-08-01 21:14:56 +01:00
jbowring
207dbb2f37 Fix stream update not persisting 2024-07-23 08:39:18 +01:00
jbowring
ae1255df27 Fix whitespace in nginx stream config 2024-07-22 20:53:21 +01:00
jbowring
7307515eed Add certificate to streams database model 2024-06-02 20:32:11 +01:00
jbowring
1d3d5be588 Add SSL column to streams table UI 2024-06-02 20:32:11 +01:00
jbowring
0cf7ed9d82 Add SSL tab to stream UI 2024-06-02 20:32:11 +01:00
jbowring
b8b80d3e80 Add SSL certificate to TCP streams if certificate in database 2024-06-02 20:32:11 +01:00
56 changed files with 1084 additions and 1826 deletions

View File

@@ -1 +1 @@
2.12.5 2.12.2

21
Jenkinsfile vendored
View File

@@ -128,7 +128,7 @@ pipeline {
sh 'docker-compose down --remove-orphans --volumes -t 30 || true' sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
} }
unstable { unstable {
dir(path: 'test/results') { dir(path: 'testing/results') {
archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml') archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml')
} }
} }
@@ -161,7 +161,7 @@ pipeline {
sh 'docker-compose down --remove-orphans --volumes -t 30 || true' sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
} }
unstable { unstable {
dir(path: 'test/results') { dir(path: 'testing/results') {
archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml') archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml')
} }
} }
@@ -199,7 +199,7 @@ pipeline {
sh 'docker-compose down --remove-orphans --volumes -t 30 || true' sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
} }
unstable { unstable {
dir(path: 'test/results') { dir(path: 'testing/results') {
archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml') archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml')
} }
} }
@@ -241,17 +241,12 @@ pipeline {
} }
steps { steps {
script { script {
npmGithubPrComment("""Docker Image for build ${BUILD_NUMBER} is available on [DockerHub](https://cloud.docker.com/repository/docker/nginxproxymanager/${IMAGE}-dev): npmGithubPrComment("""Docker Image for build ${BUILD_NUMBER} is available on
``` [DockerHub](https://cloud.docker.com/repository/docker/nginxproxymanager/${IMAGE}-dev)
nginxproxymanager/${IMAGE}-dev:${BRANCH_LOWER} as `nginxproxymanager/${IMAGE}-dev:${BRANCH_LOWER}`
```
> [!NOTE] **Note:** ensure you backup your NPM instance before testing this image! Especially if there are database changes
> Ensure you backup your NPM instance before testing this image! Especially if there are database changes. **Note:** this is a different docker image namespace than the official image
> This is a different docker image namespace than the official image.
> [!WARNING]
> Changes and additions to DNS Providers require verification by at least 2 members of the community!
""", true) """, true)
} }
} }

View File

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

View File

@@ -3,8 +3,6 @@
const schema = require('./schema'); const schema = require('./schema');
const logger = require('./logger').global; const logger = require('./logger').global;
const IP_RANGES_FETCH_ENABLED = process.env.IP_RANGES_FETCH_ENABLED !== 'false';
async function appStart () { async function appStart () {
const migrate = require('./migrate'); const migrate = require('./migrate');
const setup = require('./setup'); const setup = require('./setup');
@@ -15,16 +13,7 @@ async function appStart () {
return migrate.latest() return migrate.latest()
.then(setup) .then(setup)
.then(schema.getCompiledSchema) .then(schema.getCompiledSchema)
.then(() => { .then(internalIpRanges.fetch)
if (IP_RANGES_FETCH_ENABLED) {
logger.info('IP Ranges fetch is enabled');
return internalIpRanges.fetch().catch((err) => {
logger.error('IP Ranges fetch failed, continuing anyway:', err.message);
});
} else {
logger.info('IP Ranges fetch is disabled by environment variable');
}
})
.then(() => { .then(() => {
internalCertificate.initTimer(); internalCertificate.initTimer();
internalIpRanges.initTimer(); internalIpRanges.initTimer();

View File

@@ -258,7 +258,6 @@ const internalAccessList = {
}) })
.where('access_list.is_deleted', 0) .where('access_list.is_deleted', 0)
.andWhere('access_list.id', data.id) .andWhere('access_list.id', data.id)
.groupBy('access_list.id')
.allowGraph('[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]') .allowGraph('[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]')
.first(); .first();
@@ -508,13 +507,8 @@ const internalAccessList = {
if (typeof item.password !== 'undefined' && item.password.length) { if (typeof item.password !== 'undefined' && item.password.length) {
logger.info('Adding: ' + item.username); logger.info('Adding: ' + item.username);
utils.execFile('openssl', ['passwd', '-apr1', item.password]) utils.execFile('/usr/bin/htpasswd', ['-b', htpasswd_file, item.username, item.password])
.then((res) => { .then((/*result*/) => {
try {
fs.appendFileSync(htpasswd_file, item.username + ':' + res + '\n', {encoding: 'utf8'});
} catch (err) {
reject(err);
}
next(); next();
}) })
.catch((err) => { .catch((err) => {

View File

@@ -313,9 +313,6 @@ const internalCertificate = {
.where('is_deleted', 0) .where('is_deleted', 0)
.andWhere('id', data.id) .andWhere('id', data.id)
.allowGraph('[owner]') .allowGraph('[owner]')
.allowGraph('[proxy_hosts]')
.allowGraph('[redirection_hosts]')
.allowGraph('[dead_hosts]')
.first(); .first();
if (access_data.permission_visibility !== 'all') { if (access_data.permission_visibility !== 'all') {
@@ -467,9 +464,6 @@ const internalCertificate = {
.where('is_deleted', 0) .where('is_deleted', 0)
.groupBy('id') .groupBy('id')
.allowGraph('[owner]') .allowGraph('[owner]')
.allowGraph('[proxy_hosts]')
.allowGraph('[redirection_hosts]')
.allowGraph('[dead_hosts]')
.orderBy('nice_name', 'ASC'); .orderBy('nice_name', 'ASC');
if (access_data.permission_visibility !== 'all') { if (access_data.permission_visibility !== 'all') {

View File

@@ -9,7 +9,7 @@ const internalHost = require('./host');
const {castJsonIfNeed} = require('../lib/helpers'); const {castJsonIfNeed} = require('../lib/helpers');
function omissions () { function omissions () {
return ['is_deleted', 'owner.is_deleted', 'certificate.is_deleted']; return ['is_deleted'];
} }
const internalStream = { const internalStream = {
@@ -20,7 +20,7 @@ const internalStream = {
* @returns {Promise} * @returns {Promise}
*/ */
create: (access, data) => { create: (access, data) => {
const create_certificate = data.certificate_id === 'new'; let create_certificate = data.certificate_id === 'new';
if (create_certificate) { if (create_certificate) {
delete data.certificate_id; delete data.certificate_id;
@@ -96,7 +96,7 @@ const internalStream = {
* @return {Promise} * @return {Promise}
*/ */
update: (access, data) => { update: (access, data) => {
const create_certificate = data.certificate_id === 'new'; let create_certificate = data.certificate_id === 'new';
if (create_certificate) { if (create_certificate) {
delete data.certificate_id; delete data.certificate_id;
@@ -369,7 +369,7 @@ const internalStream = {
.where('is_deleted', 0) .where('is_deleted', 0)
.groupBy('id') .groupBy('id')
.allowGraph('[owner,certificate]') .allowGraph('[owner,certificate]')
.orderBy('incoming_port', 'ASC'); .orderByRaw('CAST(incoming_port AS INTEGER) ASC');
if (access_data.permission_visibility !== 'all') { if (access_data.permission_visibility !== 'all') {
query.andWhere('owner_user_id', access.token.getUserId(1)); query.andWhere('owner_user_id', access.token.getUserId(1));

View File

@@ -11,7 +11,7 @@ const certbot = {
/** /**
* @param {array} pluginKeys * @param {array} pluginKeys
*/ */
installPlugins: async (pluginKeys) => { installPlugins: async function (pluginKeys) {
let hasErrors = false; let hasErrors = false;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@@ -21,7 +21,7 @@ const certbot = {
} }
batchflow(pluginKeys).sequential() batchflow(pluginKeys).sequential()
.each((_i, pluginKey, next) => { .each((i, pluginKey, next) => {
certbot.installPlugin(pluginKey) certbot.installPlugin(pluginKey)
.then(() => { .then(() => {
next(); next();
@@ -51,7 +51,7 @@ const certbot = {
* @param {string} pluginKey * @param {string} pluginKey
* @returns {Object} * @returns {Object}
*/ */
installPlugin: async (pluginKey) => { installPlugin: async function (pluginKey) {
if (typeof dnsPlugins[pluginKey] === 'undefined') { if (typeof dnsPlugins[pluginKey] === 'undefined') {
// throw Error(`Certbot plugin ${pluginKey} not found`); // throw Error(`Certbot plugin ${pluginKey} not found`);
throw new error.ItemNotFoundError(pluginKey); throw new error.ItemNotFoundError(pluginKey);
@@ -63,15 +63,8 @@ const certbot = {
plugin.version = plugin.version.replace(/{{certbot-version}}/g, CERTBOT_VERSION_REPLACEMENT); plugin.version = plugin.version.replace(/{{certbot-version}}/g, CERTBOT_VERSION_REPLACEMENT);
plugin.dependencies = plugin.dependencies.replace(/{{certbot-version}}/g, CERTBOT_VERSION_REPLACEMENT); plugin.dependencies = plugin.dependencies.replace(/{{certbot-version}}/g, CERTBOT_VERSION_REPLACEMENT);
// SETUPTOOLS_USE_DISTUTILS is required for certbot plugins to install correctly const cmd = '. /opt/certbot/bin/activate && pip install --no-cache-dir ' + plugin.dependencies + ' ' + plugin.package_name + plugin.version + ' ' + ' && deactivate';
// in new versions of Python return utils.exec(cmd)
let env = Object.assign({}, process.env, {SETUPTOOLS_USE_DISTUTILS: 'stdlib'});
if (typeof plugin.env === 'object') {
env = Object.assign(env, plugin.env);
}
const cmd = `. /opt/certbot/bin/activate && pip install --no-cache-dir ${plugin.dependencies} ${plugin.package_name}${plugin.version} && deactivate`;
return utils.exec(cmd, {env})
.then((result) => { .then((result) => {
logger.complete(`Installed ${pluginKey}`); logger.complete(`Installed ${pluginKey}`);
return result; return result;

View File

@@ -1,13 +1,13 @@
const _ = require('lodash'); const _ = require('lodash');
const exec = require('node:child_process').exec; const exec = require('child_process').exec;
const execFile = require('node:child_process').execFile; const execFile = require('child_process').execFile;
const { Liquid } = require('liquidjs'); const { Liquid } = require('liquidjs');
const logger = require('../logger').global; const logger = require('../logger').global;
const error = require('./error'); const error = require('./error');
module.exports = { module.exports = {
exec: async (cmd, options = {}) => { exec: async function(cmd, options = {}) {
logger.debug('CMD:', cmd); logger.debug('CMD:', cmd);
const { stdout, stderr } = await new Promise((resolve, reject) => { const { stdout, stderr } = await new Promise((resolve, reject) => {
@@ -31,11 +31,11 @@ module.exports = {
* @param {Array} args * @param {Array} args
* @returns {Promise} * @returns {Promise}
*/ */
execFile: (cmd, args) => { execFile: function (cmd, args) {
// logger.debug('CMD: ' + cmd + ' ' + (args ? args.join(' ') : '')); // logger.debug('CMD: ' + cmd + ' ' + (args ? args.join(' ') : ''));
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
execFile(cmd, args, (err, stdout, /*stderr*/) => { execFile(cmd, args, function (err, stdout, /*stderr*/) {
if (err && typeof err === 'object') { if (err && typeof err === 'object') {
reject(err); reject(err);
} else { } else {
@@ -51,7 +51,7 @@ module.exports = {
* @param {Array} omissions * @param {Array} omissions
* @returns {Function} * @returns {Function}
*/ */
omitRow: (omissions) => { omitRow: function (omissions) {
/** /**
* @param {Object} row * @param {Object} row
* @returns {Object} * @returns {Object}
@@ -67,7 +67,7 @@ module.exports = {
* @param {Array} omissions * @param {Array} omissions
* @returns {Function} * @returns {Function}
*/ */
omitRows: (omissions) => { omitRows: function (omissions) {
/** /**
* @param {Array} rows * @param {Array} rows
* @returns {Object} * @returns {Object}
@@ -83,9 +83,9 @@ module.exports = {
/** /**
* @returns {Object} Liquid render engine * @returns {Object} Liquid render engine
*/ */
getRenderEngine: () => { getRenderEngine: function () {
const renderEngine = new Liquid({ const renderEngine = new Liquid({
root: `${__dirname}/../templates/` root: __dirname + '/../templates/'
}); });
/** /**

View File

@@ -4,6 +4,7 @@
const db = require('../db'); const db = require('../db');
const helpers = require('../lib/helpers'); const helpers = require('../lib/helpers');
const Model = require('objection').Model; const Model = require('objection').Model;
const User = require('./user');
const now = require('./now_helper'); const now = require('./now_helper');
Model.knex(db); Model.knex(db);
@@ -67,11 +68,6 @@ class Certificate extends Model {
} }
static get relationMappings () { static get relationMappings () {
const ProxyHost = require('./proxy_host');
const DeadHost = require('./dead_host');
const User = require('./user');
const RedirectionHost = require('./redirection_host');
return { return {
owner: { owner: {
relation: Model.HasOneRelation, relation: Model.HasOneRelation,
@@ -83,39 +79,6 @@ class Certificate extends Model {
modify: function (qb) { modify: function (qb) {
qb.where('user.is_deleted', 0); qb.where('user.is_deleted', 0);
} }
},
proxy_hosts: {
relation: Model.HasManyRelation,
modelClass: ProxyHost,
join: {
from: 'certificate.id',
to: 'proxy_host.certificate_id'
},
modify: function (qb) {
qb.where('proxy_host.is_deleted', 0);
}
},
dead_hosts: {
relation: Model.HasManyRelation,
modelClass: DeadHost,
join: {
from: 'certificate.id',
to: 'dead_host.certificate_id'
},
modify: function (qb) {
qb.where('dead_host.is_deleted', 0);
}
},
redirection_hosts: {
relation: Model.HasManyRelation,
modelClass: RedirectionHost,
join: {
from: 'certificate.id',
to: 'redirection_host.certificate_id'
},
modify: function (qb) {
qb.where('redirection_host.is_deleted', 0);
}
} }
}; };
} }

View File

@@ -12,11 +12,7 @@ Model.knex(db);
const boolFields = [ const boolFields = [
'is_deleted', 'is_deleted',
'ssl_forced',
'http2_support',
'enabled', 'enabled',
'hsts_enabled',
'hsts_subdomains',
]; ];
class DeadHost extends Model { class DeadHost extends Model {

View File

@@ -1,15 +1,17 @@
const Model = require('objection').Model; // Objection Docs:
// http://vincit.github.io/objection.js/
const db = require('../db'); const db = require('../db');
const helpers = require('../lib/helpers'); const helpers = require('../lib/helpers');
const Model = require('objection').Model;
const User = require('./user'); const User = require('./user');
const Certificate = require('./certificate');
const now = require('./now_helper'); const now = require('./now_helper');
const Certificate = require('./certificate');
Model.knex(db); Model.knex(db);
const boolFields = [ const boolFields = [
'is_deleted', 'is_deleted',
'enabled',
'tcp_forwarding', 'tcp_forwarding',
'udp_forwarding', 'udp_forwarding',
]; ];

View File

@@ -181,7 +181,7 @@ router
return internalUser.setPassword(res.locals.access, payload); return internalUser.setPassword(res.locals.access, payload);
}) })
.then((result) => { .then((result) => {
res.status(200) res.status(201)
.send(result); .send(result);
}) })
.catch(next); .catch(next);
@@ -212,7 +212,7 @@ router
return internalUser.setPermissions(res.locals.access, payload); return internalUser.setPermissions(res.locals.access, payload);
}) })
.then((result) => { .then((result) => {
res.status(200) res.status(201)
.send(result); .send(result);
}) })
.catch(next); .catch(next);
@@ -238,7 +238,7 @@ router
.post((req, res, next) => { .post((req, res, next) => {
internalUser.loginAs(res.locals.access, {id: parseInt(req.params.user_id, 10)}) internalUser.loginAs(res.locals.access, {id: parseInt(req.params.user_id, 10)})
.then((result) => { .then((result) => {
res.status(200) res.status(201)
.send(result); .send(result);
}) })
.catch(next); .catch(next);

View File

@@ -22,7 +22,8 @@
"enabled", "enabled",
"locations", "locations",
"hsts_enabled", "hsts_enabled",
"hsts_subdomains" "hsts_subdomains",
"certificate"
], ],
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {

View File

@@ -1,7 +1,7 @@
{ {
"type": "array", "type": "array",
"description": "Streams list", "description": "Proxy Hosts list",
"items": { "items": {
"$ref": "./stream-object.json" "$ref": "./proxy-host-object.json"
} }
} }

View File

@@ -19,7 +19,9 @@
"incoming_port": { "incoming_port": {
"type": "integer", "type": "integer",
"minimum": 1, "minimum": 1,
"maximum": 65535 "maximum": 65535,
"if": {"properties": {"tcp_forwarding": {"const": true}}},
"then": {"not": {"oneOf": [{"const": 80}, {"const": 443}]}}
}, },
"forwarding_host": { "forwarding_host": {
"anyOf": [ "anyOf": [
@@ -50,18 +52,12 @@
"udp_forwarding": { "udp_forwarding": {
"type": "boolean" "type": "boolean"
}, },
"enabled": { "domain_names": {
"$ref": "../common.json#/properties/enabled" "$ref": "../common.json#/properties/domain_names"
}, },
"certificate_id": { "certificate_id": {
"$ref": "../common.json#/properties/certificate_id" "$ref": "../common.json#/properties/certificate_id"
}, },
"meta": {
"type": "object"
},
"owner": {
"$ref": "./user-object.json"
},
"certificate": { "certificate": {
"oneOf": [ "oneOf": [
{ {
@@ -71,6 +67,12 @@
"$ref": "./certificate-object.json" "$ref": "./certificate-object.json"
} }
] ]
},
"enabled": {
"$ref": "../common.json#/properties/enabled"
},
"meta": {
"type": "object"
} }
} }
} }

View File

@@ -5,9 +5,10 @@
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"expires": { "expires": {
"description": "Token Expiry ISO Time String", "description": "Token Expiry Unix Time",
"example": "2025-02-04T20:40:46.340Z", "example": 1566540249,
"type": "string" "minimum": 1,
"type": "number"
}, },
"token": { "token": {
"description": "JWT Token", "description": "JWT Token",

View File

@@ -14,7 +14,7 @@
"description": "Expansions", "description": "Expansions",
"schema": { "schema": {
"type": "string", "type": "string",
"enum": ["owner", "certificate"] "enum": ["access_list", "owner", "certificate"]
} }
} }
], ],
@@ -40,8 +40,7 @@
"nginx_online": true, "nginx_online": true,
"nginx_err": null "nginx_err": null
}, },
"enabled": true, "enabled": true
"certificate_id": 0
} }
] ]
} }

View File

@@ -32,6 +32,9 @@
"udp_forwarding": { "udp_forwarding": {
"$ref": "../../../components/stream-object.json#/properties/udp_forwarding" "$ref": "../../../components/stream-object.json#/properties/udp_forwarding"
}, },
"domain_names": {
"$ref": "../../../components/stream-object.json#/properties/domain_names"
},
"certificate_id": { "certificate_id": {
"$ref": "../../../components/stream-object.json#/properties/certificate_id" "$ref": "../../../components/stream-object.json#/properties/certificate_id"
}, },
@@ -77,7 +80,8 @@
"avatar": "", "avatar": "",
"roles": ["admin"] "roles": ["admin"]
}, },
"certificate_id": 0 "certificate_id": 0,
"certificate": null
} }
} }
}, },

View File

@@ -40,8 +40,7 @@
"nginx_online": true, "nginx_online": true,
"nginx_err": null "nginx_err": null
}, },
"enabled": true, "enabled": true
"certificate_id": 0
} }
} }
}, },

View File

@@ -44,6 +44,9 @@
"udp_forwarding": { "udp_forwarding": {
"$ref": "../../../../components/stream-object.json#/properties/udp_forwarding" "$ref": "../../../../components/stream-object.json#/properties/udp_forwarding"
}, },
"domain_names": {
"$ref": "../../../../components/stream-object.json#/properties/domain_names"
},
"certificate_id": { "certificate_id": {
"$ref": "../../../../components/stream-object.json#/properties/certificate_id" "$ref": "../../../../components/stream-object.json#/properties/certificate_id"
}, },
@@ -64,8 +67,8 @@
"default": { "default": {
"value": { "value": {
"id": 1, "id": 1,
"created_on": "2024-10-09T02:33:45.000Z", "created_on": "2024-10-08T23:23:03.000Z",
"modified_on": "2024-10-09T02:33:45.000Z", "modified_on": "2024-10-08T23:26:37.000Z",
"owner_user_id": 1, "owner_user_id": 1,
"incoming_port": 9090, "incoming_port": 9090,
"forwarding_host": "router.internal", "forwarding_host": "router.internal",
@@ -79,17 +82,18 @@
"enabled": true, "enabled": true,
"owner": { "owner": {
"id": 1, "id": 1,
"created_on": "2024-10-09T02:33:16.000Z", "created_on": "2024-10-07T22:43:55.000Z",
"modified_on": "2024-10-09T02:33:16.000Z", "modified_on": "2024-10-08T12:52:54.000Z",
"is_deleted": false, "is_deleted": false,
"is_disabled": false, "is_disabled": false,
"email": "admin@example.com", "email": "admin@example.com",
"name": "Administrator", "name": "Administrator",
"nickname": "Admin", "nickname": "some guy",
"avatar": "", "avatar": "//www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?default=mm",
"roles": ["admin"] "roles": ["admin"]
}, },
"certificate_id": 0 "certificate": null,
"access_list": null
} }
} }
}, },

View File

@@ -15,7 +15,7 @@
"examples": { "examples": {
"default": { "default": {
"value": { "value": {
"expires": "2025-02-04T20:40:46.340Z", "expires": 1566540510,
"token": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4" "token": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4"
} }
} }

View File

@@ -38,7 +38,7 @@
"default": { "default": {
"value": { "value": {
"result": { "result": {
"expires": "2025-02-04T20:40:46.340Z", "expires": 1566540510,
"token": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4" "token": "eyJhbGciOiJSUzUxMiIsInR5cCI6IkpXVCJ9.ey...xaHKYr3Kk6MvkUjcC4"
} }
} }

View File

@@ -9,15 +9,6 @@
"url": "http://127.0.0.1:81/api" "url": "http://127.0.0.1:81/api"
} }
], ],
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
},
"paths": { "paths": {
"/": { "/": {
"get": { "get": {

View File

@@ -492,9 +492,9 @@ boxen@^4.2.0:
widest-line "^3.1.0" widest-line "^3.1.0"
brace-expansion@^1.1.7: brace-expansion@^1.1.7:
version "1.1.12" version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
dependencies: dependencies:
balanced-match "^1.0.0" balanced-match "^1.0.0"
concat-map "0.0.1" concat-map "0.0.1"

View File

@@ -18,7 +18,6 @@ services:
MYSQL_DATABASE: 'npm' MYSQL_DATABASE: 'npm'
MYSQL_USER: 'npm' MYSQL_USER: 'npm'
MYSQL_PASSWORD: 'npmpass' MYSQL_PASSWORD: 'npmpass'
MARIADB_AUTO_UPGRADE: '1'
volumes: volumes:
- mysql_vol:/var/lib/mysql - mysql_vol:/var/lib/mysql
networks: networks:

View File

@@ -22,10 +22,6 @@ services:
test: ["CMD", "/usr/bin/check-health"] test: ["CMD", "/usr/bin/check-health"]
interval: 10s interval: 10s
timeout: 3s timeout: 3s
expose:
- '80-81/tcp'
- '443/tcp'
- '1500-1503/tcp'
networks: networks:
fulltest: fulltest:
aliases: aliases:
@@ -44,7 +40,7 @@ services:
- ca.internal - ca.internal
pdns: pdns:
image: pschiffe/pdns-mysql:4.8 image: pschiffe/pdns-mysql
volumes: volumes:
- '/etc/localtime:/etc/localtime:ro' - '/etc/localtime:/etc/localtime:ro'
environment: environment:
@@ -101,7 +97,7 @@ services:
HTTP_PROXY: 'squid:3128' HTTP_PROXY: 'squid:3128'
HTTPS_PROXY: 'squid:3128' HTTPS_PROXY: 'squid:3128'
volumes: volumes:
- 'cypress_logs:/test/results' - 'cypress_logs:/results'
- './dev/resolv.conf:/etc/resolv.conf:ro' - './dev/resolv.conf:/etc/resolv.conf:ro'
- '/etc/localtime:/etc/localtime:ro' - '/etc/localtime:/etc/localtime:ro'
command: cypress run --browser chrome --config-file=cypress/config/ci.js command: cypress run --browser chrome --config-file=cypress/config/ci.js

View File

@@ -132,7 +132,7 @@ services:
- 8128:3128 - 8128:3128
pdns: pdns:
image: pschiffe/pdns-mysql:4.8 image: pschiffe/pdns-mysql
container_name: npm2dev.pdns container_name: npm2dev.pdns
volumes: volumes:
- '/etc/localtime:/etc/localtime:ro' - '/etc/localtime:/etc/localtime:ro'
@@ -218,7 +218,7 @@ services:
env_file: env_file:
- ci.env - ci.env
ports: ports:
- 9000:9000 - 9000:9000
depends_on: depends_on:
- authentik-redis - authentik-redis
- db-postgres - db-postgres

View File

@@ -23,22 +23,6 @@ chown -R "$PUID:$PGID" /etc/nginx/nginx
chown -R "$PUID:$PGID" /etc/nginx/nginx.conf chown -R "$PUID:$PGID" /etc/nginx/nginx.conf
chown -R "$PUID:$PGID" /etc/nginx/conf.d chown -R "$PUID:$PGID" /etc/nginx/conf.d
# Certbot directories - optimized approach # Prevents errors when installing python certbot plugins when non-root
CERT_INIT_FLAG="/opt/certbot/.ownership_initialized" chown "$PUID:$PGID" /opt/certbot /opt/certbot/bin
find /opt/certbot/lib/python*/site-packages -not -user "$PUID" -execdir chown "$PUID:$PGID" {} \+
if [ ! -f "$CERT_INIT_FLAG" ]; then
# Prevents errors when installing python certbot plugins when non-root
if [ "$SKIP_CERTBOT_OWNERSHIP" != "true" ]; then
log_info 'Changing ownership of /opt/certbot directories ...'
chown "$PUID:$PGID" /opt/certbot /opt/certbot/bin
fi
# Handle all site-packages directories efficiently
find /opt/certbot/lib -type d -name "site-packages" | while read -r SITE_PACKAGES_DIR; do
chown -R "$PUID:$PGID" "$SITE_PACKAGES_DIR"
done
# Create a flag file to skip this step on subsequent runs
touch "$CERT_INIT_FLAG"
chown "$PUID:$PGID" "$CERT_INIT_FLAG"
fi

View File

@@ -8,7 +8,7 @@ BLUE='\E[1;34m'
GREEN='\E[1;32m' GREEN='\E[1;32m'
RESET='\E[0m' RESET='\E[0m'
S6_OVERLAY_VERSION=3.2.1.0 S6_OVERLAY_VERSION=3.1.5.0
TARGETPLATFORM=${1:-linux/amd64} TARGETPLATFORM=${1:-linux/amd64}
# Determine the correct binary file for the architecture given # Determine the correct binary file for the architecture given

View File

@@ -161,14 +161,6 @@ The easy fix is to add a Docker environment variable to the Nginx Proxy Manager
DISABLE_IPV6: 'true' DISABLE_IPV6: 'true'
``` ```
## Disabling IP Ranges Fetch
By default, NPM fetches IP ranges from CloudFront and Cloudflare during application startup. In environments with limited internet access or to speed up container startup, this fetch can be disabled:
```yml
environment:
IP_RANGES_FETCH_ENABLED: 'false'
```
## Custom Nginx Configurations ## Custom Nginx Configurations

View File

@@ -21,7 +21,7 @@ services:
# Add any other Stream port you want to expose # Add any other Stream port you want to expose
# - '21:21' # FTP # - '21:21' # FTP
#environment: environment:
# Uncomment this if you want to change the location of # Uncomment this if you want to change the location of
# the SQLite DB file within the container # the SQLite DB file within the container
# DB_SQLITE_FILE: "/data/database.sqlite" # DB_SQLITE_FILE: "/data/database.sqlite"

View File

@@ -1065,9 +1065,9 @@ vfile@^6.0.0:
vfile-message "^4.0.0" vfile-message "^4.0.0"
vite@^5.4.8: vite@^5.4.8:
version "5.4.19" version "5.4.8"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.19.tgz#20efd060410044b3ed555049418a5e7d1998f959" resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.8.tgz#af548ce1c211b2785478d3ba3e8da51e39a287e8"
integrity sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA== integrity sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==
dependencies: dependencies:
esbuild "^0.21.3" esbuild "^0.21.3"
postcss "^8.4.43" postcss "^8.4.43"

View File

@@ -4,438 +4,444 @@ const Tokens = require('./tokens');
module.exports = { module.exports = {
/** /**
* @param {String} route * @param {String} route
* @param {Object} [options] * @param {Object} [options]
* @returns {Boolean} * @returns {Boolean}
*/ */
navigate: function (route, options) { navigate: function (route, options) {
options = options || {}; options = options || {};
Backbone.history.navigate(route.toString(), options); Backbone.history.navigate(route.toString(), options);
return true; return true;
}, },
/** /**
* Login * Login
*/ */
showLogin: function () { showLogin: function () {
window.location = '/login'; window.location = '/login';
}, },
/** /**
* Users * Users
*/ */
showUsers: function () { showUsers: function () {
const controller = this; let controller = this;
if (Cache.User.isAdmin()) { if (Cache.User.isAdmin()) {
require(['./main', './users/main'], (App, View) => { require(['./main', './users/main'], (App, View) => {
controller.navigate('/users'); controller.navigate('/users');
App.UI.showAppContent(new View()); App.UI.showAppContent(new View());
}); });
} else { } else {
this.showDashboard(); this.showDashboard();
} }
}, },
/** /**
* User Form * User Form
* *
* @param [model] * @param [model]
*/ */
showUserForm: function (model) { showUserForm: function (model) {
if (Cache.User.isAdmin()) { if (Cache.User.isAdmin()) {
require(['./main', './user/form'], function (App, View) { require(['./main', './user/form'], function (App, View) {
App.UI.showModalDialog(new View({model: model})); App.UI.showModalDialog(new View({model: model}));
}); });
} }
}, },
/** /**
* User Permissions Form * User Permissions Form
* *
* @param model * @param model
*/ */
showUserPermissions: function (model) { showUserPermissions: function (model) {
if (Cache.User.isAdmin()) { if (Cache.User.isAdmin()) {
require(['./main', './user/permissions'], function (App, View) { require(['./main', './user/permissions'], function (App, View) {
App.UI.showModalDialog(new View({model: model})); App.UI.showModalDialog(new View({model: model}));
}); });
} }
}, },
/** /**
* User Password Form * User Password Form
* *
* @param model * @param model
*/ */
showUserPasswordForm: function (model) { showUserPasswordForm: function (model) {
if (Cache.User.isAdmin() || model.get('id') === Cache.User.get('id')) { if (Cache.User.isAdmin() || model.get('id') === Cache.User.get('id')) {
require(['./main', './user/password'], function (App, View) { require(['./main', './user/password'], function (App, View) {
App.UI.showModalDialog(new View({model: model})); App.UI.showModalDialog(new View({model: model}));
}); });
} }
}, },
/** /**
* User Delete Confirm * User Delete Confirm
* *
* @param model * @param model
*/ */
showUserDeleteConfirm: function (model) { showUserDeleteConfirm: function (model) {
if (Cache.User.isAdmin() && model.get('id') !== Cache.User.get('id')) { if (Cache.User.isAdmin() && model.get('id') !== Cache.User.get('id')) {
require(['./main', './user/delete'], function (App, View) { require(['./main', './user/delete'], function (App, View) {
App.UI.showModalDialog(new View({model: model})); App.UI.showModalDialog(new View({model: model}));
}); });
} }
}, },
/** /**
* Dashboard * Dashboard
*/ */
showDashboard: function () { showDashboard: function () {
const controller = this; let controller = this;
require(['./main', './dashboard/main'], (App, View) => {
controller.navigate('/');
App.UI.showAppContent(new View());
});
},
/** require(['./main', './dashboard/main'], (App, View) => {
* Nginx Proxy Hosts controller.navigate('/');
*/ App.UI.showAppContent(new View());
showNginxProxy: function () { });
if (Cache.User.isAdmin() || Cache.User.canView('proxy_hosts')) { },
const controller = this;
require(['./main', './nginx/proxy/main'], (App, View) => { /**
controller.navigate('/nginx/proxy'); * Nginx Proxy Hosts
App.UI.showAppContent(new View()); */
}); showNginxProxy: function () {
} if (Cache.User.isAdmin() || Cache.User.canView('proxy_hosts')) {
}, let controller = this;
/** require(['./main', './nginx/proxy/main'], (App, View) => {
* Nginx Proxy Host Form controller.navigate('/nginx/proxy');
* App.UI.showAppContent(new View());
* @param [model] });
*/ }
showNginxProxyForm: function (model) { },
if (Cache.User.isAdmin() || Cache.User.canManage('proxy_hosts')) {
require(['./main', './nginx/proxy/form'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
}
},
/** /**
* Proxy Host Delete Confirm * Nginx Proxy Host Form
* *
* @param model * @param [model]
*/ */
showNginxProxyDeleteConfirm: function (model) { showNginxProxyForm: function (model) {
if (Cache.User.isAdmin() || Cache.User.canManage('proxy_hosts')) { if (Cache.User.isAdmin() || Cache.User.canManage('proxy_hosts')) {
require(['./main', './nginx/proxy/delete'], function (App, View) { require(['./main', './nginx/proxy/form'], function (App, View) {
App.UI.showModalDialog(new View({model: model})); App.UI.showModalDialog(new View({model: model}));
}); });
} }
}, },
/** /**
* Nginx Redirection Hosts * Proxy Host Delete Confirm
*/ *
showNginxRedirection: function () { * @param model
if (Cache.User.isAdmin() || Cache.User.canView('redirection_hosts')) { */
const controller = this; showNginxProxyDeleteConfirm: function (model) {
require(['./main', './nginx/redirection/main'], (App, View) => { if (Cache.User.isAdmin() || Cache.User.canManage('proxy_hosts')) {
controller.navigate('/nginx/redirection'); require(['./main', './nginx/proxy/delete'], function (App, View) {
App.UI.showAppContent(new View()); App.UI.showModalDialog(new View({model: model}));
}); });
} }
}, },
/** /**
* Nginx Redirection Host Form * Nginx Redirection Hosts
* */
* @param [model] showNginxRedirection: function () {
*/ if (Cache.User.isAdmin() || Cache.User.canView('redirection_hosts')) {
showNginxRedirectionForm: function (model) { let controller = this;
if (Cache.User.isAdmin() || Cache.User.canManage('redirection_hosts')) {
require(['./main', './nginx/redirection/form'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
}
},
/** require(['./main', './nginx/redirection/main'], (App, View) => {
* Proxy Redirection Delete Confirm controller.navigate('/nginx/redirection');
* App.UI.showAppContent(new View());
* @param model });
*/ }
showNginxRedirectionDeleteConfirm: function (model) { },
if (Cache.User.isAdmin() || Cache.User.canManage('redirection_hosts')) {
require(['./main', './nginx/redirection/delete'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
}
},
/** /**
* Nginx Stream Hosts * Nginx Redirection Host Form
*/ *
showNginxStream: function () { * @param [model]
if (Cache.User.isAdmin() || Cache.User.canView('streams')) { */
const controller = this; showNginxRedirectionForm: function (model) {
require(['./main', './nginx/stream/main'], (App, View) => { if (Cache.User.isAdmin() || Cache.User.canManage('redirection_hosts')) {
controller.navigate('/nginx/stream'); require(['./main', './nginx/redirection/form'], function (App, View) {
App.UI.showAppContent(new View()); App.UI.showModalDialog(new View({model: model}));
}); });
} }
}, },
/** /**
* Stream Form * Proxy Redirection Delete Confirm
* *
* @param [model] * @param model
*/ */
showNginxStreamForm: function (model) { showNginxRedirectionDeleteConfirm: function (model) {
if (Cache.User.isAdmin() || Cache.User.canManage('streams')) { if (Cache.User.isAdmin() || Cache.User.canManage('redirection_hosts')) {
require(['./main', './nginx/stream/form'], function (App, View) { require(['./main', './nginx/redirection/delete'], function (App, View) {
App.UI.showModalDialog(new View({model: model})); App.UI.showModalDialog(new View({model: model}));
}); });
} }
}, },
/** /**
* Stream Delete Confirm * Nginx Stream Hosts
* */
* @param model showNginxStream: function () {
*/ if (Cache.User.isAdmin() || Cache.User.canView('streams')) {
showNginxStreamDeleteConfirm: function (model) { let controller = this;
if (Cache.User.isAdmin() || Cache.User.canManage('streams')) {
require(['./main', './nginx/stream/delete'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
}
},
/** require(['./main', './nginx/stream/main'], (App, View) => {
* Nginx Dead Hosts controller.navigate('/nginx/stream');
*/ App.UI.showAppContent(new View());
showNginxDead: function () { });
if (Cache.User.isAdmin() || Cache.User.canView('dead_hosts')) { }
const controller = this; },
require(['./main', './nginx/dead/main'], (App, View) => {
controller.navigate('/nginx/404');
App.UI.showAppContent(new View());
});
}
},
/** /**
* Dead Host Form * Stream Form
* *
* @param [model] * @param [model]
*/ */
showNginxDeadForm: function (model) { showNginxStreamForm: function (model) {
if (Cache.User.isAdmin() || Cache.User.canManage('dead_hosts')) { if (Cache.User.isAdmin() || Cache.User.canManage('streams')) {
require(['./main', './nginx/dead/form'], function (App, View) { require(['./main', './nginx/stream/form'], function (App, View) {
App.UI.showModalDialog(new View({model: model})); App.UI.showModalDialog(new View({model: model}));
}); });
} }
}, },
/** /**
* Dead Host Delete Confirm * Stream Delete Confirm
* *
* @param model * @param model
*/ */
showNginxDeadDeleteConfirm: function (model) { showNginxStreamDeleteConfirm: function (model) {
if (Cache.User.isAdmin() || Cache.User.canManage('dead_hosts')) { if (Cache.User.isAdmin() || Cache.User.canManage('streams')) {
require(['./main', './nginx/dead/delete'], function (App, View) { require(['./main', './nginx/stream/delete'], function (App, View) {
App.UI.showModalDialog(new View({model: model})); App.UI.showModalDialog(new View({model: model}));
}); });
} }
}, },
/** /**
* Help Dialog * Nginx Dead Hosts
* */
* @param {String} title showNginxDead: function () {
* @param {String} content if (Cache.User.isAdmin() || Cache.User.canView('dead_hosts')) {
*/ let controller = this;
showHelp: function (title, content) {
require(['./main', './help/main'], function (App, View) {
App.UI.showModalDialog(new View({title: title, content: content}));
});
},
/** require(['./main', './nginx/dead/main'], (App, View) => {
* Nginx Access controller.navigate('/nginx/404');
*/ App.UI.showAppContent(new View());
showNginxAccess: function () { });
if (Cache.User.isAdmin() || Cache.User.canView('access_lists')) { }
const controller = this; },
require(['./main', './nginx/access/main'], (App, View) => {
controller.navigate('/nginx/access');
App.UI.showAppContent(new View());
});
}
},
/** /**
* Nginx Access List Form * Dead Host Form
* *
* @param [model] * @param [model]
*/ */
showNginxAccessListForm: function (model) { showNginxDeadForm: function (model) {
if (Cache.User.isAdmin() || Cache.User.canManage('access_lists')) { if (Cache.User.isAdmin() || Cache.User.canManage('dead_hosts')) {
require(['./main', './nginx/access/form'], function (App, View) { require(['./main', './nginx/dead/form'], function (App, View) {
App.UI.showModalDialog(new View({model: model})); App.UI.showModalDialog(new View({model: model}));
}); });
} }
}, },
/** /**
* Access List Delete Confirm * Dead Host Delete Confirm
* *
* @param model * @param model
*/ */
showNginxAccessListDeleteConfirm: function (model) { showNginxDeadDeleteConfirm: function (model) {
if (Cache.User.isAdmin() || Cache.User.canManage('access_lists')) { if (Cache.User.isAdmin() || Cache.User.canManage('dead_hosts')) {
require(['./main', './nginx/access/delete'], function (App, View) { require(['./main', './nginx/dead/delete'], function (App, View) {
App.UI.showModalDialog(new View({model: model})); App.UI.showModalDialog(new View({model: model}));
}); });
} }
}, },
/** /**
* Nginx Certificates * Help Dialog
*/ *
showNginxCertificates: function () { * @param {String} title
if (Cache.User.isAdmin() || Cache.User.canView('certificates')) { * @param {String} content
const controller = this; */
require(['./main', './nginx/certificates/main'], (App, View) => { showHelp: function (title, content) {
controller.navigate('/nginx/certificates'); require(['./main', './help/main'], function (App, View) {
App.UI.showAppContent(new View()); App.UI.showModalDialog(new View({title: title, content: content}));
}); });
} },
},
/** /**
* Nginx Certificate Form * Nginx Access
* */
* @param [model] showNginxAccess: function () {
*/ if (Cache.User.isAdmin() || Cache.User.canView('access_lists')) {
showNginxCertificateForm: function (model) { let controller = this;
if (Cache.User.isAdmin() || Cache.User.canManage('certificates')) {
require(['./main', './nginx/certificates/form'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
}
},
/** require(['./main', './nginx/access/main'], (App, View) => {
* Certificate Renew controller.navigate('/nginx/access');
* App.UI.showAppContent(new View());
* @param model });
*/ }
showNginxCertificateRenew: function (model) { },
if (Cache.User.isAdmin() || Cache.User.canManage('certificates')) {
require(['./main', './nginx/certificates/renew'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
}
},
/** /**
* Certificate Delete Confirm * Nginx Access List Form
* *
* @param model * @param [model]
*/ */
showNginxCertificateDeleteConfirm: function (model) { showNginxAccessListForm: function (model) {
if (Cache.User.isAdmin() || Cache.User.canManage('certificates')) { if (Cache.User.isAdmin() || Cache.User.canManage('access_lists')) {
require(['./main', './nginx/certificates/delete'], function (App, View) { require(['./main', './nginx/access/form'], function (App, View) {
App.UI.showModalDialog(new View({model: model})); App.UI.showModalDialog(new View({model: model}));
}); });
} }
}, },
/** /**
* Certificate Test Reachability * Access List Delete Confirm
* *
* @param model * @param model
*/ */
showNginxCertificateTestReachability: function (model) { showNginxAccessListDeleteConfirm: function (model) {
if (Cache.User.isAdmin() || Cache.User.canManage('certificates')) { if (Cache.User.isAdmin() || Cache.User.canManage('access_lists')) {
require(['./main', './nginx/certificates/test'], function (App, View) { require(['./main', './nginx/access/delete'], function (App, View) {
App.UI.showModalDialog(new View({model: model})); App.UI.showModalDialog(new View({model: model}));
}); });
} }
}, },
/** /**
* Audit Log * Nginx Certificates
*/ */
showAuditLog: function () { showNginxCertificates: function () {
const controller = this; if (Cache.User.isAdmin() || Cache.User.canView('certificates')) {
if (Cache.User.isAdmin()) { let controller = this;
require(['./main', './audit-log/main'], (App, View) => {
controller.navigate('/audit-log');
App.UI.showAppContent(new View());
});
} else {
this.showDashboard();
}
},
/** require(['./main', './nginx/certificates/main'], (App, View) => {
* Audit Log Metadata controller.navigate('/nginx/certificates');
* App.UI.showAppContent(new View());
* @param model });
*/ }
showAuditMeta: function (model) { },
if (Cache.User.isAdmin()) {
require(['./main', './audit-log/meta'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
}
},
/** /**
* Settings * Nginx Certificate Form
*/ *
showSettings: function () { * @param [model]
const controller = this; */
if (Cache.User.isAdmin()) { showNginxCertificateForm: function (model) {
require(['./main', './settings/main'], (App, View) => { if (Cache.User.isAdmin() || Cache.User.canManage('certificates')) {
controller.navigate('/settings'); require(['./main', './nginx/certificates/form'], function (App, View) {
App.UI.showAppContent(new View()); App.UI.showModalDialog(new View({model: model}));
}); });
} else { }
this.showDashboard(); },
}
},
/** /**
* Settings Item Form * Certificate Renew
* *
* @param model * @param model
*/ */
showSettingForm: function (model) { showNginxCertificateRenew: function (model) {
if (Cache.User.isAdmin()) { if (Cache.User.isAdmin() || Cache.User.canManage('certificates')) {
if (model.get('id') === 'default-site') { require(['./main', './nginx/certificates/renew'], function (App, View) {
require(['./main', './settings/default-site/main'], function (App, View) { App.UI.showModalDialog(new View({model: model}));
App.UI.showModalDialog(new View({model: model})); });
}); }
} },
}
},
/** /**
* Logout * Certificate Delete Confirm
*/ *
logout: function () { * @param model
Tokens.dropTopToken(); */
this.showLogin(); showNginxCertificateDeleteConfirm: function (model) {
} if (Cache.User.isAdmin() || Cache.User.canManage('certificates')) {
require(['./main', './nginx/certificates/delete'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
}
},
/**
* Certificate Test Reachability
*
* @param model
*/
showNginxCertificateTestReachability: function (model) {
if (Cache.User.isAdmin() || Cache.User.canManage('certificates')) {
require(['./main', './nginx/certificates/test'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
}
},
/**
* Audit Log
*/
showAuditLog: function () {
let controller = this;
if (Cache.User.isAdmin()) {
require(['./main', './audit-log/main'], (App, View) => {
controller.navigate('/audit-log');
App.UI.showAppContent(new View());
});
} else {
this.showDashboard();
}
},
/**
* Audit Log Metadata
*
* @param model
*/
showAuditMeta: function (model) {
if (Cache.User.isAdmin()) {
require(['./main', './audit-log/meta'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
}
},
/**
* Settings
*/
showSettings: function () {
let controller = this;
if (Cache.User.isAdmin()) {
require(['./main', './settings/main'], (App, View) => {
controller.navigate('/settings');
App.UI.showAppContent(new View());
});
} else {
this.showDashboard();
}
},
/**
* Settings Item Form
*
* @param model
*/
showSettingForm: function (model) {
if (Cache.User.isAdmin()) {
if (model.get('id') === 'default-site') {
require(['./main', './settings/default-site/main'], function (App, View) {
App.UI.showModalDialog(new View({model: model}));
});
}
}
},
/**
* Logout
*/
logout: function () {
Tokens.dropTopToken();
this.showLogin();
}
}; };

View File

@@ -6,85 +6,87 @@ const Helpers = require('../../lib/helpers');
const template = require('./main.ejs'); const template = require('./main.ejs');
module.exports = Mn.View.extend({ module.exports = Mn.View.extend({
template: template, template: template,
id: 'dashboard', id: 'dashboard',
columns: 0, columns: 0,
stats: {}, stats: {},
ui: { ui: {
links: 'a' links: 'a'
}, },
events: { events: {
'click @ui.links': function (e) { 'click @ui.links': function (e) {
e.preventDefault(); e.preventDefault();
Controller.navigate($(e.currentTarget).attr('href'), true); Controller.navigate($(e.currentTarget).attr('href'), true);
} }
}, },
templateContext: function () { templateContext: function () {
const view = this; let view = this;
return { return {
getUserName: function () { getUserName: function () {
return Cache.User.get('nickname') || Cache.User.get('name'); return Cache.User.get('nickname') || Cache.User.get('name');
}, },
getHostStat: function (type) { getHostStat: function (type) {
if (view.stats && typeof view.stats.hosts !== 'undefined' && typeof view.stats.hosts[type] !== 'undefined') { if (view.stats && typeof view.stats.hosts !== 'undefined' && typeof view.stats.hosts[type] !== 'undefined') {
return Helpers.niceNumber(view.stats.hosts[type]); return Helpers.niceNumber(view.stats.hosts[type]);
} }
return '-'; return '-';
}, },
canShow: function (perm) { canShow: function (perm) {
return Cache.User.isAdmin() || Cache.User.canView(perm); return Cache.User.isAdmin() || Cache.User.canView(perm);
}, },
columns: view.columns columns: view.columns
}; };
}, },
onRender: function () { onRender: function () {
const view = this; let view = this;
if (typeof view.stats.hosts === 'undefined') {
Api.Reports.getHostStats()
.then(response => {
if (!view.isDestroyed()) {
view.stats.hosts = response;
view.render();
}
})
.catch(err => {
console.log(err);
});
}
},
/** if (typeof view.stats.hosts === 'undefined') {
* @param {Object} [model] Api.Reports.getHostStats()
*/ .then(response => {
preRender: function (model) { if (!view.isDestroyed()) {
this.columns = 0; view.stats.hosts = response;
view.render();
}
})
.catch(err => {
console.log(err);
});
}
},
// calculate the available columns based on permissions for the objects /**
// and store as a variable * @param {Object} [model]
const perms = ['proxy_hosts', 'redirection_hosts', 'streams', 'dead_hosts']; */
preRender: function (model) {
this.columns = 0;
perms.map(perm => { // calculate the available columns based on permissions for the objects
this.columns += Cache.User.isAdmin() || Cache.User.canView(perm) ? 1 : 0; // and store as a variable
}); //let view = this;
let perms = ['proxy_hosts', 'redirection_hosts', 'streams', 'dead_hosts'];
// Prevent double rendering on initial calls perms.map(perm => {
if (typeof model !== 'undefined') { this.columns += Cache.User.isAdmin() || Cache.User.canView(perm) ? 1 : 0;
this.render(); });
}
},
initialize: function () { // Prevent double rendering on initial calls
this.preRender(); if (typeof model !== 'undefined') {
this.listenTo(Cache.User, 'change', this.preRender); this.render();
} }
},
initialize: function () {
this.preRender();
this.listenTo(Cache.User, 'change', this.preRender);
}
}); });

View File

@@ -33,13 +33,6 @@
<td class="<%- isExpired() ? 'text-danger' : '' %>"> <td class="<%- isExpired() ? 'text-danger' : '' %>">
<%- formatDbDate(expires_on, 'Do MMMM YYYY, h:mm a') %> <%- formatDbDate(expires_on, 'Do MMMM YYYY, h:mm a') %>
</td> </td>
<td>
<% if (active_domain_names().length > 0) { %>
<span class="status-icon bg-success"></span> <%- i18n('certificates', 'in-use') %>
<% } else { %>
<span class="status-icon bg-danger"></span> <%- i18n('certificates', 'inactive') %>
<% } %>
</td>
<% if (canManage) { %> <% if (canManage) { %>
<td class="text-right"> <td class="text-right">
<div class="item-action dropdown"> <div class="item-action dropdown">
@@ -55,14 +48,7 @@
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<% } %> <% } %>
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a> <a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
<% if (active_domain_names().length > 0) { %>
<div class="dropdown-divider"></div>
<span class="dropdown-header"><%- i18n('certificates', 'active-domain_names') %></span>
<% active_domain_names().forEach(function(host) { %>
<a href="https://<%- host %>" class="dropdown-item" target="_blank"><%- host %></a>
<% }); %>
<% } %>
</div> </div>
</div> </div>
</td> </td>
<% } %> <% } %>

View File

@@ -44,24 +44,14 @@ module.exports = Mn.View.extend({
}, },
}, },
templateContext: function () { templateContext: {
return { canManage: App.Cache.User.canManage('certificates'),
canManage: App.Cache.User.canManage('certificates'), isExpired: function () {
isExpired: function () { return moment(this.expires_on).isBefore(moment());
return moment(this.expires_on).isBefore(moment()); },
}, dns_providers: dns_providers
dns_providers: dns_providers,
active_domain_names: function () {
const { proxy_hosts = [], redirect_hosts = [], dead_hosts = [] } = this;
return [...proxy_hosts, ...redirect_hosts, ...dead_hosts].reduce((acc, host) => {
acc.push(...(host.domain_names || []));
return acc;
}, []);
}
};
}, },
initialize: function () { initialize: function () {
this.listenTo(this.model, 'change', this.render); this.listenTo(this.model, 'change', this.render);
} }

View File

@@ -3,7 +3,6 @@
<th><%- i18n('str', 'name') %></th> <th><%- i18n('str', 'name') %></th>
<th><%- i18n('all-hosts', 'cert-provider') %></th> <th><%- i18n('all-hosts', 'cert-provider') %></th>
<th><%- i18n('str', 'expires') %></th> <th><%- i18n('str', 'expires') %></th>
<th><%- i18n('str', 'status') %></th>
<% if (canManage) { %> <% if (canManage) { %>
<th>&nbsp;</th> <th>&nbsp;</th>
<% } %> <% } %>

View File

@@ -74,7 +74,7 @@ module.exports = Mn.View.extend({
e.preventDefault(); e.preventDefault();
let query = this.ui.query.val(); let query = this.ui.query.val();
this.fetch(['owner','proxy_hosts', 'dead_hosts', 'redirection_hosts'], query) this.fetch(['owner'], query)
.then(response => this.showData(response)) .then(response => this.showData(response))
.catch(err => { .catch(err => {
this.showError(err); this.showError(err);
@@ -89,7 +89,7 @@ module.exports = Mn.View.extend({
onRender: function () { onRender: function () {
let view = this; let view = this;
view.fetch(['owner','proxy_hosts', 'dead_hosts', 'redirection_hosts']) view.fetch(['owner'])
.then(response => { .then(response => {
if (!view.isDestroyed()) { if (!view.isDestroyed()) {
if (response && response.length) { if (response && response.length) {

View File

@@ -60,7 +60,7 @@
}, },
"footer": { "footer": {
"fork-me": "Fork me on Github", "fork-me": "Fork me on Github",
"copy": "&copy; 2025 <a href=\"{url}\" target=\"_blank\">jc21.com</a>.", "copy": "&copy; 2024 <a href=\"{url}\" target=\"_blank\">jc21.com</a>.",
"theme": "Theme by <a href=\"{url}\" target=\"_blank\">Tabler</a>" "theme": "Theme by <a href=\"{url}\" target=\"_blank\">Tabler</a>"
}, },
"dashboard": { "dashboard": {
@@ -208,10 +208,7 @@
"reachability-other": "There is a server found at this domain but it returned an unexpected status code {code}. Is it the NPM server? Please make sure your domain points to the IP where your NPM instance is running.", "reachability-other": "There is a server found at this domain but it returned an unexpected status code {code}. Is it the NPM server? Please make sure your domain points to the IP where your NPM instance is running.",
"download": "Download", "download": "Download",
"renew-title": "Renew Let's Encrypt Certificate", "renew-title": "Renew Let's Encrypt Certificate",
"search": "Search Certificate…", "search": "Search Certificate…"
"in-use" : "In use",
"inactive": "Inactive",
"active-domain_names": "Active domain names"
}, },
"access-lists": { "access-lists": {
"title": "Access Lists", "title": "Access Lists",

View File

@@ -167,5 +167,4 @@ $pink: #f66d9b;
textarea.form-control.text-monospace { textarea.form-control.text-monospace {
font-size: 12px; font-size: 12px;
font-family: monospace;
} }

View File

@@ -907,13 +907,6 @@ atob@^2.1.2:
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
available-typed-arrays@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846"
integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==
dependencies:
possible-typed-array-names "^1.0.0"
babel-code-frame@^6.26.0: babel-code-frame@^6.26.0:
version "6.26.0" version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
@@ -1797,32 +1790,6 @@ cacheable-request@^6.0.0:
normalize-url "^4.1.0" normalize-url "^4.1.0"
responselike "^1.0.2" responselike "^1.0.2"
call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6"
integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==
dependencies:
es-errors "^1.3.0"
function-bind "^1.1.2"
call-bind@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c"
integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==
dependencies:
call-bind-apply-helpers "^1.0.0"
es-define-property "^1.0.0"
get-intrinsic "^1.2.4"
set-function-length "^1.2.2"
call-bound@^1.0.3, call-bound@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a"
integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==
dependencies:
call-bind-apply-helpers "^1.0.2"
get-intrinsic "^1.3.0"
callsites@^3.0.0: callsites@^3.0.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
@@ -2265,7 +2232,7 @@ create-ecdh@^4.0.0:
bn.js "^4.1.0" bn.js "^4.1.0"
elliptic "^6.5.3" elliptic "^6.5.3"
create-hash@^1.1.0, create-hash@^1.2.0: create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
@@ -2276,17 +2243,7 @@ create-hash@^1.1.0, create-hash@^1.2.0:
ripemd160 "^2.0.1" ripemd160 "^2.0.1"
sha.js "^2.4.0" sha.js "^2.4.0"
create-hash@~1.1.3: create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
version "1.1.3"
resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd"
integrity sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==
dependencies:
cipher-base "^1.0.1"
inherits "^2.0.1"
ripemd160 "^2.0.0"
sha.js "^2.4.0"
create-hmac@^1.1.0, create-hmac@^1.1.7:
version "1.1.7" version "1.1.7"
resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==
@@ -2457,15 +2414,6 @@ defer-to-connect@^1.0.1:
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
define-data-property@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
dependencies:
es-define-property "^1.0.0"
es-errors "^1.3.0"
gopd "^1.0.1"
define-properties@^1.1.2, define-properties@^1.1.3: define-properties@^1.1.2, define-properties@^1.1.3:
version "1.1.3" version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
@@ -2631,15 +2579,6 @@ dot-prop@^5.2.0:
dependencies: dependencies:
is-obj "^2.0.0" is-obj "^2.0.0"
dunder-proto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"
integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==
dependencies:
call-bind-apply-helpers "^1.0.1"
es-errors "^1.3.0"
gopd "^1.2.0"
duplexer3@^0.1.4: duplexer3@^0.1.4:
version "0.1.4" version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
@@ -2709,9 +2648,9 @@ electron-to-chromium@^1.3.47:
integrity sha512-67V62Z4CFOiAtox+o+tosGfVk0QX4DJgH609tjT8QymbJZVAI/jWnAthnr8c5hnRNziIRwkc9EMQYejiVz3/9Q== integrity sha512-67V62Z4CFOiAtox+o+tosGfVk0QX4DJgH609tjT8QymbJZVAI/jWnAthnr8c5hnRNziIRwkc9EMQYejiVz3/9Q==
elliptic@^6.5.3, elliptic@^6.5.4: elliptic@^6.5.3, elliptic@^6.5.4:
version "6.6.1" version "6.6.0"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.0.tgz#5919ec723286c1edf28685aa89261d4761afa210"
integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== integrity sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==
dependencies: dependencies:
bn.js "^4.11.9" bn.js "^4.11.9"
brorand "^1.1.0" brorand "^1.1.0"
@@ -2823,23 +2762,6 @@ es-abstract@^1.17.0-next.1, es-abstract@^1.17.5:
string.prototype.trimend "^1.0.1" string.prototype.trimend "^1.0.1"
string.prototype.trimstart "^1.0.1" string.prototype.trimstart "^1.0.1"
es-define-property@^1.0.0, es-define-property@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa"
integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==
es-errors@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
es-object-atoms@^1.0.0, es-object-atoms@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1"
integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==
dependencies:
es-errors "^1.3.0"
es-to-primitive@^1.2.1: es-to-primitive@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
@@ -3209,13 +3131,6 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3" inherits "^2.0.3"
readable-stream "^2.3.6" readable-stream "^2.3.6"
for-each@^0.3.5:
version "0.3.5"
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47"
integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==
dependencies:
is-callable "^1.2.7"
for-in@^1.0.2: for-in@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@@ -3276,11 +3191,6 @@ function-bind@^1.1.1:
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
function-bind@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
functional-red-black-tree@^1.0.1: functional-red-black-tree@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
@@ -3317,30 +3227,6 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
get-intrinsic@^1.2.4, get-intrinsic@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01"
integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==
dependencies:
call-bind-apply-helpers "^1.0.2"
es-define-property "^1.0.1"
es-errors "^1.3.0"
es-object-atoms "^1.1.1"
function-bind "^1.1.2"
get-proto "^1.0.1"
gopd "^1.2.0"
has-symbols "^1.1.0"
hasown "^2.0.2"
math-intrinsics "^1.1.0"
get-proto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1"
integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==
dependencies:
dunder-proto "^1.0.1"
es-object-atoms "^1.0.0"
get-stdin@^4.0.1: get-stdin@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
@@ -3507,11 +3393,6 @@ globule@^1.0.0:
lodash "~4.17.10" lodash "~4.17.10"
minimatch "~3.0.2" minimatch "~3.0.2"
gopd@^1.0.1, gopd@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1"
integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
got@^9.6.0: got@^9.6.0:
version "9.6.0" version "9.6.0"
resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85"
@@ -3561,30 +3442,11 @@ has-flag@^4.0.0:
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
has-property-descriptors@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==
dependencies:
es-define-property "^1.0.0"
has-symbols@^1.0.0, has-symbols@^1.0.1: has-symbols@^1.0.0, has-symbols@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
has-symbols@^1.0.3, has-symbols@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338"
integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==
has-tostringtag@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc"
integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==
dependencies:
has-symbols "^1.0.3"
has-unicode@^2.0.1: has-unicode@^2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
@@ -3633,13 +3495,6 @@ has@^1.0.3:
dependencies: dependencies:
function-bind "^1.1.1" function-bind "^1.1.1"
hash-base@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1"
integrity sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==
dependencies:
inherits "^2.0.1"
hash-base@^3.0.0: hash-base@^3.0.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33"
@@ -3657,13 +3512,6 @@ hash.js@^1.0.0, hash.js@^1.0.3:
inherits "^2.0.3" inherits "^2.0.3"
minimalistic-assert "^1.0.1" minimalistic-assert "^1.0.1"
hasown@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
dependencies:
function-bind "^1.1.2"
he@1.2.x, he@^1.2.0: he@1.2.x, he@^1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
@@ -4008,11 +3856,6 @@ is-callable@^1.1.4, is-callable@^1.2.0:
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb"
integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==
is-callable@^1.2.7:
version "1.2.7"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
is-ci@^2.0.0: is-ci@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
@@ -4176,13 +4019,6 @@ is-symbol@^1.0.2:
dependencies: dependencies:
has-symbols "^1.0.1" has-symbols "^1.0.1"
is-typed-array@^1.1.14:
version "1.1.15"
resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b"
integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==
dependencies:
which-typed-array "^1.1.16"
is-typedarray@^1.0.0: is-typedarray@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
@@ -4208,11 +4044,6 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
isarray@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
isexe@^2.0.0: isexe@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@@ -4605,11 +4436,6 @@ marionette.templatecache@^1.0.0:
dependencies: dependencies:
backbone.marionette "^4.0.0, 4.0.0-beta.1" backbone.marionette "^4.0.0, 4.0.0-beta.1"
math-intrinsics@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
md5.js@^1.3.4: md5.js@^1.3.4:
version "1.3.5" version "1.3.5"
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
@@ -5463,16 +5289,15 @@ path-type@^4.0.0:
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
pbkdf2@^3.0.3: pbkdf2@^3.0.3:
version "3.1.3" version "3.1.1"
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.3.tgz#8be674d591d65658113424592a95d1517318dd4b" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94"
integrity sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA== integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==
dependencies: dependencies:
create-hash "~1.1.3" create-hash "^1.1.2"
create-hmac "^1.1.7" create-hmac "^1.1.4"
ripemd160 "=2.0.1" ripemd160 "^2.0.1"
safe-buffer "^5.2.1" safe-buffer "^5.0.1"
sha.js "^2.4.11" sha.js "^2.4.8"
to-buffer "^1.2.0"
picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1:
version "2.2.2" version "2.2.2"
@@ -5501,11 +5326,6 @@ posix-character-classes@^0.1.0:
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
possible-typed-array-names@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae"
integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==
postcss-modules-extract-imports@^2.0.0: postcss-modules-extract-imports@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e"
@@ -6066,14 +5886,6 @@ rimraf@^3.0.2:
dependencies: dependencies:
glob "^7.1.3" glob "^7.1.3"
ripemd160@=2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7"
integrity sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==
dependencies:
hash-base "^2.0.0"
inherits "^2.0.1"
ripemd160@^2.0.0, ripemd160@^2.0.1: ripemd160@^2.0.0, ripemd160@^2.0.1:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
@@ -6225,18 +6037,6 @@ set-blocking@^2.0.0:
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
set-function-length@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==
dependencies:
define-data-property "^1.1.4"
es-errors "^1.3.0"
function-bind "^1.1.2"
get-intrinsic "^1.2.4"
gopd "^1.0.1"
has-property-descriptors "^1.0.2"
set-value@^2.0.0, set-value@^2.0.1: set-value@^2.0.0, set-value@^2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
@@ -6252,7 +6052,7 @@ setimmediate@^1.0.4:
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8: sha.js@^2.4.0, sha.js@^2.4.8:
version "2.4.11" version "2.4.11"
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==
@@ -6792,15 +6592,6 @@ to-arraybuffer@^1.0.0:
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=
to-buffer@^1.2.0:
version "1.2.1"
resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.2.1.tgz#2ce650cdb262e9112a18e65dc29dcb513c8155e0"
integrity sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==
dependencies:
isarray "^2.0.5"
safe-buffer "^5.2.1"
typed-array-buffer "^1.0.3"
to-fast-properties@^1.0.3: to-fast-properties@^1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
@@ -6907,15 +6698,6 @@ type-fest@^0.8.1:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
typed-array-buffer@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536"
integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==
dependencies:
call-bound "^1.0.3"
es-errors "^1.3.0"
is-typed-array "^1.1.14"
typedarray-to-buffer@^3.1.5: typedarray-to-buffer@^3.1.5:
version "3.1.5" version "3.1.5"
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
@@ -7242,19 +7024,6 @@ which-module@^2.0.0:
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
which-typed-array@^1.1.16:
version "1.1.19"
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.19.tgz#df03842e870b6b88e117524a4b364b6fc689f956"
integrity sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==
dependencies:
available-typed-arrays "^1.0.7"
call-bind "^1.0.8"
call-bound "^1.0.4"
for-each "^0.3.5"
get-proto "^1.0.1"
gopd "^1.2.0"
has-tostringtag "^1.0.2"
which@^1.2.14, which@^1.2.9, which@^1.3.1: which@^1.2.14, which@^1.2.9, which@^1.3.1:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"

View File

@@ -10,9 +10,9 @@
"active24": { "active24": {
"name": "Active24", "name": "Active24",
"package_name": "certbot-dns-active24", "package_name": "certbot-dns-active24",
"version": "~=2.0.0", "version": "~=1.5.1",
"dependencies": "", "dependencies": "",
"credentials": "dns_active24_api_key = <identifier>\ndns_active24_secret = <secret>", "credentials": "dns_active24_token=\"TOKEN\"",
"full_plugin_name": "dns-active24" "full_plugin_name": "dns-active24"
}, },
"aliyun": { "aliyun": {
@@ -31,14 +31,6 @@
"credentials": "# This plugin supported API authentication using either Service Principals or utilizing a Managed Identity assigned to the virtual machine.\n# Regardless which authentication method used, the identity will need the “DNS Zone Contributor” role assigned to it.\n# As multiple Azure DNS Zones in multiple resource groups can exist, the config file needs a mapping of zone to resource group ID. Multiple zones -> ID mappings can be listed by using the key dns_azure_zoneX where X is a unique number. At least 1 zone mapping is required.\n\n# Using a service principal (option 1)\ndns_azure_sp_client_id = 912ce44a-0156-4669-ae22-c16a17d34ca5\ndns_azure_sp_client_secret = E-xqXU83Y-jzTI6xe9fs2YC~mck3ZzUih9\ndns_azure_tenant_id = ed1090f3-ab18-4b12-816c-599af8a88cf7\n\n# Using used assigned MSI (option 2)\n# dns_azure_msi_client_id = 912ce44a-0156-4669-ae22-c16a17d34ca5\n\n# Using system assigned MSI (option 3)\n# dns_azure_msi_system_assigned = true\n\n# Zones (at least one always required)\ndns_azure_zone1 = example.com:/subscriptions/c135abce-d87d-48df-936c-15596c6968a5/resourceGroups/dns1\ndns_azure_zone2 = example.org:/subscriptions/99800903-fb14-4992-9aff-12eaf2744622/resourceGroups/dns2", "credentials": "# This plugin supported API authentication using either Service Principals or utilizing a Managed Identity assigned to the virtual machine.\n# Regardless which authentication method used, the identity will need the “DNS Zone Contributor” role assigned to it.\n# As multiple Azure DNS Zones in multiple resource groups can exist, the config file needs a mapping of zone to resource group ID. Multiple zones -> ID mappings can be listed by using the key dns_azure_zoneX where X is a unique number. At least 1 zone mapping is required.\n\n# Using a service principal (option 1)\ndns_azure_sp_client_id = 912ce44a-0156-4669-ae22-c16a17d34ca5\ndns_azure_sp_client_secret = E-xqXU83Y-jzTI6xe9fs2YC~mck3ZzUih9\ndns_azure_tenant_id = ed1090f3-ab18-4b12-816c-599af8a88cf7\n\n# Using used assigned MSI (option 2)\n# dns_azure_msi_client_id = 912ce44a-0156-4669-ae22-c16a17d34ca5\n\n# Using system assigned MSI (option 3)\n# dns_azure_msi_system_assigned = true\n\n# Zones (at least one always required)\ndns_azure_zone1 = example.com:/subscriptions/c135abce-d87d-48df-936c-15596c6968a5/resourceGroups/dns1\ndns_azure_zone2 = example.org:/subscriptions/99800903-fb14-4992-9aff-12eaf2744622/resourceGroups/dns2",
"full_plugin_name": "dns-azure" "full_plugin_name": "dns-azure"
}, },
"baidu": {
"name": "baidu",
"package_name": "certbot-dns-baidu",
"version": "~=0.1.1",
"dependencies": "",
"credentials": "dns_baidu_access_key = 12345678\ndns_baidu_secret_key = 1234567890abcdef1234567890abcdef",
"full_plugin_name": "dns-baidu"
},
"beget": { "beget": {
"name":"Beget", "name":"Beget",
"package_name": "certbot-beget-plugin", "package_name": "certbot-beget-plugin",
@@ -55,19 +47,11 @@
"credentials": "# Bunny API token used by Certbot (see https://dash.bunny.net/account/settings)\ndns_bunny_api_key = xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", "credentials": "# Bunny API token used by Certbot (see https://dash.bunny.net/account/settings)\ndns_bunny_api_key = xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
"full_plugin_name": "dns-bunny" "full_plugin_name": "dns-bunny"
}, },
"cdmon": {
"name": "cdmon",
"package_name": "certbot-dns-cdmon",
"version": "~=0.4.1",
"dependencies": "",
"credentials": "dns_cdmon_api_key=your-cdmon-api-token\ndns_cdmon_domain=your_domain_is_optional",
"full_plugin_name": "dns-cdmon"
},
"cloudflare": { "cloudflare": {
"name": "Cloudflare", "name": "Cloudflare",
"package_name": "certbot-dns-cloudflare", "package_name": "certbot-dns-cloudflare",
"version": "=={{certbot-version}}", "version": "=={{certbot-version}}",
"dependencies": "acme=={{certbot-version}}", "dependencies": "cloudflare==2.19.* acme=={{certbot-version}}",
"credentials": "# Cloudflare API token\ndns_cloudflare_api_token=0123456789abcdef0123456789abcdef01234567", "credentials": "# Cloudflare API token\ndns_cloudflare_api_token=0123456789abcdef0123456789abcdef01234567",
"full_plugin_name": "dns-cloudflare" "full_plugin_name": "dns-cloudflare"
}, },
@@ -106,19 +90,11 @@
"cpanel": { "cpanel": {
"name": "cPanel", "name": "cPanel",
"package_name": "certbot-dns-cpanel", "package_name": "certbot-dns-cpanel",
"version": "~=0.4.0", "version": "~=0.2.2",
"dependencies": "", "dependencies": "",
"credentials": "cpanel_url = https://cpanel.example.com:2083\ncpanel_username = your_username\ncpanel_password = your_password\ncpanel_token = your_api_token", "credentials": "cpanel_url = https://cpanel.example.com:2083\ncpanel_username = user\ncpanel_password = hunter2",
"full_plugin_name": "cpanel" "full_plugin_name": "cpanel"
}, },
"ddnss": {
"name": "DDNSS",
"package_name": "certbot-dns-ddnss",
"version": "~=1.1.0",
"dependencies": "",
"credentials": "dns_ddnss_token = YOUR_DDNSS_API_TOKEN",
"full_plugin_name": "dns-ddnss"
},
"desec": { "desec": {
"name": "deSEC", "name": "deSEC",
"package_name": "certbot-dns-desec", "package_name": "certbot-dns-desec",
@@ -185,11 +161,11 @@
}, },
"domainoffensive": { "domainoffensive": {
"name": "DomainOffensive (do.de)", "name": "DomainOffensive (do.de)",
"package_name": "certbot-dns-domainoffensive", "package_name": "certbot-dns-do",
"version": "~=2.0.0", "version": "~=0.31.0",
"dependencies": "", "dependencies": "",
"credentials": "dns_domainoffensive_api_token = YOUR_DO_DE_AUTH_TOKEN", "credentials": "dns_do_api_token = YOUR_DO_DE_AUTH_TOKEN",
"full_plugin_name": "dns-domainoffensive" "full_plugin_name": "dns-do"
}, },
"domeneshop": { "domeneshop": {
"name": "Domeneshop", "name": "Domeneshop",
@@ -223,14 +199,6 @@
"credentials": "dns_eurodns_applicationId = myuser\ndns_eurodns_apiKey = mysecretpassword\ndns_eurodns_endpoint = https://rest-api.eurodns.com/user-api-gateway/proxy", "credentials": "dns_eurodns_applicationId = myuser\ndns_eurodns_apiKey = mysecretpassword\ndns_eurodns_endpoint = https://rest-api.eurodns.com/user-api-gateway/proxy",
"full_plugin_name": "dns-eurodns" "full_plugin_name": "dns-eurodns"
}, },
"firstdomains": {
"name": "First Domains",
"package_name": "certbot-dns-firstdomains",
"version": ">=1.0",
"dependencies": "",
"credentials": "dns_firstdomains_username = myremoteuser\ndns_firstdomains_password = verysecureremoteuserpassword",
"full_plugin_name": "dns-firstdomains"
},
"freedns": { "freedns": {
"name": "FreeDNS", "name": "FreeDNS",
"package_name": "certbot-dns-freedns", "package_name": "certbot-dns-freedns",
@@ -241,8 +209,8 @@
}, },
"gandi": { "gandi": {
"name": "Gandi Live DNS", "name": "Gandi Live DNS",
"package_name": "certbot-dns-gandi", "package_name": "certbot_plugin_gandi",
"version": "~=1.6.1", "version": "~=1.5.0",
"dependencies": "", "dependencies": "",
"credentials": "# Gandi personal access token\ndns_gandi_token=PERSONAL_ACCESS_TOKEN", "credentials": "# Gandi personal access token\ndns_gandi_token=PERSONAL_ACCESS_TOKEN",
"full_plugin_name": "dns-gandi" "full_plugin_name": "dns-gandi"
@@ -396,7 +364,7 @@
"package_name": "certbot-dns-mijn-host", "package_name": "certbot-dns-mijn-host",
"version": "~=0.0.4", "version": "~=0.0.4",
"dependencies": "", "dependencies": "",
"credentials": "dns_mijn_host_api_key=0123456789abcdef0123456789abcdef", "credentials": "dns-mijn-host-credentials = /etc/letsencrypt/mijnhost-credentials.ini",
"full_plugin_name": "dns-mijn-host" "full_plugin_name": "dns-mijn-host"
}, },
"namecheap": { "namecheap": {
@@ -415,14 +383,6 @@
"credentials": "dns_netcup_customer_id = 123456\ndns_netcup_api_key = 0123456789abcdef0123456789abcdef01234567\ndns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123", "credentials": "dns_netcup_customer_id = 123456\ndns_netcup_api_key = 0123456789abcdef0123456789abcdef01234567\ndns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123",
"full_plugin_name": "dns-netcup" "full_plugin_name": "dns-netcup"
}, },
"nicru": {
"name": "nic.ru",
"package_name": "certbot-dns-nicru",
"version": "~=1.0.3",
"dependencies": "",
"credentials": "dns_nicru_client_id = application-id\ndns_nicru_client_secret = application-token\ndns_nicru_username = 0001110/NIC-D\ndns_nicru_password = password\ndns_nicru_scope = .+:.+/zones/example.com(/.+)?\ndns_nicru_service = DNS_SERVICE_NAME\ndns_nicru_zone = example.com",
"full_plugin_name": "dns-nicru"
},
"njalla": { "njalla": {
"name": "Njalla", "name": "Njalla",
"package_name": "certbot-dns-njalla", "package_name": "certbot-dns-njalla",
@@ -511,30 +471,14 @@
"credentials": "[default]\naws_access_key_id=AKIAIOSFODNN7EXAMPLE\naws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", "credentials": "[default]\naws_access_key_id=AKIAIOSFODNN7EXAMPLE\naws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"full_plugin_name": "dns-route53" "full_plugin_name": "dns-route53"
}, },
"spaceship": {
"name": "Spaceship",
"package_name": "certbot-dns-spaceship",
"version": "~=1.0.4",
"dependencies": "",
"credentials": "[spaceship]\napi_key=your_api_key\napi_secret=your_api_secret",
"full_plugin_name": "dns-spaceship"
},
"strato": { "strato": {
"name": "Strato", "name": "Strato",
"package_name": "certbot-dns-strato", "package_name": "certbot-dns-strato",
"version": "~=0.2.2", "version": "~=0.2.1",
"dependencies": "", "dependencies": "",
"credentials": "dns_strato_username = user\ndns_strato_password = pass\n# uncomment if youre using two factor authentication:\n# dns_strato_totp_devicename = 2fa_device\n# dns_strato_totp_secret = 2fa_secret\n#\n# uncomment if domain name contains special characters\n# insert domain display name as seen on your account page here\n# dns_strato_domain_display_name = my-punicode-url.de\n#\n# if youre not using strato.de or another special endpoint you can customise it below\n# you will probably only need to adjust the host, but you can also change the complete endpoint url\n# dns_strato_custom_api_scheme = https\n# dns_strato_custom_api_host = www.strato.de\n# dns_strato_custom_api_port = 443\n# dns_strato_custom_api_path = \"/apps/CustomerService\"", "credentials": "dns_strato_username = user\ndns_strato_password = pass\n# uncomment if youre using two factor authentication:\n# dns_strato_totp_devicename = 2fa_device\n# dns_strato_totp_secret = 2fa_secret\n#\n# uncomment if domain name contains special characters\n# insert domain display name as seen on your account page here\n# dns_strato_domain_display_name = my-punicode-url.de\n#\n# if youre not using strato.de or another special endpoint you can customise it below\n# you will probably only need to adjust the host, but you can also change the complete endpoint url\n# dns_strato_custom_api_scheme = https\n# dns_strato_custom_api_host = www.strato.de\n# dns_strato_custom_api_port = 443\n# dns_strato_custom_api_path = \"/apps/CustomerService\"",
"full_plugin_name": "dns-strato" "full_plugin_name": "dns-strato"
}, },
"selectelv2": {
"name": "Selectel api v2",
"package_name": "certbot-dns-selectel-api-v2",
"version": "~=0.3.0",
"dependencies": "",
"credentials": "dns_selectel_api_v2_account_id = your_account_id\ndns_selectel_api_v2_project_name = your_project\ndns_selectel_api_v2_username = your_username\ndns_selectel_api_v2_password = your_password",
"full_plugin_name": "dns-selectel-api-v2"
},
"timeweb": { "timeweb": {
"name": "Timeweb Cloud", "name": "Timeweb Cloud",
"package_name": "certbot-dns-timeweb", "package_name": "certbot-dns-timeweb",
@@ -590,13 +534,5 @@
"dependencies": "", "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", "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" "full_plugin_name": "edgedns"
}, }
"zoneedit": { }
"name": "ZoneEdit",
"package_name": "certbot-dns-zoneedit",
"version": "~=0.3.2",
"dependencies": "--no-deps dnspython",
"credentials": "dns_zoneedit_user = <login-user-id>\ndns_zoneedit_token = <dyn-authentication-token>",
"full_plugin_name": "dns-zoneedit"
}
}

View File

@@ -1,22 +1,11 @@
FROM cypress/included:14.0.1 FROM cypress/included:13.9.0
COPY --chown=1000 ./test /test
# Disable Cypress CLI colors # Disable Cypress CLI colors
ENV FORCE_COLOR=0 ENV FORCE_COLOR=0
ENV NO_COLOR=1 ENV NO_COLOR=1
# testssl.sh and mkcert
RUN wget "https://github.com/testssl/testssl.sh/archive/refs/tags/v3.2rc4.tar.gz" -O /tmp/testssl.tgz -q \
&& tar -xzf /tmp/testssl.tgz -C /tmp \
&& mv /tmp/testssl.sh-3.2rc4 /testssl \
&& rm /tmp/testssl.tgz \
&& apt-get update \
&& apt-get install -y bsdmainutils curl dnsutils \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& wget "https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-amd64" -O /bin/mkcert \
&& chmod +x /bin/mkcert
COPY --chown=1000 ./test /test
WORKDIR /test WORKDIR /test
RUN yarn install && yarn cache clean RUN yarn install && yarn cache clean
ENTRYPOINT [] ENTRYPOINT []

View File

@@ -10,7 +10,7 @@ describe('Certificates endpoints', () => {
}); });
}); });
it('Validate custom certificate', () => { it('Validate custom certificate', function() {
cy.task('backendApiPostFiles', { cy.task('backendApiPostFiles', {
token: token, token: token,
path: '/api/nginx/certificates/validate', path: '/api/nginx/certificates/validate',
@@ -25,7 +25,7 @@ describe('Certificates endpoints', () => {
}); });
}); });
it('Custom certificate lifecycle', () => { it('Custom certificate lifecycle', function() {
// Create custom cert // Create custom cert
cy.task('backendApiPost', { cy.task('backendApiPost', {
token: token, token: token,
@@ -73,7 +73,7 @@ describe('Certificates endpoints', () => {
}); });
}); });
it('Request Certificate - CVE-2024-46256/CVE-2024-46257', () => { it('Request Certificate - CVE-2024-46256/CVE-2024-46257', function() {
cy.task('backendApiPost', { cy.task('backendApiPost', {
token: token, token: token,
path: '/api/nginx/certificates', path: '/api/nginx/certificates',

View File

@@ -1,25 +0,0 @@
/// <reference types="cypress" />
describe('Dashboard endpoints', () => {
let token;
before(() => {
cy.getToken().then((tok) => {
token = tok;
});
});
it('Should be able to get host counts', () => {
cy.task('backendApiGet', {
token: token,
path: '/api/reports/hosts'
}).then((data) => {
cy.validateSwaggerSchema('get', 200, '/reports/hosts', data);
expect(data).to.have.property('dead');
expect(data).to.have.property('proxy');
expect(data).to.have.property('redirection');
expect(data).to.have.property('stream');
});
});
});

View File

@@ -9,7 +9,7 @@ describe('Full Certificate Provisions', () => {
}); });
}); });
it('Should be able to create new http certificate', () => { it('Should be able to create new http certificate', function() {
cy.task('backendApiPost', { cy.task('backendApiPost', {
token: token, token: token,
path: '/api/nginx/certificates', path: '/api/nginx/certificates',
@@ -32,7 +32,7 @@ describe('Full Certificate Provisions', () => {
}); });
}); });
it('Should be able to create new DNS certificate with Powerdns', () => { it('Should be able to create new DNS certificate with Powerdns', function() {
cy.task('backendApiPost', { cy.task('backendApiPost', {
token: token, token: token,
path: '/api/nginx/certificates', path: '/api/nginx/certificates',

View File

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

View File

@@ -1,12 +1,12 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
describe('LDAP with Authentik', () => { describe('LDAP with Authentik', () => {
let _token; let token;
if (Cypress.env('skipStackCheck') === 'true' || Cypress.env('stack') === 'postgres') { if (Cypress.env('skipStackCheck') === 'true' || Cypress.env('stack') === 'postgres') {
before(() => { before(() => {
cy.getToken().then((tok) => { cy.getToken().then((tok) => {
_token = tok; token = tok;
// cy.task('backendApiPut', { // cy.task('backendApiPut', {
// token: token, // token: token,
@@ -45,7 +45,7 @@ describe('LDAP with Authentik', () => {
}); });
}); });
it.skip('Should log in with LDAP', () => { it.skip('Should log in with LDAP', function() {
// cy.task('backendApiPost', { // cy.task('backendApiPost', {
// token: token, // token: token,
// path: '/api/auth', // path: '/api/auth',

View File

@@ -1,12 +1,12 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
describe('OAuth with Authentik', () => { describe('OAuth with Authentik', () => {
let _token; let token;
if (Cypress.env('skipStackCheck') === 'true' || Cypress.env('stack') === 'postgres') { if (Cypress.env('skipStackCheck') === 'true' || Cypress.env('stack') === 'postgres') {
before(() => { before(() => {
cy.getToken().then((tok) => { cy.getToken().then((tok) => {
_token = tok; token = tok;
// cy.task('backendApiPut', { // cy.task('backendApiPut', {
// token: token, // token: token,
@@ -47,7 +47,7 @@ describe('OAuth with Authentik', () => {
}); });
}); });
it.skip('Should log in with OAuth', () => { it.skip('Should log in with OAuth', function() {
// cy.task('backendApiGet', { // cy.task('backendApiGet', {
// path: '/oauth/login?redirect_base=' + encodeURI(Cypress.config('baseUrl')), // path: '/oauth/login?redirect_base=' + encodeURI(Cypress.config('baseUrl')),
// }).then((data) => { // }).then((data) => {

View File

@@ -9,7 +9,7 @@ describe('Proxy Hosts endpoints', () => {
}); });
}); });
it('Should be able to create a http host', () => { it('Should be able to create a http host', function() {
cy.task('backendApiPost', { cy.task('backendApiPost', {
token: token, token: token,
path: '/api/nginx/proxy-hosts', path: '/api/nginx/proxy-hosts',

View File

@@ -9,7 +9,7 @@ describe('Settings endpoints', () => {
}); });
}); });
it('Get all settings', () => { it('Get all settings', function() {
cy.task('backendApiGet', { cy.task('backendApiGet', {
token: token, token: token,
path: '/api/settings', path: '/api/settings',
@@ -19,7 +19,7 @@ describe('Settings endpoints', () => {
}); });
}); });
it('Get default-site setting', () => { it('Get default-site setting', function() {
cy.task('backendApiGet', { cy.task('backendApiGet', {
token: token, token: token,
path: '/api/settings/default-site', path: '/api/settings/default-site',
@@ -30,7 +30,7 @@ describe('Settings endpoints', () => {
}); });
}); });
it('Default Site congratulations', () => { it('Default Site congratulations', function() {
cy.task('backendApiPut', { cy.task('backendApiPut', {
token: token, token: token,
path: '/api/settings/default-site', path: '/api/settings/default-site',
@@ -46,7 +46,7 @@ describe('Settings endpoints', () => {
}); });
}); });
it('Default Site 404', () => { it('Default Site 404', function() {
cy.task('backendApiPut', { cy.task('backendApiPut', {
token: token, token: token,
path: '/api/settings/default-site', path: '/api/settings/default-site',
@@ -62,7 +62,7 @@ describe('Settings endpoints', () => {
}); });
}); });
it('Default Site 444', () => { it('Default Site 444', function() {
cy.task('backendApiPut', { cy.task('backendApiPut', {
token: token, token: token,
path: '/api/settings/default-site', path: '/api/settings/default-site',
@@ -78,7 +78,7 @@ describe('Settings endpoints', () => {
}); });
}); });
it('Default Site redirect', () => { it('Default Site redirect', function() {
cy.task('backendApiPut', { cy.task('backendApiPut', {
token: token, token: token,
path: '/api/settings/default-site', path: '/api/settings/default-site',
@@ -100,7 +100,7 @@ describe('Settings endpoints', () => {
}); });
}); });
it('Default Site html', () => { it('Default Site html', function() {
cy.task('backendApiPut', { cy.task('backendApiPut', {
token: token, token: token,
path: '/api/settings/default-site', path: '/api/settings/default-site',

View File

@@ -1,225 +0,0 @@
/// <reference types="cypress" />
describe('Streams', () => {
let token;
before(() => {
cy.getToken().then((tok) => {
token = tok;
// Set default site content
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
data: {
value: 'html',
meta: {
html: '<p>yay it works</p>'
},
},
}).then((data) => {
cy.validateSwaggerSchema('put', 200, '/settings/{settingID}', data);
});
});
// Create a custom cert pair
cy.exec('mkcert -cert-file=/test/cypress/fixtures/website1.pem -key-file=/test/cypress/fixtures/website1.key.pem website1.example.com').then((result) => {
expect(result.code).to.eq(0);
// Install CA
cy.exec('mkcert -install').then((result) => {
expect(result.code).to.eq(0);
});
});
cy.exec('rm -f /test/results/testssl.json');
});
it('Should be able to create TCP Stream', () => {
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/streams',
data: {
incoming_port: 1500,
forwarding_host: '127.0.0.1',
forwarding_port: 80,
certificate_id: 0,
meta: {
dns_provider_credentials: "",
letsencrypt_agree: false,
dns_challenge: true
},
tcp_forwarding: true,
udp_forwarding: false
}
}).then((data) => {
cy.validateSwaggerSchema('post', 201, '/nginx/streams', data);
expect(data).to.have.property('id');
expect(data.id).to.be.greaterThan(0);
expect(data).to.have.property('enabled', true);
expect(data).to.have.property('tcp_forwarding', true);
expect(data).to.have.property('udp_forwarding', false);
cy.exec('curl --noproxy -- http://website1.example.com:1500').then((result) => {
expect(result.code).to.eq(0);
expect(result.stdout).to.contain('yay it works');
});
});
});
it('Should be able to create UDP Stream', () => {
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/streams',
data: {
incoming_port: 1501,
forwarding_host: '127.0.0.1',
forwarding_port: 80,
certificate_id: 0,
meta: {
dns_provider_credentials: "",
letsencrypt_agree: false,
dns_challenge: true
},
tcp_forwarding: false,
udp_forwarding: true
}
}).then((data) => {
cy.validateSwaggerSchema('post', 201, '/nginx/streams', data);
expect(data).to.have.property('id');
expect(data.id).to.be.greaterThan(0);
expect(data).to.have.property('enabled', true);
expect(data).to.have.property('tcp_forwarding', false);
expect(data).to.have.property('udp_forwarding', true);
});
});
it('Should be able to create TCP/UDP Stream', () => {
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/streams',
data: {
incoming_port: 1502,
forwarding_host: '127.0.0.1',
forwarding_port: 80,
certificate_id: 0,
meta: {
dns_provider_credentials: "",
letsencrypt_agree: false,
dns_challenge: true
},
tcp_forwarding: true,
udp_forwarding: true
}
}).then((data) => {
cy.validateSwaggerSchema('post', 201, '/nginx/streams', data);
expect(data).to.have.property('id');
expect(data.id).to.be.greaterThan(0);
expect(data).to.have.property('enabled', true);
expect(data).to.have.property('tcp_forwarding', true);
expect(data).to.have.property('udp_forwarding', true);
cy.exec('curl --noproxy -- http://website1.example.com:1502').then((result) => {
expect(result.code).to.eq(0);
expect(result.stdout).to.contain('yay it works');
});
});
});
it('Should be able to create SSL TCP Stream', () => {
let certID = 0;
// Create custom cert
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/certificates',
data: {
provider: "other",
nice_name: "Custom Certificate for SSL Stream",
},
}).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: 'website1.pem',
certificate_key: 'website1.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');
// Create the stream
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/streams',
data: {
incoming_port: 1503,
forwarding_host: '127.0.0.1',
forwarding_port: 80,
certificate_id: certID,
meta: {
dns_provider_credentials: "",
letsencrypt_agree: false,
dns_challenge: true
},
tcp_forwarding: true,
udp_forwarding: false
}
}).then((data) => {
cy.validateSwaggerSchema('post', 201, '/nginx/streams', data);
expect(data).to.have.property('id');
expect(data.id).to.be.greaterThan(0);
expect(data).to.have.property("enabled", true);
expect(data).to.have.property('tcp_forwarding', true);
expect(data).to.have.property('udp_forwarding', false);
expect(data).to.have.property('certificate_id', certID);
// Check the ssl termination
cy.task('log', '[testssl.sh] Running ...');
cy.exec('/testssl/testssl.sh --quiet --add-ca="$(/bin/mkcert -CAROOT)/rootCA.pem" --jsonfile=/test/results/testssl.json website1.example.com:1503', {
timeout: 120000, // 2 minutes
}).then((result) => {
cy.task('log', `[testssl.sh] ${result.stdout}`);
const allowedSeverities = ["INFO", "OK", "LOW", "MEDIUM"];
const ignoredIDs = [
'cert_chain_of_trust',
'cert_extlifeSpan',
'cert_revocation',
'overall_grade',
];
cy.readFile('/test/results/testssl.json').then((data) => {
// Parse each array item
for (let i = 0; i < data.length; i++) {
const item = data[i];
if (ignoredIDs.includes(item.id)) {
continue;
}
expect(item.severity).to.be.oneOf(allowedSeverities);
}
});
});
});
});
});
});
it('Should be able to List Streams', () => {
cy.task('backendApiGet', {
token: token,
path: '/api/nginx/streams?expand=owner,certificate',
}).then((data) => {
cy.validateSwaggerSchema('get', 200, '/nginx/streams', data);
expect(data.length).to.be.greaterThan(0);
expect(data[0]).to.have.property('id');
expect(data[0]).to.have.property('enabled');
});
});
});

View File

@@ -9,7 +9,7 @@ describe('Users endpoints', () => {
}); });
}); });
it('Should be able to get yourself', () => { it('Should be able to get yourself', function() {
cy.task('backendApiGet', { cy.task('backendApiGet', {
token: token, token: token,
path: '/api/users/me' path: '/api/users/me'
@@ -20,7 +20,7 @@ describe('Users endpoints', () => {
}); });
}); });
it('Should be able to get all users', () => { it('Should be able to get all users', function() {
cy.task('backendApiGet', { cy.task('backendApiGet', {
token: token, token: token,
path: '/api/users' path: '/api/users'
@@ -30,7 +30,7 @@ describe('Users endpoints', () => {
}); });
}); });
it('Should be able to update yourself', () => { it('Should be able to update yourself', function() {
cy.task('backendApiPut', { cy.task('backendApiPut', {
token: token, token: token,
path: '/api/users/me', path: '/api/users/me',

View File

@@ -4,18 +4,18 @@
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {
"@jc21/cypress-swagger-validation": "^0.3.2", "@jc21/cypress-swagger-validation": "^0.3.1",
"axios": "^1.7.9", "axios": "^1.7.7",
"cypress": "^14.0.1", "cypress": "^13.15.0",
"cypress-multi-reporters": "^2.0.5", "cypress-multi-reporters": "^1.6.4",
"cypress-wait-until": "^3.0.2", "cypress-wait-until": "^3.0.2",
"eslint": "^9.19.0", "eslint": "^9.12.0",
"eslint-plugin-align-assignments": "^1.1.2", "eslint-plugin-align-assignments": "^1.1.2",
"eslint-plugin-chai-friendly": "^1.0.1", "eslint-plugin-chai-friendly": "^1.0.1",
"eslint-plugin-cypress": "^4.1.0", "eslint-plugin-cypress": "^3.5.0",
"form-data": "^4.0.1", "form-data": "^4.0.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mocha": "^11.1.0", "mocha": "^10.7.3",
"mocha-junit-reporter": "^2.2.1" "mocha-junit-reporter": "^2.2.1"
}, },
"scripts": { "scripts": {

File diff suppressed because it is too large Load Diff