-
dockx thibault authored
Adds backend configuration allowing source / origin of data definition. Rentention properties and automatic snapshot.
Verifiedbcf0d90d
<?php
/*
This code is part of FusionDirectory (http://www.fusiondirectory.org/)
Copyright (C) 2012-2019 FusionDirectory
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
class configInLdap extends simplePlugin
{
static function plInfo (): array
{
return [
'plShortName' => _('Configuration'),
'plTitle' => _('FusionDirectory configuration'),
'plDescription' => _('Configuration screen of FusionDirectory'),
'plIcon' => 'geticon.php?context=categories&icon=settings&size=48',
'plObjectClass' => ['fusionDirectoryConf'],
'plObjectType' => [
'configuration' => [
'name' => _('FusionDirectory configuration'),
'filter' => 'objectClass=fusionDirectoryConf',
'tabClass' => 'configInLdapTabs',
'icon' => 'geticon.php?context=categories&icon=settings&size=16',
'mainAttr' => FALSE,
'ou' => preg_replace('/^[^,]+,/', '', CONFIGRDN)
]
],
'plSection' => ['conf' => ['name' => _('Configuration'), 'priority' => 20]],
'plManages' => ['configuration'],
'plPriority' => 0,
'plProvidedAcls' => parent::generatePlProvidedAcls(static::getAttributesInfo())
];
}
static function getAttributesInfo (): array
{
global $config;
return [
'look_n_feel' => [
'name' => _('Look and feel'),
'attrs' => [
new SelectAttribute(
_('Language'), _('Language of the application. If \'automatic\' or not available, the one asked by the browser will be used. This setting can be overriden per user.'),
'fdLanguage', FALSE,
['']
),
new SelectAttribute(
_('Theme'), _('Theme to be used'),
'fdTheme', TRUE,
static::get_themes(),
'breezy'
),
new SelectAttribute(
_('Timezone'), _('Timezone to be used'),
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
'fdTimezone', TRUE,
['America/New_York']
),
new HiddenAttribute('fusionConfigMd5'),
new HiddenAttribute('fdIncrementalModifierStates'),
]
],
'core_settings' => [
'name' => _('Core settings'),
'attrs' => [
new IntAttribute(
_('LDAP size limit'), _('Defines the number of entries to get from LDAP by default.'),
'fdLdapSizeLimit', FALSE,
0 /*min*/, FALSE /*no max*/, 200
),
new SelectAttribute(
_('Edit locking'),
_('Check if a entry currently being edited has been modified outside of FusionDirectory in the meantime.'),
'fdModificationDetectionAttribute', FALSE,
['', 'entryCSN', 'contextCSN'], 'entryCSN'
),
new BooleanAttribute(
_('Enable logging'),
_('Event logging on FusionDirectory side.'),
'fdLogging', FALSE,
TRUE
),
new BooleanAttribute(
_('Schema validation'),
_('Enables schema checking during login.'),
'fdSchemaCheck', FALSE,
TRUE
),
new BooleanAttribute(
_('Wildcard foreign keys'), _('Enables wildcard searches like member=* when moving a whole department. This will open all existing groups and roles to make sure foreign keys are respected. Slow on big trees.'),
'fdWildcardForeignKeys', FALSE,
TRUE
),
]
],
'password' => [
'name' => _('Password settings'),
'attrs' => [
new SetAttribute(
new SelectAttribute(
_('Allowed password hashes'), _('Password hashes which may be used for user passwords'),
'fdPasswordAllowedHashes', TRUE,
['ssha']
)
),
new SelectAttribute(
_('Password default hash'), _('Default hash to be used'),
'fdPasswordDefaultHash', TRUE,
['ssha']
),
new BooleanAttribute(
_('Force default hash'), _('Force the use of the default password hash'),
'fdForcePasswordDefaultHash'
),
new IntAttribute(
_('Password minimum length'), _('Minimum length of user passwords'),
'fdPasswordMinLength', FALSE,
0 /*min*/, FALSE /*no max*/
),
new IntAttribute(
_('Password minimum differs'), _('Minimum number of different characters from last password'),
'fdPasswordMinDiffer', FALSE,
0 /*min*/, FALSE /*no max*/
),
new BooleanAttribute(
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
_('Use account expiration'),
_('Enables shadow attribute tests during the login to FusionDirectory and forces password renewal or account locking'),
'fdHandleExpiredAccounts'
),
new StringAttribute(
_('SASL Realm'), _('SASL Realm'),
'fdSaslRealm'
),
new StringAttribute(
_('SASL Exop'), _('Attribute to be stored in the userPassword attribute'),
'fdSaslExop'
),
]
],
'login' => [
'name' => _('Login and session'),
'attrs' => [
new SelectAttribute(
_('Login attribute'),
_('Which LDAP attribute should be used as the login name during login.'),
'fdLoginAttribute', TRUE,
['uid', 'mail', 'uid,mail'], 'uid',
['uid', 'mail', 'both']
),
new BooleanAttribute(
_('Enforce encrypted connections'),
_('Enables PHP security checks to force encrypted access (https) to the web interface.'),
'fdForceSSL'
),
new BooleanAttribute(
_('Warn if session is not encrypted'),
_('will display a warning to the user when http is used instead of https.'),
'fdWarnSSL', FALSE,
TRUE
),
new IntAttribute(
_('Session lifetime'), _('Defines when a session will expire in seconds (0 to disable).'),
'fdSessionLifeTime', TRUE,
0 /*min*/, FALSE /*no max*/, 1800
),
new SelectAttribute(
_('Login method'),
_('Which login method should be used for connecting to FusionDirectory'),
'fdLoginMethod', TRUE
),
new StringAttribute(
_('Header name'), _('Name of the header containing user identifier.'),
'fdHttpHeaderAuthHeaderName', FALSE,
'AUTH_USER'
),
]
],
'ssl' => [
'name' => _('SSL'),
'attrs' => [
new TrimmedStringAttribute(
_('Key path'), _('Path to FusionDirectory private key. Unused for now.'),
'fdSslKeyPath', FALSE,
'/etc/ssl/private/fd.key'
),
new TrimmedStringAttribute(
_('Certificate path'), _('Path to FusionDirectory certificate. Unused for now.'),
'fdSslCertPath', FALSE,
'/etc/ssl/certs/fd.cert'
),
new TrimmedStringAttribute(
_('CA certificate path'), _('Path to the CA certificate. Used for validating Argonaut Server host.'),
'fdSslCaCertPath', FALSE,
'/etc/ssl/certs/ca.cert'
),
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
]
],
'cas' => [
'name' => _('CAS'),
'attrs' => [
new TrimmedStringAttribute(
_('CA certificate path'), _('Path to the CA certificate of the CAS server'),
'fdCasServerCaCertPath', FALSE,
'/etc/ssl/certs/ca.cert'
),
new StringAttribute(
_('Host'), _('Host of the CAS server'),
'fdCasHost', FALSE,
'localhost'
),
new IntAttribute(
_('Port'), _('Port the CAS server is listening on'),
'fdCasPort', FALSE,
0 /*min*/, FALSE /*no max*/, 443
),
new StringAttribute(
_('CAS context'), _('CAS context to be used'),
'fdCasContext', FALSE,
'/cas'
),
new BooleanAttribute(
_('Verbose error'), _('Activate verbose errors in phpCAS. Avoid in production.'),
'fdCasVerbose', FALSE
),
new BooleanAttribute(
_('Library CAS 1.6'), _('Activate if library CAS >= 1.6 is being used.'),
'fdCasLibraryBool', FALSE
),
new StringAttribute(
_('Client service'), _('The client service name'),
'fdCasClientServiceName', FALSE
),
]
],
'people_and_group' => [
'name' => _('People and group storage'),
'class' => ['critical'],
'attrs' => [
new SelectAttribute(
_('People DN attribute'), _('Attribute to use at the beginning of the user dn'),
'fdAccountPrimaryAttribute', TRUE,
['uid', 'cn']
),
new StringAttribute(
_('CN pattern'), _('The pattern to use to build the common name field'),
'fdCnPattern', TRUE,
'%givenName% %sn%'
),
new BooleanAttribute(
_('Mandatory first name'),
_('Whether first name (givenName) should be a mandatory field on users'),
'fdGivenNameRequired', FALSE,
TRUE
),
new BooleanAttribute(
_('Strict naming policy'),
_('Enables strict checking of user and group names'),
'fdStrictNamingRules', FALSE,
TRUE
),
new StringAttribute(
_('Users RDN'), _('The branch where users are stored.'),
'fdUserRDN', TRUE,
'ou=people'
),
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
new StringAttribute(
_('ACL role RDN'), _('The branch where ACL roles are stored.'),
'fdAclRoleRDN', TRUE,
'ou=aclroles'
),
new BooleanAttribute(
_('Restrict role members'), _('When enabled only users from the same branch or members of groups from the same branch can be added to a role.'),
'fdRestrictRoleMembers'
),
new BooleanAttribute(
_('Separate address fields'), _('Expose street, postOfficeBox and postalCode fields instead of postalAddress.'),
'fdSplitPostalAddress'
),
new PostalAddressAttribute(
_('Postal address pattern'), _('When using separate address fields, you can use a pattern to fill postalAddress field.'),
'fdPostalAddressPattern'
),
new IntAttribute(
_('Avatar max size'), _('Maximum user picture width and height in pixels. Bigger uploaded pictures will be resized.'),
'fdMaxAvatarSize', FALSE,
1, FALSE, 200
),
]
],
'debug' => [
'name' => _('Debugging'),
'attrs' => [
new BooleanAttribute(
_('Display PHP errors'),
_('Shows PHP errors in the upper part of the screen. This should be disabled in production deployments, because it may contain passwords.'),
'fdDisplayErrors'
),
new IntAttribute(
_('Maximum LDAP query time'), _('Stop LDAP actions if there is no answer within the specified number of seconds.'),
'fdLdapMaxQueryTime', FALSE,
0 /*min*/, FALSE /*no max*/
),
new BooleanAttribute(
_('Log LDAP statistics'),
_('Track LDAP timing statistics to the syslog. This may help to find indexing problems or bad search filters.'),
'fdLdapStats'
),
new DebugLevelAttribute(
new SelectAttribute(
_('Debug level'),
_('Display certain information on each page load.'),
'fdDebugLevel', FALSE,
[DEBUG_TRACE, DEBUG_LDAP, DEBUG_DB, DEBUG_SHELL, DEBUG_POST,
DEBUG_SESSION, DEBUG_ACL, DEBUG_SI, DEBUG_MAIL],
DEBUG_TRACE,
['Trace', 'LDAP', 'Database', 'Shell', 'POST',
'SESSION', 'ACL', 'SI', 'Mail']
)
),
new BooleanAttribute(
_('Log debug messages'),
_('Sends debug output to syslog as well'),
'fdDebugLogging'
),
]
],
'miscellaneous' => [
'name' => _('Miscellaneous'),
'attrs' => [
new BooleanAttribute(
_('Display summary in listings'),
_('Determines whether a status bar will be shown on the bottom of lists, displaying a short summary of type and number of elements in the list.'),
'fdListSummary', FALSE,
TRUE
),
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
new BooleanAttribute(
_('Show ACL tab on all objects'),
_('For very specific ACL rights setting where you might need to give right on a single object.'),
'fdAclTabOnObjects'
),
new SetAttribute(
new StringAttribute(
_('Available department categories'), _('Available categories in the departments dropdown'),
'fdDepartmentCategories', FALSE
),
[]
),
new OrderedArrayAttribute(
new PipeSeparatedCompositeAttribute(
_('Use this to hide some menu entry to specific groups of users'),
'fdPluginsMenuBlacklist',
[
new SelectAttribute(
'', _('Group or role'),
'blacklistGroup', TRUE,
[]
),
new SelectAttribute(
'', _('Plugin to blacklist'),
'blacklistPlugin', TRUE,
[]
),
],
'',
_('Plugin menu blacklist')
),
// no order
FALSE,
[]
),
// Needed here for ACLs
new HiddenAttribute('fdManagementConfig'),
new IntAttribute(
_('ACL target filter limit'), _('Defines the maximum number of entries an ACL target filter is allowed to return'),
'fdAclTargetFilterLimit', FALSE,
0 /*min*/, FALSE /*no max*/, 100
),
]
],
];
}
function __construct ($dn = NULL, $object = NULL, $parent = NULL, $mainTab = FALSE, $attributesInfo = NULL)
{
global $config;
$attributesInfo = static::getAttributesInfo();
/* Languages */
$languages = Language::getList(TRUE);
asort($languages);
$languages = array_merge(["" => _("Automatic")], $languages);
$attributesInfo['look_n_feel']['attrs'][0]->setChoices(array_keys($languages), array_values($languages));
/* Timezones */
$attributesInfo['look_n_feel']['attrs'][2]->setChoices(timezone::_get_tz_zones());
/* Password methods */
$methods = passwordMethod::get_available_methods();
$methods = $methods['name'];
if (!in_array('sasl', $methods)) {
$methods[] = 'sasl';
}
$attributesInfo['password']['attrs'][0]->attribute->setChoices($methods);
$attributesInfo['password']['attrs'][0]->setDefaultValue($methods);
$attributesInfo['password']['attrs'][0]->resetToDefault();
$attributesInfo['password']['attrs'][1]->setChoices($methods);
/* Login methods */
$methods = LoginMethod::getMethods();
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
$attributesInfo['login']['attrs'][4]->setChoices(array_keys($methods), array_values($methods));
$groupsAndRoles = array_merge(
array_map(
function ($group)
{
return sprintf(_('Group %s'), $group);
},
objects::ls('ogroup')
),
array_map(
function ($role)
{
return sprintf(_('Role %s'), $role);
},
objects::ls('role')
)
);
$attributesInfo['miscellaneous']['attrs'][3]->attribute->attributes[0]->setChoices(
array_keys($groupsAndRoles),
array_values($groupsAndRoles)
);
$menuPlugins = [];
$plist = session::get('plist');
foreach ($config->data['SECTIONS'] as $section => $section_infos) {
foreach ($config->data['MENU'][$section] as $info) {
if (isset($info['CLASS'])) {
list ($plHeadline, , , ) = $plist->get_infos($info['CLASS']);
$menuPlugins[$info['CLASS']] = $plHeadline;
}
}
}
asort($menuPlugins);
$attributesInfo['miscellaneous']['attrs'][3]->attribute->attributes[1]->setChoices(
array_keys($menuPlugins),
array_values($menuPlugins)
);
try {
parent::__construct($dn, $object, $parent, $mainTab, $attributesInfo);
} catch (NonExistingLdapNodeException $e) {
parent::__construct('new', $object, $parent, $mainTab, $attributesInfo);
$this->dn = $dn;
}
$this->fusionConfigMd5 = md5_file(CACHE_DIR."/".CLASS_CACHE);
$this->attributesAccess['fdForceSSL']->setManagedAttributes(
[
'disable' => [
TRUE => [
'fdWarnSSL',
]
]
]
);
$this->attributesAccess['fdSplitPostalAddress']->setManagedAttributes(
[
'disable' => [
FALSE => [
'fdPostalAddressPattern',
]
]
]
);
// CAS boolean case to allow the use of CAS library >= 1.6
$this->attributesAccess['fdCasLibraryBool']->setManagedAttributes(
[
'disable' => [
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
FALSE => [
'fdCasClientServiceName',
]
]
]
);
$this->attributesAccess['fdLoginMethod']->setManagedAttributes(
[
'multiplevalues' => [
'noncas' => [
'LoginPost',
'LoginHTTPAuth',
'LoginHTTPHeader',
],
'nonheader' => [
'LoginPost',
'LoginCAS',
'LoginHTTPAuth'
],
],
'disable' => [
'noncas' => [
'fdCasServerCaCertPath',
'fdCasHost',
'fdCasPort',
'fdCasContext',
'fdCasVerbose',
'fdCasClientServiceName',
'fdCasLibraryBool'
],
'nonheader' => [
'fdHttpHeaderAuthHeaderName',
]
]
]
);
if (empty($this->attrs['fdLoginMethod'][0])) {
// Reading OBSOLETE attributes from FD<1.4 to ease migration
if (isset($this->attrs['fdHttpAuthActivated'][0]) && ($this->attrs['fdHttpAuthActivated'][0] == 'TRUE')) {
$this->fdLoginMethod = 'LoginHTTPAuth';
} elseif (isset($this->attrs['fdCasActivated'][0]) && ($this->attrs['fdCasActivated'][0] == 'TRUE')) {
$this->fdLoginMethod = 'LoginCAS';
} elseif (isset($this->attrs['fdHttpHeaderAuthActivated'][0]) && ($this->attrs['fdHttpHeaderAuthActivated'][0] == 'TRUE')) {
$this->fdLoginMethod = 'LoginHTTPHeader';
}
}
$this->attributesAccess['fdPasswordDefaultHash']->setChoices(
$this->attributesAccess['fdPasswordAllowedHashes']->getValue()
);
}
function compute_dn (): string
{
return $this->dn;
}
function check (): array
{
$messages = parent::check();
if (($this->fdPasswordDefaultHash == 'sasl') && ($this->fdSaslRealm == '') && ($this->fdSaslExop == '')) {
$messages[] = new SimplePluginCheckError(
$this,
htmlescape(_('You need to fill saslRealm or saslExop in the configuration screen in order to use SASL'))
);
}
if ($this->attributesAccess['fdLanguage']->hasChanged() && ($this->fdLanguage != '') && !Language::isAvailable($this->fdLanguage)) {
$messages[] = new SimplePluginCheckError(
$this->attributesAccess['fdLanguage'],
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
htmlescape(sprintf(_('It seems the selected language "%s" is not installed on the system. Please install it or select an other one.'), $this->fdLanguage))
);
}
if (($this->fdLdapSizeLimit !== '') && ($this->fdLdapSizeLimit > 0)) {
$error = ldapSizeLimit::checkMaxInputVars($this->fdLdapSizeLimit);
if ($error !== FALSE) {
$messages[] = new SimplePluginCheckError(
$this->attributesAccess['fdLdapSizeLimit'],
$error->getHtmlMessage(),
$error->getCode(),
$error
);
}
}
return $messages;
}
public function update (): bool
{
$res = parent::update();
$this->attributesAccess['fdPasswordDefaultHash']->setChoices(
$this->attributesAccess['fdPasswordAllowedHashes']->getValue()
);
return $res;
}
static function get_themes ()
{
$themesdir = '../ihtml/themes/';
$themes = array_keys(session::get(IconTheme::$session_var));
if ($dir = opendir("$themesdir")) {
while (($file = readdir($dir)) !== FALSE) {
if (is_dir("$themesdir/$file") && !preg_match("/^\./", $file)) {
$themes[] = $file;
}
}
}
return array_unique($themes);
}
static function mainInc ($classname = NULL, $entry_dn = NULL, $tabs = TRUE, $edit_mode = TRUE, $objectType = FALSE)
{
global $config;
if ($classname === NULL) {
$classname = get_called_class();
}
if ($entry_dn === NULL) {
$entry_dn = CONFIGRDN.$config->current['BASE'];
}
parent::mainInc($classname, $entry_dn, $tabs, $edit_mode, $objectType);
}
}