diff --git a/lam/graphics/partiallyLocked.png b/lam/graphics/partiallyLocked.png
new file mode 100644
index 00000000..0414b21b
Binary files /dev/null and b/lam/graphics/partiallyLocked.png differ
diff --git a/lam/graphics/unlocked.png b/lam/graphics/unlocked.png
new file mode 100644
index 00000000..91891851
Binary files /dev/null and b/lam/graphics/unlocked.png differ
diff --git a/lam/lib/lists.inc b/lam/lib/lists.inc
index c7a8dc01..57b8a2aa 100644
--- a/lam/lib/lists.inc
+++ b/lam/lib/lists.inc
@@ -94,6 +94,9 @@ class lamList {
/** ID for list size config option */
const LIST_SIZE_OPTION_NAME = "L_SIZE";
+ /** prefix for virtual (non-LDAP) attributes */
+ const VIRTUAL_ATTRIBUTE_PREFIX = 'lam_virtual_';
+
/**
* Constructor
*
@@ -345,19 +348,33 @@ class lamList {
echo "\n";
// print input boxes for filters
for ($k = 0; $k < sizeof ($this->descArray); $k++) {
- $value = "";
- if (isset($_GET["filter" . strtolower($this->attrArray[$k])])) {
- $value = " value=\"" . $_GET["filter" . strtolower($this->attrArray[$k])] . "\"";
- }
- if (isset($_POST["filter" . strtolower($this->attrArray[$k])])) {
- $value = " value=\"" . $_POST["filter" . strtolower($this->attrArray[$k])] . "\"";
- }
echo "
";
- echo "attrArray[$k]) ."\"" . $value . " onkeypress=\"SubmitForm('apply_filter', event);\">";
+ if ($this->canBeFiltered($this->attrArray[$k])) {
+ $value = "";
+ if (isset($_GET["filter" . strtolower($this->attrArray[$k])])) {
+ $value = " value=\"" . $_GET["filter" . strtolower($this->attrArray[$k])] . "\"";
+ }
+ if (isset($_POST["filter" . strtolower($this->attrArray[$k])])) {
+ $value = " value=\"" . $_POST["filter" . strtolower($this->attrArray[$k])] . "\"";
+ }
+ echo "attrArray[$k]) ."\"" . $value . " onkeypress=\"SubmitForm('apply_filter', event);\">";
+ }
echo " | \n";
}
echo "\n";
}
+
+ /**
+ * Returns if the given attribute can be filtered.
+ * If filtering is not possible then no filter box will be displayed.
+ * By default all attributes can be filtered.
+ *
+ * @param String $attr attribute name
+ * @return boolean filtering possible
+ */
+ protected function canBeFiltered($attr) {
+ return true;
+ }
/**
* Prints the entry list
@@ -751,7 +768,7 @@ class lamList {
*
* @return array attribute list
*/
- private function listGetAttributeDescriptionList() {
+ protected function listGetAttributeDescriptionList() {
$ret = array();
$attr_string = $_SESSION["config"]->get_listAttributes($this->type);
$temp_array = explode(";", $attr_string);
@@ -836,6 +853,20 @@ class lamList {
$module_filter = get_ldap_filter($this->type); // basic filter is provided by modules
$filter = "(&" . $module_filter . $this->filterPart . ")";
$attrs = $this->attrArray;
+ // remove virtual attributes from list
+ for ($i = 0; $i < sizeof($attrs); $i++) {
+ if (strpos($attrs[$i], self::VIRTUAL_ATTRIBUTE_PREFIX) === 0) {
+ unset($attrs[$i]);
+ }
+ }
+ $attrs = array_values($attrs);
+ // include additional attributes
+ $additionalAttrs = $this->getAdditionalLDAPAttributesToRead();
+ for ($i = 0; $i < sizeof($additionalAttrs); $i++) {
+ if (!in_array_ignore_case($additionalAttrs[$i], $attrs)) {
+ $attrs[] = $additionalAttrs[$i];
+ }
+ }
$this->entries = searchLDAP($this->suffix, $filter, $attrs);
$lastError = getLastLDAPError();
if ($lastError != null) {
@@ -846,6 +877,16 @@ class lamList {
$this->possibleSuffixes = $typeObj->getSuffixList();
}
+ /**
+ * Returns a list of additional LDAP attributes that should be read.
+ * This can be used to show additional data even if the user selected other attributes to show in the list.
+ *
+ * @return array additional attribute names
+ */
+ protected function getAdditionalLDAPAttributesToRead() {
+ return array();
+ }
+
/**
* Returns a list of lamListTool objects to display next to the edit/delete buttons.
*
diff --git a/lam/lib/types/user.inc b/lam/lib/types/user.inc
index 065fa14b..56965541 100644
--- a/lam/lib/types/user.inc
+++ b/lam/lib/types/user.inc
@@ -178,13 +178,21 @@ class lamUserList extends lamList {
/** Controls if GID number is translated to group name */
private $trans_primary = false;
+
+ /** Controls if the account status is shown */
+ private $showAccountStatus = false;
/** translates GID to group name */
private $trans_primary_hash = array();
- /** ID for config option */
+ /** ID for config option to translate primary group GIDs to group names */
const TRANS_PRIMARY_OPTION_NAME = "LU_TP";
-
+ /** ID for config option to show account status */
+ const ACCOUNT_STATUS_OPTION_NAME = "LU_AS";
+
+ /** virtual attribute name for account status column */
+ const ATTR_ACCOUNT_STATUS = 'lam_virtual_account_status';
+
/**
* Constructor
*
@@ -219,6 +227,9 @@ class lamUserList extends lamList {
if ($this->trans_primary == "on") {
$this->refreshPrimaryGroupTranslation();
}
+ if ($this->showAccountStatus) {
+ $this->injectAccountStatusAttribute();
+ }
}
/**
@@ -243,7 +254,9 @@ class lamUserList extends lamList {
*/
protected function listPrintTableCellContent(&$entry, &$attribute) {
// check if there is something to display at all
- if (!isset($entry[$attribute]) || !is_array($entry[$attribute]) || (sizeof($entry[$attribute]) < 1)) return;
+ if (($attribute != self::ATTR_ACCOUNT_STATUS) && (!isset($entry[$attribute]) || !is_array($entry[$attribute]) || (sizeof($entry[$attribute]) < 1))) {
+ return;
+ }
// translate GID to group name
if (($attribute == "gidnumber") && ($this->trans_primary == "on")) {
if (isset($this->trans_primary_hash[$entry[$attribute][0]])) {
@@ -310,6 +323,10 @@ class lamUserList extends lamList {
}
}
}
+ // account status
+ elseif ($attribute == self::ATTR_ACCOUNT_STATUS) {
+ $this->printAccountStatus($entry);
+ }
// print all other attributes
else {
parent::listPrintTableCellContent($entry, $attribute);
@@ -337,6 +354,7 @@ class lamUserList extends lamList {
protected function listGetAllConfigOptions() {
$options = parent::listGetAllConfigOptions();
$options[] = new lamBooleanListOption(_('Translate GID number to group name'), self::TRANS_PRIMARY_OPTION_NAME);
+ $options[] = new lamBooleanListOption(_('Show account status'), self::ACCOUNT_STATUS_OPTION_NAME);
return $options;
}
@@ -347,6 +365,202 @@ class lamUserList extends lamList {
parent::listConfigurationChanged();
$tpOption = $this->listGetConfigOptionByID(self::TRANS_PRIMARY_OPTION_NAME);
$this->trans_primary = $tpOption->isSelected();
+ $asOption = $this->listGetConfigOptionByID(self::ACCOUNT_STATUS_OPTION_NAME);
+ $this->showAccountStatus = $asOption->isSelected();
+ }
+
+ /**
+ * Returns an hash array containing with all attributes to be shown and their descriptions.
+ *
Format: array(attribute => description)
+ *
+ *
The user list may display an additional account status column
+ *
+ * @return array attribute list
+ */
+ protected function listGetAttributeDescriptionList() {
+ $list = parent::listGetAttributeDescriptionList();
+ if ($this->showAccountStatus) {
+ $list[self::ATTR_ACCOUNT_STATUS] = _('Account status');
+ }
+ return $list;
+ }
+
+ /**
+ * Returns if the given attribute can be filtered.
+ * If filtering is not possible then no filter box will be displayed.
+ *
+ *
The user list allows no filtering for account status.
+ *
+ * @param String $attr attribute name
+ * @return boolean filtering possible
+ */
+ protected function canBeFiltered($attr) {
+ if ($attr == self::ATTR_ACCOUNT_STATUS) {
+ return false;
+ }
+ elseif (strtolower($attr) == 'jpegphoto') {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns a list of additional LDAP attributes that should be read.
+ * This can be used to show additional data even if the user selected other attributes to show in the list.
+ *
+ *
The user list reads pwdAccountLockedTime, sambaAcctFlags and userPassword
+ *
+ * @return array additional attribute names
+ */
+ protected function getAdditionalLDAPAttributesToRead() {
+ $attrs = parent::getAdditionalLDAPAttributesToRead();
+ if ($this->showAccountStatus) {
+ $attrs[] = 'pwdAccountLockedTime';
+ $attrs[] = 'sambaAcctFlags';
+ $attrs[] = 'userPassword';
+ $attrs[] = 'objectClass';
+ }
+ return $attrs;
+ }
+
+ /**
+ * Injects values for the virtual account status attribute to make it sortable.
+ */
+ private function injectAccountStatusAttribute() {
+ for ($i = 0; $i < sizeof($this->entries); $i++) {
+ $status = 0;
+ if (!$this->isUnixLocked($this->entries[$i])) {
+ $status++;
+ }
+ if (!$this->isSambaLocked($this->entries[$i])) {
+ $status++;
+ }
+ if (!$this->isPPolicyLocked($this->entries[$i])) {
+ $status++;
+ }
+ $this->entries[$i][self::ATTR_ACCOUNT_STATUS][0] = $status;
+ }
+ }
+
+ /**
+ * Prints the account status.
+ *
+ * @param array $attrs LDAP attributes
+ */
+ private function printAccountStatus(&$attrs) {
+ // check status
+ $unixAvailable = $this->isUnixAvailable($attrs);
+ $unixLocked = $this->isUnixLocked($attrs);
+ $sambaAvailable = $this->isSambaAvailable($attrs);
+ $sambaLocked = $this->isSambaLocked($attrs);
+ $ppolicyAvailable = $this->isPPolicyAvailable($attrs);
+ $ppolicyLocked = $this->isPPolicyLocked($attrs);
+ $partiallyLocked = $unixLocked || $sambaLocked || $ppolicyLocked;
+ $fullyLocked = ($unixAvailable || $sambaAvailable || $ppolicyAvailable)
+ && (!$unixAvailable || $unixLocked)
+ && (!$sambaAvailable || $sambaLocked)
+ && (!$ppolicyAvailable || $ppolicyLocked);
+ $icon = 'unlocked.png';
+ if ($fullyLocked) {
+ $icon = 'lock.png';
+ }
+ elseif ($partiallyLocked) {
+ $icon = 'partiallyLocked.png';
+ }
+ // print icon and detail tooltips
+ if ($unixAvailable || $sambaAvailable || $ppolicyAvailable) {
+ $tipContent = '';
+ // Unix
+ if ($unixAvailable) {
+ $unixIcon = 'unlocked.png';
+ if ($unixLocked) {
+ $unixIcon = 'lock.png';
+ }
+ $tipContent .= '' . _('Unix') . ' | |
';
+ }
+ // Samba
+ if ($sambaAvailable) {
+ $sambaIcon = 'unlocked.png';
+ if ($sambaLocked) {
+ $sambaIcon = 'lock.png';
+ }
+ $tipContent .= '' . _('Samba') . ' | |
';
+ }
+ // PPolicy
+ if ($ppolicyAvailable) {
+ $ppolicyIcon = 'unlocked.png';
+ if ($ppolicyLocked) {
+ $ppolicyIcon = 'lock.png';
+ }
+ $tipContent .= '' . _('Password policy') . ' | |
';
+ }
+ $tipContent .= '
';
+ $tooltip = "'" . $tipContent . "', TITLE, '" . _('Account status') . "'";
+ echo '';
+ }
+ else {
+ echo '';
+ }
+ }
+
+ /**
+ * Returns if the Unix part exists.
+ *
+ * @param array $attrs LDAP attributes
+ * @return boolean Unix part exists
+ */
+ private function isUnixAvailable(&$attrs) {
+ return (isset($attrs['objectclass']) && in_array_ignore_case('posixAccount', $attrs['objectclass']));
+ }
+
+ /**
+ * Returns if the Unix part is locked.
+ *
+ * @param array $attrs LDAP attributes
+ * @return boolean Unix part locked
+ */
+ private function isUnixLocked(&$attrs) {
+ return (isset($attrs['userpassword'][0]) && !pwd_is_enabled($attrs['userpassword'][0]));
+ }
+
+ /**
+ * Returns if the Samba part exists.
+ *
+ * @param array $attrs LDAP attributes
+ * @return boolean Samba part exists
+ */
+ private function isSambaAvailable(&$attrs) {
+ return (isset($attrs['objectclass']) && in_array_ignore_case('sambaSamAccount', $attrs['objectclass']));
+ }
+
+ /**
+ * Returns if the Samba part is locked.
+ *
+ * @param array $attrs LDAP attributes
+ * @return boolean Samba part is locked
+ */
+ private function isSambaLocked(&$attrs) {
+ return (isset($attrs['sambaacctflags'][0]) && strpos($attrs['sambaacctflags'][0], "D"));
+ }
+
+ /**
+ * Returns if the PPolicy part exists.
+ *
+ * @param array $attrs LDAP attributes
+ * @return boolean PPolicy part exists
+ */
+ private function isPPolicyAvailable(&$attrs) {
+ return in_array('ppolicyUser', $_SESSION['config']->get_AccountModules('user'));
+ }
+
+ /**
+ * Returns if the PPolicy part is locked.
+ *
+ * @param array $attrs LDAP attributes
+ * @return boolean PPolicy part is locked
+ */
+ private function isPPolicyLocked(&$attrs) {
+ return (isset($attrs['pwdaccountlockedtime'][0]) && ($attrs['pwdaccountlockedtime'][0] != ''));
}
}