1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-13 18:32:41 +01:00
phorge-phorge/src/applications/auth/controller/oauthregistration/PhabricatorOAuthDefaultRegistrationController.php
Chad Little 251a7b0602 Reasonable pht pass at auth.
Summary: Spent some time going through auth stuff for pht's.

Test Plan: Tested logging in, logging out, reseting password, using Github, creating a new account. I couldn't quite test everything so will double read the diff when I submit it.

Reviewers: epriestley, btrahan

Reviewed By: epriestley

CC: aran, Korvin

Differential Revision: https://secure.phabricator.com/D4671
2013-01-26 16:17:44 -08:00

225 lines
7.2 KiB
PHP

<?php
final class PhabricatorOAuthDefaultRegistrationController
extends PhabricatorOAuthRegistrationController {
public function processRequest() {
$provider = $this->getOAuthProvider();
$oauth_info = $this->getOAuthInfo();
$request = $this->getRequest();
$errors = array();
$e_username = true;
$e_email = true;
$e_realname = true;
$user = new PhabricatorUser();
$user->setUsername($provider->retrieveUserAccountName());
$user->setRealName($provider->retrieveUserRealName());
$new_email = $provider->retrieveUserEmail();
if ($new_email) {
// If the user's OAuth provider account has an email address but the
// email address domain is not allowed by the Phabricator configuration,
// we just pretend the provider did not supply an address.
//
// For instance, if the user uses Google OAuth and their Google address
// is "joe@personal.com" but Phabricator is configured to require users
// use "@company.com" addresses, we show a prompt below and tell the user
// to provide their "@company.com" address. They can still use the OAuth
// account to login, they just need to associate their account with an
// allowed address.
//
// If the OAuth address is fine, we just use it and don't prompt the user.
if (!PhabricatorUserEmail::isAllowedAddress($new_email)) {
$new_email = null;
}
}
$show_email_input = ($new_email === null);
if ($request->isFormPost()) {
$user->setUsername($request->getStr('username'));
$username = $user->getUsername();
if (!strlen($user->getUsername())) {
$e_username = pht('Required');
$errors[] = pht('Username is required.');
} else if (!PhabricatorUser::validateUsername($username)) {
$e_username = pht('Invalid');
$errors[] = PhabricatorUser::describeValidUsername();
} else {
$e_username = null;
}
if (!$new_email) {
$new_email = trim($request->getStr('email'));
if (!$new_email) {
$e_email = pht('Required');
$errors[] = pht('Email is required.');
} else {
$e_email = null;
}
}
if ($new_email) {
$email_ok = PhabricatorUserEmail::isAllowedAddress($new_email);
if (!$email_ok) {
$e_email = pht('Invalid');
$errors[] = PhabricatorUserEmail::describeAllowedAddresses();
}
}
if (!strlen($user->getRealName())) {
$user->setRealName($request->getStr('realname'));
if (!strlen($user->getRealName())) {
$e_realname = pht('Required');
$errors[] = pht('Real name is required.');
} else {
$e_realname = null;
}
}
if (!$errors) {
$image = $provider->retrieveUserProfileImage();
if ($image) {
$file = PhabricatorFile::newFromFileData(
$image,
array(
'name' => $provider->getProviderKey().'-profile.jpg',
'authorPHID' => $user->getPHID(),
));
$xformer = new PhabricatorImageTransformer();
// Resize OAuth image to a reasonable size
$small_xformed = $xformer->executeProfileTransform(
$file,
$width = 50,
$min_height = 50,
$max_height = 50);
$user->setProfileImagePHID($small_xformed->getPHID());
}
try {
// NOTE: We don't verify OAuth email addresses by default because
// OAuth providers might associate email addresses with accounts that
// haven't actually verified they own them. We could selectively
// auto-verify some providers that we trust here, but the stakes for
// verifying an email address are high because having a corporate
// address at a company is sometimes the key to the castle.
$email_obj = id(new PhabricatorUserEmail())
->setAddress($new_email)
->setIsVerified(0);
id(new PhabricatorUserEditor())
->setActor($user)
->createNewUser($user, $email_obj);
$oauth_info->setUserID($user->getID());
$oauth_info->save();
$session_key = $user->establishSession('web');
$request->setCookie('phusr', $user->getUsername());
$request->setCookie('phsid', $session_key);
$email_obj->sendVerificationEmail($user);
return id(new AphrontRedirectResponse())->setURI('/');
} catch (AphrontQueryDuplicateKeyException $exception) {
$same_username = id(new PhabricatorUser())->loadOneWhere(
'userName = %s',
$user->getUserName());
$same_email = id(new PhabricatorUserEmail())->loadOneWhere(
'address = %s',
$new_email);
if ($same_username) {
$e_username = pht('Duplicate');
$errors[] = pht('That username or email is not unique.');
} else if ($same_email) {
$e_email = pht('Duplicate');
$errors[] = pht('That email is not unique.');
} else {
throw $exception;
}
}
}
}
$error_view = null;
if ($errors) {
$error_view = new AphrontErrorView();
$error_view->setTitle(pht('Registration Failed'));
$error_view->setErrors($errors);
}
// Strip the URI down to the path, because otherwise we'll trigger
// external CSRF protection (by having a protocol in the form "action")
// and generate a form with no CSRF token.
$action_uri = new PhutilURI($provider->getRedirectURI());
$action_path = $action_uri->getPath();
$form = new AphrontFormView();
$form
->addHiddenInput('confirm_token', $provider->getAccessToken())
->addHiddenInput('expires', $oauth_info->getTokenExpires())
->addHiddenInput('state', $this->getOAuthState())
->setUser($request->getUser())
->setAction($action_path)
->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Username'))
->setName('username')
->setValue($user->getUsername())
->setError($e_username));
if ($show_email_input) {
$form->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Email'))
->setName('email')
->setValue($request->getStr('email'))
->setCaption(PhabricatorUserEmail::describeAllowedAddresses())
->setError($e_email));
}
if ($provider->retrieveUserRealName() === null) {
$form->appendChild(
id(new AphrontFormTextControl())
->setLabel(pht('Real Name'))
->setName('realname')
->setValue($request->getStr('realname'))
->setError($e_realname));
}
$form
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Create Account')));
$panel = new AphrontPanelView();
$panel->setHeader(pht('Create New Account'));
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
$panel->appendChild($form);
$panel->setNoBackground();
return $this->buildApplicationPage(
array(
$error_view,
$panel,
),
array(
'title' => pht('Create New Account'),
'device' => true
));
}
}