diff --git a/lam/HISTORY b/lam/HISTORY
index 467a07b5..818f0748 100644
--- a/lam/HISTORY
+++ b/lam/HISTORY
@@ -1,6 +1,7 @@
June 2016 5.4
- Unix: support magic numbers for UIDs/GIDs (e.g. 389 server DNA plugin)
- LAM Pro:
+ -> New module for 389ds unlocking and deactivation status
-> Self registration: support for Google reCAPTCHA
-> Password notification jobs support CC and BCC
diff --git a/lam/docs/manual-sources/howto.xml b/lam/docs/manual-sources/howto.xml
index 92261b2a..aa5d4039 100644
--- a/lam/docs/manual-sources/howto.xml
+++ b/lam/docs/manual-sources/howto.xml
@@ -2698,8 +2698,8 @@ mysql> GRANT ALL PRIVILEGES ON lam_cron.* TO 'lam_cron'@'localhost';
Show account status: If you activate this
option then there will be an additional column displayed that shows if
the account is locked. You can see more details when moving the mouse
- cursor over the lock icon. This function supports Unix, Samba and
- PPolicy.
+ cursor over the lock icon. This function supports Unix, Samba, PPolicy,
+ Windows and 389ds locking+deactivation.
diff --git a/lam/docs/manual-sources/images/userListOptionAccountStatus.png b/lam/docs/manual-sources/images/userListOptionAccountStatus.png
index b9402d13..d1f550c3 100644
Binary files a/lam/docs/manual-sources/images/userListOptionAccountStatus.png and b/lam/docs/manual-sources/images/userListOptionAccountStatus.png differ
diff --git a/lam/docs/manual-sources/images/userListOptionTransPrimary.png b/lam/docs/manual-sources/images/userListOptionTransPrimary.png
index 685020fb..1fa83602 100644
Binary files a/lam/docs/manual-sources/images/userListOptionTransPrimary.png and b/lam/docs/manual-sources/images/userListOptionTransPrimary.png differ
diff --git a/lam/graphics/unlocked.png b/lam/graphics/unlocked.png
index 91891851..0b6b805f 100644
Binary files a/lam/graphics/unlocked.png and b/lam/graphics/unlocked.png differ
diff --git a/lam/lib/baseModule.inc b/lam/lib/baseModule.inc
index 48f219c6..157dc602 100644
--- a/lam/lib/baseModule.inc
+++ b/lam/lib/baseModule.inc
@@ -1267,10 +1267,9 @@ abstract class baseModule {
* @param integer $length field length
* @param boolean $isTextArea show as text area (default false)
* @param array $autoCompleteValues values for auto-completion
- * @param boolean $readOnly this field is read-only
* @return mixed reference to htmlTableExtendedInputField/htmlTableExtendedInputTextarea
*/
- protected function &addSimpleInputTextField(&$container, $attrName, $label, $required = false, $length = null, $isTextArea = false, $autoCompleteValues = null, $readOnly = false) {
+ protected function &addSimpleInputTextField(&$container, $attrName, $label, $required = false, $length = null, $isTextArea = false, $autoCompleteValues = null) {
$value = '';
if (isset($this->attributes[$attrName][0])) {
$value = $this->attributes[$attrName][0];
@@ -1296,6 +1295,28 @@ abstract class baseModule {
return $input;
}
+ /**
+ * Adds a simple read-only field to the given container.
+ *
+ * @param htmlTable $container parent container
+ * @param String $attrName attribute name
+ * @param String $label field label
+ */
+ protected function addSimpleReadOnlyField(&$container, $attrName, $label) {
+ $val = '';
+ if (!empty($this->attributes[$attrName][0])) {
+ $values = $this->attributes[$attrName];
+ array_map('htmlspecialchars', $values);
+ $val = implode('
', $values);
+ }
+ $labelBox = new htmlOutputText($label);
+ if (!empty($this->attributes[$attrName]) && (sizeof($this->attributes[$attrName]) > 1)) {
+ $labelBox->alignment = htmlElement::ALIGN_TOP;
+ }
+ $container->addElement($labelBox);
+ $container->addElement(new htmlOutputText($val, false), true);
+ }
+
/**
* Adds a text input field that may contain multiple values to the given htmlTable.
* The field name will be the same as the attribute name plus a counting number (e.g. street_0).
@@ -1598,6 +1619,18 @@ abstract class baseModule {
else return array();
}
+ /**
+ * Returns a list of operational LDAP attributes which are managed by this module and need to be explicitly set for LDAP search.
+ *
+ * @return array list of hidden attributes
+ *
+ * @see baseModule::get_metaData()
+ */
+ public function getManagedHiddenAttributes() {
+ if (isset($this->meta['hiddenAttributes']) && is_array($this->meta['hiddenAttributes'])) return $this->meta['hiddenAttributes'];
+ else return array();
+ }
+
/**
* This function returns a list of PHP extensions (e.g. hash) which are needed by this module.
*
diff --git a/lam/lib/modules.inc b/lam/lib/modules.inc
index 4b49c72f..1f23c449 100644
--- a/lam/lib/modules.inc
+++ b/lam/lib/modules.inc
@@ -1553,8 +1553,11 @@ class accountContainer {
$this->module = array();
$modules = $_SESSION['config']->get_AccountModules($this->type);
$search = substr($dn, 0, strpos($dn, ','));
- $searchAttrs = array('*', '+', 'creatorsName', 'createTimestamp', 'modifiersName',
- 'modifyTimestamp', 'hasSubordinates', 'pwdChangedTime');
+ $searchAttrs = array('*', '+');
+ foreach ($modules as $module) {
+ $modTmp = new $module($this->type);
+ $searchAttrs = array_merge($searchAttrs, $modTmp->getManagedHiddenAttributes());
+ }
$result = @ldap_read($_SESSION['ldap']->server(), escapeDN($dn), escapeDN($search), $searchAttrs, 0, 0, 0, LDAP_DEREF_NEVER);
if (!$result) {
return array(array("ERROR", _("Unable to load LDAP entry:") . " " . htmlspecialchars($dn), getDefaultLDAPErrorString($_SESSION['ldap']->server())));
diff --git a/lam/lib/modules/.gitignore b/lam/lib/modules/.gitignore
index d25f68ab..78c0f9c0 100644
--- a/lam/lib/modules/.gitignore
+++ b/lam/lib/modules/.gitignore
@@ -34,3 +34,4 @@
/zarafaGroup.inc
/zarafaServer.inc
/zarafaUser.inc
+/locking389ds.inc
diff --git a/lam/lib/modules/generalInformation.inc b/lam/lib/modules/generalInformation.inc
index f8220456..968d1edf 100644
--- a/lam/lib/modules/generalInformation.inc
+++ b/lam/lib/modules/generalInformation.inc
@@ -3,7 +3,7 @@
$Id$
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
- Copyright (C) 2011 Roland Gruber
+ Copyright (C) 2011 - 2016 Roland Gruber
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
@@ -36,7 +36,7 @@ class generalInformation extends baseModule {
/**
* Returns true if this module can manage accounts of the current type, otherwise false.
- *
+ *
* @return boolean true if module fits
*/
public function can_manage() {
@@ -47,7 +47,7 @@ class generalInformation extends baseModule {
* Returns meta data that is interpreted by parent class
*
* @return array array with meta data
- *
+ *
* @see baseModule::get_metaData()
*/
public function get_metaData() {
@@ -60,13 +60,15 @@ class generalInformation extends baseModule {
$return['dependencies'] = array('depends' => array(), 'conflicts' => array());
// managed attributes
$return['attributes'] = array('creatorsName', 'createTimestamp', 'modifiersName',
- 'modifyTimestamp', 'hasSubordinates', 'memberOf', 'pwdChangedTime');
+ 'modifyTimestamp', 'hasSubordinates', 'memberOf');
+ $return['hiddenAttributes'] = array('creatorsName', 'createTimestamp', 'modifiersName',
+ 'modifyTimestamp', 'hasSubordinates');
return $return;
}
/**
* Returns the HTML meta data for the main account page.
- *
+ *
* @return htmlElement HTML meta data
*/
public function display_html_attributes() {
diff --git a/lam/lib/modules/inetOrgPerson.inc b/lam/lib/modules/inetOrgPerson.inc
index 4ee458c6..c5258725 100644
--- a/lam/lib/modules/inetOrgPerson.inc
+++ b/lam/lib/modules/inetOrgPerson.inc
@@ -3601,28 +3601,6 @@ class inetOrgPerson extends baseModule implements passwordService {
return $this->isBooleanConfigOptionSet('inetOrgPerson_readOnly_' . $attrName);
}
- /**
- * Adds a simple read-only field to the given container.
- *
- * @param htmlTable $container parent container
- * @param String $attrName attribute name
- * @param String $label field label
- */
- private function addSimpleReadOnlyField(&$container, $attrName, $label) {
- $val = '';
- if (!empty($this->attributes[$attrName][0])) {
- $values = $this->attributes[$attrName];
- array_map('htmlspecialchars', $values);
- $val = implode('
', $values);
- }
- $labelBox = new htmlOutputText($label);
- if (!empty($this->attributes[$attrName]) && (sizeof($this->attributes[$attrName]) > 1)) {
- $labelBox->alignment = htmlElement::ALIGN_TOP;
- }
- $container->addElement($labelBox);
- $container->addElement(new htmlOutputText($val, false), true);
- }
-
/**
* Returns a list of configuration options.
*
diff --git a/lam/lib/types/user.inc b/lam/lib/types/user.inc
index f24354df..36bd4624 100644
--- a/lam/lib/types/user.inc
+++ b/lam/lib/types/user.inc
@@ -224,9 +224,12 @@ class user extends baseType {
$sambaAvailable = (($container->getAccountModule('sambaSamAccount') != null) && $container->getAccountModule('sambaSamAccount')->isExtensionEnabled());
$ppolicyAvailable = ($container->getAccountModule('ppolicyUser') != null);
$windowsAvailable = ($container->getAccountModule('windowsUser') != null);
- if (!$unixAvailable && !$sambaAvailable && !$ppolicyAvailable && !$windowsAvailable) {
+ $is389dsLocked = ($container->getAccountModule('locking389ds') != null) && $container->getAccountModule('locking389ds')->isLocked();
+ $is389dsDeactivated = ($container->getAccountModule('locking389ds') != null) && $container->getAccountModule('locking389ds')->isDeactivated();
+ if (!$unixAvailable && !$sambaAvailable && !$ppolicyAvailable && !$windowsAvailable && !$is389dsDeactivated && !$is389dsLocked) {
return '';
}
+ $isEditable = checkIfWriteAccessIsAllowed('user') && ($unixAvailable || $sambaAvailable || $ppolicyAvailable || $windowsAvailable || $is389dsLocked);
// get locking status
$unixLocked = false;
if ($unixAvailable && $container->getAccountModule('posixAccount')->isLocked()) {
@@ -244,8 +247,8 @@ class user extends baseType {
if ($windowsAvailable && windowsUser::isDeactivated($container->getAccountModule('windowsUser')->getAttributes())) {
$windowsLocked = true;
}
- $partiallyLocked = $unixLocked || $sambaLocked || $ppolicyLocked || $windowsLocked;
- $fullyLocked = ($unixAvailable || $sambaAvailable || $ppolicyAvailable || $windowsAvailable)
+ $partiallyLocked = $unixLocked || $sambaLocked || $ppolicyLocked || $windowsLocked || $is389dsDeactivated || $is389dsLocked;
+ $fullyLocked = ($unixAvailable || $sambaAvailable || $ppolicyAvailable || $windowsAvailable || $is389dsDeactivated || $is389dsLocked)
&& (!$unixAvailable || $unixLocked)
&& (!$sambaAvailable || $sambaLocked)
&& (!$ppolicyAvailable || $ppolicyLocked)
@@ -291,15 +294,23 @@ class user extends baseType {
}
$statusTable .= '' . _('Windows') . ' | |
';
}
+ // 389ds locked
+ if ($is389dsLocked) {
+ $statusTable .= '' . _('Locked') . ' | |
';
+ }
+ // 389ds deactivated
+ if ($is389dsDeactivated) {
+ $statusTable .= '' . _('Deactivated') . ' | |
';
+ }
$statusTable .= '';
$tipContent = $statusTable;
- if (checkIfWriteAccessIsAllowed('user')) {
+ if ($isEditable) {
$tipContent .= '
';
$tipContent .= _('Please click to lock/unlock this account.');
}
- $dialogDiv = $this->buildAccountStatusDialogDiv($unixAvailable, $unixLocked, $sambaAvailable, $sambaLocked, $ppolicyAvailable, $ppolicyLocked, $windowsAvailable, $windowsLocked);
+ $dialogDiv = $this->buildAccountStatusDialogDiv($unixAvailable, $unixLocked, $sambaAvailable, $sambaLocked, $ppolicyAvailable, $ppolicyLocked, $windowsAvailable, $windowsLocked, $is389dsLocked);
$onClick = '';
- if (checkIfWriteAccessIsAllowed('user')) {
+ if ($isEditable) {
$onClick = 'onclick="showConfirmationDialog(\'' . _('Change account status') . '\', \'' . _('Ok') . '\', \'' . _('Cancel') . '\', \'lam_accountStatusDialog\', \'inputForm\', \'lam_accountStatusResult\');"';
}
return $dialogDiv . ' ';
@@ -316,10 +327,11 @@ class user extends baseType {
* @param boolean $ppolicyLocked PPolicy part is locked
* @param boolean $windowsAvailable Windows part is active
* @param boolean $windowsLocked Windows part is locked
+ * @param boolean $is389dsLocked account is locked
*/
- private function buildAccountStatusDialogDiv($unixAvailable, $unixLocked, $sambaAvailable, $sambaLocked, $ppolicyAvailable, $ppolicyLocked, $windowsAvailable, $windowsLocked) {
- $partiallyLocked = $unixLocked || $sambaLocked || $ppolicyLocked || $windowsLocked;
- $fullyLocked = ($unixAvailable || $sambaAvailable || $ppolicyAvailable || $windowsAvailable)
+ private function buildAccountStatusDialogDiv($unixAvailable, $unixLocked, $sambaAvailable, $sambaLocked, $ppolicyAvailable, $ppolicyLocked, $windowsAvailable, $windowsLocked, $is389dsLocked) {
+ $partiallyLocked = $unixLocked || $sambaLocked || $ppolicyLocked || $windowsLocked || $is389dsLocked;
+ $fullyLocked = ($unixAvailable || $sambaAvailable || $ppolicyAvailable || $windowsAvailable || $is389dsLocked)
&& (!$unixAvailable || $unixLocked)
&& (!$sambaAvailable || $sambaLocked)
&& (!$ppolicyAvailable || $ppolicyLocked)
@@ -329,7 +341,7 @@ class user extends baseType {
// show radio buttons for lock/unlock
$radioDisabled = true;
- $selectedRadio = 'lock';
+ $selectedRadio = 'unlock';
$onchange = '';
if ($partiallyLocked && !$fullyLocked) {
$radioDisabled = false;
@@ -342,8 +354,8 @@ class user extends baseType {
'jQuery(\'#lam_accountStatusDialogUnlockDiv\').removeClass(\'hidden\');' .
'};';
}
- if ($fullyLocked) {
- $selectedRadio = 'unlock';
+ if (!$fullyLocked && !$partiallyLocked) {
+ $selectedRadio = 'lock';
}
if (!$radioDisabled) {
$radio = new htmlRadio('lam_accountStatusAction', array(_('Lock') => 'lock', _('Unlock') => 'unlock'), $selectedRadio);
@@ -389,6 +401,9 @@ class user extends baseType {
}
$lockDiv = new htmlDiv('lam_accountStatusDialogLockDiv', $lockContent);
+ if ($fullyLocked || $partiallyLocked) {
+ $lockDiv->setCSSClasses(array('hidden'));
+ }
$container->addElement($lockDiv, true);
}
// unlocking part
@@ -411,9 +426,13 @@ class user extends baseType {
$unlockContent->addElement(new htmlImage('../../graphics/samba.png'));
$unlockContent->addElement(new htmlTableExtendedInputCheckbox('lam_accountStatusUnlockWindows', true, _('Windows'), null, false), true);
}
+ if ($is389dsLocked) {
+ $unlockContent->addElement(new htmlImage('../../graphics/security.png'));
+ $unlockContent->addElement(new htmlTableExtendedInputCheckbox('lam_accountStatusUnlock389ds', true, _('Unlock'), null, false), true);
+ }
$unlockDiv = new htmlDiv('lam_accountStatusDialogUnlockDiv', $unlockContent);
- if (!$fullyLocked) {
+ if (!$fullyLocked && !$partiallyLocked) {
$unlockDiv->setCSSClasses(array('hidden'));
}
$container->addElement($unlockDiv, true);
@@ -485,6 +504,10 @@ class user extends baseType {
if (isset($_POST['lam_accountStatusUnlockWindows']) && ($_POST['lam_accountStatusUnlockWindows'] == 'on')) {
$container->getAccountModule('windowsUser')->setIsDeactivated(false);
}
+ // 389ds unlocking
+ if (isset($_POST['lam_accountStatusUnlock389ds']) && ($_POST['lam_accountStatusUnlock389ds'] == 'on')) {
+ $container->getAccountModule('locking389ds')->unlock(false);
+ }
}
}
}
@@ -829,10 +852,14 @@ class lamUserList extends lamList {
$sambaLocked = self::isSambaLocked($this->entries[$i]);
$ppolicyLocked = self::isPPolicyLocked($this->entries[$i]);
$windowsLocked = self::isWindowsLocked($this->entries[$i]);
+ $is389dsLocked = self::is389dsLocked($this->entries[$i]);
+ $is389dsDeactivated = self::is389dsDeactivated($this->entries[$i]);
$hasLocked = ($unixAvailable && $unixLocked)
|| ($sambaAvailable && $sambaLocked)
|| ($ppolicyAvailable && $ppolicyLocked)
- || ($windowsAvailable && $windowsLocked);
+ || ($windowsAvailable && $windowsLocked)
+ || $is389dsDeactivated
+ || $is389dsLocked;
$hasUnlocked = ($unixAvailable && !$unixLocked)
|| ($sambaAvailable && !$sambaLocked)
|| ($ppolicyAvailable && !$ppolicyLocked)