Compare commits

..

2 Commits

Author SHA1 Message Date
luandro
348fdff5ac Merge 8cfb9a99b3 into 498109addb 2025-01-30 23:26:13 -08:00
luandro
8cfb9a99b3 Added Portuguese translations 2021-10-17 09:04:31 -03:00
71 changed files with 1503 additions and 2410 deletions

View File

@@ -1 +1 @@
2.12.6
2.12.2

15
Jenkinsfile vendored
View File

@@ -241,17 +241,12 @@ pipeline {
}
steps {
script {
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}
```
npmGithubPrComment("""Docker Image for build ${BUILD_NUMBER} is available on
[DockerHub](https://cloud.docker.com/repository/docker/nginxproxymanager/${IMAGE}-dev)
as `nginxproxymanager/${IMAGE}-dev:${BRANCH_LOWER}`
> [!NOTE]
> Ensure you backup your NPM instance before testing this image! Especially if there are database changes.
> 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!
**Note:** 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
""", true)
}
}

View File

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

View File

@@ -3,8 +3,6 @@
const schema = require('./schema');
const logger = require('./logger').global;
const IP_RANGES_FETCH_ENABLED = process.env.IP_RANGES_FETCH_ENABLED !== 'false';
async function appStart () {
const migrate = require('./migrate');
const setup = require('./setup');
@@ -15,16 +13,7 @@ async function appStart () {
return migrate.latest()
.then(setup)
.then(schema.getCompiledSchema)
.then(() => {
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(internalIpRanges.fetch)
.then(() => {
internalCertificate.initTimer();
internalIpRanges.initTimer();

View File

@@ -508,13 +508,8 @@ const internalAccessList = {
if (typeof item.password !== 'undefined' && item.password.length) {
logger.info('Adding: ' + item.username);
utils.execFile('openssl', ['passwd', '-apr1', item.password])
.then((res) => {
try {
fs.appendFileSync(htpasswd_file, item.username + ':' + res + '\n', {encoding: 'utf8'});
} catch (err) {
reject(err);
}
utils.execFile('/usr/bin/htpasswd', ['-b', htpasswd_file, item.username, item.password])
.then((/*result*/) => {
next();
})
.catch((err) => {

View File

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

View File

@@ -4,12 +4,10 @@ const utils = require('../lib/utils');
const streamModel = require('../models/stream');
const internalNginx = require('./nginx');
const internalAuditLog = require('./audit-log');
const internalCertificate = require('./certificate');
const internalHost = require('./host');
const {castJsonIfNeed} = require('../lib/helpers');
function omissions () {
return ['is_deleted', 'owner.is_deleted', 'certificate.is_deleted'];
return ['is_deleted'];
}
const internalStream = {
@@ -20,12 +18,6 @@ const internalStream = {
* @returns {Promise}
*/
create: (access, data) => {
const create_certificate = data.certificate_id === 'new';
if (create_certificate) {
delete data.certificate_id;
}
return access.can('streams:create', data)
.then((/*access_data*/) => {
// TODO: At this point the existing ports should have been checked
@@ -35,44 +27,16 @@ const internalStream = {
data.meta = {};
}
// streams aren't routed by domain name so don't store domain names in the DB
let data_no_domains = structuredClone(data);
delete data_no_domains.domain_names;
return streamModel
.query()
.insertAndFetch(data_no_domains)
.insertAndFetch(data)
.then(utils.omitRow(omissions()));
})
.then((row) => {
if (create_certificate) {
return internalCertificate.createQuickCertificate(access, data)
.then((cert) => {
// update host with cert id
return internalStream.update(access, {
id: row.id,
certificate_id: cert.id
});
})
.then(() => {
return row;
});
} else {
return row;
}
})
.then((row) => {
// re-fetch with cert
return internalStream.get(access, {
id: row.id,
expand: ['certificate', 'owner']
});
})
.then((row) => {
// Configure nginx
return internalNginx.configure(streamModel, 'stream', row)
.then(() => {
return row;
return internalStream.get(access, {id: row.id, expand: ['owner']});
});
})
.then((row) => {
@@ -96,12 +60,6 @@ const internalStream = {
* @return {Promise}
*/
update: (access, data) => {
const create_certificate = data.certificate_id === 'new';
if (create_certificate) {
delete data.certificate_id;
}
return access.can('streams:update', data.id)
.then((/*access_data*/) => {
// TODO: at this point the existing streams should have been checked
@@ -113,32 +71,16 @@ const internalStream = {
throw new error.InternalValidationError('Stream could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
}
if (create_certificate) {
return internalCertificate.createQuickCertificate(access, {
domain_names: data.domain_names || row.domain_names,
meta: _.assign({}, row.meta, data.meta)
})
.then((cert) => {
// update host with cert id
data.certificate_id = cert.id;
})
.then(() => {
return row;
});
} else {
return row;
}
})
.then((row) => {
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
data = _.assign({}, {
domain_names: row.domain_names
}, data);
return streamModel
.query()
.patchAndFetchById(row.id, data)
.then(utils.omitRow(omissions()))
.then((saved_row) => {
return internalNginx.configure(streamModel, 'stream', saved_row)
.then(() => {
return internalStream.get(access, {id: row.id, expand: ['owner']});
});
})
.then((saved_row) => {
// Add to audit log
return internalAuditLog.add(access, {
@@ -151,17 +93,6 @@ const internalStream = {
return saved_row;
});
});
})
.then(() => {
return internalStream.get(access, {id: data.id, expand: ['owner', 'certificate']})
.then((row) => {
return internalNginx.configure(streamModel, 'stream', row)
.then((new_meta) => {
row.meta = new_meta;
row = internalHost.cleanRowCertificateMeta(row);
return _.omit(row, omissions());
});
});
});
},
@@ -184,7 +115,7 @@ const internalStream = {
.query()
.where('is_deleted', 0)
.andWhere('id', data.id)
.allowGraph('[owner,certificate]')
.allowGraph('[owner]')
.first();
if (access_data.permission_visibility !== 'all') {
@@ -201,7 +132,6 @@ const internalStream = {
if (!row || !row.id) {
throw new error.ItemNotFoundError(data.id);
}
row = internalHost.cleanRowCertificateMeta(row);
// Custom omissions
if (typeof data.omit !== 'undefined' && data.omit !== null) {
row = _.omit(row, data.omit);
@@ -267,14 +197,14 @@ const internalStream = {
.then(() => {
return internalStream.get(access, {
id: data.id,
expand: ['certificate', 'owner']
expand: ['owner']
});
})
.then((row) => {
if (!row || !row.id) {
throw new error.ItemNotFoundError(data.id);
} else if (row.enabled) {
throw new error.ValidationError('Stream is already enabled');
throw new error.ValidationError('Host is already enabled');
}
row.enabled = 1;
@@ -320,7 +250,7 @@ const internalStream = {
if (!row || !row.id) {
throw new error.ItemNotFoundError(data.id);
} else if (!row.enabled) {
throw new error.ValidationError('Stream is already disabled');
throw new error.ValidationError('Host is already disabled');
}
row.enabled = 0;
@@ -368,8 +298,8 @@ const internalStream = {
.query()
.where('is_deleted', 0)
.groupBy('id')
.allowGraph('[owner,certificate]')
.orderBy('incoming_port', 'ASC');
.allowGraph('[owner]')
.orderByRaw('CAST(incoming_port AS INTEGER) ASC');
if (access_data.permission_visibility !== 'all') {
query.andWhere('owner_user_id', access.token.getUserId(1));
@@ -387,13 +317,6 @@ const internalStream = {
}
return query.then(utils.omitRows(omissions()));
})
.then((rows) => {
if (typeof expand !== 'undefined' && expand !== null && expand.indexOf('certificate') !== -1) {
return internalHost.cleanAllRowsCertificateMeta(rows);
}
return rows;
});
},

View File

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

View File

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

View File

@@ -1,38 +0,0 @@
const migrate_name = 'stream_ssl';
const logger = require('../logger').migrate;
/**
* Migrate
*
* @see http://knexjs.org/#Schema
*
* @param {Object} knex
* @returns {Promise}
*/
exports.up = function (knex) {
logger.info('[' + migrate_name + '] Migrating Up...');
return knex.schema.table('stream', (table) => {
table.integer('certificate_id').notNull().unsigned().defaultTo(0);
})
.then(function () {
logger.info('[' + migrate_name + '] stream Table altered');
});
};
/**
* Undo Migrate
*
* @param {Object} knex
* @returns {Promise}
*/
exports.down = function (knex) {
logger.info('[' + migrate_name + '] Migrating Down...');
return knex.schema.table('stream', (table) => {
table.dropColumn('certificate_id');
})
.then(function () {
logger.info('[' + migrate_name + '] stream Table altered');
});
};

View File

@@ -4,6 +4,7 @@
const db = require('../db');
const helpers = require('../lib/helpers');
const Model = require('objection').Model;
const User = require('./user');
const now = require('./now_helper');
Model.knex(db);
@@ -67,11 +68,6 @@ class Certificate extends Model {
}
static get relationMappings () {
const ProxyHost = require('./proxy_host');
const DeadHost = require('./dead_host');
const User = require('./user');
const RedirectionHost = require('./redirection_host');
return {
owner: {
relation: Model.HasOneRelation,
@@ -83,39 +79,6 @@ class Certificate extends Model {
modify: function (qb) {
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 = [
'is_deleted',
'ssl_forced',
'http2_support',
'enabled',
'hsts_enabled',
'hsts_subdomains',
];
class DeadHost extends Model {

View File

@@ -1,15 +1,16 @@
const Model = require('objection').Model;
// Objection Docs:
// http://vincit.github.io/objection.js/
const db = require('../db');
const helpers = require('../lib/helpers');
const Model = require('objection').Model;
const User = require('./user');
const Certificate = require('./certificate');
const now = require('./now_helper');
Model.knex(db);
const boolFields = [
'is_deleted',
'enabled',
'tcp_forwarding',
'udp_forwarding',
];
@@ -63,17 +64,6 @@ class Stream extends Model {
modify: function (qb) {
qb.where('user.is_deleted', 0);
}
},
certificate: {
relation: Model.HasOneRelation,
modelClass: Certificate,
join: {
from: 'stream.certificate_id',
to: 'certificate.id'
},
modify: function (qb) {
qb.where('certificate.is_deleted', 0);
}
}
};
}

View File

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

View File

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

View File

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

View File

@@ -19,7 +19,9 @@
"incoming_port": {
"type": "integer",
"minimum": 1,
"maximum": 65535
"maximum": 65535,
"if": {"properties": {"tcp_forwarding": {"const": true}}},
"then": {"not": {"oneOf": [{"const": 80}, {"const": 443}]}}
},
"forwarding_host": {
"anyOf": [
@@ -53,24 +55,8 @@
"enabled": {
"$ref": "../common.json#/properties/enabled"
},
"certificate_id": {
"$ref": "../common.json#/properties/certificate_id"
},
"meta": {
"type": "object"
},
"owner": {
"$ref": "./user-object.json"
},
"certificate": {
"oneOf": [
{
"type": "null"
},
{
"$ref": "./certificate-object.json"
}
]
}
}
}

View File

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

View File

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

View File

@@ -32,9 +32,6 @@
"udp_forwarding": {
"$ref": "../../../components/stream-object.json#/properties/udp_forwarding"
},
"certificate_id": {
"$ref": "../../../components/stream-object.json#/properties/certificate_id"
},
"meta": {
"$ref": "../../../components/stream-object.json#/properties/meta"
}
@@ -76,8 +73,7 @@
"nickname": "Admin",
"avatar": "",
"roles": ["admin"]
},
"certificate_id": 0
}
}
}
},

View File

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

View File

@@ -29,26 +29,56 @@
"additionalProperties": false,
"minProperties": 1,
"properties": {
"incoming_port": {
"$ref": "../../../../components/stream-object.json#/properties/incoming_port"
"domain_names": {
"$ref": "../../../../components/proxy-host-object.json#/properties/domain_names"
},
"forwarding_host": {
"$ref": "../../../../components/stream-object.json#/properties/forwarding_host"
"forward_scheme": {
"$ref": "../../../../components/proxy-host-object.json#/properties/forward_scheme"
},
"forwarding_port": {
"$ref": "../../../../components/stream-object.json#/properties/forwarding_port"
"forward_host": {
"$ref": "../../../../components/proxy-host-object.json#/properties/forward_host"
},
"tcp_forwarding": {
"$ref": "../../../../components/stream-object.json#/properties/tcp_forwarding"
},
"udp_forwarding": {
"$ref": "../../../../components/stream-object.json#/properties/udp_forwarding"
"forward_port": {
"$ref": "../../../../components/proxy-host-object.json#/properties/forward_port"
},
"certificate_id": {
"$ref": "../../../../components/stream-object.json#/properties/certificate_id"
"$ref": "../../../../components/proxy-host-object.json#/properties/certificate_id"
},
"ssl_forced": {
"$ref": "../../../../components/proxy-host-object.json#/properties/ssl_forced"
},
"hsts_enabled": {
"$ref": "../../../../components/proxy-host-object.json#/properties/hsts_enabled"
},
"hsts_subdomains": {
"$ref": "../../../../components/proxy-host-object.json#/properties/hsts_subdomains"
},
"http2_support": {
"$ref": "../../../../components/proxy-host-object.json#/properties/http2_support"
},
"block_exploits": {
"$ref": "../../../../components/proxy-host-object.json#/properties/block_exploits"
},
"caching_enabled": {
"$ref": "../../../../components/proxy-host-object.json#/properties/caching_enabled"
},
"allow_websocket_upgrade": {
"$ref": "../../../../components/proxy-host-object.json#/properties/allow_websocket_upgrade"
},
"access_list_id": {
"$ref": "../../../../components/proxy-host-object.json#/properties/access_list_id"
},
"advanced_config": {
"$ref": "../../../../components/proxy-host-object.json#/properties/advanced_config"
},
"enabled": {
"$ref": "../../../../components/proxy-host-object.json#/properties/enabled"
},
"meta": {
"$ref": "../../../../components/stream-object.json#/properties/meta"
"$ref": "../../../../components/proxy-host-object.json#/properties/meta"
},
"locations": {
"$ref": "../../../../components/proxy-host-object.json#/properties/locations"
}
}
}
@@ -64,32 +94,42 @@
"default": {
"value": {
"id": 1,
"created_on": "2024-10-09T02:33:45.000Z",
"modified_on": "2024-10-09T02:33:45.000Z",
"created_on": "2024-10-08T23:23:03.000Z",
"modified_on": "2024-10-08T23:26:37.000Z",
"owner_user_id": 1,
"incoming_port": 9090,
"forwarding_host": "router.internal",
"forwarding_port": 80,
"tcp_forwarding": true,
"udp_forwarding": false,
"domain_names": ["test.example.com"],
"forward_host": "192.168.0.10",
"forward_port": 8989,
"access_list_id": 0,
"certificate_id": 0,
"ssl_forced": false,
"caching_enabled": false,
"block_exploits": false,
"advanced_config": "",
"meta": {
"nginx_online": true,
"nginx_err": null
},
"allow_websocket_upgrade": false,
"http2_support": false,
"forward_scheme": "http",
"enabled": true,
"hsts_enabled": false,
"hsts_subdomains": false,
"owner": {
"id": 1,
"created_on": "2024-10-09T02:33:16.000Z",
"modified_on": "2024-10-09T02:33:16.000Z",
"created_on": "2024-10-07T22:43:55.000Z",
"modified_on": "2024-10-08T12:52:54.000Z",
"is_deleted": false,
"is_disabled": false,
"email": "admin@example.com",
"name": "Administrator",
"nickname": "Admin",
"avatar": "",
"nickname": "some guy",
"avatar": "//www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?default=mm",
"roles": ["admin"]
},
"certificate_id": 0
"certificate": null,
"access_list": null
}
}
},

View File

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

View File

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

View File

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

View File

@@ -2,7 +2,6 @@
{% if certificate.provider == "letsencrypt" %}
# Let's Encrypt SSL
include conf.d/include/letsencrypt-acme-challenge.conf;
include conf.d/include/ssl-cache.conf;
include conf.d/include/ssl-ciphers.conf;
ssl_certificate /etc/letsencrypt/live/npm-{{ certificate_id }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/npm-{{ certificate_id }}/privkey.pem;

View File

@@ -1,13 +0,0 @@
{% if certificate and certificate_id > 0 %}
{% if certificate.provider == "letsencrypt" %}
# Let's Encrypt SSL
include conf.d/include/ssl-cache-stream.conf;
include conf.d/include/ssl-ciphers.conf;
ssl_certificate /etc/letsencrypt/live/npm-{{ certificate_id }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/npm-{{ certificate_id }}/privkey.pem;
{%- else %}
# Custom SSL
ssl_certificate /data/custom_ssl/npm-{{ certificate_id }}/fullchain.pem;
ssl_certificate_key /data/custom_ssl/npm-{{ certificate_id }}/privkey.pem;
{%- endif -%}
{%- endif -%}

View File

@@ -5,10 +5,12 @@
{% if enabled %}
{% if tcp_forwarding == 1 or tcp_forwarding == true -%}
server {
listen {{ incoming_port }} {%- if certificate %} ssl {%- endif %};
{% unless ipv6 -%} # {%- endunless -%} listen [::]:{{ incoming_port }} {%- if certificate %} ssl {%- endif %};
{%- include "_certificates_stream.conf" %}
listen {{ incoming_port }};
{% if ipv6 -%}
listen [::]:{{ incoming_port }};
{% else -%}
#listen [::]:{{ incoming_port }};
{% endif %}
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
@@ -17,12 +19,14 @@ server {
include /data/nginx/custom/server_stream_tcp[.]conf;
}
{% endif %}
{% if udp_forwarding == 1 or udp_forwarding == true -%}
{% if udp_forwarding == 1 or udp_forwarding == true %}
server {
listen {{ incoming_port }} udp;
{% unless ipv6 -%} # {%- endunless -%} listen [::]:{{ incoming_port }} udp;
{% if ipv6 -%}
listen [::]:{{ incoming_port }} udp;
{% else -%}
#listen [::]:{{ incoming_port }} udp;
{% endif %}
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
# Custom

View File

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

View File

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

View File

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

View File

@@ -1,2 +0,0 @@
ssl_session_timeout 5m;
ssl_session_cache shared:SSL_stream:50m;

View File

@@ -1,2 +0,0 @@
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;

View File

@@ -1,3 +1,6 @@
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
# intermediate configuration. tweak to your needs.
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';

View File

@@ -8,53 +8,21 @@ log_info 'Setting ownership ...'
# root
chown root /tmp/nginx
locations=(
"/data"
"/etc/letsencrypt"
"/run/nginx"
"/tmp/nginx"
"/var/cache/nginx"
"/var/lib/logrotate"
"/var/lib/nginx"
"/var/log/nginx"
"/etc/nginx/nginx"
"/etc/nginx/nginx.conf"
"/etc/nginx/conf.d"
)
# npm user and group
chown -R "$PUID:$PGID" /data
chown -R "$PUID:$PGID" /etc/letsencrypt
chown -R "$PUID:$PGID" /run/nginx
chown -R "$PUID:$PGID" /tmp/nginx
chown -R "$PUID:$PGID" /var/cache/nginx
chown -R "$PUID:$PGID" /var/lib/logrotate
chown -R "$PUID:$PGID" /var/lib/nginx
chown -R "$PUID:$PGID" /var/log/nginx
chownit() {
local dir="$1"
local recursive="${2:-true}"
# Don't chown entire /etc/nginx folder as this causes crashes on some systems
chown -R "$PUID:$PGID" /etc/nginx/nginx
chown -R "$PUID:$PGID" /etc/nginx/nginx.conf
chown -R "$PUID:$PGID" /etc/nginx/conf.d
local have
have="$(stat -c '%u:%g' "$dir")"
echo "- $dir ... "
if [ "$have" != "$PUID:$PGID" ]; then
if [ "$recursive" = 'true' ] && [ -d "$dir" ]; then
chown -R "$PUID:$PGID" "$dir"
else
chown "$PUID:$PGID" "$dir"
fi
echo " DONE"
else
echo " SKIPPED"
fi
}
for loc in "${locations[@]}"; do
chownit "$loc"
done
if [ "$(is_true "${SKIP_CERTBOT_OWNERSHIP:-}")" = '1' ]; then
log_info 'Skipping ownership change of certbot directories'
else
log_info 'Changing ownership of certbot directories, this may take some time ...'
chownit "/opt/certbot" false
chownit "/opt/certbot/bin" false
# Handle all site-packages directories efficiently
find /opt/certbot/lib -type d -name "site-packages" | while read -r SITE_PACKAGES_DIR; do
chownit "$SITE_PACKAGES_DIR"
done
fi
# Prevents errors when installing python certbot plugins when non-root
chown "$PUID:$PGID" /opt/certbot /opt/certbot/bin
find /opt/certbot/lib/python*/site-packages -not -user "$PUID" -execdir chown "$PUID:$PGID" {} \+

View File

@@ -5,9 +5,12 @@ set -e
log_info 'Dynamic resolvers ...'
DISABLE_IPV6=$(echo "${DISABLE_IPV6:-}" | tr '[:upper:]' '[:lower:]')
# Dynamically generate resolvers file, if resolver is IPv6, enclose in `[]`
# thanks @tfmm
if [ "$(is_true "$DISABLE_IPV6")" = '1' ]; then
if [ "$DISABLE_IPV6" == "true" ] || [ "$DISABLE_IPV6" == "on" ] || [ "$DISABLE_IPV6" == "1" ] || [ "$DISABLE_IPV6" == "yes" ];
then
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" { sub(/%.*$/,"",$2); print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf) ipv6=off valid=10s;" > /etc/nginx/conf.d/include/resolvers.conf
else
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" { sub(/%.*$/,"",$2); print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf) valid=10s;" > /etc/nginx/conf.d/include/resolvers.conf

View File

@@ -8,11 +8,14 @@ set -e
log_info 'IPv6 ...'
# Lowercase
DISABLE_IPV6=$(echo "${DISABLE_IPV6:-}" | tr '[:upper:]' '[:lower:]')
process_folder () {
FILES=$(find "$1" -type f -name "*.conf")
SED_REGEX=
if [ "$(is_true "$DISABLE_IPV6")" = '1' ]; then
if [ "$DISABLE_IPV6" == "true" ] || [ "$DISABLE_IPV6" == "on" ] || [ "$DISABLE_IPV6" == "1" ] || [ "$DISABLE_IPV6" == "yes" ]; then
# IPV6 is disabled
echo "Disabling IPV6 in hosts in: $1"
SED_REGEX='s/^([^#]*)listen \[::\]/\1#listen [::]/g'

View File

@@ -56,13 +56,3 @@ get_group_id () {
getent group "$1" | cut -d: -f3
fi
}
# param $1: value
is_true () {
VAL=$(echo "${1:-}" | tr '[:upper:]' '[:lower:]')
if [ "$VAL" == 'true' ] || [ "$VAL" == 'on' ] || [ "$VAL" == '1' ] || [ "$VAL" == 'yes' ]; then
echo '1'
else
echo '0'
fi
}

View File

@@ -8,7 +8,7 @@ BLUE='\E[1;34m'
GREEN='\E[1;32m'
RESET='\E[0m'
S6_OVERLAY_VERSION=3.2.1.0
S6_OVERLAY_VERSION=3.1.5.0
TARGETPLATFORM=${1:-linux/amd64}
# 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'
```
## 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

View File

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

View File

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

View File

@@ -26,7 +26,7 @@ module.exports = {
* Users
*/
showUsers: function () {
const controller = this;
let controller = this;
if (Cache.User.isAdmin()) {
require(['./main', './users/main'], (App, View) => {
controller.navigate('/users');
@@ -93,7 +93,8 @@ module.exports = {
* Dashboard
*/
showDashboard: function () {
const controller = this;
let controller = this;
require(['./main', './dashboard/main'], (App, View) => {
controller.navigate('/');
App.UI.showAppContent(new View());
@@ -105,7 +106,7 @@ module.exports = {
*/
showNginxProxy: function () {
if (Cache.User.isAdmin() || Cache.User.canView('proxy_hosts')) {
const controller = this;
let controller = this;
require(['./main', './nginx/proxy/main'], (App, View) => {
controller.navigate('/nginx/proxy');
@@ -145,7 +146,8 @@ module.exports = {
*/
showNginxRedirection: function () {
if (Cache.User.isAdmin() || Cache.User.canView('redirection_hosts')) {
const controller = this;
let controller = this;
require(['./main', './nginx/redirection/main'], (App, View) => {
controller.navigate('/nginx/redirection');
App.UI.showAppContent(new View());
@@ -184,7 +186,8 @@ module.exports = {
*/
showNginxStream: function () {
if (Cache.User.isAdmin() || Cache.User.canView('streams')) {
const controller = this;
let controller = this;
require(['./main', './nginx/stream/main'], (App, View) => {
controller.navigate('/nginx/stream');
App.UI.showAppContent(new View());
@@ -223,7 +226,8 @@ module.exports = {
*/
showNginxDead: function () {
if (Cache.User.isAdmin() || Cache.User.canView('dead_hosts')) {
const controller = this;
let controller = this;
require(['./main', './nginx/dead/main'], (App, View) => {
controller.navigate('/nginx/404');
App.UI.showAppContent(new View());
@@ -274,7 +278,8 @@ module.exports = {
*/
showNginxAccess: function () {
if (Cache.User.isAdmin() || Cache.User.canView('access_lists')) {
const controller = this;
let controller = this;
require(['./main', './nginx/access/main'], (App, View) => {
controller.navigate('/nginx/access');
App.UI.showAppContent(new View());
@@ -313,7 +318,8 @@ module.exports = {
*/
showNginxCertificates: function () {
if (Cache.User.isAdmin() || Cache.User.canView('certificates')) {
const controller = this;
let controller = this;
require(['./main', './nginx/certificates/main'], (App, View) => {
controller.navigate('/nginx/certificates');
App.UI.showAppContent(new View());
@@ -377,7 +383,7 @@ module.exports = {
* Audit Log
*/
showAuditLog: function () {
const controller = this;
let controller = this;
if (Cache.User.isAdmin()) {
require(['./main', './audit-log/main'], (App, View) => {
controller.navigate('/audit-log');
@@ -405,7 +411,7 @@ module.exports = {
* Settings
*/
showSettings: function () {
const controller = this;
let controller = this;
if (Cache.User.isAdmin()) {
require(['./main', './settings/main'], (App, View) => {
controller.navigate('/settings');

View File

@@ -24,7 +24,7 @@ module.exports = Mn.View.extend({
},
templateContext: function () {
const view = this;
let view = this;
return {
getUserName: function () {
@@ -48,7 +48,8 @@ module.exports = Mn.View.extend({
},
onRender: function () {
const view = this;
let view = this;
if (typeof view.stats.hosts === 'undefined') {
Api.Reports.getHostStats()
.then(response => {
@@ -71,7 +72,8 @@ module.exports = Mn.View.extend({
// calculate the available columns based on permissions for the objects
// and store as a variable
const perms = ['proxy_hosts', 'redirection_hosts', 'streams', 'dead_hosts'];
//let view = this;
let perms = ['proxy_hosts', 'redirection_hosts', 'streams', 'dead_hosts'];
perms.map(perm => {
this.columns += Cache.User.isAdmin() || Cache.User.canView(perm) ? 1 : 0;

View File

@@ -33,13 +33,6 @@
<td class="<%- isExpired() ? 'text-danger' : '' %>">
<%- formatDbDate(expires_on, 'Do MMMM YYYY, h:mm a') %>
</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) { %>
<td class="text-right">
<div class="item-action dropdown">
@@ -55,13 +48,6 @@
<div class="dropdown-divider"></div>
<% } %>
<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>
</td>

View File

@@ -44,24 +44,14 @@ module.exports = Mn.View.extend({
},
},
templateContext: function () {
return {
templateContext: {
canManage: App.Cache.User.canManage('certificates'),
isExpired: function () {
return moment(this.expires_on).isBefore(moment());
},
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;
}, []);
}
};
dns_providers: dns_providers
},
initialize: function () {
this.listenTo(this.model, 'change', this.render);
}

View File

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

View File

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

View File

@@ -3,16 +3,8 @@
<h5 class="modal-title"><%- i18n('streams', 'form-title', {id: id}) %></h5>
<button type="button" class="close cancel" aria-label="Close" data-dismiss="modal">&nbsp;</button>
</div>
<div class="modal-body has-tabs">
<div class="alert alert-danger mb-0 rounded-0" id="le-error-info" role="alert"></div>
<div class="modal-body">
<form>
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="nav-item"><a href="#details" aria-controls="tab1" role="tab" data-toggle="tab" class="nav-link active"><i class="fe fe-zap"></i> <%- i18n('all-hosts', 'details') %></a></li>
<li role="presentation" class="nav-item"><a href="#ssl-options" aria-controls="tab2" role="tab" data-toggle="tab" class="nav-link"><i class="fe fe-shield"></i> <%- i18n('str', 'ssl') %></a></li>
</ul>
<div class="tab-content">
<!-- Details -->
<div role="tabpanel" class="tab-pane active" id="details">
<div class="row">
<div class="col-sm-12 col-md-12">
<div class="form-group">
@@ -54,137 +46,6 @@
<div class="forward-type-error invalid-feedback"><%- i18n('streams', 'forward-type-error') %></div>
</div>
</div>
</div>
<!-- SSL -->
<div role="tabpanel" class="tab-pane" id="ssl-options">
<div class="row">
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label"><%- i18n('streams', 'ssl-certificate') %></label>
<select name="certificate_id" class="form-control custom-select" placeholder="<%- i18n('all-hosts', 'none') %>">
<option selected value="0" data-data="{&quot;id&quot;:0}" <%- certificate_id ? '' : 'selected' %>><%- i18n('all-hosts', 'none') %></option>
<option selected value="new" data-data="{&quot;id&quot;:&quot;new&quot;}"><%- i18n('all-hosts', 'new-cert') %></option>
</select>
</div>
</div>
<!-- DNS challenge -->
<div class="col-sm-12 col-md-12 letsencrypt">
<div class="form-group">
<label class="form-label"><%- i18n('all-hosts', 'domain-names') %> <span class="form-required">*</span></label>
<input type="text" name="domain_names" class="form-control" id="input-domains" value="<%- domain_names.join(',') %>">
</div>
<div class="form-group">
<label class="custom-switch">
<input
type="checkbox"
class="custom-switch-input"
name="meta[dns_challenge]"
value="1"
checked
disabled
>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description"><%= i18n('ssl', 'dns-challenge') %></span>
</label>
</div>
</div>
<div class="col-sm-12 col-md-12 letsencrypt">
<fieldset class="form-fieldset dns-challenge">
<div class="text-red mb-4"><i class="fe fe-alert-triangle"></i> <%= i18n('ssl', 'certbot-warning') %></div>
<!-- Certbot DNS plugin selection -->
<div class="row">
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label"><%- i18n('ssl', 'dns-provider') %> <span class="form-required">*</span></label>
<select
name="meta[dns_provider]"
id="dns_provider"
class="form-control custom-select"
>
<option
value=""
disabled
hidden
<%- getDnsProvider() === null ? 'selected' : '' %>
>Please Choose...</option>
<% _.each(dns_plugins, function(plugin_info, plugin_name){ %>
<option
value="<%- plugin_name %>"
<%- getDnsProvider() === plugin_name ? 'selected' : '' %>
><%- plugin_info.name %></option>
<% }); %>
</select>
</div>
</div>
</div>
<!-- Certbot credentials file content -->
<div class="row credentials-file-content">
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label"><%- i18n('ssl', 'credentials-file-content') %> <span class="form-required">*</span></label>
<textarea
name="meta[dns_provider_credentials]"
class="form-control text-monospace"
id="dns_provider_credentials"
><%- getDnsProviderCredentials() %></textarea>
<div class="text-secondary small">
<i class="fe fe-info"></i>
<%= i18n('ssl', 'credentials-file-content-info') %>
</div>
<div class="text-red small">
<i class="fe fe-alert-triangle"></i>
<%= i18n('ssl', 'stored-as-plaintext-info') %>
</div>
</div>
</div>
</div>
<!-- DNS propagation delay -->
<div class="row">
<div class="col-sm-12 col-md-12">
<div class="form-group mb-0">
<label class="form-label"><%- i18n('ssl', 'propagation-seconds') %></label>
<input
type="number"
min="0"
name="meta[propagation_seconds]"
class="form-control"
id="propagation_seconds"
value="<%- getPropagationSeconds() %>"
>
<div class="text-secondary small">
<i class="fe fe-info"></i>
<%= i18n('ssl', 'propagation-seconds-info') %>
</div>
</div>
</div>
</div>
</fieldset>
</div>
<!-- Lets encrypt -->
<div class="col-sm-12 col-md-12 letsencrypt">
<div class="form-group">
<label class="form-label"><%- i18n('ssl', 'letsencrypt-email') %> <span class="form-required">*</span></label>
<input name="meta[letsencrypt_email]" type="email" class="form-control" placeholder="" value="<%- getLetsencryptEmail() %>" required disabled>
</div>
</div>
<div class="col-sm-12 col-md-12 letsencrypt">
<div class="form-group">
<label class="custom-switch">
<input type="checkbox" class="custom-switch-input" name="meta[letsencrypt_agree]" value="1" required disabled>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description"><%= i18n('ssl', 'letsencrypt-agree', {url: 'https://letsencrypt.org/repository/'}) %> <span class="form-required">*</span></span>
</label>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">

View File

@@ -2,14 +2,10 @@ const Mn = require('backbone.marionette');
const App = require('../../main');
const StreamModel = require('../../../models/stream');
const template = require('./form.ejs');
const dns_providers = require('../../../../../global/certbot-dns-plugins');
require('jquery-serializejson');
require('jquery-mask-plugin');
require('selectize');
const Helpers = require("../../../lib/helpers");
const certListItemTemplate = require("../certificates-list-item.ejs");
const i18n = require("../../i18n");
module.exports = Mn.View.extend({
template: template,
@@ -22,17 +18,7 @@ module.exports = Mn.View.extend({
buttons: '.modal-footer button',
switches: '.custom-switch-input',
cancel: 'button.cancel',
save: 'button.save',
le_error_info: '#le-error-info',
certificate_select: 'select[name="certificate_id"]',
domain_names: 'input[name="domain_names"]',
dns_challenge_switch: 'input[name="meta[dns_challenge]"]',
dns_challenge_content: '.dns-challenge',
dns_provider: 'select[name="meta[dns_provider]"]',
credentials_file_content: '.credentials-file-content',
dns_provider_credentials: 'textarea[name="meta[dns_provider_credentials]"]',
propagation_seconds: 'input[name="meta[propagation_seconds]"]',
letsencrypt: '.letsencrypt'
save: 'button.save'
},
events: {
@@ -62,35 +48,6 @@ module.exports = Mn.View.extend({
data.tcp_forwarding = !!data.tcp_forwarding;
data.udp_forwarding = !!data.udp_forwarding;
if (typeof data.meta === 'undefined') data.meta = {};
data.meta.letsencrypt_agree = data.meta.letsencrypt_agree == 1;
data.meta.dns_challenge = true;
if (data.meta.propagation_seconds === '') data.meta.propagation_seconds = undefined;
if (typeof data.domain_names === 'string' && data.domain_names) {
data.domain_names = data.domain_names.split(',');
}
// Check for any domain names containing wildcards, which are not allowed with letsencrypt
if (data.certificate_id === 'new') {
let domain_err = false;
if (!data.meta.dns_challenge) {
data.domain_names.map(function (name) {
if (name.match(/\*/im)) {
domain_err = true;
}
});
}
if (domain_err) {
alert(i18n('ssl', 'no-wildcard-without-dns'));
return;
}
} else {
data.certificate_id = parseInt(data.certificate_id, 10);
}
let method = App.Api.Nginx.Streams.create;
let is_new = true;
@@ -113,108 +70,10 @@ module.exports = Mn.View.extend({
});
})
.catch(err => {
let more_info = '';
if (err.code === 500 && err.debug) {
try {
more_info = JSON.parse(err.debug).debug.stack.join("\n");
} catch (e) {
}
}
this.ui.le_error_info[0].innerHTML = `${err.message}${more_info !== '' ? `<pre class="mt-3">${more_info}</pre>` : ''}`;
this.ui.le_error_info.show();
this.ui.le_error_info[0].scrollIntoView();
alert(err.message);
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
this.ui.save.removeClass('btn-loading');
});
},
'change @ui.certificate_select': function () {
let id = this.ui.certificate_select.val();
if (id === 'new') {
this.ui.letsencrypt.show().find('input').prop('disabled', false);
this.ui.domain_names.prop('required', 'required');
this.ui.dns_challenge_switch
.prop('disabled', true)
.parents('.form-group')
.css('opacity', 0.5);
this.ui.dns_provider.prop('required', 'required');
const selected_provider = this.ui.dns_provider[0].options[this.ui.dns_provider[0].selectedIndex].value;
if (selected_provider != '' && dns_providers[selected_provider].credentials !== false) {
this.ui.dns_provider_credentials.prop('required', 'required');
}
this.ui.dns_challenge_content.show();
} else {
this.ui.letsencrypt.hide().find('input').prop('disabled', true);
}
},
'change @ui.dns_provider': function () {
const selected_provider = this.ui.dns_provider[0].options[this.ui.dns_provider[0].selectedIndex].value;
if (selected_provider != '' && dns_providers[selected_provider].credentials !== false) {
this.ui.dns_provider_credentials.prop('required', 'required');
this.ui.dns_provider_credentials[0].value = dns_providers[selected_provider].credentials;
this.ui.credentials_file_content.show();
} else {
this.ui.dns_provider_credentials.prop('required', false);
this.ui.credentials_file_content.hide();
}
},
},
templateContext: {
getLetsencryptEmail: function () {
return App.Cache.User.get('email');
},
getDnsProvider: function () {
return typeof this.meta.dns_provider !== 'undefined' && this.meta.dns_provider != '' ? this.meta.dns_provider : null;
},
getDnsProviderCredentials: function () {
return typeof this.meta.dns_provider_credentials !== 'undefined' ? this.meta.dns_provider_credentials : '';
},
getPropagationSeconds: function () {
return typeof this.meta.propagation_seconds !== 'undefined' ? this.meta.propagation_seconds : '';
},
dns_plugins: dns_providers,
},
onRender: function () {
let view = this;
// Certificates
this.ui.le_error_info.hide();
this.ui.dns_challenge_content.hide();
this.ui.credentials_file_content.hide();
this.ui.letsencrypt.hide();
this.ui.certificate_select.selectize({
valueField: 'id',
labelField: 'nice_name',
searchField: ['nice_name', 'domain_names'],
create: false,
preload: true,
allowEmptyOption: true,
render: {
option: function (item) {
item.i18n = App.i18n;
item.formatDbDate = Helpers.formatDbDate;
return certListItemTemplate(item);
}
},
load: function (query, callback) {
App.Api.Nginx.Certificates.getAll()
.then(rows => {
callback(rows);
})
.catch(err => {
console.error(err);
callback();
});
},
onLoad: function () {
view.ui.certificate_select[0].selectize.setValue(view.model.get('certificate_id'));
}
});
},
initialize: function (options) {

View File

@@ -16,10 +16,7 @@
</td>
<td>
<div>
<% if (certificate) { %>
<span class="tag"><%- i18n('streams', 'tcp+ssl') %></span>
<% }
else if (tcp_forwarding) { %>
<% if (tcp_forwarding) { %>
<span class="tag"><%- i18n('streams', 'tcp') %></span>
<% }
if (udp_forwarding) { %>
@@ -27,9 +24,6 @@
<% } %>
</div>
</td>
<td>
<div><%- certificate && certificate_id ? i18n('ssl', certificate.provider) : i18n('all-hosts', 'none') %></div>
</td>
<td>
<%
var o = isOnline();

View File

@@ -3,7 +3,6 @@
<th><%- i18n('streams', 'incoming-port') %></th>
<th><%- i18n('str', 'destination') %></th>
<th><%- i18n('streams', 'protocol') %></th>
<th><%- i18n('str', 'ssl') %></th>
<th><%- i18n('str', 'status') %></th>
<% if (canManage) { %>
<th>&nbsp;</th>

View File

@@ -88,7 +88,7 @@ module.exports = Mn.View.extend({
onRender: function () {
let view = this;
view.fetch(['owner', 'certificate'])
view.fetch(['owner'])
.then(response => {
if (!view.isDestroyed()) {
if (response && response.length) {

View File

@@ -60,7 +60,7 @@
},
"footer": {
"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>"
},
"dashboard": {
@@ -179,9 +179,7 @@
"delete-confirm": "Are you sure you want to delete this Stream?",
"help-title": "What is a Stream?",
"help-content": "A relatively new feature for Nginx, a Stream will serve to forward TCP/UDP traffic directly to another computer on the network.\nIf you're running game servers, FTP or SSH servers this can come in handy.",
"search": "Search Incoming Port…",
"ssl-certificate": "SSL Certificate for TCP Forwarding",
"tcp+ssl": "TCP+SSL"
"search": "Search Incoming Port…"
},
"certificates": {
"title": "SSL Certificates",
@@ -208,10 +206,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.",
"download": "Download",
"renew-title": "Renew Let's Encrypt Certificate",
"search": "Search Certificate…",
"in-use" : "In use",
"inactive": "Inactive",
"active-domain_names": "Active domain names"
"search": "Search Certificate…"
},
"access-lists": {
"title": "Access Lists",
@@ -297,5 +292,277 @@
"default-site-html": "Custom Page",
"default-site-redirect": "Redirect"
}
},
"pt": {
"str": {
"email-address": "Endereço de e-mail",
"username": "Nome do usuário",
"password": "Senha",
"sign-in": "Entrar",
"sign-out": "Sair",
"try-again": "Tente novamente",
"name": "Nome",
"email": "O email",
"roles": "Papéis",
"created-on": "Data de criação}",
"save": "Salve ",
"cancel": "Cancelar",
"close": "Fechar",
"enable": "Permitir",
"disable": "Desativar",
"sure": "Sim eu tenho certeza",
"disabled": "Desabilitada",
"choose-file": "Escolher arquivo",
"source": "Fonte",
"destination": "Destino",
"ssl": "Ssl.",
"access": "Acesso",
"public": "Pública",
"edit": "Editar",
"delete": "Excluir",
"logs": "Histórica",
"status": "Status",
"online": "Conectadas",
"offline": "Desligada",
"unknown": "Desconhecida",
"expires": "Expira",
"value": "Valor",
"please-wait": "Por favor, espere...",
"all": "Tudo",
"any": "Alguma"
},
"login": {
"title": "Faça login na sua conta"
},
"main": {
"app": "NGINX Proxy Manager.",
"version": "v {version}",
"welcome": "Bem-vindo ao NGINX Proxy Manager",
"logged-in": "Você está logado como {nome}",
"unknown-error": "Erro ao carregar coisas.Por favor recarregue o aplicativo.",
"unknown-user": "Usuário desconhecido",
"sign-in-as": "Assine de volta como {nome}"
},
"roles": {
"title": "Papéis",
"admin": "Administradora",
"user": "Helicóptero Apache"
},
"menu": {
"dashboard": "Painel",
"hosts": "Anfitriãs"
},
"footer": {
"fork-me": "Garfo me no github",
"copy": "&cópia de;2021 <a href=\"{url}\" target=\"_blank\"> jc21.com </a>.",
"theme": "Tema por <a href=\" {url}\" target=\"_blank\"> taber </a>"
},
"dashboard": {
"title": "Oi {name}"
},
"all-hosts": {
"empty-subtitle": "{Gerenciar, selecione, True {Por que você não cria um?} Outros {e você não tem permissão para criar um.}}",
"details": "Detalhes",
"enable-ssl": "Ativar SSL.",
"force-ssl": "Forçar SSL.",
"http2-support": "Suporte HTTP / 2",
"domain-names": "Nomes de domínio",
"cert-provider": "Provedor de certificados",
"block-exploits": "Bloquear explorações comuns",
"caching-enabled": "Ativos de cache",
"ssl-certificate": "Certificado SSL.",
"none": "Nenhum",
"new-cert": "Solicite um novo certificado SSL",
"with-le": "com vamos criptografar",
"no-ssl": "Este host não usará HTTPS",
"advanced": "Avançada",
"advanced-warning": "Digite sua configuração personalizada do Nginx aqui por sua conta e risco!",
"advanced-config": "Configuração personalizada do NGINX.",
"hsts-enabled": "HSTs habilitado",
"hsts-subdomains": "Subdomínios do HSTS.",
"locations": "Locais personalizados"
},
"locations": {
"new_location": "Adicionar local",
"path": "/caminho",
"location_label": "Definir localização",
"delete": "Excluir"
},
"ssl": {
"letsencrypt": "Vamos criptografar",
"other": "Personalizada",
"none": "Apenas http",
"letsencrypt-email": "Endereço de e-mail para vamos criptografar",
"letsencrypt-agree": "Eu concordo com o <a href=\" {url}\" target=\"_blank\"> Vamos criptografar os Termos de Serviço </a>",
"delete-ssl": "Os certificados SSL anexados não serão removidos, eles precisarão ser removidos manualmente.",
"hosts-warning": "Esses domínios já devem estar configurados para apontar para esta instalação",
"no-wildcard-without-dns": "Não é possível solicitar Vamos criptografar o certificado para domínios curinga quando não estiver usando o DNS Challenge",
"dns-challenge": "Use um Desafio DNS",
"certbot-warning": "Esta seção requer algum conhecimento sobre o Certbot e seus plugins DNS.Por favor, consulte a respectiva documentação dos plugins.",
"dns-provider": "Provedor DNS.",
"please-choose": "Por favor escolha...",
"credentials-file-content": "Conteúdo do arquivo de credenciais",
"credentials-file-content-info": "Este plugin requer um arquivo de configuração contendo um token de API ou outras credenciais ao seu provedor",
"stored-as-plaintext-info": "Esses dados serão armazenados como texto simples no banco de dados e em um arquivo!",
"propagation-seconds": "Segundos de propagação",
"propagation-seconds-info": "Deixe vazio para usar o valor padrão dos plugins.Número de segundos para esperar pela propagação DNS.",
"processing-info": "Processamento ... Isso pode demorar alguns minutos.",
"passphrase-protection-support-info": "Os arquivos-chave protegidos com uma frase secreta não são suportados."
},
"proxy-hosts": {
"title": "Anfitriões proxy.",
"empty": "Não há hospedeiras proxy",
"add": "Adicionar anfitrião proxy.",
"form-title": "{ID, selecione, indefinido {novo} outro {editar}} host proxy",
"forward-scheme": "Esquema",
"forward-host": "Encaminhar HostName / IP",
"forward-port": "Port",
"delete": "Excluir host proxy.",
"delete-confirm": "Tem certeza de que deseja excluir o host proxy para: <strong> {domínios} </ strong>?",
"help-title": "O que é um anfitrião proxy?",
"help-content": "Um host proxy é o endpoint recebido para um serviço da Web que você deseja encaminhar.\nEle fornece rescisão SSL opcional para o seu serviço que talvez não tenha suporte a SSL embutido.\nOs hosts de proxy são o uso mais comum para o NGINX Proxy Manager.",
"access-list": "Lista de Acesso",
"allow-websocket-upgrade": "Suporte WebSockets.",
"ignore-invalid-upstream-ssl": "Ignorar SSL inválido.",
"custom-forward-host-help": "Adicione um caminho para encaminhamento de subpasta.\nExemplo: 203.0.113.25/PATH."
},
"redirection-hosts": {
"title": "Anfitriões de redirecionamento.",
"empty": "Não há anfitriões de redirecionamento",
"add": "Adicionar anfitrião de redirecionamento",
"form-title": "{ID, selecione, indefinido {novo} outro {editar}} redirecionamento host",
"forward-scheme": "Esquema",
"forward-http-status-code": "Código HTTP.",
"forward-domain": "Domínio para a frente.",
"preserve-path": "Preservar o caminho",
"delete": "Excluir host proxy.",
"delete-confirm": "Tem certeza de que deseja excluir o host de redirecionamento para: <strong> {domínios} </ strong>?",
"help-title": "O que é um host de redirecionamento?",
"help-content": "Um host de redirecionamento irá redirecionar solicitações do domínio recebido e empurrar o visualizador para outro domínio.\nO motivo mais comum para usar este tipo de host é quando o seu site muda domínios, mas você ainda tem mecanismo de pesquisa ou links referenciadores apontando para o antigo domínio."
},
"dead-hosts": {
"title": "404 anfitriões",
"empty": "Não há 404 hosts",
"add": "Adicionar 404 anfitrião",
"form-title": "{ID, selecione, indefinido {novo} outro {editar}} 404 host",
"delete": "Excluir 404 host",
"delete-confirm": "Tem certeza de que deseja excluir este host 404?",
"help-title": "O que é um hospedeiro 404?",
"help-content": "Um host 404 é simplesmente uma configuração de host que mostra uma página 404.\nIsso pode ser útil quando seu domínio está listado em mecanismos de pesquisa e você deseja fornecer uma página de erro mais agradável ou especificamente para informar os indexadores de pesquisa que as páginas de domínio não existem mais.\nOutro benefício de ter esse host é rastrear os logs para atingir e visualizar os referenciadores."
},
"streams": {
"title": "Riachos.",
"empty": "Não há fluxos",
"add": "Adicionar stream.",
"form-title": "{ID, selecione, indefinido {novo} outro {editar}} stream",
"incoming-port": "Porta de entrada",
"forwarding-host": "Anfitrião para frente.",
"forwarding-port": "Port",
"tcp-forwarding": "Encaminhamento de tcp.",
"udp-forwarding": "Encaminhamento UDP.",
"forward-type-error": "Pelo menos um tipo de protocolo deve ser ativado",
"protocol": "Protocolo",
"tcp": "Tcp.",
"udp": "UDP.",
"delete": "Excluir fluxo",
"delete-confirm": "Tem certeza de que deseja excluir este fluxo?",
"help-title": "O que é um fluxo?",
"help-content": "Um recurso relativamente novo para o NginX, um fluxo servirá para encaminhar o tráfego TCP / UDP diretamente para outro computador na rede.\nSe você estiver executando servidores de jogos, os servidores FTP ou SSH, isso pode ser útil."
},
"certificates": {
"title": "Certificados SSL.",
"empty": "Não há certificados SSL",
"add": "Adicionar certificado SSL.",
"form-title": "Adicionar {provedor, selecione, Letsencrypt {Vamos criptografar} Outros {Custom}} Certificado",
"delete": "Exclua o certificado SSL.",
"delete-confirm": "Tem certeza de que deseja excluir este certificado SSL?Algum hosts usando ele precisará ser atualizado mais tarde.",
"help-title": "Certificados SSL.",
"help-content": "Certificados SSL (conhecidos corretamente como certificados TLS) são um formulário de chave de criptografia que permite que seu site seja criptografado para o usuário final.\nO NPM usa um serviço chamado Vamos criptografar para emitir certificados SSL gratuitamente.\nSe você tiver algum tipo de informação pessoal, senhas ou dados confidenciais por trás da NPM, é provavelmente uma boa ideia usar um certificado.\nO NPM também suporta a autenticação DNS para se você não estiver executando seu site voltado para a Internet, ou se você quiser um certificado curinga.",
"other-certificate": "Certificado",
"other-certificate-key": "Certificado Key.",
"other-intermediate-certificate": "Certificado Intermediário",
"force-renew": "Renovar agora",
"download": "Download",
"renew-title": "Renew Let'Sencrypt Certificado"
},
"access-lists": {
"title": "Listas de acesso",
"empty": "Não há listas de acesso",
"add": "Adicionar lista de acesso",
"form-title": "{ID, selecione, indefinido {novo} outra {editar}} lista de acesso",
"delete": "Excluir lista de acesso",
"delete-confirm": "Tem certeza de que deseja excluir esta lista de acesso?",
"public": "Publicamente acessível",
"public-sub": "Sem restrições de acesso",
"help-title": "O que é uma lista de acesso?",
"help-content": "As listas de acesso fornecem uma lista negra ou whitelist de endereços IP específicos do cliente, juntamente com a autenticação para os hosts de proxy via autenticação básica HTTP.\nVocê pode configurar várias regras de cliente, nomes de usuários e senhas para uma única lista de acesso e, em seguida, aplicar isso a um host de proxy.\nIsso é mais útil para serviços da Web encaminhados que não possuem mecanismos de autenticação incorporados ou que você deseja proteger do acesso por clientes desconhecidos.",
"item-count": "{Contagem} {Contagem, selecione, 1 {user} Other {Users}}",
"client-count": "{Contagem} {Contagem, Selecione, 1 {Regra} Outras {regras}}",
"proxy-host-count": "{Contagem} {Contagem, Select, 1 {proxy host} Outros {proxy hosts}}",
"delete-has-hosts": "Esta lista de acesso está associada a hosts de proxy {Contagem}.Eles se tornarão disponíveis publicamente após a exclusão.",
"details": "Detalhes",
"authorization": "Autorização",
"access": "Acesso",
"satisfy": "Satisfazer",
"satisfy-any": "Satisfazer qualquer",
"pass-auth": "Passe autenticação para hospedar",
"access-add": "Adicionar",
"auth-add": "Adicionar"
},
"users": {
"title": "Comercial",
"default_error": "O endereço de e-mail padrão deve ser alterado",
"add": "Adicionar usuário",
"nickname": "Apelido",
"full-name": "Nome completo",
"edit-details": "Editar Detalhes",
"change-password": "Mudar senha",
"edit-permissions": "Editar permissões",
"sign-in-as": "Faça login como usuário",
"form-title": "{ID, selecione, indefinido {novo} outro {editar}} usuário",
"delete": "Excluir {nome, selecione, indefinido {user} Outro {{name}}}",
"delete-confirm": "Tem certeza de que deseja excluir <strong> {name} </ strong>?",
"password-title": "Alterar senha {self, selecione, false {para {name}} outro {}}",
"current-password": "Senha atual",
"new-password": "Nova Senha",
"confirm-password": "Confirme a Senha",
"permissions-title": "Permissões para {NAME}",
"admin-perms": "Este usuário é um administrador e alguns itens não podem ser alterados",
"perms-visibility": "Visibilidade do item",
"perms-visibility-user": "Itens criados apenas",
"perms-visibility-all": "Todos os itens",
"perm-manage": "Gerenciar",
"perm-view": "Visualizar apenas",
"perm-hidden": "Escondida"
},
"audit-log": {
"title": "Log de auditoria",
"empty": "Não há logs.",
"empty-subtitle": "Assim que você ou outro usuário muda alguma coisa, a história desses eventos aparecerá aqui.",
"proxy-host": "Anfitrião proxy.",
"redirection-host": "Anfitrião de redirecionamento",
"dead-host": "404 anfitrião",
"stream": "Stream",
"user": "Do utilizador",
"certificate": "Certificado",
"access-list": "Lista de Acesso",
"created": "Criado {name}",
"updated": "Atualizado {NAME}",
"deleted": "Excluído {NAME}",
"enabled": "Ativado {NAME}",
"disabled": "Desativado {name}",
"renewed": "Renovado {name}",
"meta-title": "Detalhes do evento",
"view-meta": "Ver detalhes",
"date": "Encontro"
},
"settings": {
"title": "Definições",
"default-site": "Site padrão",
"default-site-congratulations": "Parabéns Page.",
"default-site-404": "404 Página",
"default-site-html": "Página personalizada",
"default-site-redirect": "Redirecionar."
}
}
}

View File

@@ -15,11 +15,8 @@ const model = Backbone.Model.extend({
udp_forwarding: false,
enabled: true,
meta: {},
certificate_id: 0,
domain_names: [],
// The following are expansions:
owner: null,
certificate: null
owner: null
};
}
});

View File

@@ -167,5 +167,4 @@ $pink: #f66d9b;
textarea.form-control.text-monospace {
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"
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:
version "6.26.0"
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"
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:
version "3.1.0"
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"
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"
resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==
@@ -2276,17 +2243,7 @@ create-hash@^1.1.0, create-hash@^1.2.0:
ripemd160 "^2.0.1"
sha.js "^2.4.0"
create-hash@~1.1.3:
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:
create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7:
version "1.1.7"
resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff"
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"
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:
version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
@@ -2631,15 +2579,6 @@ dot-prop@^5.2.0:
dependencies:
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:
version "0.1.4"
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==
elliptic@^6.5.3, elliptic@^6.5.4:
version "6.6.1"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06"
integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==
version "6.6.0"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.0.tgz#5919ec723286c1edf28685aa89261d4761afa210"
integrity sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==
dependencies:
bn.js "^4.11.9"
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.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:
version "1.2.1"
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"
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:
version "1.0.2"
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"
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:
version "1.0.1"
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"
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:
version "4.0.1"
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"
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:
version "9.6.0"
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"
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:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
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:
version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
@@ -3633,13 +3495,6 @@ has@^1.0.3:
dependencies:
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:
version "3.1.0"
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"
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:
version "1.2.0"
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"
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:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
@@ -4176,13 +4019,6 @@ is-symbol@^1.0.2:
dependencies:
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:
version "1.0.0"
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"
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:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@@ -4605,11 +4436,6 @@ marionette.templatecache@^1.0.0:
dependencies:
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:
version "1.3.5"
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==
pbkdf2@^3.0.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.3.tgz#8be674d591d65658113424592a95d1517318dd4b"
integrity sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==
version "3.1.1"
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94"
integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==
dependencies:
create-hash "~1.1.3"
create-hmac "^1.1.7"
ripemd160 "=2.0.1"
safe-buffer "^5.2.1"
sha.js "^2.4.11"
to-buffer "^1.2.0"
create-hash "^1.1.2"
create-hmac "^1.1.4"
ripemd160 "^2.0.1"
safe-buffer "^5.0.1"
sha.js "^2.4.8"
picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1:
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"
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:
version "2.0.0"
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:
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:
version "2.0.2"
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"
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:
version "2.0.1"
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"
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"
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
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"
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:
version "1.0.3"
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"
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:
version "3.1.5"
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"
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:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"

View File

@@ -10,9 +10,9 @@
"active24": {
"name": "Active24",
"package_name": "certbot-dns-active24",
"version": "~=2.0.0",
"version": "~=1.5.1",
"dependencies": "",
"credentials": "dns_active24_api_key = <identifier>\ndns_active24_secret = <secret>",
"credentials": "dns_active24_token=\"TOKEN\"",
"full_plugin_name": "dns-active24"
},
"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",
"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": {
"name":"Beget",
"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",
"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": {
"name": "Cloudflare",
"package_name": "certbot-dns-cloudflare",
"version": "=={{certbot-version}}",
"dependencies": "acme=={{certbot-version}}",
"dependencies": "cloudflare==2.19.* acme=={{certbot-version}}",
"credentials": "# Cloudflare API token\ndns_cloudflare_api_token=0123456789abcdef0123456789abcdef01234567",
"full_plugin_name": "dns-cloudflare"
},
@@ -106,19 +90,11 @@
"cpanel": {
"name": "cPanel",
"package_name": "certbot-dns-cpanel",
"version": "~=0.4.0",
"version": "~=0.2.2",
"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"
},
"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": {
"name": "deSEC",
"package_name": "certbot-dns-desec",
@@ -185,11 +161,11 @@
},
"domainoffensive": {
"name": "DomainOffensive (do.de)",
"package_name": "certbot-dns-domainoffensive",
"version": "~=2.0.0",
"package_name": "certbot-dns-do",
"version": "~=0.31.0",
"dependencies": "",
"credentials": "dns_domainoffensive_api_token = YOUR_DO_DE_AUTH_TOKEN",
"full_plugin_name": "dns-domainoffensive"
"credentials": "dns_do_api_token = YOUR_DO_DE_AUTH_TOKEN",
"full_plugin_name": "dns-do"
},
"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",
"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": {
"name": "FreeDNS",
"package_name": "certbot-dns-freedns",
@@ -241,8 +209,8 @@
},
"gandi": {
"name": "Gandi Live DNS",
"package_name": "certbot-dns-gandi",
"version": "~=1.6.1",
"package_name": "certbot_plugin_gandi",
"version": "~=1.5.0",
"dependencies": "",
"credentials": "# Gandi personal access token\ndns_gandi_token=PERSONAL_ACCESS_TOKEN",
"full_plugin_name": "dns-gandi"
@@ -396,7 +364,7 @@
"package_name": "certbot-dns-mijn-host",
"version": "~=0.0.4",
"dependencies": "",
"credentials": "dns_mijn_host_api_key=0123456789abcdef0123456789abcdef",
"credentials": "dns-mijn-host-credentials = /etc/letsencrypt/mijnhost-credentials.ini",
"full_plugin_name": "dns-mijn-host"
},
"namecheap": {
@@ -415,14 +383,6 @@
"credentials": "dns_netcup_customer_id = 123456\ndns_netcup_api_key = 0123456789abcdef0123456789abcdef01234567\ndns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123",
"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": {
"name": "Njalla",
"package_name": "certbot-dns-njalla",
@@ -511,29 +471,13 @@
"credentials": "[default]\naws_access_key_id=AKIAIOSFODNN7EXAMPLE\naws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"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": {
"name": "Strato",
"package_name": "certbot-dns-strato",
"version": "~=0.2.2",
"version": "~=0.2.1",
"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\"",
"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": {
"name": "Timeweb Cloud",
@@ -590,13 +534,5 @@
"dependencies": "",
"credentials": "edgedns_client_secret = as3d1asd5d1a32sdfsdfs2d1asd5=\nedgedns_host = sdflskjdf-dfsdfsdf-sdfsdfsdf.luna.akamaiapis.net\nedgedns_access_token = kjdsi3-34rfsdfsdf-234234fsdfsdf\nedgedns_client_token = dkfjdf-342fsdfsd-23fsdfsdfsdf",
"full_plugin_name": "edgedns"
},
"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
ENV FORCE_COLOR=0
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
RUN yarn install && yarn cache clean
ENTRYPOINT []

View File

@@ -10,7 +10,7 @@ describe('Certificates endpoints', () => {
});
});
it('Validate custom certificate', () => {
it('Validate custom certificate', function() {
cy.task('backendApiPostFiles', {
token: token,
path: '/api/nginx/certificates/validate',
@@ -25,7 +25,7 @@ describe('Certificates endpoints', () => {
});
});
it('Custom certificate lifecycle', () => {
it('Custom certificate lifecycle', function() {
// Create custom cert
cy.task('backendApiPost', {
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', {
token: token,
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', {
token: token,
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', {
token: token,
path: '/api/nginx/certificates',

View File

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

View File

@@ -1,12 +1,12 @@
/// <reference types="cypress" />
describe('LDAP with Authentik', () => {
let _token;
let token;
if (Cypress.env('skipStackCheck') === 'true' || Cypress.env('stack') === 'postgres') {
before(() => {
cy.getToken().then((tok) => {
_token = tok;
token = tok;
// cy.task('backendApiPut', {
// 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', {
// token: token,
// path: '/api/auth',

View File

@@ -1,12 +1,12 @@
/// <reference types="cypress" />
describe('OAuth with Authentik', () => {
let _token;
let token;
if (Cypress.env('skipStackCheck') === 'true' || Cypress.env('stack') === 'postgres') {
before(() => {
cy.getToken().then((tok) => {
_token = tok;
token = tok;
// cy.task('backendApiPut', {
// 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', {
// path: '/oauth/login?redirect_base=' + encodeURI(Cypress.config('baseUrl')),
// }).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', {
token: token,
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', {
token: token,
path: '/api/settings',
@@ -19,7 +19,7 @@ describe('Settings endpoints', () => {
});
});
it('Get default-site setting', () => {
it('Get default-site setting', function() {
cy.task('backendApiGet', {
token: token,
path: '/api/settings/default-site',
@@ -30,7 +30,7 @@ describe('Settings endpoints', () => {
});
});
it('Default Site congratulations', () => {
it('Default Site congratulations', function() {
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
@@ -46,7 +46,7 @@ describe('Settings endpoints', () => {
});
});
it('Default Site 404', () => {
it('Default Site 404', function() {
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
@@ -62,7 +62,7 @@ describe('Settings endpoints', () => {
});
});
it('Default Site 444', () => {
it('Default Site 444', function() {
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
@@ -78,7 +78,7 @@ describe('Settings endpoints', () => {
});
});
it('Default Site redirect', () => {
it('Default Site redirect', function() {
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
@@ -100,7 +100,7 @@ describe('Settings endpoints', () => {
});
});
it('Default Site html', () => {
it('Default Site html', function() {
cy.task('backendApiPut', {
token: token,
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', {
token: token,
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', {
token: token,
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', {
token: token,
path: '/api/users/me',

View File

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

File diff suppressed because it is too large Load Diff