From 770458b82fab226eed92034451296b2ae1213282 Mon Sep 17 00:00:00 2001 From: Roland Gruber Date: Mon, 9 Apr 2012 13:20:24 +0000 Subject: [PATCH] quick (un)lock for users --- lam/lib/baseType.inc | 10 ++ lam/lib/modules.inc | 6 +- lam/lib/modules/posixAccount.inc | 65 ++++++-- lam/lib/modules/sambaSamAccount.inc | 40 ++++- lam/lib/types/user.inc | 223 +++++++++++++++++++++++++++- lam/templates/config/profmanage.php | 10 +- lam/templates/lib/500_lam.js | 18 ++- 7 files changed, 336 insertions(+), 36 deletions(-) diff --git a/lam/lib/baseType.inc b/lam/lib/baseType.inc index 138750fd..2a5db60d 100644 --- a/lam/lib/baseType.inc +++ b/lam/lib/baseType.inc @@ -158,6 +158,16 @@ class baseType { usort($ret, 'compareDN'); return $ret; } + + /** + * This function is called after the edit page is processed and before the page content is generated. + * This can be used to run custom handlers after each page processing. + * + * @param accountContainer $container account container + */ + public function runEditPagePostAction($container) { + + } } diff --git a/lam/lib/modules.inc b/lam/lib/modules.inc index 6687f31f..5285f444 100644 --- a/lam/lib/modules.inc +++ b/lam/lib/modules.inc @@ -751,6 +751,7 @@ class accountContainer { $result = array(); $stopProcessing = false; // when set to true, no module options are displayed $errorsOccured = false; + $typeObject = new $this->type(); $profileLoaded = $this->loadProfileIfRequested(); if ($this->subpage=='') $this->subpage='attributes'; if (isset($_POST['accountContainerReset'])) { @@ -805,8 +806,10 @@ class accountContainer { } } } - $this->sortModules(); + $this->sortModules(); } + // run type post actions + $typeObject->runEditPagePostAction($this); // save account if (!$errorsOccured && isset($_POST['accountContainerSaveAccount'])) { // check if all modules are complete @@ -877,7 +880,6 @@ class accountContainer { } } // update titles - $typeObject = new $this->type(); $this->titleBarTitle = $typeObject->getTitleBarTitle($this); $this->titleBarSubtitle = $typeObject->getTitleBarSubtitle($this); // prints a module content page diff --git a/lam/lib/modules/posixAccount.inc b/lam/lib/modules/posixAccount.inc index c4273e22..d6d84ce7 100644 --- a/lam/lib/modules/posixAccount.inc +++ b/lam/lib/modules/posixAccount.inc @@ -267,7 +267,7 @@ class posixAccount extends baseModule implements passwordService { 'example' => _('Steve Miller,Room 2.14,123-123-1234,123-123-1234') ) ); - if ($this->areGroupOfNamesActive()) { + if (self::areGroupOfNamesActive()) { $return['upload_columns'][] = array( 'name' => 'posixAccount_gon', 'description' => _('Group of names'), @@ -321,7 +321,7 @@ class posixAccount extends baseModule implements passwordService { 'cn' => _('Common name'), 'userPassword' => _('Password') ); - if ($this->areGroupOfNamesActive()) { + if (self::areGroupOfNamesActive()) { $return['PDF_fields']['gon'] = _('Group of names'); } // help Entries @@ -479,7 +479,7 @@ class posixAccount extends baseModule implements passwordService { } $this->groups_orig = $this->groups; // get additional group of names memberships - if ($this->areGroupOfNamesActive()) { + if (self::areGroupOfNamesActive()) { $gonList1 = searchLDAPByAttribute('member', $this->getAccountContainer()->dn_orig, 'groupOfNames', array('dn'), array('gon', 'group')); $gonList2 = searchLDAPByAttribute('uniqueMember', $this->getAccountContainer()->dn_orig, 'groupOfUniqueNames', array('dn'), array('gon', 'group')); $gonList = array_merge($gonList1, $gonList2); @@ -618,7 +618,7 @@ class posixAccount extends baseModule implements passwordService { } } // set group of names - if ($this->areGroupOfNamesActive()) { + if (self::areGroupOfNamesActive()) { $gons = $this->findGroupOfNames(); $toAdd = array_values(array_diff($this->gonList, $this->gonList_orig)); $toRem = array_values(array_diff($this->gonList_orig, $this->gonList)); @@ -766,10 +766,10 @@ class posixAccount extends baseModule implements passwordService { } // Load attributes if (isset($_POST['lockPassword'])) { - $this->attributes['userPassword'][0] = pwd_disable($this->attributes['userPassword'][0]); + $this->lock(); } if (isset($_POST['unlockPassword'])) { - $this->attributes['userPassword'][0] = pwd_enable($this->attributes['userPassword'][0]); + $this->unlock(); } if (isset($_POST['removePassword'])) { unset($this->attributes['userPassword']); @@ -955,7 +955,7 @@ class posixAccount extends baseModule implements passwordService { $this->groups = array_delete($_POST['removegroups'], $this->groups); } // group of names - if ($this->areGroupOfNamesActive()) { + if (self::areGroupOfNamesActive()) { if (isset($_POST['addgons']) && isset($_POST['addgons_button'])) { // Add groups to list // add new group $this->gonList = @array_merge($this->gonList, $_POST['addgons']); @@ -1224,7 +1224,7 @@ class posixAccount extends baseModule implements passwordService { $return->addElement($unixContainer); - if ($this->areGroupOfNamesActive()) { + if (self::areGroupOfNamesActive()) { $return->addElement(new htmlSpacer('100px', null)); $gons = $this->findGroupOfNames(); @@ -1371,7 +1371,7 @@ class posixAccount extends baseModule implements passwordService { $addGroupSelect->setTransformSingleSelect(false); $return->addElement($addGroupSelect, true); // group of names - if ($this->areGroupOfNamesActive()) { + if (self::areGroupOfNamesActive()) { $gons = $this->findGroupOfNames(); $gonList = array(); foreach ($gons as $dn => $attr) { @@ -1475,7 +1475,7 @@ class posixAccount extends baseModule implements passwordService { if (isset($this->attributes['gecos'][0])) { $return['posixAccount_gecos'] = array('' . _('Gecos') . '' . $this->attributes['gecos'][0] . ''); } - if ($this->areGroupOfNamesActive()) { + if (self::areGroupOfNamesActive()) { $allGons = $this->findGroupOfNames(); $gons = array(); for ($i = 0; $i < sizeof($this->gonList); $i++) { @@ -1577,7 +1577,7 @@ class posixAccount extends baseModule implements passwordService { } $existingGroups = array_keys($groupMap); // get list of existing group of names - if ($this->areGroupOfNamesActive()) { + if (self::areGroupOfNamesActive()) { $gons = $this->findGroupOfNames(); $gonList = array(); foreach ($gons as $dn => $attr) { @@ -1679,7 +1679,7 @@ class posixAccount extends baseModule implements passwordService { } } // group of names - if ($this->areGroupOfNamesActive() && ($rawAccounts[$i][$ids['posixAccount_gon']] != "")) { + if (self::areGroupOfNamesActive() && ($rawAccounts[$i][$ids['posixAccount_gon']] != "")) { $groups = explode(",", $rawAccounts[$i][$ids['posixAccount_gon']]); for ($g = 0; $g < sizeof($groups); $g++) { if (!in_array($groups[$g], $gonList)) { @@ -1850,7 +1850,7 @@ class posixAccount extends baseModule implements passwordService { $groupMap[$groupList[$i][0]] = $groupList[$i][1]; } // get list of existing group of names - if ($this->areGroupOfNamesActive()) { + if (self::areGroupOfNamesActive()) { $gonList = $this->findGroupOfNames(); $gonMap = array(); foreach ($gonList as $dn => $attr) { @@ -2334,7 +2334,7 @@ class posixAccount extends baseModule implements passwordService { * * @return boolean group of names are active */ - private function areGroupOfNamesActive() { + public static function areGroupOfNamesActive() { if (!isset($_SESSION['config'])) { return false; } @@ -2377,6 +2377,43 @@ class posixAccount extends baseModule implements passwordService { return null; } + /** + * Returns if the Unix part of the current account is locked. + * + * @return boolean password is locked + */ + public function isLocked() { + return isset($this->attributes['userPassword'][0]) && !pwd_is_enabled($this->attributes['userPassword'][0]); + } + + /** + * Locks the user password of this account. + */ + public function lock() { + $this->attributes['userPassword'][0] = pwd_disable($this->attributes['userPassword'][0]); + } + + /** + * Unlocks the user password of this account. + */ + public function unlock() { + $this->attributes['userPassword'][0] = pwd_enable($this->attributes['userPassword'][0]); + } + + /** + * Removes all Unix group memberships from this user. + */ + public function removeFromUnixGroups() { + $this->groups = array(); + } + + /** + * Removes all group of names memberships from this user. + */ + public function removeFromGONGroups() { + $this->gonList = array(); + } + } ?> diff --git a/lam/lib/modules/sambaSamAccount.inc b/lam/lib/modules/sambaSamAccount.inc index 3b8db252..8148c067 100644 --- a/lam/lib/modules/sambaSamAccount.inc +++ b/lam/lib/modules/sambaSamAccount.inc @@ -619,7 +619,7 @@ class sambaSamAccount extends baseModule implements passwordService { * @return boolean true, if settings are complete */ public function module_complete() { - if (!in_array('sambaSamAccount', $this->attributes['objectClass'])) { + if (!$this->isExtensionEnabled()) { return true; } if ($this->get_scope() == "host") { @@ -672,7 +672,7 @@ class sambaSamAccount extends baseModule implements passwordService { // skip saving if the extension was not added/modified return array(); } - if (in_array('sambaSamAccount', $this->attributes['objectClass'])) { + if ($this->isExtensionEnabled()) { if ($this->expirePassword === true) { $this->attributes['sambaPwdLastSet'][0] = '0'; } @@ -710,7 +710,7 @@ class sambaSamAccount extends baseModule implements passwordService { return array(); } // skip processing if extension is not active - if (!in_array('sambaSamAccount', $this->attributes['objectClass'])) { + if (!$this->isExtensionEnabled()) { return array(); } // delete LM hash if needed @@ -1043,7 +1043,7 @@ class sambaSamAccount extends baseModule implements passwordService { */ function display_html_attributes() { $return = new htmlTable(); - if (in_array('sambaSamAccount', $this->attributes['objectClass'])) { + if ($this->isExtensionEnabled()) { if ($this->get_scope() == "host") { $attrs = $this->getAccountContainer()->getAccountModule('posixAccount')->getAttributes(); if (substr($attrs['uid'][0], -1, 1) != '$') { @@ -2326,7 +2326,39 @@ class sambaSamAccount extends baseModule implements passwordService { $this->attributes['sambaKickoffTime'][0] = gmmktime(0, 0, 0, intval($month), intval($day), intval($year)); } + + /** + * Returns if the Samba extension is enabled. + * + * @return boolean Samba extension is active + */ + public function isExtensionEnabled() { + return in_array('sambaSamAccount', $this->attributes['objectClass']); + } + /** + * Returns if the Samba part of the current account is deactivated. + * + * @return boolean account is locked + */ + public function isDeactivated() { + return $this->deactivated; + } + + /** + * Deactivates this account. + */ + public function deactivate() { + $this->deactivated = true; + } + + /** + * Activates this account. + */ + public function activate() { + $this->deactivated = false; + } + } ?> diff --git a/lam/lib/types/user.inc b/lam/lib/types/user.inc index fc8a98da..842d9e8b 100644 --- a/lam/lib/types/user.inc +++ b/lam/lib/types/user.inc @@ -173,9 +173,9 @@ class user extends baseType { $personalAttributes = $container->getAccountModule('inetOrgPerson')->getAttributes(); } if ($personalAttributes == null) { - return null; + return $this->buildAccountStatusIcon($container); } - $subtitle = ''; + $subtitle = $this->buildAccountStatusIcon($container); $spacer = '        '; // check if an email address can be shown if (isset($personalAttributes['mail'][0])) { @@ -198,17 +198,226 @@ class user extends baseType { /** * Builds the HTML code for the icon that shows the account status (locked/unlocked). * - * @param array $attributes LDAP attributes + * @param accountContainer $container account container * @return String HTML code for icon */ - private function buildAccountStatusIcon($attributes) { - $lowerAttributes = array_change_key_case($attributes, CASE_LOWER); - if (!lamUserList::isUnixAvailable($lowerAttributes) && !lamUserList::isUnixAvailable($lowerAttributes) && !lamUserList::isPPolicyAvailable($lowerAttributes)) { + private function buildAccountStatusIcon($container) { + // check if there are account parts that can be locked + $unixAvailable = ($container->getAccountModule('posixAccount') != null); + $sambaAvailable = (($container->getAccountModule('sambaSamAccount') != null) && $container->getAccountModule('sambaSamAccount')->isExtensionEnabled()); + $ppolicyAvailable = ($container->getAccountModule('ppolicyUser') != null); + if (!$unixAvailable && !$sambaAvailable && !$ppolicyAvailable) { return ''; } - return '   '; + // get locking status + $unixLocked = false; + if ($unixAvailable && $container->getAccountModule('posixAccount')->isLocked()) { + $unixLocked = true; + } + $sambaLocked = false; + if ($sambaAvailable && $container->getAccountModule('sambaSamAccount')->isDeactivated()) { + $sambaLocked = true; + } + $ppolicyLocked = false; + if ($ppolicyAvailable && $container->getAccountModule('ppolicyUser')->isLocked()) { + $ppolicyLocked = true; + } + $partiallyLocked = $unixLocked || $sambaLocked || $ppolicyLocked; + $fullyLocked = ($unixAvailable || $sambaAvailable || $ppolicyAvailable) + && (!$unixAvailable || $unixLocked) + && (!$sambaAvailable || $sambaLocked) + && (!$ppolicyAvailable || $ppolicyLocked); + // build tooltip + $icon = 'unlocked.png'; + if ($fullyLocked) { + $icon = 'lock.png'; + } + elseif ($partiallyLocked) { + $icon = 'partiallyLocked.png'; + } + $statusTable = ''; + // Unix + if ($unixAvailable) { + $unixIcon = 'unlocked.png'; + if ($unixLocked) { + $unixIcon = 'lock.png'; + } + $statusTable .= ''; + } + // Samba + if ($sambaAvailable) { + $sambaIcon = 'unlocked.png'; + if ($sambaLocked) { + $sambaIcon = 'lock.png'; + } + $statusTable .= ''; + } + // PPolicy + if ($ppolicyAvailable) { + $ppolicyIcon = 'unlocked.png'; + if ($ppolicyLocked) { + $ppolicyIcon = 'lock.png'; + } + $statusTable .= ''; + } + $statusTable .= '
' . _('Unix') . '  
' . _('Samba') . '  
' . _('Password policy') . '  
'; + $tipContent = $statusTable; + $tipContent .= '
"hint" '; + $tipContent .= _('Please click to lock/unlock this account.'); + $tooltip = "'" . $tipContent . "', TITLE, '" . _('Account status') . "'"; + $dialogDiv = $this->buildAccountStatusDialogDiv($unixAvailable, $unixLocked, $sambaAvailable, $sambaLocked, $ppolicyAvailable, $ppolicyLocked); + $onClick = 'onclick="showConfirmationDialog(\'' . _('Change account status') . '\', \'' . _('Ok') . '\', \'' . _('Cancel') . '\', \'lam_accountStatusDialog\', \'inputForm\', \'lam_accountStatusResult\');"'; + return $dialogDiv . 'status   '; + } + + /** + * Builds the dialog to (un)lock parts of an account. + * + * @param boolean $unixAvailable Unix part is active + * @param boolean $unixLocked Unix part is locked + * @param boolean $sambaAvailable Samba part is active + * @param boolean $sambaLocked Samba part is locked + * @param boolean $ppolicyAvailable PPolicy part is active + * @param boolean $ppolicyLocked PPolicy part is locked + */ + private function buildAccountStatusDialogDiv($unixAvailable, $unixLocked, $sambaAvailable, $sambaLocked, $ppolicyAvailable, $ppolicyLocked) { + $partiallyLocked = $unixLocked || $sambaLocked || $ppolicyLocked; + $fullyLocked = ($unixAvailable || $sambaAvailable || $ppolicyAvailable) + && (!$unixAvailable || $unixLocked) + && (!$sambaAvailable || $sambaLocked) + && (!$ppolicyAvailable || $ppolicyLocked); + $dialog = ''; + return $dialog; } + /** + * This function is called after the edit page is processed and before the page content is generated. + * This can be used to run custom handlers after each page processing. + * + * @param accountContainer $container account container + */ + public function runEditPagePostAction($container) { + // check if account status should be changed + if (isset($_POST['lam_accountStatusResult']) && ($_POST['lam_accountStatusResult'] == 'ok')) { + // lock account + if ($_POST['lam_accountStatusAction'] == 'lock') { + // Unix + if (isset($_POST['lam_accountStatusLockUnix']) && ($_POST['lam_accountStatusLockUnix'] == 'on')) { + $container->getAccountModule('posixAccount')->lock(); + } + // Samba + if (isset($_POST['lam_accountStatusLockSamba']) && ($_POST['lam_accountStatusLockSamba'] == 'on')) { + $container->getAccountModule('sambaSamAccount')->deactivate(); + } + // PPolicy + if (isset($_POST['lam_accountStatusLockPPolicy']) && ($_POST['lam_accountStatusLockPPolicy'] == 'on')) { + $container->getAccountModule('ppolicyUser')->lock(); + } + // remove Unix groups + if (isset($_POST['lam_accountStatusRemoveUnixGroups']) && ($_POST['lam_accountStatusRemoveUnixGroups'] == 'on')) { + $container->getAccountModule('posixAccount')->removeFromUnixGroups(); + } + // remove group of names memberships + if (isset($_POST['lam_accountStatusRemoveGONGroups']) && ($_POST['lam_accountStatusRemoveGONGroups'] == 'on')) { + $container->getAccountModule('posixAccount')->removeFromGONGroups(); + } + } + // unlock account + elseif ($_POST['lam_accountStatusAction'] == 'unlock') { + // Unix + if (isset($_POST['lam_accountStatusUnlockUnix']) && ($_POST['lam_accountStatusUnlockUnix'] == 'on')) { + $container->getAccountModule('posixAccount')->unlock(); + } + // Samba + if (isset($_POST['lam_accountStatusUnlockSamba']) && ($_POST['lam_accountStatusUnlockSamba'] == 'on')) { + $container->getAccountModule('sambaSamAccount')->activate(); + } + // PPolicy + if (isset($_POST['lam_accountStatusUnlockPPolicy']) && ($_POST['lam_accountStatusUnlockPPolicy'] == 'on')) { + $container->getAccountModule('ppolicyUser')->unlock(); + } + } + } + } + } /** diff --git a/lam/templates/config/profmanage.php b/lam/templates/config/profmanage.php index 7c355517..6d1a4e67 100644 --- a/lam/templates/config/profmanage.php +++ b/lam/templates/config/profmanage.php @@ -238,7 +238,7 @@ $profileNewPwd2->setFieldSize(15); $container->addElement($profileNewPwd2, true); $newProfileButton = new htmlButton('btnAddProfile', _('Add')); $newProfileButton->setOnClick("jQuery('#action').val('add');showConfirmationDialog('" . _("Add profile") . "', '" . - _('Ok') . "', '" . _('Cancel') . "', 'passwordDialogDiv', 'profileForm');"); + _('Ok') . "', '" . _('Cancel') . "', 'passwordDialogDiv', 'profileForm', null);"); $container->addElement($newProfileButton, true); $container->addElement($topicSpacer, true); @@ -250,7 +250,7 @@ $oldProfileInput->setFieldSize(15); $container->addElement($oldProfileInput, true); $renameProfileButton = new htmlButton('btnRenameProfile', _('Rename')); $renameProfileButton->setOnClick("jQuery('#action').val('rename');showConfirmationDialog('" . _("Rename profile") . "', '" . - _('Ok') . "', '" . _('Cancel') . "', 'passwordDialogDiv', 'profileForm');"); + _('Ok') . "', '" . _('Cancel') . "', 'passwordDialogDiv', 'profileForm', null);"); $container->addElement($renameProfileButton, true); $container->addElement($topicSpacer, true); @@ -259,7 +259,7 @@ $container->addElement(new htmlSubTitle(_("Delete profile")), true); $container->addElement(new htmlTableExtendedSelect('delfilename', $files, array(), _('Profile name'), '232'), true); $deleteProfileButton = new htmlButton('btnDeleteProfile', _('Delete')); $deleteProfileButton->setOnClick("jQuery('#action').val('delete');showConfirmationDialog('" . _("Delete profile") . "', '" . - _('Ok') . "', '" . _('Cancel') . "', 'passwordDialogDiv', 'profileForm');"); + _('Ok') . "', '" . _('Cancel') . "', 'passwordDialogDiv', 'profileForm', null);"); $container->addElement($deleteProfileButton, true); $container->addElement($topicSpacer, true); @@ -276,7 +276,7 @@ $profileSetPwd2->setFieldSize(15); $container->addElement($profileSetPwd2, true); $setPasswordProfileButton = new htmlButton('btnSetPasswordProfile', _('Set profile password')); $setPasswordProfileButton->setOnClick("jQuery('#action').val('setpass');showConfirmationDialog('" . _("Set profile password") . "', '" . - _('Ok') . "', '" . _('Cancel') . "', 'passwordDialogDiv', 'profileForm');"); + _('Ok') . "', '" . _('Cancel') . "', 'passwordDialogDiv', 'profileForm', null);"); $container->addElement($setPasswordProfileButton, true); $container->addElement($topicSpacer, true); @@ -287,7 +287,7 @@ $container->addElement(new htmlSubTitle(_("Change default profile")), true); $container->addElement(new htmlTableExtendedSelect('defaultfilename', $files, array($defaultprofile), _('Profile name'), '234'), true); $defaultProfileButton = new htmlButton('btnDefaultProfile', _('Ok')); $defaultProfileButton->setOnClick("jQuery('#action').val('setdefault');showConfirmationDialog('" . _("Change default profile") . "', '" . - _('Ok') . "', '" . _('Cancel') . "', 'passwordDialogDiv', 'profileForm');"); + _('Ok') . "', '" . _('Cancel') . "', 'passwordDialogDiv', 'profileForm', null);"); $container->addElement($defaultProfileButton, true); $container->addElement($topicSpacer, true); diff --git a/lam/templates/lib/500_lam.js b/lam/templates/lib/500_lam.js index c8e4f6af..f46162f6 100644 --- a/lam/templates/lib/500_lam.js +++ b/lam/templates/lib/500_lam.js @@ -309,11 +309,22 @@ function passwordHandleReply(data) { * @param cancelText text for Cancel button * @param dialogDiv div that contains dialog content * @param formName form to submit + * @param resultField (hidden) input field whose value is set to ok/cancel when button is pressed */ -function showConfirmationDialog(title, okText, cancelText, dialogDiv, formName) { +function showConfirmationDialog(title, okText, cancelText, dialogDiv, formName, resultField) { var buttonList = {}; - buttonList[cancelText] = function() { jQuery(this).dialog("close"); }; - buttonList[okText] = function() { document.forms[formName].submit(); }; + buttonList[cancelText] = function() { + if (resultField) { + jQuery('#' + resultField).val('cancel'); + }; + jQuery(this).dialog("close"); + }; + buttonList[okText] = function() { + if (resultField) { + jQuery('#' + resultField).val('ok'); + }; + document.forms[formName].submit(); + }; jQuery('#' + dialogDiv).dialog({ modal: true, title: title, @@ -325,4 +336,3 @@ function showConfirmationDialog(title, okText, cancelText, dialogDiv, formName) jQuery('#' + dialogDiv).parent().appendTo(document.forms[formName]); } -