From f3d0bbea6eea6770e1ba225e64fb23e75eb10548 Mon Sep 17 00:00:00 2001 From: Till Date: Fri, 27 Sep 2024 16:41:22 +0200 Subject: [PATCH] Implements #973 PostgreSQL client database support --- .../sql/incremental/upd_dev_collection.sql | 3 + install/sql/ispconfig3.sql | 3 + install/tpl/system.ini.master | 2 +- interface/lib/classes/crypt.inc.php | 49 ++ interface/lib/classes/tform_base.inc.php | 8 + .../web/admin/form/system_config.tform.php | 11 +- .../web/admin/lib/lang/ar_server_config.lng | 1 + .../web/admin/lib/lang/ar_system_config.lng | 3 +- .../web/admin/lib/lang/bg_server_config.lng | 1 + .../web/admin/lib/lang/bg_system_config.lng | 2 +- .../web/admin/lib/lang/br_server_config.lng | 1 + .../web/admin/lib/lang/br_system_config.lng | 1 + .../web/admin/lib/lang/ca_server_config.lng | 1 + .../web/admin/lib/lang/ca_system_config.lng | 2 +- .../web/admin/lib/lang/cn_server_config.lng | 1 + .../web/admin/lib/lang/cn_system_config.lng | 2 +- .../web/admin/lib/lang/cz_server_config.lng | 1 + .../web/admin/lib/lang/cz_system_config.lng | 1 + .../web/admin/lib/lang/de_server_config.lng | 1 + .../web/admin/lib/lang/de_system_config.lng | 2 +- .../web/admin/lib/lang/dk_server_config.lng | 1 + .../web/admin/lib/lang/dk_system_config.lng | 2 +- .../web/admin/lib/lang/el_server_config.lng | 1 + .../web/admin/lib/lang/el_system_config.lng | 2 +- .../web/admin/lib/lang/en_server_config.lng | 1 + .../web/admin/lib/lang/en_system_config.lng | 2 +- .../web/admin/lib/lang/es_server_config.lng | 1 + .../web/admin/lib/lang/es_system_config.lng | 2 +- .../web/admin/lib/lang/fi_server_config.lng | 1 + .../web/admin/lib/lang/fi_system_config.lng | 2 +- .../web/admin/lib/lang/fr_server_config.lng | 1 + .../web/admin/lib/lang/fr_system_config.lng | 2 +- .../web/admin/lib/lang/hr_server_config.lng | 1 + .../web/admin/lib/lang/hr_system_config.lng | 2 +- .../web/admin/lib/lang/hu_server_config.lng | 1 + .../web/admin/lib/lang/hu_system_config.lng | 2 +- .../web/admin/lib/lang/id_server_config.lng | 1 + .../web/admin/lib/lang/id_system_config.lng | 2 +- .../web/admin/lib/lang/it_server_config.lng | 1 + .../web/admin/lib/lang/it_system_config.lng | 2 +- .../web/admin/lib/lang/ja_server_config.lng | 1 + .../web/admin/lib/lang/ja_system_config.lng | 2 +- .../web/admin/lib/lang/nl_server_config.lng | 1 + .../web/admin/lib/lang/nl_system_config.lng | 2 +- .../web/admin/lib/lang/pl_server_config.lng | 1 + .../web/admin/lib/lang/pl_system_config.lng | 2 +- .../web/admin/lib/lang/pt_server_config.lng | 1 + .../web/admin/lib/lang/pt_system_config.lng | 2 +- .../web/admin/lib/lang/ro_server_config.lng | 1 + .../web/admin/lib/lang/ro_system_config.lng | 2 +- .../web/admin/lib/lang/ru_server_config.lng | 1 + .../web/admin/lib/lang/ru_system_config.lng | 2 +- .../web/admin/lib/lang/se_server_config.lng | 1 + .../web/admin/lib/lang/se_system_config.lng | 2 +- .../web/admin/lib/lang/sk_server_config.lng | 1 + .../web/admin/lib/lang/sk_system_config.lng | 2 +- .../web/admin/lib/lang/tr_server_config.lng | 1 + .../web/admin/lib/lang/tr_system_config.lng | 2 +- .../templates/system_config_sites_edit.htm | 6 + interface/web/client/client_edit.php | 8 + interface/web/client/client_template_edit.php | 9 + interface/web/client/form/client.tform.php | 14 + .../web/client/form/client_template.tform.php | 14 + interface/web/client/form/reseller.tform.php | 14 + interface/web/client/reseller_edit.php | 12 +- .../client/templates/client_edit_limits.htm | 9 +- .../templates/client_template_edit_limits.htm | 11 +- .../client/templates/reseller_edit_limits.htm | 11 +- interface/web/sites/database_del.php | 4 +- interface/web/sites/database_edit.php | 37 +- interface/web/sites/database_user_del.php | 10 +- interface/web/sites/database_user_edit.php | 5 +- interface/web/sites/form/database.tform.php | 15 +- .../web/sites/form/database_user.tform.php | 9 + interface/web/sites/lib/lang/ar_database.lng | 4 +- .../web/sites/lib/lang/ar_database_user.lng | 3 +- interface/web/sites/lib/lang/bg_database.lng | 3 +- .../web/sites/lib/lang/bg_database_user.lng | 2 +- interface/web/sites/lib/lang/br_database.lng | 3 +- .../web/sites/lib/lang/br_database_user.lng | 1 + interface/web/sites/lib/lang/ca_database.lng | 3 +- .../web/sites/lib/lang/ca_database_user.lng | 2 +- interface/web/sites/lib/lang/cn_database.lng | 3 +- .../web/sites/lib/lang/cn_database_user.lng | 2 +- interface/web/sites/lib/lang/cz_database.lng | 3 +- .../web/sites/lib/lang/cz_database_user.lng | 1 + interface/web/sites/lib/lang/de_database.lng | 3 +- .../web/sites/lib/lang/de_database_user.lng | 2 +- interface/web/sites/lib/lang/dk_database.lng | 3 +- .../web/sites/lib/lang/dk_database_user.lng | 2 +- interface/web/sites/lib/lang/el_database.lng | 3 +- .../web/sites/lib/lang/el_database_user.lng | 2 +- interface/web/sites/lib/lang/en_database.lng | 3 +- .../web/sites/lib/lang/en_database_user.lng | 2 +- interface/web/sites/lib/lang/es_database.lng | 3 +- .../web/sites/lib/lang/es_database_user.lng | 2 +- interface/web/sites/lib/lang/fi_database.lng | 3 +- .../web/sites/lib/lang/fi_database_user.lng | 2 +- interface/web/sites/lib/lang/fr_database.lng | 3 +- .../web/sites/lib/lang/fr_database_user.lng | 2 +- interface/web/sites/lib/lang/hr_database.lng | 3 +- .../web/sites/lib/lang/hr_database_user.lng | 2 +- interface/web/sites/lib/lang/hu_database.lng | 3 +- .../web/sites/lib/lang/hu_database_user.lng | 2 +- interface/web/sites/lib/lang/id_database.lng | 3 +- .../web/sites/lib/lang/id_database_user.lng | 2 +- interface/web/sites/lib/lang/it_database.lng | 3 +- .../web/sites/lib/lang/it_database_user.lng | 2 +- interface/web/sites/lib/lang/ja_database.lng | 3 +- .../web/sites/lib/lang/ja_database_user.lng | 2 +- interface/web/sites/lib/lang/nl_database.lng | 3 +- .../web/sites/lib/lang/nl_database_user.lng | 2 +- interface/web/sites/lib/lang/pl_database.lng | 3 +- .../web/sites/lib/lang/pl_database_user.lng | 2 +- interface/web/sites/lib/lang/pt_database.lng | 3 +- .../web/sites/lib/lang/pt_database_user.lng | 2 +- interface/web/sites/lib/lang/ro_database.lng | 3 +- .../web/sites/lib/lang/ro_database_user.lng | 2 +- interface/web/sites/lib/lang/ru_database.lng | 3 +- .../web/sites/lib/lang/ru_database_user.lng | 2 +- interface/web/sites/lib/lang/se_database.lng | 3 +- .../web/sites/lib/lang/se_database_user.lng | 2 +- interface/web/sites/lib/lang/sk_database.lng | 3 +- .../web/sites/lib/lang/sk_database_user.lng | 2 +- interface/web/sites/lib/lang/tr_database.lng | 3 +- .../web/sites/lib/lang/tr_database_user.lng | 2 +- .../web/sites/templates/database_edit.htm | 18 +- .../cron.d/100-monitor_database_size.inc.php | 13 +- .../postgresql_clientdb_plugin.inc.php | 742 ++++++++++++++++++ 129 files changed, 1141 insertions(+), 103 deletions(-) create mode 100644 interface/lib/classes/crypt.inc.php create mode 100644 server/plugins-available/postgresql_clientdb_plugin.inc.php diff --git a/install/sql/incremental/upd_dev_collection.sql b/install/sql/incremental/upd_dev_collection.sql index 66e6842ebe..0a18fca125 100644 --- a/install/sql/incremental/upd_dev_collection.sql +++ b/install/sql/incremental/upd_dev_collection.sql @@ -1 +1,4 @@ ALTER TABLE `web_database_user` ADD `database_password_sha2` varchar(70) DEFAULT NULL AFTER `database_password`; +ALTER TABLE `web_database_user` ADD `database_password_postgres` varchar(255) DEFAULT NULL AFTER `database_password_mongo`; +ALTER TABLE `client` ADD `limit_database_postgresql` INT NOT NULL DEFAULT '-1' AFTER `limit_database`; +ALTER TABLE `client_template` ADD `limit_database_postgresql` INT NOT NULL DEFAULT '-1' AFTER `limit_database`; \ No newline at end of file diff --git a/install/sql/ispconfig3.sql b/install/sql/ispconfig3.sql index 0d51bd66a4..9dc8279562 100644 --- a/install/sql/ispconfig3.sql +++ b/install/sql/ispconfig3.sql @@ -233,6 +233,7 @@ CREATE TABLE `client` ( `default_dbserver` int(11) NOT NULL DEFAULT '1', `dns_servers` text, `limit_database` int(11) NOT NULL DEFAULT '-1', + `limit_database_postgresql` int(11) NOT NULL default '-1', `limit_database_user` int(11) NOT NULL DEFAULT '-1', `limit_database_quota` int(11) NOT NULL default '-1', `limit_cron` int(11) NOT NULL DEFAULT '0', @@ -363,6 +364,7 @@ CREATE TABLE `client_template` ( `limit_dns_record` int(11) NOT NULL default '-1', `db_servers` text, `limit_database` int(11) NOT NULL default '-1', + `limit_database_postgresql` int(11) NOT NULL default '-1', `limit_database_user` int(11) NOT NULL DEFAULT '-1', `limit_database_quota` int(11) NOT NULL default '-1', `limit_cron` int(11) NOT NULL default '0', @@ -1949,6 +1951,7 @@ CREATE TABLE IF NOT EXISTS `web_database_user` ( `database_password` varchar(64) DEFAULT NULL, `database_password_sha2` varchar(70) DEFAULT NULL, `database_password_mongo` varchar(32) DEFAULT NULL, + `database_password_postgres` varchar(255) DEFAULT NULL, PRIMARY KEY (`database_user_id`) ) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; diff --git a/install/tpl/system.ini.master b/install/tpl/system.ini.master index 17218c65b5..418e578355 100644 --- a/install/tpl/system.ini.master +++ b/install/tpl/system.ini.master @@ -40,7 +40,7 @@ show_aps_menu=n client_protection=y ssh_authentication= le_caa_autocreate_options=y - +postgresql_database=n [tools] diff --git a/interface/lib/classes/crypt.inc.php b/interface/lib/classes/crypt.inc.php new file mode 100644 index 0000000000..24d26a7a71 --- /dev/null +++ b/interface/lib/classes/crypt.inc.php @@ -0,0 +1,49 @@ +db->getPasswordHash($record[$key], 'caching_sha2_password'); $sql_insert_val .= "'".$app->db->quote($record[$key])."', "; + } elseif (isset($field['encryption']) && $field['encryption'] == 'POSTGRESHA256') { + $app->uses('crypt'); + $record[$key] = $app->crypt->postgres_scram_sha_256($record[$key]); + $sql_insert_val .= "'".$app->db->quote($record[$key])."', "; } else { $record[$key] = md5(stripslashes($record[$key])); $sql_insert_val .= "'".$app->db->quote($record[$key])."', "; @@ -1413,6 +1417,10 @@ class tform_base { } elseif (isset($field['encryption']) && $field['encryption'] == 'MYSQLSHA2') { $record[$key] = $app->db->getPasswordHash($record[$key], 'caching_sha2_password'); $sql_update .= "`$key` = '".$app->db->quote($record[$key])."', "; + } elseif (isset($field['encryption']) && $field['encryption'] == 'POSTGRESHA256') { + $app->uses('crypt'); + $record[$key] = $app->crypt->postgres_scram_sha_256($record[$key]); + $sql_update .= "`$key` = '".$app->db->quote($record[$key])."', "; } else { $record[$key] = md5(stripslashes($record[$key])); $sql_update .= "`$key` = '".$app->db->quote($record[$key])."', "; diff --git a/interface/web/admin/form/system_config.tform.php b/interface/web/admin/form/system_config.tform.php index 68e5710588..40e5877f9f 100644 --- a/interface/web/admin/form/system_config.tform.php +++ b/interface/web/admin/form/system_config.tform.php @@ -252,7 +252,16 @@ $form["tabs"]['sites'] = array ( 'formtype' => 'CHECKBOX', 'default' => 'y', 'value' => array(0 => 'n', 1 => 'y') - ), + ), + 'postgresql_database' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'CHECKBOX', + 'default' => 'n', + 'value' => array ( + 0 => 'n', + 1 => 'y' + ) + ), //################################# // END Datatable fields //################################# diff --git a/interface/web/admin/lib/lang/ar_server_config.lng b/interface/web/admin/lib/lang/ar_server_config.lng index eff8662079..39783e1824 100644 --- a/interface/web/admin/lib/lang/ar_server_config.lng +++ b/interface/web/admin/lib/lang/ar_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/ar_system_config.lng b/interface/web/admin/lib/lang/ar_system_config.lng index 4eb3d443d8..3bc387c2f1 100644 --- a/interface/web/admin/lib/lang/ar_system_config.lng +++ b/interface/web/admin/lib/lang/ar_system_config.lng @@ -110,4 +110,5 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; + diff --git a/interface/web/admin/lib/lang/bg_server_config.lng b/interface/web/admin/lib/lang/bg_server_config.lng index 94f805fae9..32e88b102a 100644 --- a/interface/web/admin/lib/lang/bg_server_config.lng +++ b/interface/web/admin/lib/lang/bg_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/bg_system_config.lng b/interface/web/admin/lib/lang/bg_system_config.lng index e7c95b8ce2..006703bb33 100644 --- a/interface/web/admin/lib/lang/bg_system_config.lng +++ b/interface/web/admin/lib/lang/bg_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/br_server_config.lng b/interface/web/admin/lib/lang/br_server_config.lng index aa83f0dbba..ca176e9d6c 100644 --- a/interface/web/admin/lib/lang/br_server_config.lng +++ b/interface/web/admin/lib/lang/br_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/br_system_config.lng b/interface/web/admin/lib/lang/br_system_config.lng index c6bf1f4221..d3ad7d08ce 100644 --- a/interface/web/admin/lib/lang/br_system_config.lng +++ b/interface/web/admin/lib/lang/br_system_config.lng @@ -111,3 +111,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/ca_server_config.lng b/interface/web/admin/lib/lang/ca_server_config.lng index 39feb97f35..12ff02f318 100644 --- a/interface/web/admin/lib/lang/ca_server_config.lng +++ b/interface/web/admin/lib/lang/ca_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/ca_system_config.lng b/interface/web/admin/lib/lang/ca_system_config.lng index 89ea62be2e..a8d57456ae 100644 --- a/interface/web/admin/lib/lang/ca_system_config.lng +++ b/interface/web/admin/lib/lang/ca_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/cn_server_config.lng b/interface/web/admin/lib/lang/cn_server_config.lng index bc728bb632..6080a3b0ca 100644 --- a/interface/web/admin/lib/lang/cn_server_config.lng +++ b/interface/web/admin/lib/lang/cn_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/cn_system_config.lng b/interface/web/admin/lib/lang/cn_system_config.lng index eedf1f1029..cc28ab154d 100644 --- a/interface/web/admin/lib/lang/cn_system_config.lng +++ b/interface/web/admin/lib/lang/cn_system_config.lng @@ -109,4 +109,4 @@ $wb['dns_show_zoneexport_txt'] = '显示区域导出。'; $wb['le_caa_autocreate_options_txt'] = '在颁发 LE 时启用 CAA 记录的自动创建'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/cz_server_config.lng b/interface/web/admin/lib/lang/cz_server_config.lng index 96ea04fb96..13e6719ca6 100644 --- a/interface/web/admin/lib/lang/cz_server_config.lng +++ b/interface/web/admin/lib/lang/cz_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/cz_system_config.lng b/interface/web/admin/lib/lang/cz_system_config.lng index 6e6729d79d..aecf6c5fbe 100644 --- a/interface/web/admin/lib/lang/cz_system_config.lng +++ b/interface/web/admin/lib/lang/cz_system_config.lng @@ -111,3 +111,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/de_server_config.lng b/interface/web/admin/lib/lang/de_server_config.lng index 92297bb355..d69f9fea85 100644 --- a/interface/web/admin/lib/lang/de_server_config.lng +++ b/interface/web/admin/lib/lang/de_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Datenbank'; diff --git a/interface/web/admin/lib/lang/de_system_config.lng b/interface/web/admin/lib/lang/de_system_config.lng index cbd2cc8eea..39e5d57287 100644 --- a/interface/web/admin/lib/lang/de_system_config.lng +++ b/interface/web/admin/lib/lang/de_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Automatische Erstellung des CAA-Records $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Datenbank'; diff --git a/interface/web/admin/lib/lang/dk_server_config.lng b/interface/web/admin/lib/lang/dk_server_config.lng index 05f5402202..3b3c878ae7 100644 --- a/interface/web/admin/lib/lang/dk_server_config.lng +++ b/interface/web/admin/lib/lang/dk_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/dk_system_config.lng b/interface/web/admin/lib/lang/dk_system_config.lng index 8fb1c66db7..682264475b 100644 --- a/interface/web/admin/lib/lang/dk_system_config.lng +++ b/interface/web/admin/lib/lang/dk_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/el_server_config.lng b/interface/web/admin/lib/lang/el_server_config.lng index ecedc25243..cea1147f52 100644 --- a/interface/web/admin/lib/lang/el_server_config.lng +++ b/interface/web/admin/lib/lang/el_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/el_system_config.lng b/interface/web/admin/lib/lang/el_system_config.lng index 28d5968c8b..87bd0267e6 100644 --- a/interface/web/admin/lib/lang/el_system_config.lng +++ b/interface/web/admin/lib/lang/el_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/en_server_config.lng b/interface/web/admin/lib/lang/en_server_config.lng index af7beb9a4d..2dd003ce89 100644 --- a/interface/web/admin/lib/lang/en_server_config.lng +++ b/interface/web/admin/lib/lang/en_server_config.lng @@ -364,3 +364,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/en_system_config.lng b/interface/web/admin/lib/lang/en_system_config.lng index 6e0907c432..7a63da9fea 100644 --- a/interface/web/admin/lib/lang/en_system_config.lng +++ b/interface/web/admin/lib/lang/en_system_config.lng @@ -111,4 +111,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/es_server_config.lng b/interface/web/admin/lib/lang/es_server_config.lng index 8961010f73..558a8798ce 100644 --- a/interface/web/admin/lib/lang/es_server_config.lng +++ b/interface/web/admin/lib/lang/es_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/es_system_config.lng b/interface/web/admin/lib/lang/es_system_config.lng index 331a18a7b7..b62e52b774 100644 --- a/interface/web/admin/lib/lang/es_system_config.lng +++ b/interface/web/admin/lib/lang/es_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/fi_server_config.lng b/interface/web/admin/lib/lang/fi_server_config.lng index 68f12468a0..5b454de0f4 100644 --- a/interface/web/admin/lib/lang/fi_server_config.lng +++ b/interface/web/admin/lib/lang/fi_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/fi_system_config.lng b/interface/web/admin/lib/lang/fi_system_config.lng index 2b2569cb98..cde97192b4 100644 --- a/interface/web/admin/lib/lang/fi_system_config.lng +++ b/interface/web/admin/lib/lang/fi_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/fr_server_config.lng b/interface/web/admin/lib/lang/fr_server_config.lng index fb5d1e2f97..42a6576da4 100644 --- a/interface/web/admin/lib/lang/fr_server_config.lng +++ b/interface/web/admin/lib/lang/fr_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/fr_system_config.lng b/interface/web/admin/lib/lang/fr_system_config.lng index 172442cea2..c4faa624ce 100644 --- a/interface/web/admin/lib/lang/fr_system_config.lng +++ b/interface/web/admin/lib/lang/fr_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/hr_server_config.lng b/interface/web/admin/lib/lang/hr_server_config.lng index b40c7fd49e..db6ace2a25 100644 --- a/interface/web/admin/lib/lang/hr_server_config.lng +++ b/interface/web/admin/lib/lang/hr_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/hr_system_config.lng b/interface/web/admin/lib/lang/hr_system_config.lng index a167f4e4a3..ccbc203a66 100644 --- a/interface/web/admin/lib/lang/hr_system_config.lng +++ b/interface/web/admin/lib/lang/hr_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/hu_server_config.lng b/interface/web/admin/lib/lang/hu_server_config.lng index 526b800cbd..c75d4dd19d 100644 --- a/interface/web/admin/lib/lang/hu_server_config.lng +++ b/interface/web/admin/lib/lang/hu_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/hu_system_config.lng b/interface/web/admin/lib/lang/hu_system_config.lng index 4a8c266677..648cf2beef 100644 --- a/interface/web/admin/lib/lang/hu_system_config.lng +++ b/interface/web/admin/lib/lang/hu_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/id_server_config.lng b/interface/web/admin/lib/lang/id_server_config.lng index daaa08c24a..94ba6415c8 100644 --- a/interface/web/admin/lib/lang/id_server_config.lng +++ b/interface/web/admin/lib/lang/id_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/id_system_config.lng b/interface/web/admin/lib/lang/id_system_config.lng index e37cd5b967..be99b10113 100644 --- a/interface/web/admin/lib/lang/id_system_config.lng +++ b/interface/web/admin/lib/lang/id_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/it_server_config.lng b/interface/web/admin/lib/lang/it_server_config.lng index 9e7064fe14..905fa49d6a 100644 --- a/interface/web/admin/lib/lang/it_server_config.lng +++ b/interface/web/admin/lib/lang/it_server_config.lng @@ -357,3 +357,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/it_system_config.lng b/interface/web/admin/lib/lang/it_system_config.lng index adfeada357..e503221ffa 100644 --- a/interface/web/admin/lib/lang/it_system_config.lng +++ b/interface/web/admin/lib/lang/it_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/ja_server_config.lng b/interface/web/admin/lib/lang/ja_server_config.lng index fa9abcaaf1..acfa0c7471 100644 --- a/interface/web/admin/lib/lang/ja_server_config.lng +++ b/interface/web/admin/lib/lang/ja_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/ja_system_config.lng b/interface/web/admin/lib/lang/ja_system_config.lng index eeb2b1078f..68169d9f28 100644 --- a/interface/web/admin/lib/lang/ja_system_config.lng +++ b/interface/web/admin/lib/lang/ja_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/nl_server_config.lng b/interface/web/admin/lib/lang/nl_server_config.lng index a8a8d47366..73800de773 100644 --- a/interface/web/admin/lib/lang/nl_server_config.lng +++ b/interface/web/admin/lib/lang/nl_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/nl_system_config.lng b/interface/web/admin/lib/lang/nl_system_config.lng index d6d57639aa..6812c67d34 100644 --- a/interface/web/admin/lib/lang/nl_system_config.lng +++ b/interface/web/admin/lib/lang/nl_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/pl_server_config.lng b/interface/web/admin/lib/lang/pl_server_config.lng index 83460000a2..92c0e1b276 100644 --- a/interface/web/admin/lib/lang/pl_server_config.lng +++ b/interface/web/admin/lib/lang/pl_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/pl_system_config.lng b/interface/web/admin/lib/lang/pl_system_config.lng index 0218e86eaf..edc15d68c1 100644 --- a/interface/web/admin/lib/lang/pl_system_config.lng +++ b/interface/web/admin/lib/lang/pl_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/pt_server_config.lng b/interface/web/admin/lib/lang/pt_server_config.lng index f856344b0a..0e6e4f3aac 100644 --- a/interface/web/admin/lib/lang/pt_server_config.lng +++ b/interface/web/admin/lib/lang/pt_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/pt_system_config.lng b/interface/web/admin/lib/lang/pt_system_config.lng index 320d45a8a2..17374d12ae 100644 --- a/interface/web/admin/lib/lang/pt_system_config.lng +++ b/interface/web/admin/lib/lang/pt_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/ro_server_config.lng b/interface/web/admin/lib/lang/ro_server_config.lng index d69c33ed65..461c044112 100644 --- a/interface/web/admin/lib/lang/ro_server_config.lng +++ b/interface/web/admin/lib/lang/ro_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/ro_system_config.lng b/interface/web/admin/lib/lang/ro_system_config.lng index d9bfa02c68..f31a8dbaeb 100644 --- a/interface/web/admin/lib/lang/ro_system_config.lng +++ b/interface/web/admin/lib/lang/ro_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/ru_server_config.lng b/interface/web/admin/lib/lang/ru_server_config.lng index 2fdb42393e..853a23d454 100644 --- a/interface/web/admin/lib/lang/ru_server_config.lng +++ b/interface/web/admin/lib/lang/ru_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/ru_system_config.lng b/interface/web/admin/lib/lang/ru_system_config.lng index 3000aa1735..29f7bc4251 100644 --- a/interface/web/admin/lib/lang/ru_system_config.lng +++ b/interface/web/admin/lib/lang/ru_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/se_server_config.lng b/interface/web/admin/lib/lang/se_server_config.lng index 24df537a56..24c93ca229 100644 --- a/interface/web/admin/lib/lang/se_server_config.lng +++ b/interface/web/admin/lib/lang/se_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/se_system_config.lng b/interface/web/admin/lib/lang/se_system_config.lng index f61f922477..a4a417f4f6 100644 --- a/interface/web/admin/lib/lang/se_system_config.lng +++ b/interface/web/admin/lib/lang/se_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/sk_server_config.lng b/interface/web/admin/lib/lang/sk_server_config.lng index 965ef09719..afbfcbe253 100644 --- a/interface/web/admin/lib/lang/sk_server_config.lng +++ b/interface/web/admin/lib/lang/sk_server_config.lng @@ -358,3 +358,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/sk_system_config.lng b/interface/web/admin/lib/lang/sk_system_config.lng index 8603147c96..ef25b1982a 100644 --- a/interface/web/admin/lib/lang/sk_system_config.lng +++ b/interface/web/admin/lib/lang/sk_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/tr_server_config.lng b/interface/web/admin/lib/lang/tr_server_config.lng index fcc26b10fd..a906fefdf2 100644 --- a/interface/web/admin/lib/lang/tr_server_config.lng +++ b/interface/web/admin/lib/lang/tr_server_config.lng @@ -355,3 +355,4 @@ $wb['soft_delete_keep_7_txt'] = 'Purge after 7 days'; $wb['soft_delete_keep_30_txt'] = 'Purge after 30 days'; $wb['soft_delete_keep_90_txt'] = 'Purge after 90 days'; $wb['soft_delete_keep_365_txt'] = 'Purge after 365 days'; +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/lib/lang/tr_system_config.lng b/interface/web/admin/lib/lang/tr_system_config.lng index 98f0221689..9181932af0 100644 --- a/interface/web/admin/lib/lang/tr_system_config.lng +++ b/interface/web/admin/lib/lang/tr_system_config.lng @@ -110,4 +110,4 @@ $wb['le_caa_autocreate_options_txt'] = 'Enable automatic creation of CAA record $wb['show_delete_on_forms_txt'] = 'Show delete button on edit forms'; $wb['dns_external_slave_server_txt'] = 'External DNS servers (comma separated)'; $wb['mailbox_show_last_access_txt'] = 'Show last access time for mail accounts'; -?> +$wb['postgresql_database_txt'] = 'PostgreSQL Database'; diff --git a/interface/web/admin/templates/system_config_sites_edit.htm b/interface/web/admin/templates/system_config_sites_edit.htm index 9a36e3275e..944fba5ec5 100644 --- a/interface/web/admin/templates/system_config_sites_edit.htm +++ b/interface/web/admin/templates/system_config_sites_edit.htm @@ -109,6 +109,12 @@ {tmpl_var name='le_caa_autocreate_options'} +
+ +
+ {tmpl_var name='postgresql_database'} +
+
diff --git a/interface/web/client/client_edit.php b/interface/web/client/client_edit.php index d9082d7395..972d89d64f 100644 --- a/interface/web/client/client_edit.php +++ b/interface/web/client/client_edit.php @@ -103,6 +103,14 @@ class page_action extends tform_actions { $app->tpl->setVar('contact_name', $tmp['contact_name']); $app->tpl->setVar('email', $tmp['email']); + $app->uses('getconf,system'); + $web_config = $app->getconf->get_global_config('sites'); + if($web_config['postgresql_database'] == 'y') { + $app->tpl->setVar('show_postgresql', true); + } else { + $app->tpl->setVar('show_postgresql', false); + } + parent::onShowEdit(); } diff --git a/interface/web/client/client_template_edit.php b/interface/web/client/client_template_edit.php index 7cc3ab5ff9..b004ec9de3 100644 --- a/interface/web/client/client_template_edit.php +++ b/interface/web/client/client_template_edit.php @@ -80,6 +80,15 @@ class page_action extends tform_actions { } else { $app->tpl->setVar("show_aps_menu", 0); } + + $app->uses('getconf,system'); + $web_config = $app->getconf->get_global_config('sites'); + if($web_config['postgresql_database'] == 'y') { + $app->tpl->setVar('show_postgresql', true); + } else { + $app->tpl->setVar('show_postgresql', false); + } + parent::onShowEnd(); } diff --git a/interface/web/client/form/client.tform.php b/interface/web/client/form/client.tform.php index 0980412576..59d2190f75 100644 --- a/interface/web/client/form/client.tform.php +++ b/interface/web/client/form/client.tform.php @@ -1466,6 +1466,20 @@ $form["tabs"]['limits'] = array ( 'rows' => '', 'cols' => '' ), + 'limit_database_postgresql' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'ISINT', + 'errmsg'=> 'limit_database_error_notint'), + ), + 'default' => '-1', + 'value' => '', + 'separator' => '', + 'width' => '10', + 'maxlength' => '10', + 'rows' => '', + 'cols' => '' + ), 'limit_cron' => array ( 'datatype' => 'INTEGER', 'formtype' => 'TEXT', diff --git a/interface/web/client/form/client_template.tform.php b/interface/web/client/form/client_template.tform.php index adf72670f8..3dda317492 100644 --- a/interface/web/client/form/client_template.tform.php +++ b/interface/web/client/form/client_template.tform.php @@ -860,6 +860,20 @@ $form["tabs"]['limits'] = array ( 'rows' => '', 'cols' => '' ), + 'limit_database_postgresql' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'ISINT', + 'errmsg'=> 'limit_database_error_notint'), + ), + 'default' => '-1', + 'value' => '', + 'separator' => '', + 'width' => '10', + 'maxlength' => '10', + 'rows' => '', + 'cols' => '' + ), 'limit_cron' => array ( 'datatype' => 'INTEGER', 'formtype' => 'TEXT', diff --git a/interface/web/client/form/reseller.tform.php b/interface/web/client/form/reseller.tform.php index 9cf3b6bbad..35cb511bcd 100644 --- a/interface/web/client/form/reseller.tform.php +++ b/interface/web/client/form/reseller.tform.php @@ -1441,6 +1441,20 @@ $form["tabs"]['limits'] = array ( 'rows' => '', 'cols' => '' ), + 'limit_database_postgresql' => array ( + 'datatype' => 'INTEGER', + 'formtype' => 'TEXT', + 'validators' => array ( 0 => array ( 'type' => 'ISINT', + 'errmsg'=> 'limit_database_error_notint'), + ), + 'default' => '-1', + 'value' => '', + 'separator' => '', + 'width' => '10', + 'maxlength' => '10', + 'rows' => '', + 'cols' => '' + ), 'limit_cron' => array ( 'datatype' => 'INTEGER', 'formtype' => 'TEXT', diff --git a/interface/web/client/reseller_edit.php b/interface/web/client/reseller_edit.php index 4dc89293f9..7600dcd62d 100644 --- a/interface/web/client/reseller_edit.php +++ b/interface/web/client/reseller_edit.php @@ -107,6 +107,14 @@ class page_action extends tform_actions { $app->tpl->setVar('contact_name', $tmp['contact_name']); $app->tpl->setVar('email', $tmp['email']); + $app->uses('getconf,system'); + $web_config = $app->getconf->get_global_config('sites'); + if($web_config['postgresql_database'] == 'y') { + $app->tpl->setVar('show_postgresql', true); + } else { + $app->tpl->setVar('show_postgresql', false); + } + parent::onShowEdit(); } @@ -326,8 +334,8 @@ class page_action extends tform_actions { $subject = str_replace('{password}', $this->dataRecord['password'], $subject); break; case 'gender': - $message = str_replace('{salutation}', $wb['gender_'.$val.'_txt'], $message); - $subject = str_replace('{salutation}', $wb['gender_'.$val.'_txt'], $subject); + $message = str_replace('{salutation}', $app->lng('gender_'.$val.'_txt'), $message); + $subject = str_replace('{salutation}', $app->lng('gender_'.$val.'_txt'), $subject); break; default: $message = str_replace('{'.$key.'}', $val, $message); diff --git a/interface/web/client/templates/client_edit_limits.htm b/interface/web/client/templates/client_edit_limits.htm index 9a2578b697..b8183a3585 100644 --- a/interface/web/client/templates/client_edit_limits.htm +++ b/interface/web/client/templates/client_edit_limits.htm @@ -342,8 +342,15 @@
- +
+ +
+ +
+ + +
diff --git a/interface/web/client/templates/client_template_edit_limits.htm b/interface/web/client/templates/client_template_edit_limits.htm index ef15d18358..1f13fcaf82 100644 --- a/interface/web/client/templates/client_template_edit_limits.htm +++ b/interface/web/client/templates/client_template_edit_limits.htm @@ -299,9 +299,16 @@
- +
-
+ +
+ +
+ + +
+
diff --git a/interface/web/client/templates/reseller_edit_limits.htm b/interface/web/client/templates/reseller_edit_limits.htm index eee685ac51..4ca8ab14a9 100644 --- a/interface/web/client/templates/reseller_edit_limits.htm +++ b/interface/web/client/templates/reseller_edit_limits.htm @@ -343,9 +343,16 @@
- +
-
+ +
+ +
+ + +
+
diff --git a/interface/web/sites/database_del.php b/interface/web/sites/database_del.php index ba079e220b..7d1ff02596 100644 --- a/interface/web/sites/database_del.php +++ b/interface/web/sites/database_del.php @@ -48,10 +48,10 @@ $app->auth->check_module_permissions('sites'); $app->uses("tform_actions"); class page_action extends tform_actions { function onBeforeDelete() { - global $app; $conf; + global $app, $conf; if($app->tform->checkPerm($this->id, 'd') == false) $app->error($app->lng('error_no_delete_permission')); - $app->uses('sites_database_plugin'); + // $app->uses('sites_database_plugin'); //$app->sites_database_plugin->processDatabaseDelete($this->id); } diff --git a/interface/web/sites/database_edit.php b/interface/web/sites/database_edit.php index 00af8363ae..c37c6c8d57 100644 --- a/interface/web/sites/database_edit.php +++ b/interface/web/sites/database_edit.php @@ -163,6 +163,7 @@ class page_action extends tform_actions { $edit_disabled = @($_SESSION["s"]["user"]["typ"] == 'admin')? 0 : 1; //* admin can change the database-name $app->tpl->setVar("edit_disabled", $edit_disabled); $app->tpl->setVar("server_id_value", $this->dataRecord["server_id"], true); + $app->tpl->setVar("type_value", $this->dataRecord["type"], true); $app->tpl->setVar("database_charset_value", $this->dataRecord["database_charset"], true); $app->tpl->setVar("limit_database_quota", $this->dataRecord["database_quota"], true); } else { @@ -221,7 +222,7 @@ class page_action extends tform_actions { // Get the limits of the reseller $reseller = $app->db->queryOneRecord("SELECT limit_database, limit_database_quota FROM client WHERE client_id = ?", $client['parent_client_id']); - //* Check the website quota of the client + //* Check the database quota of the client if ($reseller['limit_database_quota'] >= 0) { //* get the database prefix $app->uses('getconf,tools_sites'); @@ -252,14 +253,22 @@ class page_action extends tform_actions { $app->error($app->tform->wordbook['error_not_allowed_server_id']); } - // Check if the user may add another database + // Check if the user may add another MySQL database if($client["limit_database"] >= 0) { - $tmp = $app->db->queryOneRecord("SELECT count(database_id) as number FROM web_database WHERE sys_groupid = ?", $client_group_id); + $tmp = $app->db->queryOneRecord("SELECT count(`database_id`) as `number` FROM `web_database` WHERE `type` = 'mysql' AND `sys_groupid` = ?", $client_group_id); if($tmp["number"] >= $client["limit_database"]) { $app->error($app->tform->wordbook["limit_database_txt"]); } } + // Check if the user may add another PostgreSQL database + if($client["limit_database_postgresql"] >= 0) { + $tmp = $app->db->queryOneRecord("SELECT count(`database_id`) as `number` FROM `web_database` WHERE `type` = 'postgresql' AND `sys_groupid` = ?", $client_group_id); + if($tmp["number"] >= $client["limit_database_postgresql"]) { + $app->error($app->tform->wordbook["limit_database_txt"]); + } + } + //* Check client quota if ($client['limit_database_quota'] >= 0) { $tmp = $app->db->queryOneRecord("SELECT sum(database_quota) as db_quota FROM web_database WHERE sys_groupid = ?", $client_group_id); @@ -334,7 +343,7 @@ class page_action extends tform_actions { if($old_record["server_id"] != $this->dataRecord["server_id"]) { //* Add a error message and switch back to old server $app->tform->errorMessage .= $app->lng('The Server can not be changed.'); - $this->dataRecord["server_id"] = $rec['server_id']; + $this->dataRecord["server_id"] = $old_record['server_id']; } } unset($old_record); @@ -357,6 +366,16 @@ class page_action extends tform_actions { $tmp = $app->db->queryOneRecord("SELECT count(database_id) as dbnum FROM web_database WHERE database_name = ? AND server_id = ? AND database_id != ?", $this->dataRecord['database_name'], $this->dataRecord["server_id"], $this->id); if($tmp['dbnum'] > 0) $app->tform->errorMessage .= $app->lng('database_name_error_unique').'
'; + // PostgreSQL specific checks + if($this->dataRecord['type'] == 'postgresql') { + // Check that database user is not used by any other postgres database + $tmp = $app->db->queryOneRecord('SELECT `database_id` FROM `web_database` WHERE `type` = "postgresql" AND `server_id` = ? AND (`database_user_id` = ? OR `database_ro_user_id` = ?) AND `database_id` != ?', $this->dataRecord['server_id'],$this->dataRecord['database_user_id'],$this->dataRecord['database_user_id'], $this->id); + if(!empty($tmp)) $app->tform->errorMessage .= $app->tform->lng('error_db_user_in_use_txt').'
'; + // Check that database ro user is not used by any other postgres database + $tmp = $app->db->queryOneRecord('SELECT `database_id` FROM `web_database` WHERE `type` = "postgresql" AND `server_id` = ? AND (`database_user_id` = ? OR `database_ro_user_id` = ?) AND `database_id` != ?', $this->dataRecord['server_id'],$this->dataRecord['database_ro_user_id'],$this->dataRecord['database_ro_user_id'], $this->id); + if(!empty($tmp)) $app->tform->errorMessage .= $app->tform->lng('error_db_ro_user_in_use_txt').'
'; + } + // get the web server ip (parent domain) $tmp = $app->db->queryOneRecord("SELECT server_id FROM web_domain WHERE domain_id = ?", $this->dataRecord['parent_domain_id']); if($tmp['server_id'] && $tmp['server_id'] != $this->dataRecord['server_id']) { @@ -464,6 +483,16 @@ class page_action extends tform_actions { $tmp = $app->db->queryOneRecord("SELECT count(database_id) as dbnum FROM web_database WHERE database_name = ? AND server_id = ?", $this->dataRecord['database_name'], $this->dataRecord["server_id"]); if($tmp['dbnum'] > 0) $app->tform->errorMessage .= $app->tform->lng('database_name_error_unique').'
'; + // PostgreSQL specific checks + if($this->dataRecord['type'] == 'postgresql') { + // Check that database user is not used by any other postgres database + $tmp = $app->db->queryOneRecord('SELECT `database_id` FROM `web_database` WHERE `type` = "postgresql" AND `server_id` = ? AND (`database_user_id` = ? OR `database_ro_user_id` = ?)', $this->dataRecord['server_id'],$this->dataRecord['database_user_id'],$this->dataRecord['database_user_id']); + if(!empty($tmp)) $app->tform->errorMessage .= $app->tform->lng('error_db_user_in_use_txt').'
'; + // Check that database ro user is not used by any other postgres database + $tmp = $app->db->queryOneRecord('SELECT `database_id` FROM `web_database` WHERE `type` = "postgresql" AND `server_id` = ? AND (`database_user_id` = ? OR `database_ro_user_id` = ?)', $this->dataRecord['server_id'],$this->dataRecord['database_ro_user_id'],$this->dataRecord['database_ro_user_id']); + if(!empty($tmp)) $app->tform->errorMessage .= $app->tform->lng('error_db_ro_user_in_use_txt').'
'; + } + // get the web server ip (parent domain) $tmp = $app->db->queryOneRecord("SELECT server_id FROM web_domain WHERE domain_id = ?", $this->dataRecord['parent_domain_id']); if($tmp['server_id'] && $tmp['server_id'] != $this->dataRecord['server_id']) { diff --git a/interface/web/sites/database_user_del.php b/interface/web/sites/database_user_del.php index 379a9a179b..6d67e4d516 100644 --- a/interface/web/sites/database_user_del.php +++ b/interface/web/sites/database_user_del.php @@ -49,11 +49,17 @@ $app->uses("tform_actions"); class page_action extends tform_actions { function onBeforeDelete() { - global $app; $conf; + global $app, $conf; if($app->tform->checkPerm($this->id, 'd') == false) $app->error($app->lng('error_no_delete_permission')); $old_record = $app->tform->getDataRecord($this->id); + // Check if there are databases still using this user + $tmp = $app->db->queryOneRecord('SELECT `database_id` FROM `web_database` WHERE `database_user_id` = ? OR `database_ro_user_id` = ?', $this->id, $this->id); + if(!empty($tmp)) { + $app->error($app->tform->lng('error_del_db_user_in_use_txt')); + } + /* we cannot use datalogDelete here, as we need to set server_id to 0 */ $app->db->query("DELETE FROM `web_database_user` WHERE `database_user_id` = ?", $this->id); $new_rec = array(); @@ -62,7 +68,7 @@ class page_action extends tform_actions { } function onAfterDelete() { // this has to be done on AFTER delete, because we need the db user still in the database when the server plugin processes the datalog - global $app; $conf; + global $app, $conf; //* Update all records that belog to this user $records = $app->db->queryAllRecords("SELECT database_id FROM web_database WHERE database_user_id = ?", $this->id); diff --git a/interface/web/sites/database_user_edit.php b/interface/web/sites/database_user_edit.php index eadc434ece..66632270b4 100644 --- a/interface/web/sites/database_user_edit.php +++ b/interface/web/sites/database_user_edit.php @@ -168,11 +168,13 @@ class page_action extends tform_actions { $this->dataRecord['database_user'] = substr($dbuser_prefix . $this->dataRecord['database_user'], 0, 32); } - // always copy over the password to the SHA2 column + // always copy over the password to the SHA2 and postgres column if($this->dataRecord['database_password']) { $this->dataRecord['database_password_sha2'] = $this->dataRecord['database_password']; + $this->dataRecord['database_password_postgres'] = $this->dataRecord['database_password']; } else { $this->dataRecord['database_password_sha2'] = ''; + $this->dataRecord['database_password_postgres'] = ''; } /* prepare password for MongoDB */ @@ -197,6 +199,7 @@ class page_action extends tform_actions { // always copy over the password to the SHA2 column $this->dataRecord['database_password_sha2'] = $this->dataRecord['database_password']; + $this->dataRecord['database_password_postgres'] = $this->dataRecord['database_password']; //* Get the database name and database user prefix $app->uses('getconf,tools_sites'); diff --git a/interface/web/sites/form/database.tform.php b/interface/web/sites/form/database.tform.php index 81a4f79bf2..70a29b4362 100644 --- a/interface/web/sites/form/database.tform.php +++ b/interface/web/sites/form/database.tform.php @@ -56,6 +56,16 @@ $form["auth_preset"]["perm_user"] = 'riud'; //r = read, i = insert, u = update, $form["auth_preset"]["perm_group"] = 'riud'; //r = read, i = insert, u = update, d = delete $form["auth_preset"]["perm_other"] = ''; //r = read, i = insert, u = update, d = delete +$app->uses('getconf,system'); +$web_config = $app->getconf->get_global_config('sites'); + +// Available database types +$database_type = ['mysql' => 'MySQL']; +if($web_config['postgresql_database'] == 'y') { + $database_type['postgresql'] = 'PostgreSQL'; +} + + $form["tabs"]['database'] = array ( 'title' => "Database", 'width' => 100, @@ -90,10 +100,7 @@ $form["tabs"]['database'] = array ( 'datatype' => 'VARCHAR', 'formtype' => 'SELECT', 'default' => 'mysql', - 'value' => array( - /*'mongo' => 'MongoDB',*/ - 'mysql' => 'MySQL' - ) + 'value' => $database_type ), 'backup_interval' => [ 'datatype' => 'VARCHAR', diff --git a/interface/web/sites/form/database_user.tform.php b/interface/web/sites/form/database_user.tform.php index d28ea6e0ab..b3c06f209b 100644 --- a/interface/web/sites/form/database_user.tform.php +++ b/interface/web/sites/form/database_user.tform.php @@ -126,6 +126,15 @@ $form["tabs"]['database_user'] = array ( 'width' => '30', 'maxlength' => '255' ), + 'database_password_postgres' => array ( + 'datatype' => 'VARCHAR', + 'formtype' => 'PASSWORD', + 'encryption' => 'POSTGRESHA256', + 'default' => '', + 'value' => '', + 'width' => '30', + 'maxlength' => '255' + ), 'database_password_mongo' => array ( 'datatype' => 'VARCHAR', 'formtype' => 'PASSWORD', diff --git a/interface/web/sites/lib/lang/ar_database.lng b/interface/web/sites/lib/lang/ar_database.lng index bc684700fa..9d1bd9bbe4 100644 --- a/interface/web/sites/lib/lang/ar_database.lng +++ b/interface/web/sites/lib/lang/ar_database.lng @@ -52,4 +52,6 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; + diff --git a/interface/web/sites/lib/lang/ar_database_user.lng b/interface/web/sites/lib/lang/ar_database_user.lng index e9860030cc..4313ec2ef3 100644 --- a/interface/web/sites/lib/lang/ar_database_user.lng +++ b/interface/web/sites/lib/lang/ar_database_user.lng @@ -22,4 +22,5 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Search'; $wb['globalsearch_suggestions_text_txt'] = 'Suggestions'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; + diff --git a/interface/web/sites/lib/lang/bg_database.lng b/interface/web/sites/lib/lang/bg_database.lng index 305f6094e4..07326ae14d 100644 --- a/interface/web/sites/lib/lang/bg_database.lng +++ b/interface/web/sites/lib/lang/bg_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/bg_database_user.lng b/interface/web/sites/lib/lang/bg_database_user.lng index e9860030cc..7a034103f8 100644 --- a/interface/web/sites/lib/lang/bg_database_user.lng +++ b/interface/web/sites/lib/lang/bg_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Search'; $wb['globalsearch_suggestions_text_txt'] = 'Suggestions'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/br_database.lng b/interface/web/sites/lib/lang/br_database.lng index d9e13270e5..bfb0be80be 100644 --- a/interface/web/sites/lib/lang/br_database.lng +++ b/interface/web/sites/lib/lang/br_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Diário'; $wb['weekly_backup_txt'] = 'Semanal'; $wb['monthly_backup_txt'] = 'Mensal'; $wb['backup_interval_txt'] = 'Intervalo entre backups'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/br_database_user.lng b/interface/web/sites/lib/lang/br_database_user.lng index 64b1919ee6..debab2cb9f 100644 --- a/interface/web/sites/lib/lang/br_database_user.lng +++ b/interface/web/sites/lib/lang/br_database_user.lng @@ -22,3 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Pesquisar'; $wb['globalsearch_suggestions_text_txt'] = 'Sugestões'; $wb['limit_database_user_txt'] = 'O limite de usuários do Banco de Dados para esta conta foi alcançado.'; $wb['database_password_error_empty'] = 'Senha do Banco de Dados está vazio.'; +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; \ No newline at end of file diff --git a/interface/web/sites/lib/lang/ca_database.lng b/interface/web/sites/lib/lang/ca_database.lng index 6b0123767a..3c877c04ad 100644 --- a/interface/web/sites/lib/lang/ca_database.lng +++ b/interface/web/sites/lib/lang/ca_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; \ No newline at end of file diff --git a/interface/web/sites/lib/lang/ca_database_user.lng b/interface/web/sites/lib/lang/ca_database_user.lng index 2588671b59..41522a2c85 100644 --- a/interface/web/sites/lib/lang/ca_database_user.lng +++ b/interface/web/sites/lib/lang/ca_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Search'; $wb['globalsearch_suggestions_text_txt'] = 'Suggestions'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/cn_database.lng b/interface/web/sites/lib/lang/cn_database.lng index 0b901fa012..69164f92bf 100644 --- a/interface/web/sites/lib/lang/cn_database.lng +++ b/interface/web/sites/lib/lang/cn_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = '每日'; $wb['weekly_backup_txt'] = '每周'; $wb['monthly_backup_txt'] = '每月'; $wb['backup_interval_txt'] = '备份间隔'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/cn_database_user.lng b/interface/web/sites/lib/lang/cn_database_user.lng index 2d46e78c92..096c724cc6 100644 --- a/interface/web/sites/lib/lang/cn_database_user.lng +++ b/interface/web/sites/lib/lang/cn_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = '搜索'; $wb['globalsearch_suggestions_text_txt'] = '建议'; $wb['limit_database_user_txt'] = '已达到数据库用户的最大数量。'; $wb['database_password_error_empty'] = '数据库密码为空。'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/cz_database.lng b/interface/web/sites/lib/lang/cz_database.lng index 6213575847..7dacf61144 100644 --- a/interface/web/sites/lib/lang/cz_database.lng +++ b/interface/web/sites/lib/lang/cz_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Denní'; $wb['weekly_backup_txt'] = 'Týdenní'; $wb['monthly_backup_txt'] = 'Měsíční'; $wb['backup_interval_txt'] = 'Interval zálohování'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/cz_database_user.lng b/interface/web/sites/lib/lang/cz_database_user.lng index d9e9bda5ff..727ad03e90 100644 --- a/interface/web/sites/lib/lang/cz_database_user.lng +++ b/interface/web/sites/lib/lang/cz_database_user.lng @@ -22,3 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Hledat'; $wb['globalsearch_suggestions_text_txt'] = 'Návrhy'; $wb['limit_database_user_txt'] = 'Byl dosažen maximální počet uživatelů databáze.'; $wb['database_password_error_empty'] = 'Databázové heslo je prázdné.'; +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; \ No newline at end of file diff --git a/interface/web/sites/lib/lang/de_database.lng b/interface/web/sites/lib/lang/de_database.lng index f422a68376..95e2b179c2 100644 --- a/interface/web/sites/lib/lang/de_database.lng +++ b/interface/web/sites/lib/lang/de_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'täglich'; $wb['weekly_backup_txt'] = 'wöchentlich'; $wb['monthly_backup_txt'] = 'monatlich'; $wb['backup_interval_txt'] = 'Backup-Interval'; -?> +$wb['error_db_user_in_use_txt'] = 'Der Datenbank-Benutzer wird bereits verwendet. Wähle einen anderen Benutzer aus.'; +$wb['error_db_ro_user_in_use_txt'] = 'Der nur lesen Datenbank-Benutzer wird bereits verwendet. Wähle einen anderen Benutzer aus.'; diff --git a/interface/web/sites/lib/lang/de_database_user.lng b/interface/web/sites/lib/lang/de_database_user.lng index 6627519b32..b8a856e7b4 100644 --- a/interface/web/sites/lib/lang/de_database_user.lng +++ b/interface/web/sites/lib/lang/de_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Suche'; $wb['globalsearch_suggestions_text_txt'] = 'Vorschläge'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Datenbank-Passwort ist leer.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'Der Benutzer kann nicht gelöscht werden. Er wird noch von einer Datenbank verwendet.'; diff --git a/interface/web/sites/lib/lang/dk_database.lng b/interface/web/sites/lib/lang/dk_database.lng index 0621c16472..91875dd88d 100644 --- a/interface/web/sites/lib/lang/dk_database.lng +++ b/interface/web/sites/lib/lang/dk_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/dk_database_user.lng b/interface/web/sites/lib/lang/dk_database_user.lng index 1689845d8a..449b0b659c 100644 --- a/interface/web/sites/lib/lang/dk_database_user.lng +++ b/interface/web/sites/lib/lang/dk_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Søg'; $wb['globalsearch_suggestions_text_txt'] = 'Forslag'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/el_database.lng b/interface/web/sites/lib/lang/el_database.lng index 085ae1f375..a2ae646cfa 100644 --- a/interface/web/sites/lib/lang/el_database.lng +++ b/interface/web/sites/lib/lang/el_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/el_database_user.lng b/interface/web/sites/lib/lang/el_database_user.lng index e9860030cc..7a034103f8 100644 --- a/interface/web/sites/lib/lang/el_database_user.lng +++ b/interface/web/sites/lib/lang/el_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Search'; $wb['globalsearch_suggestions_text_txt'] = 'Suggestions'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/en_database.lng b/interface/web/sites/lib/lang/en_database.lng index 18bb524ef2..a6339243b4 100644 --- a/interface/web/sites/lib/lang/en_database.lng +++ b/interface/web/sites/lib/lang/en_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/en_database_user.lng b/interface/web/sites/lib/lang/en_database_user.lng index e9860030cc..7a034103f8 100644 --- a/interface/web/sites/lib/lang/en_database_user.lng +++ b/interface/web/sites/lib/lang/en_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Search'; $wb['globalsearch_suggestions_text_txt'] = 'Suggestions'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/es_database.lng b/interface/web/sites/lib/lang/es_database.lng index 050209a3fa..44bd384afd 100644 --- a/interface/web/sites/lib/lang/es_database.lng +++ b/interface/web/sites/lib/lang/es_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Diariamente'; $wb['weekly_backup_txt'] = 'Semanalmente'; $wb['monthly_backup_txt'] = 'Mensualmente'; $wb['backup_interval_txt'] = 'Intervalo de copias de seguridad'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/es_database_user.lng b/interface/web/sites/lib/lang/es_database_user.lng index 71ac13a084..03680917a5 100644 --- a/interface/web/sites/lib/lang/es_database_user.lng +++ b/interface/web/sites/lib/lang/es_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Buscar'; $wb['globalsearch_suggestions_text_txt'] = 'Sugerencias'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/fi_database.lng b/interface/web/sites/lib/lang/fi_database.lng index 06d5dc6746..f7986dfa41 100644 --- a/interface/web/sites/lib/lang/fi_database.lng +++ b/interface/web/sites/lib/lang/fi_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/fi_database_user.lng b/interface/web/sites/lib/lang/fi_database_user.lng index e9860030cc..7a034103f8 100644 --- a/interface/web/sites/lib/lang/fi_database_user.lng +++ b/interface/web/sites/lib/lang/fi_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Search'; $wb['globalsearch_suggestions_text_txt'] = 'Suggestions'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/fr_database.lng b/interface/web/sites/lib/lang/fr_database.lng index 4ae2592546..8057fbecbb 100644 --- a/interface/web/sites/lib/lang/fr_database.lng +++ b/interface/web/sites/lib/lang/fr_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Journalier'; $wb['weekly_backup_txt'] = 'Hebdomadaire'; $wb['monthly_backup_txt'] = 'Mensuel'; $wb['backup_interval_txt'] = 'Intervalle des Backups'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/fr_database_user.lng b/interface/web/sites/lib/lang/fr_database_user.lng index a0c2906ba3..21565bb3d4 100644 --- a/interface/web/sites/lib/lang/fr_database_user.lng +++ b/interface/web/sites/lib/lang/fr_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Search'; $wb['globalsearch_suggestions_text_txt'] = 'Suggestions'; $wb['limit_database_user_txt'] = 'Le nombre maximum d\'utilisateurs base de données a été atteint.'; $wb['database_password_error_empty'] = 'Le mot de passe de la base de données est vide.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/hr_database.lng b/interface/web/sites/lib/lang/hr_database.lng index 06674caf36..2dd1b18e19 100644 --- a/interface/web/sites/lib/lang/hr_database.lng +++ b/interface/web/sites/lib/lang/hr_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/hr_database_user.lng b/interface/web/sites/lib/lang/hr_database_user.lng index b6d632daa5..ef6f321604 100644 --- a/interface/web/sites/lib/lang/hr_database_user.lng +++ b/interface/web/sites/lib/lang/hr_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Traži'; $wb['globalsearch_suggestions_text_txt'] = 'Sugestija'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/hu_database.lng b/interface/web/sites/lib/lang/hu_database.lng index c387440577..c37a76af44 100644 --- a/interface/web/sites/lib/lang/hu_database.lng +++ b/interface/web/sites/lib/lang/hu_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/hu_database_user.lng b/interface/web/sites/lib/lang/hu_database_user.lng index e9860030cc..7a034103f8 100644 --- a/interface/web/sites/lib/lang/hu_database_user.lng +++ b/interface/web/sites/lib/lang/hu_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Search'; $wb['globalsearch_suggestions_text_txt'] = 'Suggestions'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/id_database.lng b/interface/web/sites/lib/lang/id_database.lng index 389a987cd7..9171b57b23 100644 --- a/interface/web/sites/lib/lang/id_database.lng +++ b/interface/web/sites/lib/lang/id_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/id_database_user.lng b/interface/web/sites/lib/lang/id_database_user.lng index e9860030cc..7a034103f8 100644 --- a/interface/web/sites/lib/lang/id_database_user.lng +++ b/interface/web/sites/lib/lang/id_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Search'; $wb['globalsearch_suggestions_text_txt'] = 'Suggestions'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/it_database.lng b/interface/web/sites/lib/lang/it_database.lng index 0ef8d635f8..84755bccf9 100644 --- a/interface/web/sites/lib/lang/it_database.lng +++ b/interface/web/sites/lib/lang/it_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Giornaliero'; $wb['weekly_backup_txt'] = 'Settimanale'; $wb['monthly_backup_txt'] = 'Mensile'; $wb['backup_interval_txt'] = 'Intervallo di Backup'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/it_database_user.lng b/interface/web/sites/lib/lang/it_database_user.lng index b024964bbc..4fc5059da5 100644 --- a/interface/web/sites/lib/lang/it_database_user.lng +++ b/interface/web/sites/lib/lang/it_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Cerca'; $wb['globalsearch_suggestions_text_txt'] = 'Suggerimenti'; $wb['limit_database_user_txt'] = 'Hai raggiunto il numero massimo di utenti database.'; $wb['database_password_error_empty'] = 'La password del Database è vuota.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/ja_database.lng b/interface/web/sites/lib/lang/ja_database.lng index bc684700fa..1d49b333a7 100644 --- a/interface/web/sites/lib/lang/ja_database.lng +++ b/interface/web/sites/lib/lang/ja_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/ja_database_user.lng b/interface/web/sites/lib/lang/ja_database_user.lng index e9860030cc..7a034103f8 100644 --- a/interface/web/sites/lib/lang/ja_database_user.lng +++ b/interface/web/sites/lib/lang/ja_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Search'; $wb['globalsearch_suggestions_text_txt'] = 'Suggestions'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/nl_database.lng b/interface/web/sites/lib/lang/nl_database.lng index abc5886ad3..43fcab9a8f 100644 --- a/interface/web/sites/lib/lang/nl_database.lng +++ b/interface/web/sites/lib/lang/nl_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/nl_database_user.lng b/interface/web/sites/lib/lang/nl_database_user.lng index 97b1fe761f..f61e60889f 100644 --- a/interface/web/sites/lib/lang/nl_database_user.lng +++ b/interface/web/sites/lib/lang/nl_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Zoeken'; $wb['globalsearch_suggestions_text_txt'] = 'Suggesties'; $wb['limit_database_user_txt'] = 'Het max. aantal database gebruikers is bereikt.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/pl_database.lng b/interface/web/sites/lib/lang/pl_database.lng index ffd8137c46..f8e05e9907 100644 --- a/interface/web/sites/lib/lang/pl_database.lng +++ b/interface/web/sites/lib/lang/pl_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/pl_database_user.lng b/interface/web/sites/lib/lang/pl_database_user.lng index e9860030cc..7a034103f8 100644 --- a/interface/web/sites/lib/lang/pl_database_user.lng +++ b/interface/web/sites/lib/lang/pl_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Search'; $wb['globalsearch_suggestions_text_txt'] = 'Suggestions'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/pt_database.lng b/interface/web/sites/lib/lang/pt_database.lng index 428129e381..1385fae3d5 100644 --- a/interface/web/sites/lib/lang/pt_database.lng +++ b/interface/web/sites/lib/lang/pt_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/pt_database_user.lng b/interface/web/sites/lib/lang/pt_database_user.lng index e9860030cc..7a034103f8 100644 --- a/interface/web/sites/lib/lang/pt_database_user.lng +++ b/interface/web/sites/lib/lang/pt_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Search'; $wb['globalsearch_suggestions_text_txt'] = 'Suggestions'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/ro_database.lng b/interface/web/sites/lib/lang/ro_database.lng index b9ed72443c..6c564067aa 100644 --- a/interface/web/sites/lib/lang/ro_database.lng +++ b/interface/web/sites/lib/lang/ro_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/ro_database_user.lng b/interface/web/sites/lib/lang/ro_database_user.lng index e9860030cc..7a034103f8 100644 --- a/interface/web/sites/lib/lang/ro_database_user.lng +++ b/interface/web/sites/lib/lang/ro_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Search'; $wb['globalsearch_suggestions_text_txt'] = 'Suggestions'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/ru_database.lng b/interface/web/sites/lib/lang/ru_database.lng index 31da0f8060..2adf5fcf42 100644 --- a/interface/web/sites/lib/lang/ru_database.lng +++ b/interface/web/sites/lib/lang/ru_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Ежедневно'; $wb['weekly_backup_txt'] = 'Еженедельно'; $wb['monthly_backup_txt'] = 'Ежемесячно'; $wb['backup_interval_txt'] = 'Интервал резервного копирования'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/ru_database_user.lng b/interface/web/sites/lib/lang/ru_database_user.lng index 47e419fc04..4d42804d26 100644 --- a/interface/web/sites/lib/lang/ru_database_user.lng +++ b/interface/web/sites/lib/lang/ru_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Поиск'; $wb['globalsearch_suggestions_text_txt'] = 'Подсказки'; $wb['limit_database_user_txt'] = 'Лимит пользователей баз данных достигнут.'; $wb['database_password_error_empty'] = 'Пароль базы данных пустой.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/se_database.lng b/interface/web/sites/lib/lang/se_database.lng index 77715a1912..c33fe5fe25 100644 --- a/interface/web/sites/lib/lang/se_database.lng +++ b/interface/web/sites/lib/lang/se_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/se_database_user.lng b/interface/web/sites/lib/lang/se_database_user.lng index 1dad984133..4faf679a5c 100644 --- a/interface/web/sites/lib/lang/se_database_user.lng +++ b/interface/web/sites/lib/lang/se_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Sök'; $wb['globalsearch_suggestions_text_txt'] = 'Förslag'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/sk_database.lng b/interface/web/sites/lib/lang/sk_database.lng index a3a914b21d..df4b77e35d 100644 --- a/interface/web/sites/lib/lang/sk_database.lng +++ b/interface/web/sites/lib/lang/sk_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Daily'; $wb['weekly_backup_txt'] = 'Weekly'; $wb['monthly_backup_txt'] = 'Monthly'; $wb['backup_interval_txt'] = 'Backup interval'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/sk_database_user.lng b/interface/web/sites/lib/lang/sk_database_user.lng index e9860030cc..7a034103f8 100644 --- a/interface/web/sites/lib/lang/sk_database_user.lng +++ b/interface/web/sites/lib/lang/sk_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Search'; $wb['globalsearch_suggestions_text_txt'] = 'Suggestions'; $wb['limit_database_user_txt'] = 'The max. number of database users is reached.'; $wb['database_password_error_empty'] = 'Database password is empty.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/lib/lang/tr_database.lng b/interface/web/sites/lib/lang/tr_database.lng index 07e963c25b..ff086a4e98 100644 --- a/interface/web/sites/lib/lang/tr_database.lng +++ b/interface/web/sites/lib/lang/tr_database.lng @@ -52,4 +52,5 @@ $wb['daily_backup_txt'] = 'Günlük'; $wb['weekly_backup_txt'] = 'Haftalık'; $wb['monthly_backup_txt'] = 'Aylık'; $wb['backup_interval_txt'] = 'Yedekleme Sıklığı'; -?> +$wb['error_db_user_in_use_txt'] = 'The database user is already in use. Please select a different user.'; +$wb['error_db_ro_user_in_use_txt'] = 'The readonly database user is already in use. Please select a different user.'; diff --git a/interface/web/sites/lib/lang/tr_database_user.lng b/interface/web/sites/lib/lang/tr_database_user.lng index 9e51fa6150..d4376e2450 100644 --- a/interface/web/sites/lib/lang/tr_database_user.lng +++ b/interface/web/sites/lib/lang/tr_database_user.lng @@ -22,4 +22,4 @@ $wb['globalsearch_searchfield_watermark_txt'] = 'Arama'; $wb['globalsearch_suggestions_text_txt'] = 'Öneriler'; $wb['limit_database_user_txt'] = 'Hesabınıza ekleyebileceğiniz en fazla veritabanı kullanıcısı sayısına ulaştınız.'; $wb['database_password_error_empty'] = 'Veritabanı parolası boş.'; -?> +$wb['error_del_db_user_in_use_txt'] = 'The user cannot be deleted. It is still being used by a database.'; diff --git a/interface/web/sites/templates/database_edit.htm b/interface/web/sites/templates/database_edit.htm index e6aa508e5f..7c4e2642bf 100644 --- a/interface/web/sites/templates/database_edit.htm +++ b/interface/web/sites/templates/database_edit.htm @@ -40,10 +40,18 @@
- -
+ + +
+ + + +
+
@@ -92,7 +100,7 @@
- +
diff --git a/server/lib/classes/cron.d/100-monitor_database_size.inc.php b/server/lib/classes/cron.d/100-monitor_database_size.inc.php index 3f0abed709..5cadd5722b 100644 --- a/server/lib/classes/cron.d/100-monitor_database_size.inc.php +++ b/server/lib/classes/cron.d/100-monitor_database_size.inc.php @@ -78,7 +78,7 @@ class cronjob_monitor_database_size extends cronjob { $state = 'ok'; /** Fetch the data of all databases into an array */ - $databases = $app->db->queryAllRecords("SELECT database_id, database_name, sys_groupid, database_quota, quota_exceeded FROM web_database WHERE server_id = ? ORDER BY sys_groupid, database_name ASC", $server_id); + $databases = $app->db->queryAllRecords("SELECT `database_id`, `database_name`, `sys_groupid`, `database_quota`, `quota_exceeded`, `type` FROM `web_database` WHERE `server_id` = ? ORDER BY `sys_groupid`, `database_name` ASC", $server_id); if(is_array($databases) && !empty($databases)) { @@ -88,7 +88,16 @@ class cronjob_monitor_database_size extends cronjob { $rec = $databases[$i]; $data[$i]['database_name']= $rec['database_name']; - $data[$i]['size'] = $app->db->getDatabaseSize($rec['database_name']); + if($rec['type'] == 'mysql') { + $data[$i]['size'] = $app->db->getDatabaseSize($rec['database_name']); + } elseif ($rec['type'] == 'postgresql') { + exec("cd /tmp; sudo -u postgres psql -d postgres -t -c \"SELECT pg_database_size('".escapeshellcmd($rec['database_name'])."');\"",$out); + if(is_array($out) && isset($out[0])) { + $data[$i]['size'] = trim($out[0]); + } else { + $data[$i]['size'] = 0; + } + } $data[$i]['sys_groupid'] = $rec['sys_groupid']; $quota = $rec['database_quota'] * 1024 * 1024; diff --git a/server/plugins-available/postgresql_clientdb_plugin.inc.php b/server/plugins-available/postgresql_clientdb_plugin.inc.php new file mode 100644 index 0000000000..d1b5fdcc74 --- /dev/null +++ b/server/plugins-available/postgresql_clientdb_plugin.inc.php @@ -0,0 +1,742 @@ +plugins->registerEvent('database_insert', $this->plugin_name, 'dbInsert'); + $app->plugins->registerEvent('database_update', $this->plugin_name, 'dbUpdate'); + $app->plugins->registerEvent('database_delete', $this->plugin_name, 'dbDelete'); + + //* Database users + // $app->plugins->registerEvent('database_user_insert', $this->plugin_name, 'dbUserInsert'); <- stale user accounts are useless ;) + $app->plugins->registerEvent('database_user_update', $this->plugin_name, 'dbUserUpdate'); + //$app->plugins->registerEvent('database_user_delete', $this->plugin_name, 'dbUserDelete'); + } + + function dbInsert($event_name, $data) { + global $app; + + if($data['new']['type'] != 'postgresql') { + return; + } + + // Create the database + $db_create_success = $this->createDatabase($data['new']); + + // Create the database users if database is active + if($db_create_success) { + if($data['new']['active'] == 'y') { + $db_user = $app->db->queryOneRecord('SELECT * FROM `web_database_user` WHERE `database_user_id` = ?', $data['new']['database_user_id']); + $db_ro_user = $app->db->queryOneRecord('SELECT * FROM `web_database_user` WHERE `database_user_id` = ?', $data['new']['database_ro_user_id']); + $host_list = $this->getHostList($data['new']); + + $this->createDBUser($data['new']['database_name'],$db_user,$host_list,'rw'); + if(!empty($db_ro_user)) $this->createDBUser($data['new']['database_name'],$db_ro_user,$host_list,'r'); + } + + // Reload postgres + $this->pg_reload_service(); + } + + } + + function dbUpdate($event_name, $data) { + global $app; + + if($data['new']['type'] != 'postgresql') { + return; + } + + // skip processing if database was and is inactive + if($data['new']['active'] == 'n' && $data['old']['active'] == 'n') { + return; + } + + $postgres_reload = false; + + // Database name changed + if($data['new']['database_name'] != $data['old']['database_name']) { + // Terminate connections + $sql = 'SELECT pg_terminate_backend(pg_stat_activity.pid) + FROM pg_stat_activity + WHERE pg_stat_activity.datname = '.$this->pg_escape_string($data['old']['database_name']).' + AND pid <> pg_backend_pid();'; + if($this->pg_query($sql)) { + $app->log('PostgreSQL terminate connections: ' . $sql, LOGLEVEL_DEBUG); + } else { + $app->log('PostgreSQL terminate connections failed: ' . $this->psql_error, LOGLEVEL_WARN); + } + + // Rename database + $sql = 'ALTER DATABASE '.$data['old']['database_name'].' RENAME TO '.$data['new']['database_name'].';'; + if($this->pg_query($sql)) { + $app->log('PostgreSQL rename DB: ' . $sql, LOGLEVEL_DEBUG); + } else { + $app->log('PostgreSQL rename DB failed: ' . $this->psql_error, LOGLEVEL_WARN); + } + } + + + // RO user has been changed + if($data['new']['database_ro_user_id'] != $data['old']['database_ro_user_id']) { + // Remove old ro user, if there is one + $db_ro_user = $app->db->queryOneRecord('SELECT * FROM `web_database_user` WHERE `database_user_id` = ?', $data['old']['database_ro_user_id']); + if(!empty($db_ro_user)) $this->deleteDBUser($data['new'], $db_ro_user); + if($data['new']['database_ro_user_id'] > 0) { + $host_list = $this->getHostList($data['new']); + $db_ro_user = $app->db->queryOneRecord('SELECT * FROM `web_database_user` WHERE `database_user_id` = ?', $data['new']['database_ro_user_id']); + $this->createDBUser($data['new']['database_name'],$db_ro_user,$host_list,'r'); + } + $postgres_reload = true; + } + + // RW user has been changed + if($data['new']['database_user_id'] != $data['old']['database_user_id']) { + + // create new user first + $host_list = $this->getHostList($data['new']); + $db_user = $app->db->queryOneRecord('SELECT * FROM `web_database_user` WHERE `database_user_id` = ?', $data['new']['database_user_id']); + $old_db_user = $app->db->queryOneRecord('SELECT * FROM `web_database_user` WHERE `database_user_id` = ?', $data['old']['database_user_id']); + $this->createDBUser($data['new']['database_name'],$db_user,$host_list,'rw'); + + // Assign content of old user to new user + $sql = 'REASSIGN OWNED BY '.$old_db_user['database_user'].' TO '.$db_user['database_user'].';'; + if($this->pg_query($sql)) { + $app->log('PostgreSQL reassigning data: ' . $sql, LOGLEVEL_DEBUG); + } else { + $app->log('PostgreSQL reassigning data ' . $this->psql_error, LOGLEVEL_WARN); + } + + // Remove old user + $this->deleteDBUser($data['new'], $old_db_user); + $postgres_reload = true; + } + + // Database has been activated + if($data['new']['active'] == 'y' && $data['old']['active'] == 'n') { + if($data['new']['active'] == 'y') { + $db_user = $app->db->queryOneRecord('SELECT * FROM `web_database_user` WHERE `database_user_id` = ?', $data['new']['database_user_id']); + $db_ro_user = $app->db->queryOneRecord('SELECT * FROM `web_database_user` WHERE `database_user_id` = ?', $data['new']['database_ro_user_id']); + $host_list = $this->getHostList($data['new']); + + $this->createDBUser($data['new']['database_name'],$db_user,$host_list,'rw'); + if(!empty($db_ro_user)) $this->createDBUser($data['new']['database_name'],$db_ro_user,$host_list,'r'); + } + + $postgres_reload = true; + } + + // Database has been deactivated + if($data['new']['active'] == 'n' && $data['old']['active'] == 'y') { + // Get record for db and ro user + $db_user = $app->db->queryOneRecord('SELECT * FROM `web_database_user` WHERE `database_user_id` = ?', $data['new']['database_user_id']); + $db_ro_user = $app->db->queryOneRecord('SELECT * FROM `web_database_user` WHERE `database_user_id` = ?', $data['new']['database_ro_user_id']); + + // Delete database user + if(!empty($db_user)) $this->deleteDBUser($data['new'], $db_user); + if(!empty($db_ro_user)) $this->deleteDBUser($data['new'], $db_ro_user); + $postgres_reload = true; + } + + + // hosts list has been changed or database has been changed so we must update pg_hba.conf + if($data['new']['remote_access'] != $data['old']['remote_access'] || + $data['new']['remote_ips'] != $data['old']['remote_ips'] || + $data['new']['database_name'] != $data['old']['database_name']) { + + $host_list = $this->getHostList($data['new']); + + $db_user = $app->db->queryOneRecord('SELECT * FROM `web_database_user` WHERE `database_user_id` = ?', $data['new']['database_user_id']); + $db_ro_user = $app->db->queryOneRecord('SELECT * FROM `web_database_user` WHERE `database_user_id` = ?', $data['new']['database_ro_user_id']); + + $this->pg_hba_user_del($db_user['database_user'],$data['new']['database_name']); + if(!empty($db_ro_user)) $this->pg_hba_user_del($db_ro_user['database_user'],$data['new']['database_name']); + if($data['new']['database_name'] != $data['old']['database_name']) { + $this->pg_hba_user_del($db_user['database_user'],$data['old']['database_name']); + if(!empty($db_ro_user)) $this->pg_hba_user_del($db_ro_user['database_user'],$data['old']['database_name']); + } + + // Configure hosts for the user + if(is_array($host_list)) { + foreach($host_list as $host) { + $this->pg_hba_user_add($db_user['database_user'],$data['new']['database_name'],$host); + if(!empty($db_ro_user)) $this->pg_hba_user_add($db_ro_user['database_user'],$data['new']['database_name'],$host); + } + } + + $postgres_reload = true; + } + + // Reload postgres + if($postgres_reload) { + $this->pg_reload_service(); + } + } + + function dbDelete($event_name, $data) { + global $app; + + if($data['old']['type'] != 'postgresql') { + return; + } + + // Delete the PostgreSQL database + $this->deleteDatabase($data['old']); + + // Get record for db and ro user + $db_user = $app->db->queryOneRecord('SELECT * FROM `web_database_user` WHERE `database_user_id` = ?', $data['old']['database_user_id']); + $db_ro_user = $app->db->queryOneRecord('SELECT * FROM `web_database_user` WHERE `database_user_id` = ?', $data['old']['database_ro_user_id']); + + // Delete database user + if(!empty($db_user)) $this->deleteDBUser($data['old'], $db_user); + if(!empty($db_ro_user)) $this->deleteDBUser($data['old'], $db_ro_user); + + // Reload postgres + $this->pg_reload_service(); + + } + + function dbUserUpdate($event_name, $data) { + global $app; + + // nothing to do when username and password are the same. No need to check postgresql password since it is always in sync with database_password + if($data['old']['database_user'] == $data['new']['database_user'] && ($data['old']['database_password'] == $data['new']['database_password'] || $data['new']['database_password'] == '')) { + return; + } + + // get all databases this user was active for + $user_id = intval($data['old']['database_user_id']); + $db_list = $app->db->queryAllRecords('SELECT `remote_access`, `remote_ips` FROM `web_database` WHERE (`database_user_id` = ? OR database_ro_user_id = ?) AND `type` = "postgresql"', $user_id, $user_id); + // nothing to do on this server for this db user + if(empty($db_list)) { + return; + } + + // Update the password + if($data['old']['database_password'] != $data['new']['database_password']) { + $sql = 'ALTER ROLE '.$data['old']['database_user'].' WITH ENCRYPTED PASSWORD '.$this->pg_escape_string($data['new']['database_password_postgres']).';'; + if($this->pg_query($sql)) { + $app->log('PostgreSQL user password changed: ' . $sql, LOGLEVEL_DEBUG); + } else { + $app->log('PostgreSQL user password changed ' . $this->psql_error, LOGLEVEL_WARN); + } + } + + // update the username + if($data['old']['database_user'] != $data['new']['database_user']) { + $sql = 'ALTER ROLE '.$data['old']['database_user'].' RENAME TO '.$data['new']['database_user'].';'; + if($this->pg_query($sql)) { + $app->log('PostgreSQL username changed: ' . $sql, LOGLEVEL_DEBUG); + } else { + $app->log('PostgreSQL username changed ' . $this->psql_error, LOGLEVEL_WARN); + } + // get database name + $databases = $app->db->queryAllRecords('SELECT * FROM `web_database` WHERE `database_user_id` = ? OR `database_ro_user_id` = ?',$data['new']['database_user_id'],$data['new']['database_user_id']); + if(is_array($databases)) { + foreach($databases as $database) { + $this->pg_hba_user_del($data['old']['database_user'],$database['database_name']); + $host_list = $this->getHostList($database); + // Configure hosts for the user + if(is_array($host_list)) { + foreach($host_list as $host) { + $this->pg_hba_user_add($data['new']['database_user'],$database['database_name'],$host); + } + } + } + } + + // Reload postgres + $this->pg_reload_service(); + } + + } + + /** + * Creates a PostgreSQL database + * + * @param array $record + * @return bool + */ + private function createDatabase($record) { + global $app; + + if(in_array(strtolower($record['database_name']), $this->denylist_database)) { + $app->log('Refuse to create database ' . $record['database_name'], LOGLEVEL_WARN); + return false; + } + + if(!$this->pg_connect()) return false; + + // Charset for the new table + $query_charset_table = ''; + /* + if($record['database_charset'] != '') { + if($record['database_charset'] == 'utf8mb4') $record['database_charset'] = 'utf8'; + $query_charset_table = " WITH ENCODING " . $this->pg_escape_string(strtoupper($record['database_charset'])).""; + } else { + $query_charset_table = ''; + } + */ + + //* Create the new database + $sql = 'CREATE DATABASE ' . $record['database_name'] . '' . $query_charset_table.';'; + if($this->pg_query($sql)) { + $app->log('Created PostgreSQL database: ' . $sql, LOGLEVEL_DEBUG); + return true; + } else { + $app->log('Unable to create the database: ' . $this->psql_error, LOGLEVEL_WARN); + return false; + } + } + + /** + * Drops a PostgeSQL database + * + * @param array $record + * @return bool + */ + private function deleteDatabase($record) { + global $app; + + if(in_array(strtolower($record['database_name']), $this->denylist_database)) { + $app->log('Refuse to delete database ' . $record['database_name'], LOGLEVEL_WARN); + return false; + } + + $sql = 'DROP DATABASE IF EXISTS ' . $record['database_name'] . ' WITH (FORCE);'; + if($this->pg_query($sql)) { + $app->log('Dropping PostgreSQL database: ' . $sql, LOGLEVEL_DEBUG); + return true; + } else { + $app->log('Error while dropping PostgreSQL database: ' . $record['database_name'] . ' ' . $this->psql_error, LOGLEVEL_WARN); + return false; + } + } + + + function createDBUser($database, $db_user, $host_list, $mode) { + global $app; + + if(in_array(strtolower($db_user['database_user']), $this->denylist_user)) { + $app->log('Refuse to set password for user ' . $db_user['database_user'], LOGLEVEL_WARN); + return false; + } + + $username = $db_user['database_user']; + $password = !empty($db_user['database_password_postgres']) ? $db_user['database_password_postgres'] : ''; + + // Create the user + $sql = 'DO $$ +BEGIN + IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '.$this->pg_escape_string($username).') THEN + CREATE ROLE '.$username.' WITH LOGIN ENCRYPTED PASSWORD '.$this->pg_escape_string($password).'; + END IF; +END $$;'; + + if($this->pg_query($sql)) { + $app->log('Created PostgreSQL user: ' . $sql, LOGLEVEL_DEBUG); + } else { + $app->log('Unable to create PostgreSQL user: '.$sql. ' --- ' . $this->psql_error, LOGLEVEL_WARN); + return false; + } + + // Grant permissions + $sql = 'GRANT CONNECT ON DATABASE '.$database.' TO '.$username.';'; + if($this->pg_query($sql)) { + $app->log('Created PostgreSQL user: ' . $sql, LOGLEVEL_DEBUG); + } else { + $app->log('Unable to create PostgreSQL user: '.$sql. ' --- ' . $this->psql_error, LOGLEVEL_WARN); + return false; + } + + if($mode == 'r') { + $sql = 'GRANT pg_read_all_data TO '.$username.';'; + if($this->pg_query($sql)) { + $app->log('Created PostgreSQL user: ' . $sql, LOGLEVEL_DEBUG); + } else { + $app->log('Unable to create PostgreSQL user: '.$sql. ' --- ' . $this->psql_error, LOGLEVEL_WARN); + return false; + } + } else { + $sql = 'ALTER DATABASE '.$database.' OWNER TO '.$username.';'; + if($this->pg_query($sql)) { + $app->log('Created PostgreSQL user: ' . $sql, LOGLEVEL_DEBUG); + } else { + $app->log('Unable to create PostgreSQL user: '.$sql. ' --- ' . $this->psql_error, LOGLEVEL_WARN); + return false; + } + } + + // Configure hosts for the user + if(is_array($host_list)) { + foreach($host_list as $host) { + $this->pg_hba_user_add($username,$database,$host); + } + } + } + + function deleteDBUser($db_rec, $db_user) { + global $app; + + if(in_array(strtolower($db_user['database_user']), $this->denylist_user)) { + $app->log('Refuse to set password for user ' . $db_user['database_user'], LOGLEVEL_WARN); + return false; + } + + if(!is_array($db_rec) || !is_array($db_user)) { + $app->log('ÜostgreSQL DB or user record is not an array.', LOGLEVEL_DEBUG); + return false; + } + + $username = $db_user['database_user']; + $database = $db_rec['database_name']; + + // Delete user if no other database is using it + $sql = "SELECT * FROM `web_database` WHERE (`database_user_id` = ? OR `database_ro_user_id` = ?) AND `type` = 'postgresql' AND `database_id` != ?"; + $tmp = $app->db->queryAllRecords($sql,$db_user['database_user_id'],$db_user['database_user_id'],$db_rec['database_id']); + if(empty($tmp)) { + $sql = 'DROP USER IF EXISTS '.$username.';'; + if($this->pg_query($sql)) { + $app->log('Drop PostgreSQL user: ' . $sql, LOGLEVEL_DEBUG); + } else { + $app->log('Unable to drop PostgreSQL user: '.$sql. ' --- ' . $this->psql_error, LOGLEVEL_WARN); + return false; + } + } + + + // Delete user permissions in pg_hba.conf + $this->pg_hba_user_del($username,$database); + } + + /** + * Get list of hosts that this database is accessible from. + * + * @param array $db_record + * @return array + */ + private function getHostList($db_record) { + $host_list = []; + if($db_record['remote_access'] == 'y') { + $host_list = array_filter(array_map(function($ip) { + return filter_var(trim($ip), FILTER_VALIDATE_IP); + }, explode(',', $db_record['remote_ips'] ?: ''))); + if(empty($host_list)) { + $host_list[] = '0.0.0.0/0'; + } + } + $host_list[] = '127.0.0.1/32'; + $host_list = array_values(array_unique($host_list)); + sort($host_list); + + return $host_list; + } + + + /** + * Get host list of all other databases of the user. + * + * @param int $database_id + * @param int $user_id + * @return array + */ + private function getOtherHostList($database_id, $user_id) { + global $app; + + $db_user_host_list = []; + $other_user_databases = $app->db->queryAllRecords("SELECT `remote_access`, `remote_ips` FROM web_database WHERE (database_user_id = ? OR database_ro_user_id = ?) AND active = 'y' AND database_id != ?", + $user_id, $user_id, $database_id); + foreach($other_user_databases as $record) { + $db_user_host_list = array_merge($db_user_host_list, $this->getHostList($record)); + } + + return array_values(array_unique($db_user_host_list)); + } + + private function pg_connect() { + global $app; + + if($this->link) { + return true; + } else { + + if(!function_exists('pg_connect')) { + $app->log('PostgreSQL functions in PHP missing. Please install PHP postgresql extension.', LOGLEVEL_WARN); + return false; + } + + $clientdb_host = ''; + $clientdb_user = ''; + $clientdb_password = ''; + + // Check if we have a ISPConfig postgres config file + if(!file_exists(ISPC_LIB_PATH . '/postgresql_clientdb.conf')) { + // Create a new ispconfig posgres users and config file + $clientdb_host = 'localhost'; + $clientdb_user = 'ispconfig'; + $clientdb_password = $this->generatePassword(); + + $config_file_content = 'psql("CREATE ROLE ispconfig WITH SUPERUSER CREATEDB CREATEROLE LOGIN PASSWORD '$clientdb_password';"); + + $pg_hba_path = $this->get_pg_hba_path(); + $config = "local all ispconfig scram-sha-256\nhost all ispconfig 127.0.0.1/32 scram-sha-256"; + file_put_contents($pg_hba_path,$config,FILE_APPEND); + + $this->pg_reload_service(); + + } else { + if(!include ISPC_LIB_PATH . '/postgresql_clientdb.conf') { + $app->log('Unable to open' . ISPC_LIB_PATH . '/postgresql_clientdb.conf', LOGLEVEL_WARN); + return false; + } + } + + $this->clientdb_host = $clientdb_host; + $this->clientdb_user = $clientdb_user; + $this->clientdb_password = $clientdb_password; + + $this->link = pg_connect("host=".$this->clientdb_host." dbname=postgres user=".$this->clientdb_user." password=".$this->clientdb_password); + + if(!$this->link) { + $app->log("PostgreSQL Login failed.", LOGLEVEL_WARN); + return false; + } else { + // Check Postgres version + if($this->pg_version_check()) { + return true; + } else { + $app->log("Minimum PostgreSQL version is: ".$this->pg_min_version, LOGLEVEL_WARN); + return false; + } + } + } + } + + private function pg_escape_string($string) { + if(!$this->pg_connect()) return false; + return pg_escape_literal($this->link,$string); + } + + private function pg_query($sql) { + if(!$this->pg_connect()) return false; + return pg_query($this->link,$sql); + } + + private function pg_query_one_record($sql) { + $result = $this->pg_query($sql); + return pg_fetch_array($result, NULL, PGSQL_ASSOC); + } + + private function pg_disconnect() { + if ($this->link) { + pg_close($this->link); + $this->link = null; + } + } + + private function generatePassword($length = 16) { + // Define character sets + $lowercase = 'abcdefghijklmnopqrstuvwxyz'; + $uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $digits = '0123456789'; + $specialChars = '!@#$%^&*()_-+=<>?{}[]|'; + + // Ensure the password contains at least one character from each set + $password = ''; + $password .= $lowercase[random_int(0, strlen($lowercase) - 1)]; + $password .= $uppercase[random_int(0, strlen($uppercase) - 1)]; + $password .= $digits[random_int(0, strlen($digits) - 1)]; + $password .= $specialChars[random_int(0, strlen($specialChars) - 1)]; + + // Create a pool of all characters and add more to meet the required length + $allChars = $lowercase . $uppercase . $digits . $specialChars; + for ($i = 4; $i < $length; $i++) { + $password .= $allChars[random_int(0, strlen($allChars) - 1)]; + } + + // Shuffle the password to randomize the order of characters + return str_shuffle($password); + } + + // Run postgres sql commands via command_line as postgres user + private function psql($query) { + // Sanitize and escape the query to avoid shell injection + $escapedQuery = escapeshellarg($query); + + // Build the command using `sudo -u postgres` to execute as the `postgres` user + $command = "sudo -u postgres psql -c $escapedQuery 2>&1"; + + // Execute the command using exec() + exec($command, $output, $returnVar); + + // Check if the execution was successful + if ($returnVar !== 0) { + // If there was an error, return false and the error message + $this->psql_error = implode("\n", $output); + return false; + } + + // Return the output if the query executed successfully + return implode("\n", $output); + } + + private function get_pg_hba_path() { + $files = glob('/etc/postgresql/*/main/pg_hba.conf'); + if(is_array($files) && !empty($files[0])) { + return $files[0]; + } else { + return false; + } + } + + private function pg_hba_user_del ($username,$database = '',$host = '') { + $file_path = $this->get_pg_hba_path(); + if(!empty($file_path)) { + $lines = explode("\n",file_get_contents($file_path)); + $out_array = []; + $regex = '/^(local|host)\s+(\S+)\s+(\S+)(\s+(\S+\/\d+|\S+))?\s+(peer|scram-sha-256)$/'; + foreach($lines as $line) { + $line = trim($line); + if(!empty($line) && substr($line,0,1) != '#') { + if(preg_match($regex,$line,$match)) { + list($full_match, $m_connection_type, $m_database, $m_username, $m_host, $m_auth_method) = $match; + $m_connection_type = trim($m_connection_type); + $m_database = trim($m_database); + $m_username = trim($m_username); + $m_host = trim($m_host); + $m_auth_method = trim($m_auth_method); + if($database == '' && $host == '') { + if($m_username == $username) continue; + } elseif ($database != '' && $host == '') { + if($m_username == $username && $m_database == $database) continue; + } else { + if($m_username == $username && $m_database == $database && $m_host == $host) continue; + } + } + } + $out_array[] = $line; + } + file_put_contents($file_path,implode("\n",$out_array)); + } + } + + private function pg_hba_user_add ($username,$database,$host) { + $file_path = $this->get_pg_hba_path(); + if(!empty($file_path)) { + + if($host == 'local') { + $config = "local $database $username scram-sha-256"; + } else { + $config = "host $database $username $host scram-sha-256"; + } + $lines = explode("\n",file_get_contents($file_path)); + $lines[] = $config; + file_put_contents($file_path,implode("\n",$lines)); + } + } + + private function pg_reload_service() { + exec('systemctl reload postgresql'); + } + + private function pg_version_check() { + $rec = $this->pg_query_one_record("SELECT current_setting('server_version');"); + if(is_array($rec)) { + $version = $rec['current_setting']; + $version = explode(' ',$version); + if(version_compare($version[0],$this->pg_min_version) >= 0) { + return true; + } else { + return false; + } + } else { + return false; + } + + + } + + +} // end class -- GitLab