From 05272273171a2b0cf0ac4d256dd15d9fd1c93252 Mon Sep 17 00:00:00 2001 From: Dim145 Date: Sat, 19 Oct 2024 02:40:26 +0200 Subject: [PATCH 1/3] add postgresql support --- backend/lib/config.js | 41 +++++++++++++++ backend/package.json | 3 +- backend/yarn.lock | 118 ++++++++++++++++++++++++++++++++++++------ 3 files changed, 145 insertions(+), 17 deletions(-) diff --git a/backend/lib/config.js b/backend/lib/config.js index f7fbdca6..3e47d34f 100644 --- a/backend/lib/config.js +++ b/backend/lib/config.js @@ -46,6 +46,27 @@ 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: 'pg', + 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 = { @@ -146,6 +167,26 @@ module.exports = { return instance.database.knex && instance.database.knex.client === 'sqlite3'; }, + /** + * Is this a mysql configuration? + * + * @returns {boolean} + */ + isMysql: function () { + instance === null && configure(); + return instance.database.engine === 'mysql2'; + }, + + /** + * Is this a postgres configuration? + * + * @returns {boolean} + */ + isPostgres: function () { + instance === null && configure(); + return instance.database.engine === 'pg'; + }, + /** * Are we running in debug mdoe? * diff --git a/backend/package.json b/backend/package.json index 1bc3ef16..41ef9c01 100644 --- a/backend/package.json +++ b/backend/package.json @@ -21,8 +21,9 @@ "moment": "^2.29.4", "mysql2": "^3.11.1", "node-rsa": "^1.0.8", - "objection": "3.0.1", + "objection": "3.1.5", "path": "^0.12.7", + "pg": "^8.13.0", "signale": "1.4.0", "sqlite3": "5.1.6", "temp-write": "^4.0.0" diff --git a/backend/yarn.lock b/backend/yarn.lock index 5441a511..74b60e0c 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -235,6 +235,13 @@ ajv-draft-04@^1.0.0: resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8" integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw== +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + ajv@^6.10.0, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -245,7 +252,7 @@ ajv@^6.10.0, ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.17.1, ajv@^8.6.3: +ajv@^8.0.0, ajv@^8.17.1, ajv@^8.6.3: version "8.17.1" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== @@ -255,16 +262,6 @@ ajv@^8.17.1, ajv@^8.6.3: json-schema-traverse "^1.0.0" require-from-string "^2.0.2" -ajv@^8.6.2: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - ansi-align@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" @@ -2546,12 +2543,13 @@ object-inspect@^1.13.1: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== -objection@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/objection/-/objection-3.0.1.tgz#f67dc698187d10524e5d1b5d37a54e5bba49a42a" - integrity sha512-rqNnyQE+C55UHjdpTOJEKQHJGZ/BGtBBtgxdUpKG4DQXRUmqxfmgS/MhPWxB9Pw0mLSVLEltr6soD4c0Sddy0Q== +objection@3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/objection/-/objection-3.1.5.tgz#53c32f6b6cba2958bc28cf723de96c2676da8286" + integrity sha512-Hx/ipAwXSuRBbOMWFKtRsAN0yITafqXtWB4OT4Z9wED7ty1h7bOnBdhLtcNus23GwLJqcMsRWdodL2p5GwlnfQ== dependencies: - ajv "^8.6.2" + ajv "^8.17.1" + ajv-formats "^2.1.1" db-errors "^0.2.3" on-finished@2.4.1: @@ -2735,11 +2733,67 @@ path@^0.12.7: process "^0.11.1" util "^0.10.3" +pg-cloudflare@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98" + integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q== + pg-connection-string@2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34" integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ== +pg-connection-string@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.7.0.tgz#f1d3489e427c62ece022dba98d5262efcb168b37" + integrity sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA== + +pg-int8@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" + integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== + +pg-pool@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.7.0.tgz#d4d3c7ad640f8c6a2245adc369bafde4ebb8cbec" + integrity sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g== + +pg-protocol@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.7.0.tgz#ec037c87c20515372692edac8b63cf4405448a93" + integrity sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ== + +pg-types@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" + integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== + dependencies: + pg-int8 "1.0.1" + postgres-array "~2.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.4" + postgres-interval "^1.1.0" + +pg@^8.13.0: + version "8.13.0" + resolved "https://registry.yarnpkg.com/pg/-/pg-8.13.0.tgz#e3d245342eb0158112553fcc1890a60720ae2a3d" + integrity sha512-34wkUTh3SxTClfoHB3pQ7bIMvw9dpFU1audQQeZG837fmHfHpr14n/AELVDoOYVDW2h5RDWU78tFjkD+erSBsw== + dependencies: + pg-connection-string "^2.7.0" + pg-pool "^3.7.0" + pg-protocol "^1.7.0" + pg-types "^2.1.0" + pgpass "1.x" + optionalDependencies: + pg-cloudflare "^1.1.1" + +pgpass@1.x: + version "1.0.5" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" + integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== + dependencies: + split2 "^4.1.0" + picomatch@^2.0.4, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" @@ -2758,6 +2812,28 @@ pkg-conf@^2.1.0: find-up "^2.0.0" load-json-file "^4.0.0" +postgres-array@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" + integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== + +postgres-bytea@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w== + +postgres-date@~1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8" + integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== + +postgres-interval@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" + integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== + dependencies: + xtend "^4.0.0" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -3194,6 +3270,11 @@ socks@^2.6.2: ip "^2.0.0" smart-buffer "^4.2.0" +split2@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -3665,6 +3746,11 @@ xdg-basedir@^4.0.0: resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== +xtend@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + y18n@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" From 33562fb2c0358281e589350c1ee95f31c56f7365 Mon Sep 17 00:00:00 2001 From: Dim145 Date: Sat, 19 Oct 2024 02:42:33 +0200 Subject: [PATCH 2/3] 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({ From 170239cec136c99672feb1795360b458b37c7c2d Mon Sep 17 00:00:00 2001 From: Dim145 Date: Sat, 19 Oct 2024 02:49:57 +0200 Subject: [PATCH 3/3] add docker compose file for postgres ci --- docker/docker-compose.ci.postgresql.yml | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 docker/docker-compose.ci.postgresql.yml diff --git a/docker/docker-compose.ci.postgresql.yml b/docker/docker-compose.ci.postgresql.yml new file mode 100644 index 00000000..7cda8622 --- /dev/null +++ b/docker/docker-compose.ci.postgresql.yml @@ -0,0 +1,29 @@ +# WARNING: This is a CI docker-compose file used for building and testing of the entire app, it should not be used for production. +services: + + fullstack: + environment: + DB_POSTGRESQL_HOST: 'db' + DB_POSTGRESQL_PORT: '5432' + DB_POSTGRESQL_USER: 'npm' + DB_POSTGRESQL_PASSWORD: 'npmpass' + DB_POSTGRESQL_NAME: 'npm' + depends_on: + - db-postgresql + + db-postgresql: + image: postgres:14.2-alpine + environment: + POSTGRES_PASSWORD: "npmpass" + POSTGRES_USER: "npm" + POSTGRES_DB: "npm" + ports: + - 5432:5432 + volumes: + - postgres_vol:/var/lib/postgresql/data + networks: + - fulltest + + +volumes: + postgres_vol: \ No newline at end of file