diff --git a/src/applications/auth/provider/PhabricatorAuthProviderLDAP.php b/src/applications/auth/provider/PhabricatorAuthProviderLDAP.php
index 72ee552466..8f88990023 100644
--- a/src/applications/auth/provider/PhabricatorAuthProviderLDAP.php
+++ b/src/applications/auth/provider/PhabricatorAuthProviderLDAP.php
@@ -31,6 +31,8 @@ final class PhabricatorAuthProviderLDAP
PhabricatorEnv::getEnvConfig('ldap.search_attribute'))
->setUsernameAttribute(
PhabricatorEnv::getEnvConfig('ldap.username-attribute'))
+ ->setRealNameAttributes(
+ PhabricatorEnv::getEnvConfig('ldap.real_name_attributes'))
->setLDAPVersion(PhabricatorEnv::getEnvConfig('ldap.version'))
->setLDAPReferrals(PhabricatorEnv::getEnvConfig('ldap.referrals'))
->setLDAPStartTLS(PhabricatorEnv::getEnvConfig('ldap.start-tls'))
@@ -171,4 +173,243 @@ final class PhabricatorAuthProviderLDAP
return array($this->loadOrCreateAccount($account_id), $response);
}
+
+ const KEY_HOSTNAME = 'ldap:host';
+ const KEY_PORT = 'ldap:port';
+ const KEY_DISTINGUISHED_NAME = 'ldap:dn';
+ const KEY_SEARCH_ATTRIBUTE = 'ldap:search-attribute';
+ const KEY_USERNAME_ATTRIBUTE = 'ldap:username-attribute';
+ const KEY_REALNAME_ATTRIBUTES = 'ldap:realname-attributes';
+ const KEY_VERSION = 'ldap:version';
+ const KEY_REFERRALS = 'ldap:referrals';
+ const KEY_START_TLS = 'ldap:start-tls';
+ const KEY_ANONYMOUS_USERNAME = 'ldap:anoynmous-username';
+ const KEY_ANONYMOUS_PASSWORD = 'ldap:anonymous-password';
+ const KEY_SEARCH_FIRST = 'ldap:search-first';
+ const KEY_ACTIVEDIRECTORY_DOMAIN = 'ldap:activedirectory-domain';
+
+ private function getPropertyKeys() {
+ return array(
+ self::KEY_HOSTNAME,
+ self::KEY_PORT,
+ self::KEY_DISTINGUISHED_NAME,
+ self::KEY_SEARCH_ATTRIBUTE,
+ self::KEY_USERNAME_ATTRIBUTE,
+ self::KEY_VERSION,
+ self::KEY_REFERRALS,
+ self::KEY_START_TLS,
+ self::KEY_ANONYMOUS_USERNAME,
+ self::KEY_ANONYMOUS_PASSWORD,
+ self::KEY_SEARCH_FIRST,
+ self::KEY_ACTIVEDIRECTORY_DOMAIN,
+ );
+ }
+
+ private function getPropertyLabels() {
+ return array(
+ self::KEY_HOSTNAME => pht('LDAP Hostname'),
+ self::KEY_PORT => pht('LDAP Port'),
+ self::KEY_DISTINGUISHED_NAME => pht('Base Distinguished Name'),
+ self::KEY_SEARCH_ATTRIBUTE => pht('Search Attribute'),
+ self::KEY_USERNAME_ATTRIBUTE => pht('Username Attribute'),
+ self::KEY_REALNAME_ATTRIBUTES => pht('Realname Attributes'),
+ self::KEY_VERSION => pht('LDAP Version'),
+ self::KEY_REFERRALS => pht('Enable Referrals'),
+ self::KEY_START_TLS => pht('Use TLS'),
+ self::KEY_SEARCH_FIRST => pht('Search First'),
+ self::KEY_ANONYMOUS_USERNAME => pht('Anonymous Username'),
+ self::KEY_ANONYMOUS_PASSWORD => pht('Anonymous Password'),
+ self::KEY_ACTIVEDIRECTORY_DOMAIN => pht('ActiveDirectory Domain'),
+ );
+ }
+
+ public function readFormValuesFromProvider() {
+ return array(
+ self::KEY_HOSTNAME =>
+ PhabricatorEnv::getEnvConfig('ldap.hostname'),
+ self::KEY_PORT =>
+ PhabricatorEnv::getEnvConfig('ldap.port'),
+ self::KEY_DISTINGUISHED_NAME =>
+ PhabricatorEnv::getEnvConfig('ldap.base_dn'),
+ self::KEY_SEARCH_ATTRIBUTE =>
+ PhabricatorEnv::getEnvConfig('ldap.search_attribute'),
+ self::KEY_USERNAME_ATTRIBUTE =>
+ PhabricatorEnv::getEnvConfig('ldap.username-attribute'),
+ self::KEY_REALNAME_ATTRIBUTES =>
+ PhabricatorEnv::getEnvConfig('ldap.real_name_attributes'),
+ self::KEY_VERSION =>
+ PhabricatorEnv::getEnvConfig('ldap.version'),
+ self::KEY_REFERRALS =>
+ PhabricatorEnv::getEnvConfig('ldap.referrals'),
+ self::KEY_START_TLS =>
+ PhabricatorEnv::getEnvConfig('ldap.start-tls'),
+ self::KEY_ANONYMOUS_USERNAME =>
+ PhabricatorEnv::getEnvConfig('ldap.anonymous-user-name'),
+ self::KEY_ANONYMOUS_PASSWORD =>
+ PhabricatorEnv::getEnvConfig('ldap.anonymous-user-password'),
+ self::KEY_SEARCH_FIRST =>
+ PhabricatorEnv::getEnvConfig('ldap.search-first'),
+ self::KEY_ACTIVEDIRECTORY_DOMAIN =>
+ PhabricatorEnv::getEnvConfig('ldap.activedirectory_domain'),
+ );
+ }
+
+ public function readFormValuesFromRequest(AphrontRequest $request) {
+ $values = array();
+ foreach ($this->getPropertyKeys() as $key) {
+ switch ($key) {
+ case self::KEY_REALNAME_ATTRIBUTES:
+ $values[$key] = $request->getStrList($key);
+ break;
+ default:
+ $values[$key] = $request->getStr($key);
+ break;
+ }
+ }
+ return $values;
+ }
+
+ public function processEditForm(
+ AphrontRequest $request,
+ array $values) {
+ $errors = array();
+ $issues = array();
+ return array($errors, $issues, $values);
+ }
+
+ public function extendEditForm(
+ AphrontRequest $request,
+ AphrontFormView $form,
+ array $values,
+ array $issues) {
+
+ $labels = $this->getPropertyLabels();
+
+ $captions = array(
+ self::KEY_HOSTNAME =>
+ pht('Example: %s',
+ hsprintf('%s', pht('ldap.example.com'))),
+ self::KEY_DISTINGUISHED_NAME =>
+ pht('Example: %s',
+ hsprintf('%s', pht('ou=People, dc=example, dc=com'))),
+ self::KEY_SEARCH_ATTRIBUTE =>
+ pht('Example: %s',
+ hsprintf('%s', pht('sn'))),
+ self::KEY_USERNAME_ATTRIBUTE =>
+ pht('Optional, if different from search attribute.'),
+ self::KEY_REALNAME_ATTRIBUTES =>
+ pht('Optional. Example: %s',
+ hsprintf('%s', pht('firstname, lastname'))),
+ self::KEY_REFERRALS =>
+ pht('Follow referrals. Disable this for Windows AD 2003.'),
+ self::KEY_START_TLS =>
+ pht('Start TLS after binding to the LDAP server.'),
+ self::KEY_SEARCH_FIRST =>
+ pht(
+ 'When the user enters their username, search for a matching '.
+ 'record using the "Search Attribute", then try to bind using '.
+ 'the DN for the record. This is useful if usernames are not '.
+ 'part of the record DN.'),
+ self::KEY_ANONYMOUS_USERNAME =>
+ pht('Username to bind with before searching.'),
+ self::KEY_ANONYMOUS_PASSWORD =>
+ pht('Password to bind with before searching.'),
+ );
+
+ $types = array(
+ self::KEY_REFERRALS => 'checkbox',
+ self::KEY_START_TLS => 'checkbox',
+ self::KEY_SEARCH_FIRST => 'checkbox',
+ self::KEY_REALNAME_ATTRIBUTES => 'list',
+ self::KEY_ANONYMOUS_PASSWORD => 'password',
+ );
+
+ foreach ($labels as $key => $label) {
+ $caption = idx($captions, $key);
+ $type = idx($types, $key);
+ $value = idx($values, $key);
+
+ $control = null;
+ switch ($type) {
+ case 'checkbox':
+ $control = id(new AphrontFormCheckboxControl())
+ ->addCheckbox(
+ $key,
+ 1,
+ hsprintf('%s: %s', $label, $caption),
+ $value);
+ break;
+ case 'list':
+ $control = id(new AphrontFormTextControl())
+ ->setName($key)
+ ->setLabel($label)
+ ->setCaption($caption)
+ ->setValue(implode(', ', $value));
+ break;
+ case 'password':
+ $control = id(new AphrontFormPasswordControl())
+ ->setName($key)
+ ->setLabel($label)
+ ->setCaption($caption)
+ ->setValue($value);
+ break;
+ default:
+ $control = id(new AphrontFormTextControl())
+ ->setName($key)
+ ->setLabel($label)
+ ->setCaption($caption)
+ ->setValue($value);
+ break;
+ }
+
+ $form->appendChild($control);
+ }
+ }
+
+ public function renderConfigPropertyTransactionTitle(
+ PhabricatorAuthProviderConfigTransaction $xaction) {
+
+ $author_phid = $xaction->getAuthorPHID();
+ $old = $xaction->getOldValue();
+ $new = $xaction->getNewValue();
+ $key = $xaction->getMetadataValue(
+ PhabricatorAuthProviderConfigTransaction::PROPERTY_KEY);
+
+ $labels = $this->getPropertyLabels();
+ if (isset($labels[$key])) {
+ $label = $labels[$key];
+
+ $mask = false;
+ switch ($key) {
+ case self::KEY_ANONYMOUS_PASSWORD:
+ $mask = true;
+ break;
+ }
+
+ if ($mask) {
+ return pht(
+ '%s updated the "%s" value.',
+ $xaction->renderHandleLink($author_phid),
+ $label);
+ }
+
+ if (!strlen($old)) {
+ return pht(
+ '%s set the "%s" value to "%s".',
+ $xaction->renderHandleLink($author_phid),
+ $label,
+ $new);
+ } else {
+ return pht(
+ '%s changed the "%s" value from "%s" to "%s".',
+ $xaction->renderHandleLink($author_phid),
+ $label,
+ $old,
+ $new);
+ }
+ }
+
+ return parent::renderConfigPropertyTransactionTitle($xaction);
+ }
+
}