Skip to content

v2.12.3 #4347

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Feb 6, 2025
Merged

v2.12.3 #4347

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
1e32280
Add ZoneEdit certbot plugin
badkeyy Dec 4, 2024
5d087f1
Update DomainOffensive certbot plugin
FabianK3 Dec 15, 2024
356b98b
Add Gcore DNS Provider
GergelyGombai Dec 22, 2024
73110d5
Update Gcore apikey format
GergelyGombai Dec 22, 2024
f1c97c7
fix: add missing group_by clause for access_list get
Dim145 Jan 2, 2025
4de4b65
Merge pull request #4252 from GergelyGombai/develop
jc21 Jan 6, 2025
5a234bb
Fix incorrect test folder in ci results
jc21 Jan 6, 2025
9687e9e
Use previous version of powerdns image, newer version is broken
jc21 Jan 7, 2025
080bd0b
Added status of certificates to the certificate list and show on whic…
badkeyy Dec 4, 2024
aedaaa1
Fix whitespace
badkeyy Jan 10, 2025
59362b7
feat: change htpasswd to openssl
icaksh Jan 12, 2025
6343b39
Add --no-deps
badkeyy Jan 15, 2025
c05f969
Merge branch 'develop' into feature/add-zone-edit-certbot-plugin
badkeyy Jan 15, 2025
bb4ecf8
Bump vite from 5.4.8 to 5.4.14 in /docs
dependabot[bot] Jan 22, 2025
3f3aacd
Merge pull request #4274 from Dim145/develop
jc21 Jan 28, 2025
498109a
Merge pull request #4310 from NginxProxyManager/dependabot/npm_and_ya…
jc21 Jan 28, 2025
ad5936c
Update certbot-dns-plugins.json (mijn-host)
nwagenmakers Feb 1, 2025
57cd2a1
Fix type for token.expires
Sander0542 Feb 3, 2025
3091c21
Add SSL certificate to TCP streams if certificate in database
jbowring Mar 24, 2024
3dbc70f
Add SSL tab to stream UI
jbowring Mar 24, 2024
ee4250d
Add SSL column to streams table UI
jbowring Apr 27, 2024
cd80cc8
Add certificate to streams database model
jbowring Jun 2, 2024
4452f01
Fix whitespace in nginx stream config
jbowring Jul 22, 2024
2657af9
Fix stream update not persisting
jbowring Jul 23, 2024
68a7803
Fix api schema after merging latest changes
jc21 Feb 4, 2025
b4793d3
Adds testssl.sh and mkcert to cypress stack
jc21 Feb 4, 2025
6a60627
Cypress test for Streams
jc21 Feb 4, 2025
c56c95a
Merge pull request #4344 from NginxProxyManager/stream-ssl
jc21 Feb 5, 2025
e1c84a5
Merge pull request #4338 from Sander0542/fix/token-expires-type
jc21 Feb 5, 2025
3a01b2c
Merge pull request #4334 from nwagenmakers/mijn-host-patch
jc21 Feb 5, 2025
0d5d2b1
Merge pull request #4283 from badkeyy/feature/show-active-host-in-cer…
jc21 Feb 5, 2025
dc9d884
Merge pull request #4292 from icaksh/patch-1
jc21 Feb 5, 2025
2a07544
Merge pull request #4235 from FabianK3/update-domainoffensive-certbot…
jc21 Feb 5, 2025
4283677
Merge branch 'develop' into feature/add-zone-edit-certbot-plugin
jc21 Feb 5, 2025
0a9141f
Merge pull request #4208 from badkeyy/feature/add-zone-edit-certbot-p…
jc21 Feb 5, 2025
0a05d8f
Bump version
jc21 Feb 5, 2025
34c703f
Merge branch 'master' into develop
jc21 Feb 5, 2025
c4df89d
Fix dashboard loading loop and freezing the page
jc21 Feb 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.12.2
2.12.3
6 changes: 3 additions & 3 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ pipeline {
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
}
unstable {
dir(path: 'testing/results') {
dir(path: 'test/results') {
archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml')
}
}
Expand Down Expand Up @@ -161,7 +161,7 @@ pipeline {
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
}
unstable {
dir(path: 'testing/results') {
dir(path: 'test/results') {
archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml')
}
}
Expand Down Expand Up @@ -199,7 +199,7 @@ pipeline {
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
}
unstable {
dir(path: 'testing/results') {
dir(path: 'test/results') {
archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml')
}
}
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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.2-green.svg?style=for-the-badge">
<img src="https://img.shields.io/badge/version-2.12.3-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>
Expand Down
10 changes: 8 additions & 2 deletions backend/internal/access-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ const internalAccessList = {
})
.where('access_list.is_deleted', 0)
.andWhere('access_list.id', data.id)
.groupBy('access_list.id')
.allowGraph('[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]')
.first();

Expand Down Expand Up @@ -507,8 +508,13 @@ const internalAccessList = {
if (typeof item.password !== 'undefined' && item.password.length) {
logger.info('Adding: ' + item.username);

utils.execFile('/usr/bin/htpasswd', ['-b', htpasswd_file, item.username, item.password])
.then((/*result*/) => {
utils.execFile('openssl', ['passwd', '-apr1', item.password])
.then((res) => {
try {
fs.appendFileSync(htpasswd_file, item.username + ':' + res + '\n', {encoding: 'utf8'});
} catch (err) {
reject(err);
}
next();
})
.catch((err) => {
Expand Down
6 changes: 6 additions & 0 deletions backend/internal/certificate.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,9 @@ 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') {
Expand Down Expand Up @@ -464,6 +467,9 @@ 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') {
Expand Down
119 changes: 98 additions & 21 deletions backend/internal/stream.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
const _ = require('lodash');
const error = require('../lib/error');
const utils = require('../lib/utils');
const streamModel = require('../models/stream');
const internalNginx = require('./nginx');
const internalAuditLog = require('./audit-log');
const {castJsonIfNeed} = require('../lib/helpers');
const _ = require('lodash');
const error = require('../lib/error');
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'];
return ['is_deleted', 'owner.is_deleted', 'certificate.is_deleted'];
}

const internalStream = {
Expand All @@ -18,6 +20,12 @@ 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
Expand All @@ -27,16 +35,44 @@ 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)
.insertAndFetch(data_no_domains)
.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 internalStream.get(access, {id: row.id, expand: ['owner']});
return row;
});
})
.then((row) => {
Expand All @@ -60,6 +96,12 @@ 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
Expand All @@ -71,16 +113,32 @@ 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, {
Expand All @@ -93,6 +151,17 @@ 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());
});
});
});
},

