added local filtering
This commit is contained in:
		
							parent
							
								
									dfc3dcb4c6
								
							
						
					
					
						commit
						e2e75ece20
					
				|  | @ -2,6 +2,7 @@ June 2018 6.4 | ||||||
|   - Imagick PHP extension required |   - Imagick PHP extension required | ||||||
|   - Passwords can be checked against external service (e.g. https://api.pwnedpasswords.com/range) |   - Passwords can be checked against external service (e.g. https://api.pwnedpasswords.com/range) | ||||||
|   - Personal/Windows: image cropping support |   - Personal/Windows: image cropping support | ||||||
|  |   - Better filtering of account lists | ||||||
|   - Unix: Unix and group of names memberships can be synced in group selection |   - Unix: Unix and group of names memberships can be synced in group selection | ||||||
|   - IMAP: create mailbox via file upload |   - IMAP: create mailbox via file upload | ||||||
|   - PHP 7.2 support |   - PHP 7.2 support | ||||||
|  |  | ||||||
|  | @ -174,7 +174,7 @@ $helpArray = array ( | ||||||
| 				"249" => array ("Headline" => _('External password check'), | 				"249" => array ("Headline" => _('External password check'), | ||||||
| 					"Text" => _('Please specify the URL (e.g. "https://api.pwnedpasswords.com/range/{SHA1PREFIX}") of your external password check.')), | 					"Text" => _('Please specify the URL (e.g. "https://api.pwnedpasswords.com/range/{SHA1PREFIX}") of your external password check.')), | ||||||
| 				"250" => array ("Headline" => _("Filter"), | 				"250" => array ("Headline" => _("Filter"), | ||||||
| 					"Text" => _("Here you can input simple filter expressions (e.g. 'value' or 'v*'). The filter is case-sensitive.")), | 					"Text" => _("Here you can input simple filter expressions (e.g. 'value' or 'v*'). The filter is case-insensitive.")), | ||||||
| 				"260" => array ("Headline" => _("Additional LDAP filter"), | 				"260" => array ("Headline" => _("Additional LDAP filter"), | ||||||
| 					"Text" => _('Use this to enter an additional LDAP filter (e.g. "(cn!=admin)") to reduce the number of visible elements for this account type.') | 					"Text" => _('Use this to enter an additional LDAP filter (e.g. "(cn!=admin)") to reduce the number of visible elements for this account type.') | ||||||
| 						. ' ' . _('You can use the wildcard @@LOGIN_DN@@ which will be substituted with the DN of the user who is currently logged in to LAM.') | 						. ' ' . _('You can use the wildcard @@LOGIN_DN@@ which will be substituted with the DN of the user who is currently logged in to LAM.') | ||||||
|  |  | ||||||
|  | @ -108,8 +108,8 @@ class lamList { | ||||||
| 	const VIRTUAL_ATTRIBUTE_PREFIX = 'lam_virtual_'; | 	const VIRTUAL_ATTRIBUTE_PREFIX = 'lam_virtual_'; | ||||||
| 
 | 
 | ||||||
| 	const SERVER_SIDE_FILTER_ATTRIBUTES = array( | 	const SERVER_SIDE_FILTER_ATTRIBUTES = array( | ||||||
| 		'cn', 'uid', 'memberuid', 'description', | 		'cn', 'commonname', 'uid', 'memberuid', 'description', | ||||||
| 		'sn', 'surname', 'gn', 'givenname' | 		'sn', 'surname', 'gn', 'givenname', 'company', 'mail' | ||||||
| 	); | 	); | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  | @ -174,6 +174,8 @@ class lamList { | ||||||
| 		if ($this->refresh) { | 		if ($this->refresh) { | ||||||
| 			$this->listRefreshData(); | 			$this->listRefreshData(); | ||||||
| 		} | 		} | ||||||
|  | 		// local filtering
 | ||||||
|  | 		$this->applyLocalFilters(); | ||||||
| 		// sort rows by sort column
 | 		// sort rows by sort column
 | ||||||
| 		if (isset($this->entries)) { | 		if (isset($this->entries)) { | ||||||
| 			$this->listCreateSortMapping($this->entries); | 			$this->listCreateSortMapping($this->entries); | ||||||
|  | @ -1033,6 +1035,55 @@ class lamList { | ||||||
| 		return in_array(strtolower($attrName), lamList::SERVER_SIDE_FILTER_ATTRIBUTES); | 		return in_array(strtolower($attrName), lamList::SERVER_SIDE_FILTER_ATTRIBUTES); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Applies any local filters for attributes that cannot be filtered server side. | ||||||
|  | 	 */ | ||||||
|  | 	protected function applyLocalFilters() { | ||||||
|  | 		$this->entries = array(); | ||||||
|  | 		foreach ($this->ldapEntries as $index => &$data) { | ||||||
|  | 			$this->entries[$index] = &$data; | ||||||
|  | 		} | ||||||
|  | 		$toFilter = array(); | ||||||
|  | 		foreach ($this->filters as $filterAttribute => $filterValue) { | ||||||
|  | 			if ($this->isAttributeFilteredByServer($filterAttribute) || ($filterValue === '')) { | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			foreach ($this->entries as $index => &$data) { | ||||||
|  | 				if (in_array($index, $toFilter)) { | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				$regex = str_replace(array('*'), array('.*'), $filterValue); | ||||||
|  | 				$regex = '/^' . $regex . '$/i'; | ||||||
|  | 				if (!$this->isFilterMatching($data, $filterAttribute, $regex)) { | ||||||
|  | 					$toFilter[] = $index; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		foreach ($toFilter as $index) { | ||||||
|  | 			unset($this->entries[$index]); | ||||||
|  | 		} | ||||||
|  | 		$this->entries = array_values($this->entries); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Checks if the given LDAP data matches the filter. | ||||||
|  | 	 * | ||||||
|  | 	 * @param array $data LDAP attributes | ||||||
|  | 	 * @param string $filterAttribute filter attribute name | ||||||
|  | 	 * @param string $regex filter attribute regex | ||||||
|  | 	 */ | ||||||
|  | 	protected function isFilterMatching(&$data, $filterAttribute, $regex) { | ||||||
|  | 		if (!isset($data[$filterAttribute])) { | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 		foreach ($data[$filterAttribute] as $value) { | ||||||
|  | 			if (preg_match($regex, $value)) { | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Forces a refresh of the LDAP data. | 	 * Forces a refresh of the LDAP data. | ||||||
| 	 * Function must be called before $this->refresh option is checked to load new LDAP data (e.g. in listGetParams). | 	 * Function must be called before $this->refresh option is checked to load new LDAP data (e.g. in listGetParams). | ||||||
|  |  | ||||||
|  | @ -694,7 +694,7 @@ class lamUserList extends lamList { | ||||||
| 		} | 		} | ||||||
| 		// show account status
 | 		// show account status
 | ||||||
| 		if ($this->showAccountStatus) { | 		if ($this->showAccountStatus) { | ||||||
| 			$this->injectAccountStatusAttributeAndFilterByStatus(); | 			$this->injectAccountStatusAttribute(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -968,7 +968,7 @@ class lamUserList extends lamList { | ||||||
| 	/** | 	/** | ||||||
| 	 * Injects values for the virtual account status attribute to make it sortable. | 	 * Injects values for the virtual account status attribute to make it sortable. | ||||||
| 	 */ | 	 */ | ||||||
| 	private function injectAccountStatusAttributeAndFilterByStatus() { | 	private function injectAccountStatusAttribute() { | ||||||
| 		$entryCount = sizeof($this->ldapEntries); | 		$entryCount = sizeof($this->ldapEntries); | ||||||
| 		for ($i = 0; $i < $entryCount; $i++) { | 		for ($i = 0; $i < $entryCount; $i++) { | ||||||
| 			$unixAvailable = self::isUnixAvailable($this->ldapEntries[$i]); | 			$unixAvailable = self::isUnixAvailable($this->ldapEntries[$i]); | ||||||
|  | @ -1007,17 +1007,29 @@ class lamUserList extends lamList { | ||||||
| 			elseif (!$hasUnlocked && $hasLocked) { | 			elseif (!$hasUnlocked && $hasLocked) { | ||||||
| 				$status = self::FILTER_LOCKED; | 				$status = self::FILTER_LOCKED; | ||||||
| 			} | 			} | ||||||
| 			// filter accounts
 |  | ||||||
| 			if (!empty($this->accountStatusFilter)) { |  | ||||||
| 				if ($status != $this->accountStatusFilter) { |  | ||||||
| 					unset($this->ldapEntries[$i]); |  | ||||||
| 					continue; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			// add virtual attribute
 | 			// add virtual attribute
 | ||||||
| 			$this->ldapEntries[$i][self::ATTR_ACCOUNT_STATUS][0] = $status; | 			$this->ldapEntries[$i][self::ATTR_ACCOUNT_STATUS][0] = $status; | ||||||
| 		} | 		} | ||||||
| 		$this->ldapEntries = array_values($this->ldapEntries); | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * {@inheritDoc} | ||||||
|  | 	 * @see lamList::isFilterMatching() | ||||||
|  | 	 */ | ||||||
|  | 	protected function isFilterMatching(&$data, $filterAttribute, $regex) { | ||||||
|  | 		if ($filterAttribute == self::ATTR_ACCOUNT_STATUS) { | ||||||
|  | 			return preg_match($regex, $data[self::ATTR_ACCOUNT_STATUS][0]); | ||||||
|  | 		} | ||||||
|  | 		if (($filterAttribute == 'gidnumber') && ($this->trans_primary == "on")) { | ||||||
|  | 			if (!isset($data[$filterAttribute])) { | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 			if (!isset($this->trans_primary_hash[$data[$filterAttribute][0]])) { | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 			return preg_match($regex, $this->trans_primary_hash[$data[$filterAttribute][0]]); | ||||||
|  | 		} | ||||||
|  | 		return parent::isFilterMatching($data, $filterAttribute, $regex); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue