Page MenuHomec4science

PhabricatorAuthProviderShibboleth.php
No OneTemporary

File Metadata

Created
Tue, Sep 3, 02:53

PhabricatorAuthProviderShibboleth.php

<?php
final class PhabricatorAuthProviderShibboleth
extends PhabricatorAuthProvider {
private $adapter;
public function getProviderName() {
return pht('Shibboleth');
}
public function getDescriptionForCreate() {
return pht(
'Configure a trust relationship for Shibboleth (Single Sign On) '.
'authenticated users to automatically log in to Phabricator.');
}
public function getDefaultProviderConfig() {
return parent::getDefaultProviderConfig();
}
public function getAdapter() {
if (!$this->adapter) {
$conf = $this->getProviderConfig();
$adapter = id(new PhutilAuthAdapterShibboleth())
->setShibSessionIdField(
$conf->getProperty(self::KEY_SHIB_SESSION_ID_FIELD))
->setShibApplicationIdField(
$conf->getProperty(self::KEY_SHIB_APPLICATION_ID_FIELD))
->setUseridField(
$conf->getProperty(self::KEY_USERID_FIELD))
->setUsernameField(
$conf->getProperty(self::KEY_USERNAME_FIELD))
->setRealnameField(
$conf->getProperty(self::KEY_REALNAME_FIELD))
->setFirstnameField(
$conf->getProperty(self::KEY_FIRSTNAME_FIELD))
->setLastnameField(
$conf->getProperty(self::KEY_LASTNAME_FIELD))
->setEmailField(
$conf->getProperty(self::KEY_EMAIL_FIELD))
->setPageURIPattern(
$conf->getProperty(self::KEY_PAGE_URI_PATTERN))
->setImageURIPattern(
$conf->getProperty(self::KEY_IMAGE_URI_PATTERN))
->setAddUserToProject(
$conf->getProperty(self::KEY_ADD_USER_TO_PROJECT))
->setUserProject(
$conf->getProperty(self::KEY_USER_PROJECT))
->setIsGeneratedUsername(
$conf->getProperty(self::KEY_USERNAME_FROM_REALNAME))
->setOrgField(
$conf->getProperty(self::KEY_ORG_FIELD))
->setOrgCustomField(
$conf->getProperty(self::KEY_ORG_CUSTOM_FIELD))
->setOrgTypeField(
$conf->getProperty(self::KEY_ORG_TYPE_FIELD))
->setOrgTypeCustomField(
$conf->getProperty(self::KEY_ORG_TYPE_CUSTOM_FIELD));
$this->adapter = $adapter;
}
return $this->adapter;
}
protected function renderLoginForm(AphrontRequest $request, $mode) {
$attributes = array(
'method' => 'GET',
'uri' => $this->getLoginURI(),
);
return $this->renderStandardLoginButton($request, $mode, $attributes);
}
public function isLoginFormAButton() {
return true;
}
public function processLoginRequest(
PhabricatorAuthLoginController $controller) {
$request = $controller->getRequest();
$response = null;
$account = null;
$adapter = $this->getAdapter();
$env = array();
$env_names = $adapter->getEnvNames();
foreach ($env_names as $h) {
if(array_key_exists($h, $_SERVER)) {
$env[$h] = $_SERVER[$h];
}
}
if (! $adapter->setUserDataFromRequest($env)) {
$response = $controller->buildProviderPageResponse(
$this,
id(new PHUIInfoView())
->setErrors(array(pht('Invalid Shibboleth session.')))
->addButton(id(new PHUIButtonView())
->setTag('a')
->setText(pht('Return to home'))
->setHref('/')
)
);
return array($account, $response);
}
$account_id = $adapter->getAccountID();
return array($this->loadOrCreateAccount($account_id), $response);
}
protected function loadOrCreateAccount($account_id) {
$account = parent::loadOrCreateAccount($account_id);
$adapter = $this->getAdapter();
if(!$adapter) {
return $account;
}
if(!$account->getUserPHID()){
// User account not yet created
return $account;
}
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
// Organization
if(strlen($adapter->getOrg()) &&
strlen($adapter->getOrgType()) &&
strlen($adapter->getOrgCustom()) &&
strlen($adapter->getOrgTypeCustom())
) {
$account->setProperty($adapter->getOrgCustom(), $adapter->getOrg());
$account->setProperty($adapter->getOrgTypeCustom(), $adapter->getOrgType());
$account->save();
}
// Default project
$projects = $adapter->getUserProject();
if(count($projects)) {
$admin = id(new PhabricatorUser())
->loadOneWhere('isAdmin = 1');
$results = id(new PhabricatorProjectQuery())
->setViewer($admin)
->withPHIDs($projects)
->execute();
// Add user to project
foreach($results as $project) {
$spec = array(
'+' => array($account->getUserPHID() => $account->getUserPHID()),
);
$edge_type = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST;
$xactions = array();
$xactions[] = id(new PhabricatorProjectTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
->setMetadataValue('edge:type', $edge_type)
->setNewValue($spec);
$editor = id(new PhabricatorProjectTransactionEditor())
->setActor($admin)
->setContentSource(new PhabricatorConsoleContentSource())
->setContinueOnNoEffect(true)
->applyTransactions($project, $xactions);
}
}
unset($unguarded);
return $account;
}
const KEY_SHIB_SESSION_ID_FIELD = 'shibboleth:session_id_field';
const KEY_SHIB_APPLICATION_ID_FIELD = 'shibboleth:application_id_field';
const KEY_USERID_FIELD = 'shibboleth:userid_field';
const KEY_USERNAME_FIELD = 'shibboleth:username_field';
const KEY_REALNAME_FIELD = 'shibboleth:realname_field';
const KEY_FIRSTNAME_FIELD = 'shibboleth:firstname_field';
const KEY_LASTNAME_FIELD = 'shibboleth:lastname_field';
const KEY_EMAIL_FIELD = 'shibboleth:email_field';
const KEY_ORG_FIELD = 'shibboleth:org';
const KEY_ORG_TYPE_FIELD = 'shibboleth:org_type';
const KEY_ORG_CUSTOM_FIELD = 'shibboleth:org_custom';
const KEY_ORG_TYPE_CUSTOM_FIELD = 'shibboleth:org_type_custm';
const KEY_PAGE_URI_PATTERN = 'shibboleth:page_uri_pattern';
const KEY_IMAGE_URI_PATTERN = 'shibboleth:image_uri_pattern';
const KEY_USERNAME_FROM_REALNAME = 'shibboleth:username_from_realname';
const KEY_ADD_USER_TO_PROJECT = 'shibboleth:add_user_to_project';
const KEY_USER_PROJECT = 'shibboleth:user_project';
private function getPropertyKeys() {
return array(
self::KEY_SHIB_SESSION_ID_FIELD,
self::KEY_SHIB_APPLICATION_ID_FIELD,
self::KEY_USERID_FIELD,
self::KEY_USERNAME_FIELD,
self::KEY_REALNAME_FIELD,
self::KEY_FIRSTNAME_FIELD,
self::KEY_LASTNAME_FIELD,
self::KEY_EMAIL_FIELD,
self::KEY_ORG_FIELD,
self::KEY_ORG_CUSTOM_FIELD,
self::KEY_ORG_TYPE_FIELD,
self::KEY_ORG_TYPE_CUSTOM_FIELD,
self::KEY_PAGE_URI_PATTERN,
self::KEY_IMAGE_URI_PATTERN,
self::KEY_USERNAME_FROM_REALNAME,
self::KEY_ADD_USER_TO_PROJECT,
self::KEY_USER_PROJECT
);
}
private function getPropertyLabels() {
return array(
self::KEY_SHIB_SESSION_ID_FIELD => pht('Session ID'),
self::KEY_SHIB_APPLICATION_ID_FIELD => pht('Application ID'),
self::KEY_USERID_FIELD => pht('User ID'),
self::KEY_USERNAME_FIELD => pht('Username'),
self::KEY_REALNAME_FIELD => pht('Real name'),
self::KEY_FIRSTNAME_FIELD => pht('Firstname'),
self::KEY_LASTNAME_FIELD => pht('Lastname'),
self::KEY_EMAIL_FIELD => pht('User emailname'),
self::KEY_ORG_FIELD => pht('Organization'),
self::KEY_ORG_CUSTOM_FIELD => pht('Organization custom field'),
self::KEY_ORG_TYPE_FIELD => pht('Organization type'),
self::KEY_ORG_TYPE_CUSTOM_FIELD => pht('Organization type custom field'),
self::KEY_PAGE_URI_PATTERN => pht('User page URI pattern'),
self::KEY_IMAGE_URI_PATTERN => pht('User image URI pattern'),
);
}
public function readFormValuesFromProvider() {
$properties = array();
foreach ($this->getPropertyKeys() as $key) {
$properties[$key] = $this->getProviderConfig()->getProperty($key);
}
return $properties;
}
public function readFormValuesFromRequest(AphrontRequest $request) {
$values = array();
foreach ($this->getPropertyKeys() as $key) {
if($key == self::KEY_USER_PROJECT) {
$values[$key] = $request->getArr($key);
} else {
$values[$key] = $request->getStr($key);
}
}
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_SHIB_SESSION_ID_FIELD => pht('Shibboleth Session ID, e.g.: Shib-Session-ID'),
self::KEY_SHIB_APPLICATION_ID_FIELD => pht('Shibboleth application id, e.g.: Shib-Application-ID'),
self::KEY_USERID_FIELD => pht('Unique user id for internal Phabricator use. e.g.: uniqueID'),
self::KEY_USERNAME_FIELD => pht('Visible username, can be left empty if you choose to autogenerate it. e.g.: username'),
self::KEY_REALNAME_FIELD => pht('Visible in the user profile. e.g.: displayName'),
self::KEY_FIRSTNAME_FIELD => pht('Use this only when you autogenerate username. e.g.: givenName'),
self::KEY_LASTNAME_FIELD => pht('Use this only when you autogenerate username. e.g.: surname'),
self::KEY_EMAIL_FIELD => pht('Unique email address. e.g.: email'),
self::KEY_ORG_FIELD => pht('Organization name. e.g.: homeOrganization'),
self::KEY_ORG_CUSTOM_FIELD => pht('Organization name custom field in Phabricator. e.g.: mycompany:org'),
self::KEY_ORG_TYPE_FIELD => pht('Organization type. e.g.: homeOrganizationType'),
self::KEY_ORG_TYPE_CUSTOM_FIELD => pht('Organization type custom field in Phabricator. e.g.: mycompany:orgtype'),
self::KEY_PAGE_URI_PATTERN => pht('URI pattern to a user pag. Add %%s for replacement with the username'),
self::KEY_IMAGE_URI_PATTERN => pht('URI pattern to an image for the user. Add %%s for replacement with the username'),
self::KEY_USER_PROJECT => pht('Project ID to add the user to. e.g.: PHID-PROJ-itwdg3fgxutsrdnqjklb'),
);
// Text fields
foreach ($labels as $key => $label) {
$caption = idx($captions, $key);
$value = idx($values, $key);
$control = null;
$control = id(new AphrontFormTextControl())
->setName($key)
->setLabel($label)
->setCaption($caption)
->setValue($value);
$form->appendChild($control);
}
// Add to project
$form->appendChild(
id(new AphrontFormCheckboxControl())
->addCheckbox(
self::KEY_ADD_USER_TO_PROJECT,
1,
hsprintf('<strong>%s:</strong> %s', "Add to default Project",
"Automatically add the new user to a default project"),
idx($values, self::KEY_ADD_USER_TO_PROJECT))
);
$projects = idx($values, self::KEY_USER_PROJECT, array());
$viewer = $request->getViewer();
$form->appendChild(
id(new AphrontFormTokenizerControl())
->setLabel(pht('Projects'))
->setName(self::KEY_USER_PROJECT)
->setValue($projects)
->setUser($viewer)
//->setDisabled(!idx($values, self::KEY_ADD_USER_TO_PROJECT))
->setDatasource(new PhabricatorProjectDatasource())
);
// Generate username
$form->appendChild(
id(new AphrontFormCheckboxControl())
->addCheckbox(
self::KEY_USERNAME_FROM_REALNAME,
1,
hsprintf('<strong>%s:</strong> %s', "Generated username",
"Create a unique username from the surname and firstname which complies with Phabricator policies."),
idx($values, self::KEY_USERNAME_FROM_REALNAME))
);
}
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];
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);
}
public static function getShibbolethProvider() {
$providers = self::getAllEnabledProviders();
foreach ($providers as $provider) {
if ($provider instanceof PhabricatorAuthProviderShibboleth) {
return $provider;
}
}
return null;
}
}

Event Timeline