diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 4be33f8125..a693d6e391 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -822,6 +822,7 @@ phutil_register_library_map(array( 'PhabricatorPasteViewController' => 'applications/paste/controller/PhabricatorPasteViewController.php', 'PhabricatorPeopleController' => 'applications/people/controller/PhabricatorPeopleController.php', 'PhabricatorPeopleEditController' => 'applications/people/controller/PhabricatorPeopleEditController.php', + 'PhabricatorPeopleLdapController' => 'applications/people/controller/PhabricatorPeopleLdapController.php', 'PhabricatorPeopleListController' => 'applications/people/controller/PhabricatorPeopleListController.php', 'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php', 'PhabricatorPeopleProfileController' => 'applications/people/controller/PhabricatorPeopleProfileController.php', @@ -1792,6 +1793,7 @@ phutil_register_library_map(array( 'PhabricatorPasteViewController' => 'PhabricatorPasteController', 'PhabricatorPeopleController' => 'PhabricatorController', 'PhabricatorPeopleEditController' => 'PhabricatorPeopleController', + 'PhabricatorPeopleLdapController' => 'PhabricatorPeopleController', 'PhabricatorPeopleListController' => 'PhabricatorPeopleController', 'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController', 'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController', diff --git a/src/aphront/configuration/AphrontDefaultApplicationConfiguration.php b/src/aphront/configuration/AphrontDefaultApplicationConfiguration.php index 4f56a77cfe..ec0a84b356 100644 --- a/src/aphront/configuration/AphrontDefaultApplicationConfiguration.php +++ b/src/aphront/configuration/AphrontDefaultApplicationConfiguration.php @@ -72,6 +72,7 @@ class AphrontDefaultApplicationConfiguration 'logs/' => 'PhabricatorPeopleLogsController', 'edit/(?:(?P\d+)/(?:(?P\w+)/)?)?' => 'PhabricatorPeopleEditController', + 'ldap/' => 'PhabricatorPeopleLdapController', ), '/p/(?P[\w._-]+)/(?:(?P\w+)/)?' => 'PhabricatorPeopleProfileController', diff --git a/src/applications/auth/ldap/PhabricatorLDAPProvider.php b/src/applications/auth/ldap/PhabricatorLDAPProvider.php index d1d0b29c31..3f9241b897 100644 --- a/src/applications/auth/ldap/PhabricatorLDAPProvider.php +++ b/src/applications/auth/ldap/PhabricatorLDAPProvider.php @@ -53,22 +53,26 @@ final class PhabricatorLDAPProvider { public function retrieveUserEmail() { return $this->userData['mail'][0]; } - + public function retrieveUserRealName() { + return $this->retrieveUserRealNameFromData($this->userData); + } + + public function retrieveUserRealNameFromData($data) { $name_attributes = PhabricatorEnv::getEnvConfig( 'ldap.real_name_attributes'); $real_name = ''; if (is_array($name_attributes)) { foreach ($name_attributes AS $attribute) { - if (isset($this->userData[$attribute][0])) { - $real_name .= $this->userData[$attribute][0] . ' '; + if (isset($data[$attribute][0])) { + $real_name .= $data[$attribute][0] . ' '; } } trim($real_name); - } else if (isset($this->userData[$name_attributes][0])) { - $real_name = $this->userData[$name_attributes][0]; + } else if (isset($data[$name_attributes][0])) { + $real_name = $data[$name_attributes][0]; } if ($real_name == '') { @@ -146,4 +150,46 @@ final class PhabricatorLDAPProvider { return $entries[0]; } + + public function search($query) { + $result = ldap_search($this->getConnection(), $this->getBaseDN(), + $query); + + if (!$result) { + throw new Exception('Search failed. Please check your LDAP and HTTP '. + 'logs for more information.'); + } + + $entries = ldap_get_entries($this->getConnection(), $result); + + if ($entries === false) { + throw new Exception('Could not get entries'); + } + + if ($entries['count'] == 0) { + throw new Exception('No results found'); + } + + + $rows = array(); + + for($i = 0; $i < $entries['count']; $i++) { + $row = array(); + $entry = $entries[$i]; + // Get username, email and realname + $username = $entry[$this->getSearchAttribute()][0]; + if(empty($username)) { + continue; + } + $row[] = $username; + $row[] = $entry['mail'][0]; + $row[] = $this->retrieveUserRealNameFromData($entry); + + + $rows[] = $row; + } + + return $rows; + + } } diff --git a/src/applications/people/controller/PhabricatorPeopleLdapController.php b/src/applications/people/controller/PhabricatorPeopleLdapController.php new file mode 100644 index 0000000000..e0e4b3a3eb --- /dev/null +++ b/src/applications/people/controller/PhabricatorPeopleLdapController.php @@ -0,0 +1,224 @@ +view = idx($data, 'view'); + } + + public function processRequest() { + + $request = $this->getRequest(); + $admin = $request->getUser(); + + $base_uri = '/people/edit/'; + + $content = array(); + + + $response = $this->processBasicRequest(); + + if ($response instanceof AphrontResponse) { + return $response; + } + + $content[] = $response; + + + return $this->buildStandardPageResponse( + $content, + array( + 'title' => 'Import Ldap Users', + )); + } + + /** + * Displays a ldap login form, as we need to auth before we can search + */ + private function processBasicRequest() { + $panels = array(); + + $request = $this->getRequest(); + + $admin = $request->getUser(); + + $form = id(new AphrontFormView()) + ->setUser($admin) + ->appendChild( + id(new AphrontFormTextControl()) + ->setLabel('LDAP username') + ->setName('username')) + ->appendChild( + id(new AphrontFormPasswordControl()) + ->setLabel('Password') + ->setName('password')) + ->appendChild( + id(new AphrontFormTextControl()) + ->setLabel('LDAP query') + ->setName('query')) + ->setAction($request->getRequestURI()->alter('search', 'true')->alter('import', null)) + ->appendChild( + id(new AphrontFormSubmitControl()) + ->setValue('Search')); + + $panel = new AphrontPanelView(); + $panel->setHeader('Import Ldap Users'); + $panel->appendChild($form); + + + if($request->getStr('import')) { + $panels[] = $this->processImportRequest($request); + } + + $panels[] = $panel; + + if($request->getStr('search')) { + $panels[] = $this->processSearchRequest($request); + } + + return $panels; + + } + + private function processImportRequest($request) { + $admin = $request->getUser(); + $usernames = $request->getArr('usernames'); + $emails = $request->getArr('email'); + $names = $request->getArr('name'); + + $panel = new AphrontErrorView(); + $panel->setSeverity(AphrontErrorView::SEVERITY_NOTICE); + $panel->setTitle("Import Successful"); + $errors = array("Successfully imported users from ldap"); + + + foreach($usernames as $username) { + $user = new PhabricatorUser(); + $user->setUsername($username); + $user->setRealname($names[$username]); + + $email_obj = id(new PhabricatorUserEmail()) + ->setAddress($emails[$username]) + ->setIsVerified(1); + try { + id(new PhabricatorUserEditor()) + ->setActor($admin) + ->createNewUser($user, $email_obj); + + $ldap_info = new PhabricatorUserLDAPInfo(); + $ldap_info->setLDAPUsername($username); + $ldap_info->setUserID($user->getID()); + $ldap_info->save(); + $errors[] = 'Succesfully added ' . $username; + } catch (Exception $ex) { + $errors[] = 'Failed to add ' . $username . ' ' . $ex->getMessage(); + } + } + + $panel->setErrors($errors); + return $panel; + + } + + private function processSearchRequest($request) { + $panel = new AphrontPanelView(); + + $admin = $request->getUser(); + + $username = $request->getStr('username'); + $password = $request->getStr('password'); + $search = $request->getStr('query'); + + try { + $ldapProvider = new PhabricatorLDAPProvider(); + $ldapProvider->auth($username, $password); + $results = $ldapProvider->search($search); + foreach($results as $key => $result) { + $results[$key][] = $this->renderUserInputs($result); + } + + $form = id(new AphrontFormView()) + ->setUser($admin); + + $table = new AphrontTableView($results); + $table->setHeaders( + array( + 'Username', + 'Email', + 'RealName', + '', + )); + $form->appendChild($table); + $form->setAction($request->getRequestURI()->alter('import', 'true')->alter('search', null)) + ->appendChild( + id(new AphrontFormSubmitControl()) + ->setValue('Import')); + + + $panel->appendChild($form); + } catch (Exception $ex) { + $error_view = new AphrontErrorView(); + $error_view->setTitle('LDAP Search Failed'); + $error_view->setErrors(array($ex->getMessage())); + return $error_view; + } + return $panel; + + } + + private function renderUserInputs($user) { + $username = $user[0]; + $inputs = phutil_render_tag( + 'input', + array( + 'type' => 'checkbox', + 'name' => 'usernames[]', + 'value' =>$username, + ), + ''); + + $inputs .= phutil_render_tag( + 'input', + array( + 'type' => 'hidden', + 'name' => "email[$username]", + 'value' =>$user[1], + ), + ''); + + $inputs .= phutil_render_tag( + 'input', + array( + 'type' => 'hidden', + 'name' => "name[$username]", + 'value' =>$user[2], + ), + ''); + + return $inputs; + + } +} diff --git a/src/applications/people/controller/PhabricatorPeopleListController.php b/src/applications/people/controller/PhabricatorPeopleListController.php index cb41eab371..a9577f5003 100644 --- a/src/applications/people/controller/PhabricatorPeopleListController.php +++ b/src/applications/people/controller/PhabricatorPeopleListController.php @@ -130,6 +130,16 @@ final class PhabricatorPeopleListController 'class' => 'button green', ), 'Create New Account')); + if (PhabricatorEnv::getEnvConfig('ldap.auth-enabled')) { + $panel->addButton( + phutil_render_tag( + 'a', + array( + 'href' => '/people/ldap', + 'class' => 'button green' + ), + 'Import from Ldap')); + } } return $this->buildStandardPageResponse($panel, array(