Compare commits

...

13 Commits

Author SHA1 Message Date
Michael Kaufmann
775d50306c set version to 2.1.6 for bugfix/regression release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-02-03 14:22:33 +01:00
Michael Kaufmann
3821144c3b also fix unittests accordingly
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-02-03 14:08:23 +01:00
Michael Kaufmann
a1da70c221 fix password crypt hash being always evaluated to argon2i as the case always returns true if PASSWORD_ARGON2I is defined but the froxlor setting might be set to another hash leading to a useless password
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-02-03 13:49:43 +01:00
Michael Kaufmann
bb2db0fed0 set version to 2.1.5 for bugfix release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-02-02 11:18:48 +01:00
Michael Kaufmann
9680f24640 fix check for allowed_phpconfigs if using mod_php when adding/editing a customer
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-30 19:32:10 +01:00
Michael Kaufmann
c732fbd81b set correct channel for update-check if switching from apt-installed stable/testing to nightly
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-26 13:57:51 +01:00
Michael Kaufmann
7980b8d14d create empty dns-server config if no (dns-enabled) domain is determined; fixes #1230
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-24 08:39:16 +01:00
Michael Kaufmann
13e88f5b47 fix incorrect top-5 customers in traffic overview for admins; show manual update command if webupdate is disabled
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-19 09:22:12 +01:00
sro0
031596301b Check for argon2 support before using constant PASSWORD_ARGON2X (#1228) 2024-01-16 21:40:03 +01:00
Michael Kaufmann
b34ab45746 disable pam auth in dovecot for debian bookworm (like the other distros do it)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-07 09:06:15 +01:00
Michael Kaufmann
dbf83c6f24 build nightly only from main branch #2
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-06 15:01:52 +01:00
Michael Kaufmann
4cb974839c build nightly only from main branch
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-06 14:54:23 +01:00
Michael Kaufmann
1fa714ef2c add v2.1 branch to security md as currently supported as well as update main-branch version; add field.disabled attribute to formfield-input-template
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-06 14:48:41 +01:00
19 changed files with 65 additions and 39 deletions

View File

@@ -53,7 +53,7 @@ jobs:
name: Create nightly/testing tarball
runs-on: ubuntu-latest
needs: froxlor
if: ${{ github.event_name == 'push' }}
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
steps:
- name: Checkout

View File

@@ -10,7 +10,8 @@ With that, good luck hacking us ;)
## Supported versions
- ️✅ **2.1.x** (`main` git-branch)
- ️✅ **2.2.x** (`main` git-branch)
- ️✅ **2.1.x** (`v2.1` git-branch)
- ❌ 2.0.x (`2.0.x`-tags)
- ❌ 0.10.x (`0.10.x`-tags)
- ❌ other git-branches

View File

@@ -726,7 +726,7 @@ opcache.validate_timestamps'),
('panel', 'logo_overridecustom', '0'),
('panel', 'settings_mode', '0'),
('panel', 'menu_collapsed', '1'),
('panel', 'version', '2.1.4'),
('panel', 'version', '2.1.6'),
('panel', 'db_version', '202312120');

View File

@@ -279,3 +279,13 @@ if (Froxlor::isFroxlorVersion('2.1.3')) {
Update::showUpdateStep("Updating from 2.1.3 to 2.1.4", false);
Froxlor::updateToVersion('2.1.4');
}
if (Froxlor::isFroxlorVersion('2.1.4')) {
Update::showUpdateStep("Updating from 2.1.4 to 2.1.5", false);
Froxlor::updateToVersion('2.1.5');
}
if (Froxlor::isFroxlorVersion('2.1.5')) {
Update::showUpdateStep("Updating from 2.1.5 to 2.1.6", false);
Froxlor::updateToVersion('2.1.6');
}

View File

