add possibility to enable/disable api access on a per user base

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
Michael Kaufmann
2019-10-09 11:43:22 +02:00
parent 88d85fc02e
commit 4543c73b4f
13 changed files with 115 additions and 50 deletions

View File

@@ -132,6 +132,7 @@ CREATE TABLE `panel_admins` (
`custom_notes_show` tinyint(1) NOT NULL default '0', `custom_notes_show` tinyint(1) NOT NULL default '0',
`type_2fa` tinyint(1) NOT NULL default '0', `type_2fa` tinyint(1) NOT NULL default '0',
`data_2fa` varchar(500) NOT NULL default '', `data_2fa` varchar(500) NOT NULL default '',
`api_allowed` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`adminid`), PRIMARY KEY (`adminid`),
UNIQUE KEY `loginname` (`loginname`) UNIQUE KEY `loginname` (`loginname`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -199,6 +200,7 @@ CREATE TABLE `panel_customers` (
`allowed_phpconfigs` varchar(500) NOT NULL default '', `allowed_phpconfigs` varchar(500) NOT NULL default '',
`type_2fa` tinyint(1) NOT NULL default '0', `type_2fa` tinyint(1) NOT NULL default '0',
`data_2fa` varchar(500) NOT NULL default '', `data_2fa` varchar(500) NOT NULL default '',
`api_allowed` tinyint(1) NOT NULL default '1',
`logviewenabled` tinyint(1) NOT NULL default '0', `logviewenabled` tinyint(1) NOT NULL default '0',
PRIMARY KEY (`customerid`), PRIMARY KEY (`customerid`),
UNIQUE KEY `loginname` (`loginname`) UNIQUE KEY `loginname` (`loginname`)
@@ -684,7 +686,7 @@ opcache.interned_strings_buffer'),
('panel', 'customer_hide_options', ''), ('panel', 'customer_hide_options', ''),
('panel', 'is_configured', '0'), ('panel', 'is_configured', '0'),
('panel', 'version', '0.10.0'), ('panel', 'version', '0.10.0'),
('panel', 'db_version', '201910030'); ('panel', 'db_version', '201910090');
DROP TABLE IF EXISTS `panel_tasks`; DROP TABLE IF EXISTS `panel_tasks`;

View File

@@ -407,6 +407,7 @@ class FroxlorInstall
`name` = 'Froxlor-Administrator', `name` = 'Froxlor-Administrator',
`email` = :email, `email` = :email,
`def_language` = :deflang, `def_language` = :deflang,
`api_allowed` = 1,
`customers` = -1, `customers` = -1,
`customers_see_all` = 1, `customers_see_all` = 1,
`caneditphpsettings` = 1, `caneditphpsettings` = 1,

View File

@@ -339,3 +339,13 @@ if (\Froxlor\Froxlor::isDatabaseVersion('201909150')) {
\Froxlor\Froxlor::updateToDbVersion('201910030'); \Froxlor\Froxlor::updateToDbVersion('201910030');
} }
if (\Froxlor\Froxlor::isDatabaseVersion('201910030')) {
showUpdateStep("Adding field api_allowed to admins and customers");
Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` ADD `api_allowed` tinyint(1) NOT NULL default '1';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `api_allowed` tinyint(1) NOT NULL default '1';");
lastStepStatus(0);
\Froxlor\Froxlor::updateToDbVersion('201910090');
}

View File

@@ -97,6 +97,8 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, default auto-generated * optional, default auto-generated
* @param string $def_language * @param string $def_language
* optional, default is system-default language * optional, default is system-default language
* @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false
* @param string $custom_notes * @param string $custom_notes
* optional, default empty * optional, default empty
* @param bool $custom_notes_show * @param bool $custom_notes_show
@@ -171,6 +173,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// parameters // parameters
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage')); $def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
$api_allowed = $this->getBoolParam('api_allowed', true, Settings::Get('api.enabled'));
$custom_notes = $this->getParam('custom_notes', true, ''); $custom_notes = $this->getParam('custom_notes', true, '');
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0); $custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
$password = $this->getParam('admin_password', true, ''); $password = $this->getParam('admin_password', true, '');
@@ -271,6 +274,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
'name' => $name, 'name' => $name,
'email' => $email, 'email' => $email,
'lang' => $def_language, 'lang' => $def_language,
'api_allowed' => $api_allowed,
'change_serversettings' => $change_serversettings, 'change_serversettings' => $change_serversettings,
'customers' => $customers, 'customers' => $customers,
'customers_see_all' => $customers_see_all, 'customers_see_all' => $customers_see_all,
@@ -299,6 +303,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
`name` = :name, `name` = :name,
`email` = :email, `email` = :email,
`def_language` = :lang, `def_language` = :lang,
`api_allowed` = :api_allowed,
`change_serversettings` = :change_serversettings, `change_serversettings` = :change_serversettings,
`customers` = :customers, `customers` = :customers,
`customers_see_all` = :customers_see_all, `customers_see_all` = :customers_see_all,
@@ -350,6 +355,8 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
* optional, default auto-generated * optional, default auto-generated
* @param string $def_language * @param string $def_language
* optional, default is system-default language * optional, default is system-default language
* @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false
* @param string $custom_notes * @param string $custom_notes
* optional, default empty * optional, default empty
* @param string $theme * @param string $theme
@@ -444,6 +451,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
// you cannot edit some of the details of yourself // you cannot edit some of the details of yourself
if ($result['adminid'] == $this->getUserDetail('adminid')) { if ($result['adminid'] == $this->getUserDetail('adminid')) {
$api_allowed = $result['api_allowed'];
$deactivated = $result['deactivated']; $deactivated = $result['deactivated'];
$customers = $result['customers']; $customers = $result['customers'];
$domains = $result['domains']; $domains = $result['domains'];
@@ -462,6 +470,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$traffic = $result['traffic']; $traffic = $result['traffic'];
$ipaddress = ($result['ip'] != - 1 ? json_decode($result['ip'], true) : - 1); $ipaddress = ($result['ip'] != - 1 ? json_decode($result['ip'], true) : - 1);
} else { } else {
$api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']);
$deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']); $deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']);
$dec_places = Settings::Get('panel.decimal_places'); $dec_places = Settings::Get('panel.decimal_places');
@@ -578,6 +587,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
'name' => $name, 'name' => $name,
'email' => $email, 'email' => $email,
'lang' => $def_language, 'lang' => $def_language,
'api_allowed' => $api_allowed,
'change_serversettings' => $change_serversettings, 'change_serversettings' => $change_serversettings,
'customers' => $customers, 'customers' => $customers,
'customers_see_all' => $customers_see_all, 'customers_see_all' => $customers_see_all,
@@ -607,6 +617,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
`name` = :name, `name` = :name,
`email` = :email, `email` = :email,
`def_language` = :lang, `def_language` = :lang,
`api_allowed` = :api_allowed,
`change_serversettings` = :change_serversettings, `change_serversettings` = :change_serversettings,
`customers` = :customers, `customers` = :customers,
`customers_see_all` = :customers_see_all, `customers_see_all` = :customers_see_all,

View File

@@ -136,6 +136,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* optional * optional
* @param string $def_language, * @param string $def_language,
* optional, default is system-default language * optional, default is system-default language
* @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false
* @param int $gender * @param int $gender
* optional, 0 = no-gender, 1 = male, 2 = female * optional, 0 = no-gender, 1 = male, 2 = female
* @param string $custom_notes * @param string $custom_notes
@@ -229,6 +231,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$fax = $this->getParam('fax', true, ''); $fax = $this->getParam('fax', true, '');
$customernumber = $this->getParam('customernumber', true, ''); $customernumber = $this->getParam('customernumber', true, '');
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage')); $def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
$api_allowed = $this->getBoolParam('api_allowed', true, Settings::Get('api.enabled'));
$gender = (int) $this->getParam('gender', true, 0); $gender = (int) $this->getParam('gender', true, 0);
$custom_notes = $this->getParam('custom_notes', true, ''); $custom_notes = $this->getParam('custom_notes', true, '');
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0); $custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
@@ -388,26 +391,6 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
\Froxlor\UI\Response::standard_error('documentrootexists', $documentroot, true); \Froxlor\UI\Response::standard_error('documentrootexists', $documentroot, true);
} }
if ($createstdsubdomain != '1') {
$createstdsubdomain = '0';
}
if ($phpenabled != '0') {
$phpenabled = '1';
}
if ($perlenabled != '0') {
$perlenabled = '1';
}
if ($dnsenabled != '0') {
$dnsenabled = '1';
}
if ($logviewenabled != '0') {
$logviewenabled = '1';
}
if ($password == '') { if ($password == '') {
$password = \Froxlor\System\Crypt::generatePassword(); $password = \Froxlor\System\Crypt::generatePassword();
} }
@@ -430,6 +413,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'email' => $email, 'email' => $email,
'customerno' => $customernumber, 'customerno' => $customernumber,
'lang' => $def_language, 'lang' => $def_language,
'api_allowed' => $api_allowed,
'docroot' => $documentroot, 'docroot' => $documentroot,
'guid' => $guid, 'guid' => $guid,
'diskspace' => $diskspace, 'diskspace' => $diskspace,
@@ -470,6 +454,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
`email` = :email, `email` = :email,
`customernumber` = :customerno, `customernumber` = :customerno,
`def_language` = :lang, `def_language` = :lang,
`api_allowed` = :api_allowed,
`documentroot` = :docroot, `documentroot` = :docroot,
`guid` = :guid, `guid` = :guid,
`diskspace` = :diskspace, `diskspace` = :diskspace,
@@ -755,6 +740,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
* optional * optional
* @param string $def_language, * @param string $def_language,
* optional, default is system-default language * optional, default is system-default language
* @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false
* @param int $gender * @param int $gender
* optional, 0 = no-gender, 1 = male, 2 = female * optional, 0 = no-gender, 1 = male, 2 = female
* @param string $custom_notes * @param string $custom_notes
@@ -857,6 +844,7 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
$fax = $this->getParam('fax', true, $result['fax']); $fax = $this->getParam('fax', true, $result['fax']);
$customernumber = $this->getParam('customernumber', true, $result['customernumber']); $customernumber = $this->getParam('customernumber', true, $result['customernumber']);
$def_language = $this->getParam('def_language', true, $result['def_language']); $def_language = $this->getParam('def_language', true, $result['def_language']);
$api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']);
$gender = (int) $this->getParam('gender', true, $result['gender']); $gender = (int) $this->getParam('gender', true, $result['gender']);
$custom_notes = $this->getParam('custom_notes', true, $result['custom_notes']); $custom_notes = $this->getParam('custom_notes', true, $result['custom_notes']);
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, $result['custom_notes_show']); $custom_notes_show = $this->getBoolParam('custom_notes_show', true, $result['custom_notes_show']);
@@ -999,30 +987,10 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
\Froxlor\System\Cronjob::inserttask('1'); \Froxlor\System\Cronjob::inserttask('1');
} }
if ($deactivated != '1') {
$deactivated = '0';
}
if ($phpenabled != '0') {
$phpenabled = '1';
}
if ($perlenabled != '0') {
$perlenabled = '1';
}
if ($dnsenabled != '0') {
$dnsenabled = '1';
}
if ($phpenabled != $result['phpenabled'] || $perlenabled != $result['perlenabled']) { if ($phpenabled != $result['phpenabled'] || $perlenabled != $result['perlenabled']) {
\Froxlor\System\Cronjob::inserttask('1'); \Froxlor\System\Cronjob::inserttask('1');
} }
if ($logviewenabled != '0') {
$logviewenabled = '1';
}
// activate/deactivate customer services // activate/deactivate customer services
if ($deactivated != $result['deactivated']) { if ($deactivated != $result['deactivated']) {
@@ -1166,7 +1134,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
'dnsenabled' => $dnsenabled, 'dnsenabled' => $dnsenabled,
'logviewenabled' => $logviewenabled, 'logviewenabled' => $logviewenabled,
'custom_notes' => $custom_notes, 'custom_notes' => $custom_notes,
'custom_notes_show' => $custom_notes_show 'custom_notes_show' => $custom_notes_show,
'api_allowed' => $api_allowed
); );
$upd_data = $upd_data + $admin_upd_data; $upd_data = $upd_data + $admin_upd_data;
} }
@@ -1207,7 +1176,8 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
`dnsenabled` = :dnsenabled, `dnsenabled` = :dnsenabled,
`logviewenabled` = :logviewenabled, `logviewenabled` = :logviewenabled,
`custom_notes` = :custom_notes, `custom_notes` = :custom_notes,
`custom_notes_show` = :custom_notes_show"; `custom_notes_show` = :custom_notes_show,
`api_allowed` = :api_allowed";
$upd_query .= $admin_upd_query; $upd_query .= $admin_upd_query;
} }
$upd_query .= " WHERE `customerid` = :customerid"; $upd_query .= " WHERE `customerid` = :customerid";

View File

@@ -55,13 +55,20 @@ class FroxlorRPC
*/ */
private static function validateAuth($key, $secret) private static function validateAuth($key, $secret)
{ {
$sel_stmt = \Froxlor\Database\Database::prepare("SELECT * FROM `api_keys` WHERE `apikey` = :ak AND `secret` = :as"); $sel_stmt = \Froxlor\Database\Database::prepare("
SELECT ak.*, a.api_allowed as admin_api_allowed, c.api_allowed as cust_api_allowed
FROM `api_keys` ak
LEFT JOIN `panel_admins` a ON a.adminid = ak.adminid
LEFT JOIN `panel_customers` c ON c.customerid = ak.customerid
WHERE `apikey` = :ak AND `secret` = :as
");
$result = \Froxlor\Database\Database::pexecute_first($sel_stmt, array( $result = \Froxlor\Database\Database::pexecute_first($sel_stmt, array(
'ak' => $key, 'ak' => $key,
'as' => $secret 'as' => $secret
), true, true); ), true, true);
if ($result) { if ($result) {
if ($result['apikey'] == $key && $result['secret'] == $secret && ($result['valid_until'] == - 1 || $result['valid_until'] >= time())) { if ($result['apikey'] == $key && $result['secret'] == $secret && ($result['valid_until'] == - 1 || $result['valid_until'] >= time()) && (($result['customerid'] == 0 && $result['admin_api_allowed'] == 1) || ($result['customerid'] > 0 && $result['cust_api_allowed'] == 1))) {
// get user to check whether api call is allowed
if (! empty($result['allowed_from'])) { if (! empty($result['allowed_from'])) {
// @todo allow specification and validating of whole subnets later // @todo allow specification and validating of whole subnets later
$ip_list = explode(",", $result['allowed_from']); $ip_list = explode(",", $result['allowed_from']);

View File

@@ -10,7 +10,7 @@ final class Froxlor
const VERSION = '0.10.0'; const VERSION = '0.10.0';
// Database version (YYYYMMDDC where C is a daily counter) // Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '201910030'; const DBVERSION = '201910090';
// Distribution branding-tag (used for Debian etc.) // Distribution branding-tag (used for Debian etc.)
const BRANDING = ''; const BRANDING = '';

View File

@@ -44,6 +44,21 @@ return array(
'label' => $lng['login']['language'], 'label' => $lng['login']['language'],
'type' => 'select', 'type' => 'select',
'select_var' => $language_options 'select_var' => $language_options
),
'api_allowed' => array(
'label' => $lng['usersettings']['api_allowed']['title'],
'desc' => $lng['usersettings']['api_allowed']['description'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array(
'1'
),
'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
) )
) )
), ),

View File

@@ -59,6 +59,21 @@ return array(
'type' => 'select', 'type' => 'select',
'select_var' => $language_options, 'select_var' => $language_options,
'visible' => ($result['adminid'] == $userinfo['userid'] ? false : true) 'visible' => ($result['adminid'] == $userinfo['userid'] ? false : true)
),
'api_allowed' => array(
'label' => $lng['usersettings']['api_allowed']['title'],
'desc' => $lng['usersettings']['api_allowed']['description'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array(
$result['api_allowed']
),
'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
) )
) )
), ),

View File

@@ -81,6 +81,21 @@ return array(
'label' => $lng['login']['language'], 'label' => $lng['login']['language'],
'type' => 'select', 'type' => 'select',
'select_var' => $language_options 'select_var' => $language_options
),
'api_allowed' => array(
'label' => $lng['usersettings']['api_allowed']['title'],
'desc' => $lng['usersettings']['api_allowed']['description'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array(
'1'
),
'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
) )
) )
), ),
@@ -294,9 +309,9 @@ return array(
'values' => $phpconfigs, 'values' => $phpconfigs,
'value' => ((int) \Froxlor\Settings::Get('system.mod_fcgid') == 1 ? array( 'value' => ((int) \Froxlor\Settings::Get('system.mod_fcgid') == 1 ? array(
\Froxlor\Settings::Get('system.mod_fcgid_defaultini') \Froxlor\Settings::Get('system.mod_fcgid_defaultini')
) : (int) \Froxlor\Settings::Get('phpfpm.enabled') == 1 ? array( ) : ((int) \Froxlor\Settings::Get('phpfpm.enabled') == 1 ? array(
\Froxlor\Settings::Get('phpfpm.defaultini') \Froxlor\Settings::Get('phpfpm.defaultini')
) : array()), ) : array())),
'is_array' => 1 'is_array' => 1
), ),
'perlenabled' => array( 'perlenabled' => array(

View File

@@ -74,6 +74,21 @@ return array(
'label' => $lng['login']['language'], 'label' => $lng['login']['language'],
'type' => 'select', 'type' => 'select',
'select_var' => $language_options 'select_var' => $language_options
),
'api_allowed' => array(
'label' => $lng['usersettings']['api_allowed']['title'],
'desc' => $lng['usersettings']['api_allowed']['description'],
'type' => 'checkbox',
'values' => array(
array(
'label' => $lng['panel']['yes'],
'value' => '1'
)
),
'value' => array(
$result['api_allowed']
),
'visible' => (\Froxlor\Settings::Get('api.enabled') == '1' ? true : false)
) )
) )
), ),

View File

@@ -2069,3 +2069,5 @@ $lng['serversettings']['froxloraliases']['description'] = "Comma separated list
$lng['serversettings']['ssl']['tlsv13_cipher_list']['title'] = 'Configure explicit TLSv1.3 ciphers if used'; $lng['serversettings']['ssl']['tlsv13_cipher_list']['title'] = 'Configure explicit TLSv1.3 ciphers if used';
$lng['serversettings']['ssl']['tlsv13_cipher_list']['description'] = 'This is a list of ciphers that you want (or don\'t want) to use when talking TLSv1.3. For a list of ciphers and how to include/exclude them, see <a href="https://wiki.openssl.org/index.php/TLS1.3">the docs for TLSv1.3</a>.<br /><br /><b>Default value is empty</b>'; $lng['serversettings']['ssl']['tlsv13_cipher_list']['description'] = 'This is a list of ciphers that you want (or don\'t want) to use when talking TLSv1.3. For a list of ciphers and how to include/exclude them, see <a href="https://wiki.openssl.org/index.php/TLS1.3">the docs for TLSv1.3</a>.<br /><br /><b>Default value is empty</b>';
$lng['usersettings']['api_allowed']['title'] = 'Allow API access';
$lng['usersettings']['api_allowed']['description'] = 'When enabled in the settings, this user can create API keys and access the froxlor API';

View File

@@ -1716,3 +1716,5 @@ $lng['serversettings']['froxloraliases']['description'] = "Komma getrennte Liste
$lng['serversettings']['ssl']['tlsv13_cipher_list']['title'] = 'Explizite TLSv1.3 Ciphers, wenn genutzt'; $lng['serversettings']['ssl']['tlsv13_cipher_list']['title'] = 'Explizite TLSv1.3 Ciphers, wenn genutzt';
$lng['serversettings']['ssl']['tlsv13_cipher_list']['description'] = 'Dies ist eine Liste von Ciphers, die genutzt werden sollen (oder auch nicht genutzt werden sollen), wenn eine TLSv1.3 Verbindung hergestellt werden soll. Eine Liste aller Ciphers und wie diese hinzugefügt/ausgeschlossen werden ist <a href="https://wiki.openssl.org/index.php/TLS1.3">der Dokumentation für TLSv1.3</a> zu entnehmen.<br /><br /><b>Standard-Wert ist leer</b>'; $lng['serversettings']['ssl']['tlsv13_cipher_list']['description'] = 'Dies ist eine Liste von Ciphers, die genutzt werden sollen (oder auch nicht genutzt werden sollen), wenn eine TLSv1.3 Verbindung hergestellt werden soll. Eine Liste aller Ciphers und wie diese hinzugefügt/ausgeschlossen werden ist <a href="https://wiki.openssl.org/index.php/TLS1.3">der Dokumentation für TLSv1.3</a> zu entnehmen.<br /><br /><b>Standard-Wert ist leer</b>';
$lng['usersettings']['api_allowed']['title'] = 'Erlaube API Zugriff';
$lng['usersettings']['api_allowed']['description'] = 'Wenn in den Einstellungen aktiviert, kann der Benutzer API Schlüssel erstellen und auf die froxlor API Zugreifen';