merge current enhancements from main branch to v2.2 (#1261)

This commit is contained in:
Michael Kaufmann
2024-07-21 10:41:24 +02:00
committed by GitHub
parent b3dc7f9187
commit b888e920f4
21 changed files with 201 additions and 55 deletions

View File

@@ -270,15 +270,6 @@ class Emails extends ApiCommand implements ResourceEntity
throw new Exception("You cannot access this resource", 405);
}
// if enabling catchall is not allowed by settings, we do not need
// to run update()
if (Settings::Get('catchall.catchall_enabled') != '1') {
Response::standardError([
'operationnotpermitted',
'featureisdisabled'
], 'catchall', true);
}
$id = $this->getParam('id', true, 0);
$ea_optional = $id > 0;
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
@@ -297,30 +288,41 @@ class Emails extends ApiCommand implements ResourceEntity
$iscatchall = $this->getBoolParam('iscatchall', true, $result['iscatchall']);
$description = $this->getParam('description', true, $result['description']);
// if enabling catchall is not allowed by settings, we do not need
// to run update()
if ($iscatchall && $result['iscatchall'] == 0 && Settings::Get('catchall.catchall_enabled') != '1') {
Response::standardError([
'operationnotpermitted',
'featureisdisabled'
], 'catchall', true);
}
// get needed customer info to reduce the email-address-counter by one
$customer = $this->getCustomerData();
// check for catchall-flag
$email = $result['email_full'];
if ($iscatchall) {
$iscatchall = '1';
$email_parts = explode('@', $result['email_full']);
$email = '@' . $email_parts[1];
// catchall check
$stmt = Database::prepare("
SELECT `email_full` FROM `" . TABLE_MAIL_VIRTUAL . "`
WHERE `email` = :email AND `customerid` = :cid AND `iscatchall` = '1'
");
$params = [
"email" => $email,
"cid" => $customer['customerid']
];
$email_check = Database::pexecute_first($stmt, $params, true, true);
if ($email_check) {
Response::standardError('youhavealreadyacatchallforthisdomain', '', true);
$email = $result['email'];
// update only required if it was not a catchall before
if ($result['iscatchall'] == 0) {
$email_parts = explode('@', $result['email_full']);
$email = '@' . $email_parts[1];
// catchall check
$stmt = Database::prepare("
SELECT `email_full` FROM `" . TABLE_MAIL_VIRTUAL . "`
WHERE `email` = :email AND `customerid` = :cid AND `iscatchall` = '1'
");
$params = [
"email" => $email,
"cid" => $customer['customerid']
];
$email_check = Database::pexecute_first($stmt, $params, true, true);
if ($email_check) {
Response::standardError('youhavealreadyacatchallforthisdomain', '', true);
}
}
} else {
$iscatchall = '0';
$email = $result['email_full'];
}
$spam_tag_level = Validate::validate($spam_tag_level, 'spam_tag_level', '/^\d{1,}(\.\d{1,2})?$/', '', [7.0], true);

View File

@@ -983,9 +983,11 @@ class SubDomains extends ApiCommand implements ResourceEntity
'`d`.`letsencrypt`',
'`d`.`registration_date`',
'`d`.`termination_date`',
'`d`.`deactivated`'
'`d`.`deactivated`',
'`d`.`email_only`',
];
}
$query_fields = [];
// prepare select statement
@@ -996,7 +998,6 @@ class SubDomains extends ApiCommand implements ResourceEntity
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `pd` ON `pd`.`id`=`d`.`parentdomainid`
WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ")
AND `d`.`email_only` = '0'
" . $this->getSearchWhere($query_fields, true) . " GROUP BY `d`.`id` ORDER BY `parentdomainname` ASC, `d`.`parentdomainid` ASC " . $this->getOrderBy(true) . $this->getLimit());
$result = [];
@@ -1092,13 +1093,13 @@ class SubDomains extends ApiCommand implements ResourceEntity
$this->getUserDetail('customerid')
];
}
if (!empty($customer_ids)) {
// prepare select statement
$domains_stmt = Database::prepare("
SELECT COUNT(*) as num_subdom
FROM `" . TABLE_PANEL_DOMAINS . "` `d`
WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ")
AND `d`.`email_only` = '0'
");
$result = Database::pexecute_first($domains_stmt, null, true, true);
if ($result) {

View File

@@ -171,8 +171,9 @@ final class MasterCron extends CliCommand
FroxlorLogger::getInstanceOf()->setCronLog(0);
}
// clean up possible old login-links
// clean up possible old login-links and 2fa tokens
Database::query("DELETE FROM `" . TABLE_PANEL_LOGINLINKS . "` WHERE `valid_until` < UNIX_TIMESTAMP()");
Database::query("DELETE FROM `" . TABLE_PANEL_2FA_TOKENS . "` WHERE `valid_until` < UNIX_TIMESTAMP()");
return $result;
}

View File

@@ -54,7 +54,7 @@ class Dns
$dom_data['uid'] = $userinfo['userid'];
}
} else {
$where_clause = '`customerid` = :uid AND ';
$where_clause = '`customerid` = :uid AND `email_only` = "0" AND ';
$dom_data['uid'] = $userinfo['userid'];
}

View File

@@ -31,10 +31,10 @@ final class Froxlor
{
// Main version variable
const VERSION = '2.2.0-rc1';
const VERSION = '2.2.0-rc2';
// Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '202401090';
const DBVERSION = '202407200';
// Distribution branding-tag (used for Debian etc.)
const BRANDING = '';

View File

@@ -74,6 +74,9 @@ class Domain
if ($attributes['fields']['deactivated']) {
return lng('admin.deactivated');
}
if ($attributes['fields']['email_only']) {
return lng('domains.email_only');
}
// path or redirect
if (preg_match('/^https?\:\/\//', $attributes['fields']['documentroot'])) {
return [
@@ -127,7 +130,7 @@ class Domain
public static function canViewLogs(array $attributes): bool
{
if ((!CurrentUser::isAdmin() || (CurrentUser::isAdmin() && (int)$attributes['fields']['email_only'] == 0)) && !$attributes['fields']['deactivated']) {
if ((int)$attributes['fields']['email_only'] == 0 && !$attributes['fields']['deactivated']) {
if ((int)UI::getCurrentUser()['adminsession'] == 0 && (bool)UI::getCurrentUser()['logviewenabled']) {
return true;
} elseif ((int)UI::getCurrentUser()['adminsession'] == 1) {
@@ -157,6 +160,7 @@ class Domain
&& $attributes['fields']['caneditdomain'] == '1'
&& Settings::Get('system.bind_enable') == '1'
&& Settings::Get('system.dnsenabled') == '1'
&& !$attributes['fields']['email_only']
&& !$attributes['fields']['deactivated'];
}
@@ -169,7 +173,7 @@ class Domain
public static function hasLetsEncryptActivated(array $attributes): bool
{
return ((bool)$attributes['fields']['letsencrypt'] && (!CurrentUser::isAdmin() || (CurrentUser::isAdmin() && (int)$attributes['fields']['email_only'] == 0)));
return ((bool)$attributes['fields']['letsencrypt'] && (int)$attributes['fields']['email_only'] == 0);
}
/**
@@ -181,7 +185,7 @@ class Domain
&& DDomain::domainHasSslIpPort($attributes['fields']['id'])
&& (CurrentUser::isAdmin() || (!CurrentUser::isAdmin() && (int)$attributes['fields']['caneditdomain'] == 1))
&& (int)$attributes['fields']['letsencrypt'] == 0
&& (!CurrentUser::isAdmin() || (CurrentUser::isAdmin() && (int)$attributes['fields']['email_only'] == 0))
&& !(int)$attributes['fields']['email_only']
&& !$attributes['fields']['deactivated']
) {
return true;

View File

@@ -52,6 +52,14 @@ class Text
];
}
public static function type2fa(array $attributes): array
{
return [
'macro' => 'type2fa',
'data' => (int)$attributes['data']
];
}
public static function customerfullname(array $attributes): string
{
return User::getCorrectFullUserDetails($attributes['fields'], true);

View File

@@ -47,13 +47,14 @@ return [
'values' => $domainips
],
'alias' => [
'visible' => $alias_check == '0',
'visible' => $alias_check == '0' && (int)$result['email_only'] == 0,
'label' => lng('domains.aliasdomain'),
'type' => 'select',
'select_var' => $domains,
'selected' => $result['aliasdomain']
],
'path' => [
'visible' => (int)$result['email_only'] == 0,
'label' => lng('panel.path'),
'desc' => (Settings::Get('panel.pathedit') != 'Dropdown' ? lng('panel.pathDescriptionSubdomain').(Settings::Get('system.documentroot_use_default_value') == 1 ? lng('panel.pathDescriptionEx') : '') : null),
'type' => $pathSelect['type'],
@@ -63,13 +64,13 @@ return [
'note' => $pathSelect['note'] ?? '',
],
'url' => [
'visible' => Settings::Get('panel.pathedit') == 'Dropdown',
'visible' => Settings::Get('panel.pathedit') == 'Dropdown' && (int)$result['email_only'] == 0,
'label' => lng('panel.urloverridespath'),
'type' => 'text',
'value' => $urlvalue
],
'redirectcode' => [
'visible' => Settings::Get('customredirect.enabled') == '1',
'visible' => Settings::Get('customredirect.enabled') == '1' && (int)$result['email_only'] == 0,
'label' => lng('domains.redirectifpathisurl'),
'desc' => lng('domains.redirectifpathisurlinfo'),
'type' => 'select',
@@ -77,7 +78,7 @@ return [
'selected' => $def_code
],
'selectserveralias' => [
'visible' => ($result['parentdomainid'] == '0' && $userinfo['subdomains'] != '0') || $result['parentdomainid'] != '0',
'visible' => (($result['parentdomainid'] == '0' && $userinfo['subdomains'] != '0') || $result['parentdomainid'] != '0') && (int)$result['email_only'] == 0,
'label' => lng('admin.selectserveralias'),
'desc' => lng('admin.selectserveralias_desc'),
'type' => 'select',
@@ -85,27 +86,28 @@ return [
'selected' => $serveraliasoptions_selected
],
'isemaildomain' => [
'visible' => ($result['subcanemaildomain'] == '1' || $result['subcanemaildomain'] == '2') && $result['parentdomainid'] != '0',
'visible' => (($result['subcanemaildomain'] == '1' || $result['subcanemaildomain'] == '2') && $result['parentdomainid'] != '0') && (int)$result['email_only'] == 0,
'label' => 'Emaildomain',
'type' => 'checkbox',
'value' => '1',
'checked' => $result['isemaildomain']
],
'openbasedir_path' => [
'visible' => $result['openbasedir'] == '1',
'visible' => $result['openbasedir'] == '1' && (int)$result['email_only'] == 0,
'label' => lng('domain.openbasedirpath'),
'type' => 'select',
'select_var' => $openbasedir,
'selected' => $result['openbasedir_path']
],
'phpsettingid' => [
'visible' => ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) && count($phpconfigs) > 0 && $userinfo['phpenabled'] == '1' && $result['phpenabled'] == '1',
'visible' => ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) && count($phpconfigs) > 0 && $userinfo['phpenabled'] == '1' && $result['phpenabled'] == '1' && (int)$result['email_only'] == 0,
'label' => lng('admin.phpsettings.title'),
'type' => 'select',
'select_var' => $phpconfigs,
'selected' => $result['phpsettingid']
],
'speciallogfile' => [
'visible' => (int)$result['email_only'] == 0,
'label' => lng('admin.speciallogfile.title'),
'desc' => lng('admin.speciallogfile.description'),
'type' => 'checkbox',
@@ -139,7 +141,7 @@ return [
'section_bssl' => [
'title' => lng('admin.webserversettings_ssl'),
'image' => 'icons/domain_edit.png',
'visible' => Settings::Get('system.use_ssl') == '1' && $ssl_ipsandports && Domain::domainHasSslIpPort($result['id']),
'visible' => Settings::Get('system.use_ssl') == '1' && $ssl_ipsandports && Domain::domainHasSslIpPort($result['id']) && (int)$result['email_only'] == 0,
'fields' => [
'sslenabled' => [
'label' => lng('admin.domain_sslenabled'),
@@ -194,6 +196,7 @@ return [
]
]
]
]
],
'buttons' => ((int)$result['email_only'] == 1) ? [] : null
]
];

View File

@@ -110,6 +110,12 @@ return [
'class' => 'text-center',
'callback' => [Text::class, 'boolean'],
],
'type_2fa' => [
'label' => lng('2fa.type_2fa'),
'field' => 'type_2fa',
'class' => 'text-center',
'callback' => [Text::class, 'type2fa'],
],
],
'visible_columns' => Listing::getVisibleColumnsForListing('admin_list', [
'loginname',

View File

@@ -149,6 +149,12 @@ return [
'class' => 'text-center',
'callback' => [Text::class, 'boolean'],
],
'c.type_2fa' => [
'label' => lng('2fa.type_2fa'),
'field' => 'type_2fa',
'class' => 'text-center',
'callback' => [Text::class, 'type2fa'],
],
],
'visible_columns' => Listing::getVisibleColumnsForListing('customer_list', [
'c.name',

View File

@@ -57,3 +57,4 @@ const TABLE_PANEL_PLANS = 'panel_plans';
const TABLE_API_KEYS = 'api_keys';
const TABLE_PANEL_USERCOLUMNS = 'panel_usercolumns';
const TABLE_PANEL_LOGINLINKS = 'panel_loginlinks';
const TABLE_PANEL_2FA_TOKENS = 'panel_2fa_tokens';