Expand All @@ -115,7 +184,7 @@ const internalStream = {
.query()
.where('is_deleted', 0)
.andWhere('id', data.id)
.allowGraph('[owner]')
.allowGraph('[owner,certificate]')
.first();

if (access_data.permission_visibility !== 'all') {
Expand All @@ -132,6 +201,7 @@ 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);
Expand Down Expand Up @@ -197,14 +267,14 @@ const internalStream = {
.then(() => {
return internalStream.get(access, {
id: data.id,
expand: ['owner']
expand: ['certificate', 'owner']
});
})
.then((row) => {
if (!row || !row.id) {
throw new error.ItemNotFoundError(data.id);
} else if (row.enabled) {
throw new error.ValidationError('Host is already enabled');
throw new error.ValidationError('Stream is already enabled');
}

row.enabled = 1;
Expand Down Expand Up @@ -250,7 +320,7 @@ const internalStream = {
if (!row || !row.id) {
throw new error.ItemNotFoundError(data.id);
} else if (!row.enabled) {
throw new error.ValidationError('Host is already disabled');
throw new error.ValidationError('Stream is already disabled');
}

row.enabled = 0;
Expand Down Expand Up @@ -298,7 +368,7 @@ const internalStream = {
.query()
.where('is_deleted', 0)
.groupBy('id')
.allowGraph('[owner]')
.allowGraph('[owner,certificate]')
.orderByRaw('CAST(incoming_port AS INTEGER) ASC');

if (access_data.permission_visibility !== 'all') {
Expand All @@ -317,6 +387,13 @@ 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;
});
},

Expand Down
38 changes: 38 additions & 0 deletions backend/migrations/20240427161436_stream_ssl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
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');
});
};
Loading
Loading