diff options
Diffstat (limited to 'apps/user_ldap/lib')
-rw-r--r-- | apps/user_ldap/lib/Access.php | 147 | ||||
-rw-r--r-- | apps/user_ldap/lib/Command/CreateEmptyConfig.php | 28 | ||||
-rw-r--r-- | apps/user_ldap/lib/Configuration.php | 9 | ||||
-rw-r--r-- | apps/user_ldap/lib/Connection.php | 5 | ||||
-rw-r--r-- | apps/user_ldap/lib/Controller/ConfigAPIController.php | 322 | ||||
-rw-r--r-- | apps/user_ldap/lib/Helper.php | 19 | ||||
-rw-r--r-- | apps/user_ldap/lib/Mapping/AbstractMapping.php | 11 | ||||
-rw-r--r-- | apps/user_ldap/lib/Settings/Section.php | 21 |
8 files changed, 513 insertions, 49 deletions
diff --git a/apps/user_ldap/lib/Access.php b/apps/user_ldap/lib/Access.php index d88378c1888..9f6639c0db0 100644 --- a/apps/user_ldap/lib/Access.php +++ b/apps/user_ldap/lib/Access.php @@ -182,46 +182,146 @@ class Access extends LDAPUtility implements IUserTools { // 0 won't result in replies, small numbers may leave out groups // (cf. #12306), 500 is default for paging and should work everywhere. $maxResults = $pagingSize > 20 ? $pagingSize : 500; - $this->initPagedSearch($filter, array($dn), array($attr), $maxResults, 0); + $attr = mb_strtolower($attr, 'UTF-8'); + // the actual read attribute later may contain parameters on a ranged + // request, e.g. member;range=99-199. Depends on server reply. + $attrToRead = $attr; + + $values = []; + $isRangeRequest = false; + do { + $result = $this->executeRead($cr, $dn, $attrToRead, $filter, $maxResults); + if(is_bool($result)) { + // when an exists request was run and it was successful, an empty + // array must be returned + return $result ? [] : false; + } + + if (!$isRangeRequest) { + $values = $this->extractAttributeValuesFromResult($result, $attr); + if (!empty($values)) { + return $values; + } + } + + $isRangeRequest = false; + $result = $this->extractRangeData($result, $attr); + if (!empty($result)) { + $normalizedResult = $this->extractAttributeValuesFromResult( + [ $attr => $result['values'] ], + $attr + ); + $values = array_merge($values, $normalizedResult); + + if($result['rangeHigh'] === '*') { + // when server replies with * as high range value, there are + // no more results left + return $values; + } else { + $low = $result['rangeHigh'] + 1; + $attrToRead = $result['attributeName'] . ';range=' . $low . '-*'; + $isRangeRequest = true; + } + } + } while($isRangeRequest); + + \OCP\Util::writeLog('user_ldap', 'Requested attribute '.$attr.' not found for '.$dn, \OCP\Util::DEBUG); + return false; + } + + /** + * Runs an read operation against LDAP + * + * @param resource $cr the LDAP connection + * @param string $dn + * @param string $attribute + * @param string $filter + * @param int $maxResults + * @return array|bool false if there was any error, true if an exists check + * was performed and the requested DN found, array with the + * returned data on a successful usual operation + */ + public function executeRead($cr, $dn, $attribute, $filter, $maxResults) { + $this->initPagedSearch($filter, array($dn), array($attribute), $maxResults, 0); $dn = $this->helper->DNasBaseParameter($dn); - $rr = @$this->ldap->read($cr, $dn, $filter, array($attr)); - if(!$this->ldap->isResource($rr)) { - if ($attr !== '') { + $rr = @$this->ldap->read($cr, $dn, $filter, array($attribute)); + if (!$this->ldap->isResource($rr)) { + if ($attribute !== '') { //do not throw this message on userExists check, irritates - \OCP\Util::writeLog('user_ldap', 'readAttribute failed for DN '.$dn, \OCP\Util::DEBUG); + \OCP\Util::writeLog('user_ldap', 'readAttribute failed for DN ' . $dn, \OCP\Util::DEBUG); } //in case an error occurs , e.g. object does not exist return false; } - if ($attr === '' && ($filter === 'objectclass=*' || $this->ldap->countEntries($cr, $rr) === 1)) { - \OCP\Util::writeLog('user_ldap', 'readAttribute: '.$dn.' found', \OCP\Util::DEBUG); - return array(); + if ($attribute === '' && ($filter === 'objectclass=*' || $this->ldap->countEntries($cr, $rr) === 1)) { + \OCP\Util::writeLog('user_ldap', 'readAttribute: ' . $dn . ' found', \OCP\Util::DEBUG); + return true; } $er = $this->ldap->firstEntry($cr, $rr); - if(!$this->ldap->isResource($er)) { + if (!$this->ldap->isResource($er)) { //did not match the filter, return false return false; } //LDAP attributes are not case sensitive $result = \OCP\Util::mb_array_change_key_case( - $this->ldap->getAttributes($cr, $er), MB_CASE_LOWER, 'UTF-8'); - $attr = mb_strtolower($attr, 'UTF-8'); + $this->ldap->getAttributes($cr, $er), MB_CASE_LOWER, 'UTF-8'); - if(isset($result[$attr]) && $result[$attr]['count'] > 0) { - $values = array(); - for($i=0;$i<$result[$attr]['count'];$i++) { - if($this->resemblesDN($attr)) { - $values[] = $this->helper->sanitizeDN($result[$attr][$i]); - } elseif(strtolower($attr) === 'objectguid' || strtolower($attr) === 'guid') { - $values[] = $this->convertObjectGUID2Str($result[$attr][$i]); + return $result; + } + + /** + * Normalizes a result grom getAttributes(), i.e. handles DNs and binary + * data if present. + * + * @param array $result from ILDAPWrapper::getAttributes() + * @param string $attribute the attribute name that was read + * @return string[] + */ + public function extractAttributeValuesFromResult($result, $attribute) { + $values = []; + if(isset($result[$attribute]) && $result[$attribute]['count'] > 0) { + $lowercaseAttribute = strtolower($attribute); + for($i=0;$i<$result[$attribute]['count'];$i++) { + if($this->resemblesDN($attribute)) { + $values[] = $this->helper->sanitizeDN($result[$attribute][$i]); + } elseif($lowercaseAttribute === 'objectguid' || $lowercaseAttribute === 'guid') { + $values[] = $this->convertObjectGUID2Str($result[$attribute][$i]); } else { - $values[] = $result[$attr][$i]; + $values[] = $result[$attribute][$i]; } } - return $values; } - \OCP\Util::writeLog('user_ldap', 'Requested attribute '.$attr.' not found for '.$dn, \OCP\Util::DEBUG); - return false; + return $values; + } + + /** + * Attempts to find ranged data in a getAttribute results and extracts the + * returned values as well as information on the range and full attribute + * name for further processing. + * + * @param array $result from ILDAPWrapper::getAttributes() + * @param string $attribute the attribute name that was read. Without ";range=…" + * @return array If a range was detected with keys 'values', 'attributeName', + * 'attributeFull' and 'rangeHigh', otherwise empty. + */ + public function extractRangeData($result, $attribute) { + $keys = array_keys($result); + foreach($keys as $key) { + if($key !== $attribute && strpos($key, $attribute) === 0) { + $queryData = explode(';', $key); + if(strpos($queryData[1], 'range=') === 0) { + $high = substr($queryData[1], 1 + strpos($queryData[1], '-')); + $data = [ + 'values' => $result[$key], + 'attributeName' => $queryData[0], + 'attributeFull' => $key, + 'rangeHigh' => $high, + ]; + return $data; + } + } + } + return []; } /** @@ -578,6 +678,9 @@ class Access extends LDAPUtility implements IUserTools { */ public function cacheUserDisplayName($ocName, $displayName, $displayName2 = '') { $user = $this->userManager->get($ocName); + if($user === null) { + return; + } $displayName = $user->composeAndStoreDisplayName($displayName, $displayName2); $cacheKeyTrunk = 'getDisplayName'; $this->connection->writeToCache($cacheKeyTrunk.$ocName, $displayName); diff --git a/apps/user_ldap/lib/Command/CreateEmptyConfig.php b/apps/user_ldap/lib/Command/CreateEmptyConfig.php index 28d3a1d8bff..38d3192058c 100644 --- a/apps/user_ldap/lib/Command/CreateEmptyConfig.php +++ b/apps/user_ldap/lib/Command/CreateEmptyConfig.php @@ -29,6 +29,7 @@ use OCA\User_LDAP\Configuration; use OCA\User_LDAP\Helper; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; class CreateEmptyConfig extends Command { @@ -47,29 +48,24 @@ class CreateEmptyConfig extends Command { $this ->setName('ldap:create-empty-config') ->setDescription('creates an empty LDAP configuration') + ->addOption( + 'only-print-prefix', + 'p', + InputOption::VALUE_NONE, + 'outputs only the prefix' + ) ; } protected function execute(InputInterface $input, OutputInterface $output) { - $configPrefix = $this->getNewConfigurationPrefix(); - $output->writeln("Created new configuration with configID '{$configPrefix}'"); - + $configPrefix = $this->helper->getNextServerConfigurationPrefix(); $configHolder = new Configuration($configPrefix); $configHolder->saveConfiguration(); - } - protected function getNewConfigurationPrefix() { - $serverConnections = $this->helper->getServerConfigurationPrefixes(); - - // first connection uses no prefix - if(sizeof($serverConnections) == 0) { - return ''; + $prose = ''; + if(!$input->getOption('only-print-prefix')) { + $prose = 'Created new configuration with configID '; } - - sort($serverConnections); - $lastKey = array_pop($serverConnections); - $lastNumber = intval(str_replace('s', '', $lastKey)); - $nextPrefix = 's' . str_pad($lastNumber + 1, 2, '0', STR_PAD_LEFT); - return $nextPrefix; + $output->writeln($prose . "{$configPrefix}"); } } diff --git a/apps/user_ldap/lib/Configuration.php b/apps/user_ldap/lib/Configuration.php index eb4fcd3fbe6..65ee9c70807 100644 --- a/apps/user_ldap/lib/Configuration.php +++ b/apps/user_ldap/lib/Configuration.php @@ -393,9 +393,12 @@ class Configuration { * @return bool */ protected function saveValue($varName, $value) { - return \OCP\Config::setAppValue('user_ldap', - $this->configPrefix.$varName, - $value); + \OC::$server->getConfig()->setAppValue( + 'user_ldap', + $this->configPrefix.$varName, + $value + ); + return true; } /** diff --git a/apps/user_ldap/lib/Connection.php b/apps/user_ldap/lib/Connection.php index d74afa42fe8..92b874e7a15 100644 --- a/apps/user_ldap/lib/Connection.php +++ b/apps/user_ldap/lib/Connection.php @@ -327,11 +327,6 @@ class Connection extends LDAPUtility { foreach(array('ldapBaseUsers', 'ldapBaseGroups') as $keyBase) { $val = $this->configuration->$keyBase; if(empty($val)) { - $obj = strpos('Users', $keyBase) !== false ? 'Users' : 'Groups'; - \OCP\Util::writeLog('user_ldap', - 'Base tree for '.$obj. - ' is empty, using Base DN', - \OCP\Util::INFO); $this->configuration->$keyBase = $this->configuration->ldapBase; } } diff --git a/apps/user_ldap/lib/Controller/ConfigAPIController.php b/apps/user_ldap/lib/Controller/ConfigAPIController.php new file mode 100644 index 00000000000..7d51b0aafe4 --- /dev/null +++ b/apps/user_ldap/lib/Controller/ConfigAPIController.php @@ -0,0 +1,322 @@ +<?php +/** + * @copyright Copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\User_LDAP\Controller; + +use OC\CapabilitiesManager; +use OC\Core\Controller\OCSController; +use OC\Security\Bruteforce\Throttler; +use OC\Security\IdentityProof\Manager; +use OCA\User_LDAP\Configuration; +use OCA\User_LDAP\Helper; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\OCS\OCSBadRequestException; +use OCP\AppFramework\OCS\OCSException; +use OCP\AppFramework\OCS\OCSNotFoundException; +use OCP\ILogger; +use OCP\IRequest; +use OCP\IUserManager; +use OCP\IUserSession; + +class ConfigAPIController extends OCSController { + + /** @var Helper */ + private $ldapHelper; + + /** @var ILogger */ + private $logger; + + public function __construct( + $appName, + IRequest $request, + CapabilitiesManager $capabilitiesManager, + IUserSession $userSession, + IUserManager $userManager, + Throttler $throttler, + Manager $keyManager, + Helper $ldapHelper, + ILogger $logger + ) { + parent::__construct( + $appName, + $request, + $capabilitiesManager, + $userSession, + $userManager, + $throttler, + $keyManager + ); + + + $this->ldapHelper = $ldapHelper; + $this->logger = $logger; + } + + /** + * creates a new (empty) configuration and returns the resulting prefix + * + * Example: curl -X POST -H "OCS-APIREQUEST: true" -u $admin:$password \ + * https://nextcloud.server/ocs/v2.php/apps/user_ldap/api/v1/config + * + * results in: + * + * <?xml version="1.0"?> + * <ocs> + * <meta> + * <status>ok</status> + * <statuscode>200</statuscode> + * <message>OK</message> + * </meta> + * <data> + * <configID>s40</configID> + * </data> + * </ocs> + * + * Failing example: if an exception is thrown (e.g. Database connection lost) + * the detailed error will be logged. The output will then look like: + * + * <?xml version="1.0"?> + * <ocs> + * <meta> + * <status>failure</status> + * <statuscode>999</statuscode> + * <message>An issue occurred when creating the new config.</message> + * </meta> + * <data/> + * </ocs> + * + * For JSON output provide the format=json parameter + * + * @return DataResponse + * @throws OCSException + */ + public function create() { + try { + $configPrefix = $this->ldapHelper->getNextServerConfigurationPrefix(); + $configHolder = new Configuration($configPrefix); + $configHolder->saveConfiguration(); + } catch (\Exception $e) { + $this->logger->logException($e); + throw new OCSException('An issue occurred when creating the new config.'); + } + return new DataResponse(['configID' => $configPrefix]); + } + + /** + * Deletes a LDAP configuration, if present. + * + * Example: + * curl -X DELETE -H "OCS-APIREQUEST: true" -u $admin:$password \ + * https://nextcloud.server/ocs/v2.php/apps/user_ldap/api/v1/config/s60 + * + * <?xml version="1.0"?> + * <ocs> + * <meta> + * <status>ok</status> + * <statuscode>200</statuscode> + * <message>OK</message> + * </meta> + * <data/> + * </ocs> + * + * @param string $configID + * @return DataResponse + * @throws OCSBadRequestException + * @throws OCSException + */ + public function delete($configID) { + try { + $this->ensureConfigIDExists($configID); + if(!$this->ldapHelper->deleteServerConfiguration($configID)) { + throw new OCSException('Could not delete configuration'); + } + } catch(OCSException $e) { + throw $e; + } catch(\Exception $e) { + $this->logger->logException($e); + throw new OCSException('An issue occurred when deleting the config.'); + } + + return new DataResponse(); + } + + /** + * modifies a configuration + * + * Example: + * curl -X PUT -d "configData[ldapHost]=ldaps://my.ldap.server&configData[ldapPort]=636" \ + * -H "OCS-APIREQUEST: true" -u $admin:$password \ + * https://nextcloud.server/ocs/v2.php/apps/user_ldap/api/v1/config/s60 + * + * <?xml version="1.0"?> + * <ocs> + * <meta> + * <status>ok</status> + * <statuscode>200</statuscode> + * <message>OK</message> + * </meta> + * <data/> + * </ocs> + * + * @param string $configID + * @param array $configData + * @return DataResponse + * @throws OCSException + */ + public function modify($configID, $configData) { + try { + $this->ensureConfigIDExists($configID); + + if(!is_array($configData)) { + throw new OCSBadRequestException('configData is not properly set'); + } + + $configuration = new Configuration($configID); + $configKeys = $configuration->getConfigTranslationArray(); + + foreach ($configKeys as $i => $key) { + if(isset($configData[$key])) { + $configuration->$key = $configData[$key]; + } + } + + $configuration->saveConfiguration(); + } catch(OCSException $e) { + throw $e; + } catch (\Exception $e) { + $this->logger->logException($e); + throw new OCSException('An issue occurred when modifying the config.'); + } + + return new DataResponse(); + } + + /** + * retrieves a configuration + * + * <?xml version="1.0"?> + * <ocs> + * <meta> + * <status>ok</status> + * <statuscode>200</statuscode> + * <message>OK</message> + * </meta> + * <data> + * <ldapHost>ldaps://my.ldap.server</ldapHost> + * <ldapPort>7770</ldapPort> + * <ldapBackupHost></ldapBackupHost> + * <ldapBackupPort></ldapBackupPort> + * <ldapBase>ou=small,dc=my,dc=ldap,dc=server</ldapBase> + * <ldapBaseUsers>ou=users,ou=small,dc=my,dc=ldap,dc=server</ldapBaseUsers> + * <ldapBaseGroups>ou=small,dc=my,dc=ldap,dc=server</ldapBaseGroups> + * <ldapAgentName>cn=root,dc=my,dc=ldap,dc=server</ldapAgentName> + * <ldapAgentPassword>clearTextWithShowPassword=1</ldapAgentPassword> + * <ldapTLS>1</ldapTLS> + * <turnOffCertCheck>0</turnOffCertCheck> + * <ldapIgnoreNamingRules/> + * <ldapUserDisplayName>displayname</ldapUserDisplayName> + * <ldapUserDisplayName2>uid</ldapUserDisplayName2> + * <ldapUserFilterObjectclass>inetOrgPerson</ldapUserFilterObjectclass> + * <ldapUserFilterGroups></ldapUserFilterGroups> + * <ldapUserFilter>(&(objectclass=nextcloudUser)(nextcloudEnabled=TRUE))</ldapUserFilter> + * <ldapUserFilterMode>1</ldapUserFilterMode> + * <ldapGroupFilter>(&(|(objectclass=nextcloudGroup)))</ldapGroupFilter> + * <ldapGroupFilterMode>0</ldapGroupFilterMode> + * <ldapGroupFilterObjectclass>nextcloudGroup</ldapGroupFilterObjectclass> + * <ldapGroupFilterGroups></ldapGroupFilterGroups> + * <ldapGroupDisplayName>cn</ldapGroupDisplayName> + * <ldapGroupMemberAssocAttr>memberUid</ldapGroupMemberAssocAttr> + * <ldapLoginFilter>(&(|(objectclass=inetOrgPerson))(uid=%uid))</ldapLoginFilter> + * <ldapLoginFilterMode>0</ldapLoginFilterMode> + * <ldapLoginFilterEmail>0</ldapLoginFilterEmail> + * <ldapLoginFilterUsername>1</ldapLoginFilterUsername> + * <ldapLoginFilterAttributes></ldapLoginFilterAttributes> + * <ldapQuotaAttribute></ldapQuotaAttribute> + * <ldapQuotaDefault></ldapQuotaDefault> + * <ldapEmailAttribute>mail</ldapEmailAttribute> + * <ldapCacheTTL>20</ldapCacheTTL> + * <ldapUuidUserAttribute>auto</ldapUuidUserAttribute> + * <ldapUuidGroupAttribute>auto</ldapUuidGroupAttribute> + * <ldapOverrideMainServer></ldapOverrideMainServer> + * <ldapConfigurationActive>1</ldapConfigurationActive> + * <ldapAttributesForUserSearch>uid;sn;givenname</ldapAttributesForUserSearch> + * <ldapAttributesForGroupSearch></ldapAttributesForGroupSearch> + * <ldapExperiencedAdmin>0</ldapExperiencedAdmin> + * <homeFolderNamingRule></homeFolderNamingRule> + * <hasPagedResultSupport></hasPagedResultSupport> + * <hasMemberOfFilterSupport></hasMemberOfFilterSupport> + * <useMemberOfToDetectMembership>1</useMemberOfToDetectMembership> + * <ldapExpertUsernameAttr>uid</ldapExpertUsernameAttr> + * <ldapExpertUUIDUserAttr>uid</ldapExpertUUIDUserAttr> + * <ldapExpertUUIDGroupAttr></ldapExpertUUIDGroupAttr> + * <lastJpegPhotoLookup>0</lastJpegPhotoLookup> + * <ldapNestedGroups>0</ldapNestedGroups> + * <ldapPagingSize>500</ldapPagingSize> + * <turnOnPasswordChange>1</turnOnPasswordChange> + * <ldapDynamicGroupMemberURL></ldapDynamicGroupMemberURL> + * </data> + * </ocs> + * + * @param string $configID + * @param bool|string $showPassword + * @return DataResponse + * @throws OCSException + */ + public function show($configID, $showPassword = false) { + try { + $this->ensureConfigIDExists($configID); + + $config = new Configuration($configID); + $data = $config->getConfiguration(); + if(!boolval(intval($showPassword))) { + $data['ldapAgentPassword'] = '***'; + } + foreach ($data as $key => $value) { + if(is_array($value)) { + $value = implode(';', $value); + $data[$key] = $value; + } + } + } catch(OCSException $e) { + throw $e; + } catch (\Exception $e) { + $this->logger->logException($e); + throw new OCSException('An issue occurred when modifying the config.'); + } + + return new DataResponse($data); + } + + /** + * if the given config ID is not available, an exception is thrown + * + * @param string $configID + * @throws OCSNotFoundException + */ + private function ensureConfigIDExists($configID) { + $prefixes = $this->ldapHelper->getServerConfigurationPrefixes(); + if(!in_array($configID, $prefixes, true)) { + throw new OCSNotFoundException('Config ID not found'); + } + } +} diff --git a/apps/user_ldap/lib/Helper.php b/apps/user_ldap/lib/Helper.php index b48b4001f9d..f1186ffa310 100644 --- a/apps/user_ldap/lib/Helper.php +++ b/apps/user_ldap/lib/Helper.php @@ -105,6 +105,25 @@ class Helper { return $result; } + /** + * return the next available configuration prefix + * + * @return string + */ + public function getNextServerConfigurationPrefix() { + $serverConnections = $this->getServerConfigurationPrefixes(); + + if(count($serverConnections) === 0) { + return 's01'; + } + + sort($serverConnections); + $lastKey = array_pop($serverConnections); + $lastNumber = intval(str_replace('s', '', $lastKey)); + $nextPrefix = 's' . str_pad($lastNumber + 1, 2, '0', STR_PAD_LEFT); + return $nextPrefix; + } + private function getServersConfig($value) { $regex = '/' . $value . '$/S'; diff --git a/apps/user_ldap/lib/Mapping/AbstractMapping.php b/apps/user_ldap/lib/Mapping/AbstractMapping.php index 8e7f1f8b137..6fb4a5436c3 100644 --- a/apps/user_ldap/lib/Mapping/AbstractMapping.php +++ b/apps/user_ldap/lib/Mapping/AbstractMapping.php @@ -209,6 +209,17 @@ abstract class AbstractMapping { * @return bool */ public function map($fdn, $name, $uuid) { + if(mb_strlen($fdn) > 255) { + \OC::$server->getLogger()->error( + 'Cannot map, because the DN exceeds 255 characters: {dn}', + [ + 'app' => 'user_ldap', + 'dn' => $fdn, + ] + ); + return false; + } + $row = array( 'ldap_dn' => $fdn, 'owncloud_name' => $name, diff --git a/apps/user_ldap/lib/Settings/Section.php b/apps/user_ldap/lib/Settings/Section.php index 82d8d0c84fa..86d293d3879 100644 --- a/apps/user_ldap/lib/Settings/Section.php +++ b/apps/user_ldap/lib/Settings/Section.php @@ -24,13 +24,21 @@ namespace OCA\User_LDAP\Settings; use OCP\IL10N; -use OCP\Settings\ISection; +use OCP\IURLGenerator; +use OCP\Settings\IIconSection; -class Section implements ISection { +class Section implements IIconSection { /** @var IL10N */ private $l; + /** @var IURLGenerator */ + private $url; - public function __construct(IL10N $l) { + /** + * @param IURLGenerator $url + * @param IL10N $l + */ + public function __construct(IURLGenerator $url, IL10N $l) { + $this->url = $url; $this->l = $l; } @@ -64,4 +72,11 @@ class Section implements ISection { public function getPriority() { return 25; } + + /** + * {@inheritdoc} + */ + public function getIcon() { + return $this->url->imagePath('user_ldap', 'app-dark.svg'); + } } |