From 33562fb2c0358281e589350c1ee95f31c56f7365 Mon Sep 17 00:00:00 2001 From: Dim145 Date: Sat, 19 Oct 2024 02:42:33 +0200 Subject: [PATCH] refactor: adapt many sql queries for postgresql --- backend/internal/access-list.js | 13 +++++++++---- backend/internal/audit-log.js | 7 ++++--- backend/internal/dead-host.js | 5 +++-- backend/internal/host.js | 7 ++++--- backend/internal/proxy-host.js | 5 +++-- backend/internal/redirection-host.js | 5 +++-- backend/internal/stream.js | 3 ++- backend/lib/helpers.js | 20 ++++++++++++++++++-- backend/setup.js | 8 ++++---- 9 files changed, 50 insertions(+), 23 deletions(-) diff --git a/backend/internal/access-list.js b/backend/internal/access-list.js index 72326be6..380db4b4 100644 --- a/backend/internal/access-list.js +++ b/backend/internal/access-list.js @@ -81,7 +81,7 @@ const internalAccessList = { return internalAccessList.build(row) .then(() => { - if (row.proxy_host_count) { + if (parseInt(row.proxy_host_count)) { return internalNginx.bulkGenerateConfigs('proxy_host', row.proxy_hosts); } }) @@ -223,7 +223,7 @@ const internalAccessList = { .then((row) => { return internalAccessList.build(row) .then(() => { - if (row.proxy_host_count) { + if (parseInt(row.proxy_host_count)) { return internalNginx.bulkGenerateConfigs('proxy_host', row.proxy_hosts); } }).then(internalNginx.reload) @@ -252,9 +252,12 @@ 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) + .groupBy('access_list.id') .allowGraph('[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]') .first(); @@ -373,7 +376,9 @@ 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]') diff --git a/backend/internal/audit-log.js b/backend/internal/audit-log.js index cb48261b..b5c6b843 100644 --- a/backend/internal/audit-log.js +++ b/backend/internal/audit-log.js @@ -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 = { @@ -24,7 +25,7 @@ const internalAuditLog = { // Query is used for searching if (typeof search_query === 'string') { query.where(function () { - this.where('meta', 'like', '%' + search_query + '%'); + this.where(castJsonIfNeed('meta'), 'like', '%' + search_query + '%'); }); } diff --git a/backend/internal/dead-host.js b/backend/internal/dead-host.js index e672775e..64ccb819 100644 --- a/backend/internal/dead-host.js +++ b/backend/internal/dead-host.js @@ -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']; @@ -409,7 +410,7 @@ 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)); @@ -418,7 +419,7 @@ const internalDeadHost = { // Query is used for searching if (typeof search_query === 'string') { query.where(function () { - this.where('domain_names', 'like', '%' + search_query + '%'); + this.where(castJsonIfNeed('domain_names'), 'like', '%' + search_query + '%'); }); } diff --git a/backend/internal/host.js b/backend/internal/host.js index 58e1d09a..a3c30218 100644 --- a/backend/internal/host.js +++ b/backend/internal/host.js @@ -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 = { @@ -129,15 +130,15 @@ const internalHost = { 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) diff --git a/backend/internal/proxy-host.js b/backend/internal/proxy-host.js index 61ac8b8c..204a0e46 100644 --- a/backend/internal/proxy-host.js +++ b/backend/internal/proxy-host.js @@ -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']; @@ -416,7 +417,7 @@ 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)); @@ -425,7 +426,7 @@ const internalProxyHost = { // Query is used for searching if (typeof search_query === 'string') { query.where(function () { - this.where('domain_names', 'like', '%' + search_query + '%'); + this.where(castJsonIfNeed('domain_names'), 'like', '%' + search_query + '%'); }); } diff --git a/backend/internal/redirection-host.js b/backend/internal/redirection-host.js index 41ff5b09..a44d7369 100644 --- a/backend/internal/redirection-host.js +++ b/backend/internal/redirection-host.js @@ -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']; @@ -409,7 +410,7 @@ 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)); @@ -418,7 +419,7 @@ const internalRedirectionHost = { // Query is used for searching if (typeof search_query === 'string') { query.where(function () { - this.where('domain_names', 'like', '%' + search_query + '%'); + this.where(castJsonIfNeed('domain_names'), 'like', '%' + search_query + '%'); }); } diff --git a/backend/internal/stream.js b/backend/internal/stream.js index ee88d46f..fe15497a 100644 --- a/backend/internal/stream.js +++ b/backend/internal/stream.js @@ -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']; @@ -307,7 +308,7 @@ const internalStream = { // Query is used for searching if (typeof search_query === 'string') { query.where(function () { - this.where('incoming_port', 'like', '%' + search_query + '%'); + this.where(castJsonIfNeed('incoming_port'), 'like', '%' + search_query + '%'); }); } diff --git a/backend/lib/helpers.js b/backend/lib/helpers.js index f7e98beb..7c6aa915 100644 --- a/backend/lib/helpers.js +++ b/backend/lib/helpers.js @@ -1,4 +1,6 @@ -const moment = require('moment'); +const moment = require('moment'); +const {isPostgres} = require('./config'); +const {ref} = require('objection'); module.exports = { @@ -45,6 +47,20 @@ module.exports = { } }); return obj; - } + }, + /** + * Casts a column to json if using postgres + * + * @param {string} colName + * @returns {string|Objection.ReferenceBuilder} + */ + castJsonIfNeed: function (colName) { + if (isPostgres()) { + return ref(colName).castText(); + } + else { + return colName; + } + } }; diff --git a/backend/setup.js b/backend/setup.js index 9a7b6970..decdd088 100644 --- a/backend/setup.js +++ b/backend/setup.js @@ -15,11 +15,11 @@ const certbot = require('./lib/certbot'); const setupDefaultUser = () => { return userModel .query() - .select(userModel.raw('COUNT(`id`) as `count`')) + .count('id', {as: 'count'}) .where('is_deleted', 0) .first() .then((row) => { - if (!row.count) { + if (!parseInt(row.count)) { // Create a new user and set password let email = process.env.INITIAL_ADMIN_EMAIL || 'admin@example.com'; let password = process.env.INITIAL_ADMIN_PASSWORD || 'changeme'; @@ -77,11 +77,11 @@ const setupDefaultUser = () => { const setupDefaultSettings = () => { return settingModel .query() - .select(settingModel.raw('COUNT(`id`) as `count`')) + .count('id', {as: 'count'}) .where({id: 'default-site'}) .first() .then((row) => { - if (!row.count) { + if (!parseInt(row.count)) { settingModel .query() .insert({