Skip to content

[pull] develop from NginxProxyManager:develop #14

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 4 commits into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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.1
2.12.2
38 changes: 38 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,44 @@ pipeline {
}
}
}
stage('Test Postgres') {
environment {
COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}_postgres"
COMPOSE_FILE = 'docker/docker-compose.ci.yml:docker/docker-compose.ci.postgres.yml'
}
when {
not {
equals expected: 'UNSTABLE', actual: currentBuild.result
}
}
steps {
sh 'rm -rf ./test/results/junit/*'
sh './scripts/ci/fulltest-cypress'
}
post {
always {
// Dumps to analyze later
sh 'mkdir -p debug/postgres'
sh 'docker logs $(docker-compose ps --all -q fullstack) > debug/postgres/docker_fullstack.log 2>&1'
sh 'docker logs $(docker-compose ps --all -q stepca) > debug/postgres/docker_stepca.log 2>&1'
sh 'docker logs $(docker-compose ps --all -q pdns) > debug/postgres/docker_pdns.log 2>&1'
sh 'docker logs $(docker-compose ps --all -q pdns-db) > debug/postgres/docker_pdns-db.log 2>&1'
sh 'docker logs $(docker-compose ps --all -q dnsrouter) > debug/postgres/docker_dnsrouter.log 2>&1'
sh 'docker logs $(docker-compose ps --all -q db-postgres) > debug/postgres/docker_db-postgres.log 2>&1'
sh 'docker logs $(docker-compose ps --all -q authentik) > debug/postgres/docker_authentik.log 2>&1'
sh 'docker logs $(docker-compose ps --all -q authentik-redis) > debug/postgres/docker_authentik-redis.log 2>&1'
sh 'docker logs $(docker-compose ps --all -q authentik-ldap) > debug/postgres/docker_authentik-ldap.log 2>&1'

junit 'test/results/junit/*'
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
}
unstable {
dir(path: 'testing/results') {
archiveArtifacts(allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml')
}
}
}
}
stage('MultiArch Build') {
when {
not {
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.1-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>
Expand Down
14 changes: 10 additions & 4 deletions backend/internal/access-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const internalAccessList = {

return internalAccessList.build(row)
.then(() => {
if (row.proxy_host_count) {
if (parseInt(row.proxy_host_count, 10)) {
return internalNginx.bulkGenerateConfigs('proxy_host', row.proxy_hosts);
}
})
Expand Down Expand Up @@ -223,7 +223,7 @@ const internalAccessList = {
.then((row) => {
return internalAccessList.build(row)
.then(() => {
if (row.proxy_host_count) {
if (parseInt(row.proxy_host_count, 10)) {
return internalNginx.bulkGenerateConfigs('proxy_host', row.proxy_hosts);
}
}).then(internalNginx.reload)
Expand Down Expand Up @@ -252,7 +252,10 @@ const internalAccessList = {
let query = accessListModel
.query()
.select('access_list.*', accessListModel.raw('COUNT(proxy_host.id) as proxy_host_count'))
.joinRaw('LEFT JOIN `proxy_host` ON `proxy_host`.`access_list_id` = `access_list`.`id` AND `proxy_host`.`is_deleted` = 0')
.leftJoin('proxy_host', function() {
this.on('proxy_host.access_list_id', '=', 'access_list.id')
.andOn('proxy_host.is_deleted', '=', 0);
})
.where('access_list.is_deleted', 0)
.andWhere('access_list.id', data.id)
.allowGraph('[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]')
Expand Down Expand Up @@ -373,7 +376,10 @@ const internalAccessList = {
let query = accessListModel
.query()
.select('access_list.*', accessListModel.raw('COUNT(proxy_host.id) as proxy_host_count'))
.joinRaw('LEFT JOIN `proxy_host` ON `proxy_host`.`access_list_id` = `access_list`.`id` AND `proxy_host`.`is_deleted` = 0')
.leftJoin('proxy_host', function() {
this.on('proxy_host.access_list_id', '=', 'access_list.id')
.andOn('proxy_host.is_deleted', '=', 0);
})
.where('access_list.is_deleted', 0)
.groupBy('access_list.id')
.allowGraph('[owner,items,clients]')
Expand Down
9 changes: 5 additions & 4 deletions backend/internal/audit-log.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const error = require('../lib/error');
const auditLogModel = require('../models/audit-log');
const error = require('../lib/error');
const auditLogModel = require('../models/audit-log');
const {castJsonIfNeed} = require('../lib/helpers');

const internalAuditLog = {

Expand All @@ -22,9 +23,9 @@ const internalAuditLog = {
.allowGraph('[user]');

// Query is used for searching
if (typeof search_query === 'string') {
if (typeof search_query === 'string' && search_query.length > 0) {
query.where(function () {
this.where('meta', 'like', '%' + search_query + '%');
this.where(castJsonIfNeed('meta'), 'like', '%' + search_query + '%');
});
}

Expand Down
7 changes: 4 additions & 3 deletions backend/internal/dead-host.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const internalHost = require('./host');
const internalNginx = require('./nginx');
const internalAuditLog = require('./audit-log');
const internalCertificate = require('./certificate');
const {castJsonIfNeed} = require('../lib/helpers');

function omissions () {
return ['is_deleted'];
Expand Down Expand Up @@ -409,16 +410,16 @@ const internalDeadHost = {
.where('is_deleted', 0)
.groupBy('id')
.allowGraph('[owner,certificate]')
.orderBy('domain_names', 'ASC');
.orderBy(castJsonIfNeed('domain_names'), 'ASC');

if (access_data.permission_visibility !== 'all') {
query.andWhere('owner_user_id', access.token.getUserId(1));
}

// Query is used for searching
if (typeof search_query === 'string') {
if (typeof search_query === 'string' && search_query.length > 0) {
query.where(function () {
this.where('domain_names', 'like', '%' + search_query + '%');
this.where(castJsonIfNeed('domain_names'), 'like', '%' + search_query + '%');
});
}

Expand Down
13 changes: 7 additions & 6 deletions backend/internal/host.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const _ = require('lodash');
const proxyHostModel = require('../models/proxy_host');
const redirectionHostModel = require('../models/redirection_host');
const deadHostModel = require('../models/dead_host');
const {castJsonIfNeed} = require('../lib/helpers');

const internalHost = {

Expand All @@ -17,7 +18,7 @@ const internalHost = {
cleanSslHstsData: function (data, existing_data) {
existing_data = existing_data === undefined ? {} : existing_data;

let combined_data = _.assign({}, existing_data, data);
const combined_data = _.assign({}, existing_data, data);

if (!combined_data.certificate_id) {
combined_data.ssl_forced = false;
Expand Down Expand Up @@ -73,7 +74,7 @@ const internalHost = {
* @returns {Promise}
*/
getHostsWithDomains: function (domain_names) {
let promises = [
const promises = [
proxyHostModel
.query()
.where('is_deleted', 0),
Expand Down Expand Up @@ -125,19 +126,19 @@ const internalHost = {
* @returns {Promise}
*/
isHostnameTaken: function (hostname, ignore_type, ignore_id) {
let promises = [
const promises = [
proxyHostModel
.query()
.where('is_deleted', 0)
.andWhere('domain_names', 'like', '%' + hostname + '%'),
.andWhere(castJsonIfNeed('domain_names'), 'like', '%' + hostname + '%'),
redirectionHostModel
.query()
.where('is_deleted', 0)
.andWhere('domain_names', 'like', '%' + hostname + '%'),
.andWhere(castJsonIfNeed('domain_names'), 'like', '%' + hostname + '%'),
deadHostModel
.query()
.where('is_deleted', 0)
.andWhere('domain_names', 'like', '%' + hostname + '%')
.andWhere(castJsonIfNeed('domain_names'), 'like', '%' + hostname + '%')
];

return Promise.all(promises)
Expand Down
7 changes: 4 additions & 3 deletions backend/internal/proxy-host.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const internalHost = require('./host');
const internalNginx = require('./nginx');
const internalAuditLog = require('./audit-log');
const internalCertificate = require('./certificate');
const {castJsonIfNeed} = require('../lib/helpers');

function omissions () {
return ['is_deleted', 'owner.is_deleted'];
Expand Down Expand Up @@ -416,16 +417,16 @@ const internalProxyHost = {
.where('is_deleted', 0)
.groupBy('id')
.allowGraph('[owner,access_list,certificate]')
.orderBy('domain_names', 'ASC');
.orderBy(castJsonIfNeed('domain_names'), 'ASC');

if (access_data.permission_visibility !== 'all') {
query.andWhere('owner_user_id', access.token.getUserId(1));
}

// Query is used for searching
if (typeof search_query === 'string') {
if (typeof search_query === 'string' && search_query.length > 0) {
query.where(function () {
this.where('domain_names', 'like', '%' + search_query + '%');
this.where(castJsonIfNeed('domain_names'), 'like', `%${search_query}%`);
});
}

Expand Down
7 changes: 4 additions & 3 deletions backend/internal/redirection-host.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const internalHost = require('./host');
const internalNginx = require('./nginx');
const internalAuditLog = require('./audit-log');
const internalCertificate = require('./certificate');
const {castJsonIfNeed} = require('../lib/helpers');

function omissions () {
return ['is_deleted'];
Expand Down Expand Up @@ -409,16 +410,16 @@ const internalRedirectionHost = {
.where('is_deleted', 0)
.groupBy('id')
.allowGraph('[owner,certificate]')
.orderBy('domain_names', 'ASC');
.orderBy(castJsonIfNeed('domain_names'), 'ASC');

if (access_data.permission_visibility !== 'all') {
query.andWhere('owner_user_id', access.token.getUserId(1));
}

// Query is used for searching
if (typeof search_query === 'string') {
if (typeof search_query === 'string' && search_query.length > 0) {
query.where(function () {
this.where('domain_names', 'like', '%' + search_query + '%');
this.where(castJsonIfNeed('domain_names'), 'like', `%${search_query}%`);
});
}

Expand Down
13 changes: 7 additions & 6 deletions backend/internal/stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const utils = require('../lib/utils');
const streamModel = require('../models/stream');
const internalNginx = require('./nginx');
const internalAuditLog = require('./audit-log');
const {castJsonIfNeed} = require('../lib/helpers');

function omissions () {
return ['is_deleted'];
Expand Down Expand Up @@ -293,21 +294,21 @@ const internalStream = {
getAll: (access, expand, search_query) => {
return access.can('streams:list')
.then((access_data) => {
let query = streamModel
const query = streamModel
.query()
.where('is_deleted', 0)
.groupBy('id')
.allowGraph('[owner]')
.orderBy('incoming_port', 'ASC');
.orderByRaw('CAST(incoming_port AS INTEGER) ASC');

if (access_data.permission_visibility !== 'all') {
query.andWhere('owner_user_id', access.token.getUserId(1));
}

// Query is used for searching
if (typeof search_query === 'string') {
if (typeof search_query === 'string' && search_query.length > 0) {
query.where(function () {
this.where('incoming_port', 'like', '%' + search_query + '%');
this.where(castJsonIfNeed('incoming_port'), 'like', `%${search_query}%`);
});
}

Expand All @@ -327,9 +328,9 @@ const internalStream = {
* @returns {Promise}
*/
getCount: (user_id, visibility) => {
let query = streamModel
const query = streamModel
.query()
.count('id as count')
.count('id AS count')
.where('is_deleted', 0);

if (visibility !== 'all') {
Expand Down
53 changes: 48 additions & 5 deletions backend/lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ const fs = require('fs');
const NodeRSA = require('node-rsa');
const logger = require('../logger').global;

const keysFile = '/data/keys.json';
const keysFile = '/data/keys.json';
const mysqlEngine = 'mysql2';
const postgresEngine = 'pg';
const sqliteClientName = 'sqlite3';

let instance = null;

Expand All @@ -14,7 +17,7 @@ const configure = () => {
let configData;
try {
configData = require(filename);
} catch (err) {
} catch (_) {
// do nothing
}

Expand All @@ -34,7 +37,7 @@ const configure = () => {
logger.info('Using MySQL configuration');
instance = {
database: {
engine: 'mysql2',
engine: mysqlEngine,
host: envMysqlHost,
port: process.env.DB_MYSQL_PORT || 3306,
user: envMysqlUser,
Expand All @@ -46,13 +49,33 @@ const configure = () => {
return;
}

const envPostgresHost = process.env.DB_POSTGRES_HOST || null;
const envPostgresUser = process.env.DB_POSTGRES_USER || null;
const envPostgresName = process.env.DB_POSTGRES_NAME || null;
if (envPostgresHost && envPostgresUser && envPostgresName) {
// we have enough postgres creds to go with postgres
logger.info('Using Postgres configuration');
instance = {
database: {
engine: postgresEngine,
host: envPostgresHost,
port: process.env.DB_POSTGRES_PORT || 5432,
user: envPostgresUser,
password: process.env.DB_POSTGRES_PASSWORD,
name: envPostgresName,
},
keys: getKeys(),
};
return;
}

const envSqliteFile = process.env.DB_SQLITE_FILE || '/data/database.sqlite';
logger.info(`Using Sqlite: ${envSqliteFile}`);
instance = {
database: {
engine: 'knex-native',
knex: {
client: 'sqlite3',
client: sqliteClientName,
connection: {
filename: envSqliteFile
},
Expand Down Expand Up @@ -143,7 +166,27 @@ module.exports = {
*/
isSqlite: function () {
instance === null && configure();
return instance.database.knex && instance.database.knex.client === 'sqlite3';
return instance.database.knex && instance.database.knex.client === sqliteClientName;
},

/**
* Is this a mysql configuration?
*
* @returns {boolean}
*/
isMysql: function () {
instance === null && configure();
return instance.database.engine === mysqlEngine;
},

/**
* Is this a postgres configuration?
*
* @returns {boolean}
*/
isPostgres: function () {
instance === null && configure();
return instance.database.engine === postgresEngine;
},

/**
Expand Down
Loading