/** * Returns the LDAP user groups with information merged with local TYPO3 user groups. * * @param \Causal\IgLdapSsoAuth\Domain\Model\Configuration $configuration * @param string $mode * @return array */ protected function getAvailableUserGroups(\Causal\IgLdapSsoAuth\Domain\Model\Configuration $configuration, $mode) { $userGroups = array(); $config = $mode === 'be' ? Configuration::getBackendConfiguration() : Configuration::getFrontendConfiguration(); $ldapGroups = array(); if (!empty($config['groups']['basedn'])) { $filter = Configuration::replaceFilterMarkers($config['groups']['filter']); $attributes = Configuration::getLdapAttributes($config['groups']['mapping']); $ldapGroups = Ldap::getInstance()->search($config['groups']['basedn'], $filter, $attributes); unset($ldapGroups['count']); } // Populate an array of TYPO3 group records corresponding to the LDAP groups // If a given LDAP group has no associated group in TYPO3, a fresh record // will be created so that $ldapGroups[i] <=> $typo3Groups[i] $typo3GroupPid = Configuration::getPid($config['groups']['mapping']); $table = $mode === 'be' ? 'be_groups' : 'fe_groups'; $typo3Groups = Authentication::getTypo3Groups($ldapGroups, $table, $typo3GroupPid); foreach ($ldapGroups as $index => $ldapGroup) { $userGroup = Authentication::merge($ldapGroup, $typo3Groups[$index], $config['groups']['mapping']); // Attempt to free memory by unsetting fields which are unused in the view $keepKeys = array('uid', 'pid', 'deleted', 'title', 'tx_igldapssoauth_dn'); $keys = array_keys($userGroup); foreach ($keys as $key) { if (!in_array($key, $keepKeys)) { unset($userGroup[$key]); } } $userGroups[] = $userGroup; } return $userGroups; }
/** * @test */ public function parentGroupIsNotMerged() { $mapping = <<<EOT \t\t\tpid = 1 \t\t\ttitle = <cn> \t\t\tdescription = LDAP Group <cn> \t\t\tparentGroup = <memberOf> EOT; $expected = $this->typo3GroupFixture; $expected['pid'] = '1'; $expected['title'] = 'Scientists'; $expected['description'] = 'LDAP Group Scientists'; $mapping = Configuration::parseMapping($mapping); $group = Authentication::merge($this->ldapGroupFixture, $this->typo3GroupFixture, $mapping); $this->assertEquals($expected, $group); }
/** * Performs the synchronization of LDAP users according to selected parameters. * * @return boolean Returns TRUE on successful execution, FALSE on error * @throws ImportUsersException */ public function execute() { // Assemble a list of configuration and contexts for import /** @var \Causal\IgLdapSsoAuth\Domain\Repository\ConfigurationRepository $configurationRepository */ $configurationRepository = GeneralUtility::makeInstance('Causal\\IgLdapSsoAuth\\Domain\\Repository\\ConfigurationRepository'); if (empty($this->configuration)) { $ldapConfigurations = $configurationRepository->findAll(); } else { $configuration = $configurationRepository->findByUid($this->configuration); $ldapConfigurations = array(); if ($configuration !== NULL) { $ldapConfigurations[] = $configuration; } } if ($this->context === 'both') { $executionContexts = array('fe', 'be'); } else { $executionContexts = array($this->context); } $mode = $this->getMode(); // Start a database transaction with all our changes // Syntax is compatible with MySQL, Oracle, MSSQL and PostgreSQL $this->getDatabaseConnection()->sql_query('START TRANSACTION'); // Loop on each configuration and context and import the related users $failures = 0; foreach ($ldapConfigurations as $configuration) { foreach ($executionContexts as $aContext) { /** @var \Causal\IgLdapSsoAuth\Utility\UserImportUtility $importUtility */ $importUtility = GeneralUtility::makeInstance('Causal\\IgLdapSsoAuth\\Utility\\UserImportUtility', $configuration, $aContext); $config = $importUtility->getConfiguration(); if (empty($config['users']['filter'])) { // Current context is not configured for this LDAP configuration record static::getLogger()->debug(sprintf('Configuration record %s is not configured for context "%s"', $configuration->getUid(), $aContext)); unset($importUtility); continue; } // Start by connecting to the designated LDAP/AD server $success = Ldap::getInstance()->connect(Configuration::getLdapConfiguration()); // Proceed with import if successful if (!$success) { $failures++; unset($importUtility); continue; } $ldapUsers = $importUtility->fetchLdapUsers(); // Consider that fetching no users from LDAP is an error if (count($ldapUsers) === 0) { static::getLogger()->error(sprintf('No users (%s) found for configuration record %s', $aContext, $configuration->getUid())); $failures++; } else { // Disable or delete users, according to settings if ($this->missingUsersHandling === 'disable') { static::getLogger()->debug(sprintf('Disabling users (%s) for configuration record %s', $aContext, $configuration->getUid())); $importUtility->disableUsers(); } elseif ($this->missingUsersHandling === 'delete') { static::getLogger()->debug(sprintf('Deleting users (%s) for configuration record %s', $aContext, $configuration->getUid())); $importUtility->deleteUsers(); } // Proceed with import (handle partial result sets until every LDAP record has been returned) do { $typo3Users = $importUtility->fetchTypo3Users($ldapUsers); // Loop on all users and import them foreach ($ldapUsers as $index => $aUser) { if ($mode === 'sync' && empty($typo3Users[$index]['uid'])) { // New LDAP user => skip it since only existing TYPO3 users should get synchronized continue; } // Merge LDAP and TYPO3 information $user = Authentication::merge($aUser, $typo3Users[$index], $config['users']['mapping']); // Import the user using information from LDAP $importUtility->import($user, $aUser, $this->restoredUsersHandling); } static::getLogger()->info(sprintf('Configuration record %s: processed %s LDAP users (%s)', $configuration->getUid(), count($ldapUsers), $aContext)); // Free memory before going on $typo3Users = NULL; $ldapUsers = NULL; $ldapUsers = $importUtility->hasMoreLdapUsers() ? $importUtility->fetchLdapUsers(TRUE) : array(); } while (count($ldapUsers) > 0); } // Clean up unset($importUtility); Ldap::getInstance()->disconnect(); } } // If some failures were registered, rollback the whole transaction and report error if ($failures > 0) { $this->getDatabaseConnection()->sql_query('ROLLBACK'); $message = 'Some or all imports failed. Synchronisation was aborted. Check your settings or your network connection'; static::getLogger()->error($message); throw new ImportUsersException($message, 1410774015); } else { // Everything went fine, commit the changes $this->getDatabaseConnection()->sql_query('COMMIT'); } return TRUE; }