@@ -400,8 +400,11 @@ class Customers extends ApiCommand implements ResourceEntity
$allowed_phpconfigs = array_map('intval', $allowed_phpconfigs);
if (empty($allowed_phpconfigs) && $phpenabled == 1) {
// only required if not using mod_php
if ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) {
Response::standardError('customerphpenabledbutnoconfig', '', true);
}
}
$allowed_mysqlserver = array();
if (! empty($p_allowed_mysqlserver) && is_array($p_allowed_mysqlserver)) {
@@ -1114,8 +1117,11 @@ class Customers extends ApiCommand implements ResourceEntity
$allowed_phpconfigs = array_map('intval', $allowed_phpconfigs);
}
if (empty($allowed_phpconfigs) && $phpenabled == 1) {
// only required if not using mod_php
if ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) {
Response::standardError('customerphpenabledbutnoconfig', '', true);
}
}
// add permission for allowed mysql usage if customer was not allowed to use mysql prior
if ($result['mysqls'] == 0 && ($mysqls == -1 || $mysqls > 0)) {

View File

@@ -157,10 +157,10 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
// prefix hash-algo
switch (Settings::Get('system.passwordcryptfunc')) {
case PASSWORD_ARGON2I:
case 'argon2i':
$cpPrefix = '{ARGON2I}';
break;
case PASSWORD_ARGON2ID:
case 'argon2id':
$cpPrefix = '{ARGON2ID}';
break;
default:
@@ -404,10 +404,10 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
$password = Crypt::validatePassword($password, true);
// prefix hash-algo
switch (Settings::Get('system.passwordcryptfunc')) {
case PASSWORD_ARGON2I:
case 'argon2i':
$cpPrefix = '{ARGON2I}';
break;
case PASSWORD_ARGON2ID:
case 'argon2id':
$cpPrefix = '{ARGON2ID}';
break;
default:

View File

@@ -110,7 +110,7 @@ final class UpdateCommand extends CliCommand
$newversionavail = true;
$output->writeln('<comment>' . $text . '</>');
$result = self::SUCCESS;
} else if ($aucheck < 0 || $aucheck > 1) {
} elseif ($aucheck < 0 || $aucheck > 1) {
if ($input->getOption('integer-return')) {
$output->write(-1);
return self::INVALID;

View File

@@ -55,12 +55,10 @@ class Bind extends DnsBase
$domains = $this->getDomainList();
if (empty($domains)) {
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, skipping...');
return;
}
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, not creating any zones...');
$this->bindconf_file = '';
} else {
$this->bindconf_file = '# ' . Settings::Get('system.bindconf_directory') . 'froxlor_bind.conf' . "\n" . '# Created ' . date('d.m.Y H:i') . "\n" . '# Do NOT manually edit this file, all changes will be deleted after the next domain change at the panel.' . "\n\n";
foreach ($domains as $domain) {
if ($domain['is_child']) {
// domains that are subdomains to other main domains are handled by recursion within walkDomainList()
@@ -68,6 +66,7 @@ class Bind extends DnsBase
}
$this->walkDomainList($domain, $domains);
}
}
$bindconf_file_handler = fopen(FileDir::makeCorrectFile(Settings::Get('system.bindconf_directory') . '/froxlor_bind.conf'), 'w');
fwrite($bindconf_file_handler, $this->bindconf_file);

View File

@@ -45,10 +45,8 @@ class PowerDNS extends DnsBase
$this->clearZoneTables($domains);
if (empty($domains)) {
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, skipping...');
return;
}
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, not creating any zones...');
} else {
foreach ($domains as $domain) {
if ($domain['is_child']) {
// domains that are subdomains to other main domains are handled by recursion within walkDomainList()
@@ -56,7 +54,7 @@ class PowerDNS extends DnsBase
}
$this->walkDomainList($domain, $domains);
}
}
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'PowerDNS database updated');
$this->reloadDaemon();
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task4 finished');

View File

@@ -31,7 +31,7 @@ final class Froxlor
{
// Main version variable
const VERSION = '2.1.4';
const VERSION = '2.1.6';
// Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '202312120';

View File

@@ -69,7 +69,7 @@ class AutoUpdate
if (Settings::Get('system.update_channel') == 'testing') {
$channel = '/testing';
} elseif (Settings::Get('system.update_channel') == 'nightly') {
if (empty(Froxlor::BRANDING)) {
if (empty(Froxlor::BRANDING) || substr(Froxlor::BRANDING, 0, 1) == '-') {
$channel = '/nightly.0000000';
} else {
$channel = '/' . substr(Froxlor::BRANDING, 1);

View File

@@ -102,6 +102,14 @@ class Traffic
$years_avail = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC);
}
// sort users by total traffic
usort($users, function ($user_a, $user_b) {
if ($user_a['total'] == $user_b['total']) {
return 0;
}
return ($user_a['total'] < $user_b['total']) ? 1 : -1;
});
return [
'metrics' => $metrics,
'users' => $users,

View File

@@ -2547,6 +2547,7 @@ plugin {
</file>
</files>
<commands index="1">
<command><![CDATA[sed -i.bak 's/^!include auth-system.conf.ext/#!include auth-system.conf.ext/' /etc/dovecot/conf.d/10-auth.conf]]></command>
<command><![CDATA[service dovecot restart]]></command>
</commands>
</general>

View File

@@ -2270,7 +2270,7 @@ Vielen Dank, Ihr Administrator',
'install' => [
'top' => 'Abschluss',
'title' => 'Ein letzter Schritt...',
'description' => 'Der untenstehende Befehl lädt, installiert und konfiguriert die benötigten Dienste auf dem System aufgrund der Angaben die während des Installationsprozessen gesammelt wurden.<br><br><span class="text-danger">Führe die gezeigten Befehle als <b>root</b> in der Shell/Konsole des Servers aus.</span>',
'description' => 'Der untenstehende Befehl lädt, installiert und konfiguriert die benötigten Dienste auf dem System aufgrund der Angaben die während des Installationsprozessen gesammelt wurden.<br><br><span class="text-danger">Führe die gezeigten Befehle als <b>root</b> in der Shell/Konsole des Servers aus. <b>Beachte bitte</b> das dieser Befehl vorhandene Konfigurationen <b>überschreibt</b> (Sicherungsdateien werden erstellt)!<br>Sollte dies nicht gewünscht sein, wähle <i>Ich werden die Dienste manuell konfigurieren</i> am Ende dieser Seite.</span>',
'runcmd' => 'Folgende Befehle ausführen, um die Installation abzuschließen:',
'manual_config' => 'Ich werden die Dienste manuell konfigurieren, direkt zum Login umleiten',
'waitforconfig' => 'Warte auf Abschluss der Dienstkonfiguration...',

View File

@@ -2406,7 +2406,7 @@ Yours sincerely, your administrator',
'install' => [
'top' => 'Finish setup',
'title' => 'One last step...',
'description' => 'The command below will download, install and configure required services on your system according to the data you have given in this installation process.<br><br><span class="text-danger">Be sure to run the following command as <b>root</b> on the server\'s shell/terminal.</span>',
'description' => 'The command below will download, install and configure required services on your system according to the data you have given in this installation process.<br><br><span class="text-danger">Be sure to run the following command as <b>root</b> on the server\'s shell/terminal and <b>be aware</b> that this command will <b>overwrite</b> any existing configuration for the used services (backups will be created)!.<br>If you do not want to overwrite any configurations, select <i>I will manually configure the services</i> at the bottom of this page!</span>',
'runcmd' => 'Run the following command to finish the installation:',
'manual_config' => 'I will manually configure the services, just take me to the login',
'waitforconfig' => 'Waiting for services to be configured...',

View File

@@ -159,7 +159,7 @@
{% if field.next_to is defined %}
<div class="input-group">
{% endif %}
<input type="{{ field.type }}" {% if field.visible is defined and field.visible == false %} disabled {% endif %} {% if field.type == 'number' and field.min is defined %} min="{{ field.min }}" {% endif %} {% if field.type == 'number' and field.max is defined %} max="{{ field.max }}" {% endif %} {% if field.type != 'number' and field.maxlength is defined %} maxlength="{{ field.maxlength }}" {% endif %} id="{{ id }}" name="{{ id }}" value="{{ field.value|raw }}" class="form-control {% if field.valid is defined and field.valid == false %}is-invalid{% endif %}" {% if field.mandatory is defined and field.mandatory %} required {% endif %} {% if field.readonly is defined and field.readonly %} readonly {% endif %} {% if field.autocomplete is defined %} autocomplete="{{ field.autocomplete }}" {% endif %} {% if field.placeholder is defined %} placeholder="{{ field.placeholder }}" {% endif %} {% if field.type == 'file' and field.accept is defined %} accept="{{ field.accept }}" {% endif %} {% if field.pattern is defined %} pattern="{{ field.pattern }}" {% endif %}/>
<input type="{{ field.type }}" {% if (field.visible is defined and field.visible == false) or (field.disabled is defined and field.disabled == true) %} disabled {% endif %} {% if field.type == 'number' and field.min is defined %} min="{{ field.min }}" {% endif %} {% if field.type == 'number' and field.max is defined %} max="{{ field.max }}" {% endif %} {% if field.type != 'number' and field.maxlength is defined %} maxlength="{{ field.maxlength }}" {% endif %} id="{{ id }}" name="{{ id }}" value="{{ field.value|raw }}" class="form-control {% if field.valid is defined and field.valid == false %}is-invalid{% endif %}" {% if field.mandatory is defined and field.mandatory %} required {% endif %} {% if field.readonly is defined and field.readonly %} readonly {% endif %} {% if field.autocomplete is defined %} autocomplete="{{ field.autocomplete }}" {% endif %} {% if field.placeholder is defined %} placeholder="{{ field.placeholder }}" {% endif %} {% if field.type == 'file' and field.accept is defined %} accept="{{ field.accept }}" {% endif %} {% if field.pattern is defined %} pattern="{{ field.pattern }}" {% endif %}/>
{% if field.type == 'hidden' and field.display is defined %}
<input type="text" readonly class="form-control-plaintext" value="{{ field.display|raw }}">
{% endif %}

View File

@@ -21,6 +21,9 @@
<p>{{ message }}</p>
{% if get_config('enable_webupdate') %}
<a class='btn d-block btn-outline-warning' href='admin_autoupdate.php?page=overview'>Open updater</a>
{% else %}
<p>Run the following command in your shell to update:</p>
<code>{{ call_static('\\Froxlor\\Froxlor', 'getInstallDir') }}bin/froxlor-cli froxlor:update</code>
{% endif %}
{% endif %}
{% endmacro %}

View File

@@ -152,7 +152,7 @@
{% if userinfo.adminsession == 1 %}
const labelsC = [];
const dataValues = [];
{% for user in users|sort((a, b) => a.total <=> b.total)|slice(0, 5) %}
{% for user in users|slice(0, 5) %}
labelsC.push('{{ user.loginname }}');
dataValues.push({value: '{{ user.total|default(0) }}', formatted: '{{ user.total|formatBytes }}'});
{% endfor %}

View File

@@ -426,10 +426,10 @@ class MailsTest extends TestCase
$this->assertEquals(1, $result['popaccountid']);
switch (Settings::Get('system.passwordcryptfunc')) {
case PASSWORD_ARGON2I:
case 'argon2i':
$cpPrefix = '{ARGON2I}';
break;
case PASSWORD_ARGON2ID:
case 'argon2id':
$cpPrefix = '{ARGON2ID}';
break;
default: