Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2895309
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
31 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php b/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php
index a0edc324bb..cb663344b2 100644
--- a/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php
+++ b/src/applications/auth/controller/PhabricatorAuthOneTimeLoginController.php
@@ -1,199 +1,190 @@
<?php
final class PhabricatorAuthOneTimeLoginController
extends PhabricatorAuthController {
private $id;
private $key;
private $emailID;
private $linkType;
public function shouldRequireLogin() {
return false;
}
public function willProcessRequest(array $data) {
$this->linkType = $data['type'];
$this->id = $data['id'];
$this->key = $data['key'];
$this->emailID = idx($data, 'emailID');
}
public function processRequest() {
$request = $this->getRequest();
if ($request->getUser()->isLoggedIn()) {
return $this->renderError(
pht('You are already logged in.'));
}
$target_user = id(new PhabricatorPeopleQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withIDs(array($this->id))
->executeOne();
if (!$target_user) {
return new Aphront404Response();
}
// NOTE: As a convenience to users, these one-time login URIs may also
// be associated with an email address which will be verified when the
// URI is used.
// This improves the new user experience for users receiving "Welcome"
// emails on installs that require verification: if we did not verify the
// email, they'd immediately get roadblocked with a "Verify Your Email"
// error and have to go back to their email account, wait for a
// "Verification" email, and then click that link to actually get access to
// their account. This is hugely unwieldy, and if the link was only sent
// to the user's email in the first place we can safely verify it as a
// side effect of login.
// The email hashed into the URI so users can't verify some email they
// do not own by doing this:
//
// - Add some address you do not own;
// - request a password reset;
// - change the URI in the email to the address you don't own;
// - login via the email link; and
// - get a "verified" address you don't control.
$target_email = null;
if ($this->emailID) {
$target_email = id(new PhabricatorUserEmail())->loadOneWhere(
'userPHID = %s AND id = %d',
$target_user->getPHID(),
$this->emailID);
if (!$target_email) {
return new Aphront404Response();
}
}
$engine = new PhabricatorAuthSessionEngine();
$token = $engine->loadOneTimeLoginKey(
$target_user,
$target_email,
$this->key);
if (!$token) {
return $this->newDialog()
->setTitle(pht('Unable to Login'))
->setShortTitle(pht('Login Failure'))
->appendParagraph(
pht(
'The login link you clicked is invalid, out of date, or has '.
'already been used.'))
->appendParagraph(
pht(
'Make sure you are copy-and-pasting the entire link into '.
'your browser. Login links are only valid for 24 hours, and '.
'can only be used once.'))
->appendParagraph(
pht('You can try again, or request a new link via email.'))
->addCancelButton('/login/email/', pht('Send Another Email'));
}
if ($request->isFormPost()) {
// If we have an email bound into this URI, verify email so that clicking
// the link in the "Welcome" email is good enough, without requiring users
// to go through a second round of email verification.
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
// Nuke the token so that this URI is one-time only.
$token->delete();
if ($target_email) {
- $target_user->openTransaction();
- $target_email->setIsVerified(1);
- $target_email->save();
-
- // If this was the user's primary email address, also mark their
- // account as verified.
- $primary_email = $target_user->loadPrimaryEmail();
- if ($primary_email->getID() == $target_email->getID()) {
- $target_user->setIsEmailVerified(1);
- $target_user->save();
- }
- $target_user->saveTransaction();
+ id(new PhabricatorUserEditor())
+ ->setActor($target_user)
+ ->verifyEmail($target_user, $target_email);
}
unset($unguarded);
$next = '/';
if (!PhabricatorAuthProviderPassword::getPasswordProvider()) {
$next = '/settings/panel/external/';
} else if (PhabricatorEnv::getEnvConfig('account.editable')) {
// We're going to let the user reset their password without knowing
// the old one. Generate a one-time token for that.
$key = Filesystem::readRandomCharacters(16);
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
id(new PhabricatorAuthTemporaryToken())
->setObjectPHID($target_user->getPHID())
->setTokenType(
PhabricatorAuthSessionEngine::PASSWORD_TEMPORARY_TOKEN_TYPE)
->setTokenExpires(time() + phutil_units('1 hour in seconds'))
->setTokenCode(PhabricatorHash::digest($key))
->save();
unset($unguarded);
$next = (string)id(new PhutilURI('/settings/panel/password/'))
->setQueryParams(
array(
'key' => $key,
));
$request->setTemporaryCookie(PhabricatorCookies::COOKIE_HISEC, 'yes');
}
PhabricatorCookies::setNextURICookie($request, $next, $force = true);
return $this->loginUser($target_user);
}
// NOTE: We need to CSRF here so attackers can't generate an email link,
// then log a user in to an account they control via sneaky invisible
// form submissions.
switch ($this->linkType) {
case PhabricatorAuthSessionEngine::ONETIME_WELCOME:
$title = pht('Welcome to Phabricator');
break;
case PhabricatorAuthSessionEngine::ONETIME_RECOVER:
$title = pht('Account Recovery');
break;
case PhabricatorAuthSessionEngine::ONETIME_USERNAME:
case PhabricatorAuthSessionEngine::ONETIME_RESET:
default:
$title = pht('Login to Phabricator');
break;
}
$body = array();
$body[] = pht(
'Use the button below to log in as: %s',
phutil_tag('strong', array(), $target_user->getUsername()));
if ($target_email && !$target_email->getIsVerified()) {
$body[] = pht(
'Logging in will verify %s as an email address you own.',
phutil_tag('strong', array(), $target_email->getAddress()));
}
$body[] = pht(
'After logging in you should set a password for your account, or '.
'link your account to an external account that you can use to '.
'authenticate in the future.');
$dialog = $this->newDialog()
->setTitle($title)
->addSubmitButton(pht('Login (%s)', $target_user->getUsername()))
->addCancelButton('/');
foreach ($body as $paragraph) {
$dialog->appendParagraph($paragraph);
}
return id(new AphrontDialogResponse())->setDialog($dialog);
}
}
diff --git a/src/applications/auth/controller/PhabricatorEmailVerificationController.php b/src/applications/auth/controller/PhabricatorEmailVerificationController.php
index bca3f27f20..644b5ca7f5 100644
--- a/src/applications/auth/controller/PhabricatorEmailVerificationController.php
+++ b/src/applications/auth/controller/PhabricatorEmailVerificationController.php
@@ -1,108 +1,98 @@
<?php
final class PhabricatorEmailVerificationController
extends PhabricatorAuthController {
private $code;
public function willProcessRequest(array $data) {
$this->code = $data['code'];
}
public function shouldRequireEmailVerification() {
// Since users need to be able to hit this endpoint in order to verify
// email, we can't ever require email verification here.
return false;
}
public function shouldRequireEnabledUser() {
// Unapproved users are allowed to verify their email addresses. We'll kick
// disabled users out later.
return false;
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
if ($user->getIsDisabled()) {
// We allowed unapproved and disabled users to hit this controller, but
// want to kick out disabled users now.
return new Aphront400Response();
}
$email = id(new PhabricatorUserEmail())->loadOneWhere(
'userPHID = %s AND verificationCode = %s',
$user->getPHID(),
$this->code);
$submit = null;
if (!$email) {
$title = pht('Unable to Verify Email');
$content = pht(
'The verification code you provided is incorrect, or the email '.
'address has been removed, or the email address is owned by another '.
'user. Make sure you followed the link in the email correctly and are '.
'logged in with the user account associated with the email address.');
$continue = pht('Rats!');
} else if ($email->getIsVerified() && $user->getIsEmailVerified()) {
$title = pht('Address Already Verified');
$content = pht(
'This email address has already been verified.');
$continue = pht('Continue to Phabricator');
} else if ($request->isFormPost()) {
- $email->openTransaction();
- $email->setIsVerified(1);
- $email->save();
-
- // If the user just verified their primary email address, mark their
- // account as email verified.
- $user_primary = $user->loadPrimaryEmail();
- if ($user_primary->getID() == $email->getID()) {
- $user->setIsEmailVerified(1);
- $user->save();
- }
-
- $email->saveTransaction();
+ id(new PhabricatorUserEditor())
+ ->setActor($user)
+ ->verifyEmail($user, $email);
$title = pht('Address Verified');
$content = pht(
'The email address %s is now verified.',
phutil_tag('strong', array(), $email->getAddress()));
$continue = pht('Continue to Phabricator');
} else {
$title = pht('Verify Email Address');
$content = pht(
'Verify this email address (%s) and attach it to your account?',
phutil_tag('strong', array(), $email->getAddress()));
$continue = pht('Cancel');
$submit = pht('Verify %s', $email->getAddress());
}
$dialog = id(new AphrontDialogView())
->setUser($user)
->setTitle($title)
->addCancelButton('/', $continue)
->appendChild($content);
if ($submit) {
$dialog->addSubmitButton($submit);
}
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Verify Email'));
return $this->buildApplicationPage(
array(
$crumbs,
$dialog,
),
array(
'title' => pht('Verify Email'),
'device' => true,
));
}
}
diff --git a/src/applications/people/editor/PhabricatorUserEditor.php b/src/applications/people/editor/PhabricatorUserEditor.php
index fa889f1223..21724b6e08 100644
--- a/src/applications/people/editor/PhabricatorUserEditor.php
+++ b/src/applications/people/editor/PhabricatorUserEditor.php
@@ -1,519 +1,578 @@
<?php
/**
* Editor class for creating and adjusting users. This class guarantees data
* integrity and writes logs when user information changes.
*
* @task config Configuration
* @task edit Creating and Editing Users
* @task role Editing Roles
* @task email Adding, Removing and Changing Email
* @task internal Internals
*/
final class PhabricatorUserEditor extends PhabricatorEditor {
private $logs = array();
/* -( Creating and Editing Users )----------------------------------------- */
/**
* @task edit
*/
public function createNewUser(
PhabricatorUser $user,
PhabricatorUserEmail $email) {
if ($user->getID()) {
throw new Exception("User has already been created!");
}
if ($email->getID()) {
throw new Exception("Email has already been created!");
}
if (!PhabricatorUser::validateUsername($user->getUsername())) {
$valid = PhabricatorUser::describeValidUsername();
throw new Exception("Username is invalid! {$valid}");
}
// Always set a new user's email address to primary.
$email->setIsPrimary(1);
// If the primary address is already verified, also set the verified flag
// on the user themselves.
if ($email->getIsVerified()) {
$user->setIsEmailVerified(1);
}
$this->willAddEmail($email);
$user->openTransaction();
try {
$user->save();
$email->setUserPHID($user->getPHID());
$email->save();
} catch (AphrontQueryDuplicateKeyException $ex) {
// We might have written the user but failed to write the email; if
// so, erase the IDs we attached.
$user->setID(null);
$user->setPHID(null);
$user->killTransaction();
throw $ex;
}
$log = PhabricatorUserLog::initializeNewLog(
$this->requireActor(),
$user->getPHID(),
PhabricatorUserLog::ACTION_CREATE);
$log->setNewValue($email->getAddress());
$log->save();
$user->saveTransaction();
return $this;
}
/**
* @task edit
*/
public function updateUser(
PhabricatorUser $user,
PhabricatorUserEmail $email = null) {
if (!$user->getID()) {
throw new Exception("User has not been created yet!");
}
$user->openTransaction();
$user->save();
if ($email) {
$email->save();
}
$log = PhabricatorUserLog::initializeNewLog(
$this->requireActor(),
$user->getPHID(),
PhabricatorUserLog::ACTION_EDIT);
$log->save();
$user->saveTransaction();
return $this;
}
/**
* @task edit
*/
public function changePassword(
PhabricatorUser $user,
PhutilOpaqueEnvelope $envelope) {
if (!$user->getID()) {
throw new Exception("User has not been created yet!");
}
$user->openTransaction();
$user->reload();
$user->setPassword($envelope);
$user->save();
$log = PhabricatorUserLog::initializeNewLog(
$this->requireActor(),
$user->getPHID(),
PhabricatorUserLog::ACTION_CHANGE_PASSWORD);
$log->save();
$user->saveTransaction();
}
/**
* @task edit
*/
public function changeUsername(PhabricatorUser $user, $username) {
$actor = $this->requireActor();
if (!$user->getID()) {
throw new Exception("User has not been created yet!");
}
if (!PhabricatorUser::validateUsername($username)) {
$valid = PhabricatorUser::describeValidUsername();
throw new Exception("Username is invalid! {$valid}");
}
$old_username = $user->getUsername();
$user->openTransaction();
$user->reload();
$user->setUsername($username);
try {
$user->save();
} catch (AphrontQueryDuplicateKeyException $ex) {
$user->setUsername($old_username);
$user->killTransaction();
throw $ex;
}
$log = PhabricatorUserLog::initializeNewLog(
$actor,
$user->getPHID(),
PhabricatorUserLog::ACTION_CHANGE_USERNAME);
$log->setOldValue($old_username);
$log->setNewValue($username);
$log->save();
$user->saveTransaction();
$user->sendUsernameChangeEmail($actor, $old_username);
}
/* -( Editing Roles )------------------------------------------------------ */
/**
* @task role
*/
public function makeAdminUser(PhabricatorUser $user, $admin) {
$actor = $this->requireActor();
if (!$user->getID()) {
throw new Exception("User has not been created yet!");
}
$user->openTransaction();
$user->beginWriteLocking();
$user->reload();
if ($user->getIsAdmin() == $admin) {
$user->endWriteLocking();
$user->killTransaction();
return $this;
}
$log = PhabricatorUserLog::initializeNewLog(
$actor,
$user->getPHID(),
PhabricatorUserLog::ACTION_ADMIN);
$log->setOldValue($user->getIsAdmin());
$log->setNewValue($admin);
$user->setIsAdmin((int)$admin);
$user->save();
$log->save();
$user->endWriteLocking();
$user->saveTransaction();
return $this;
}
/**
* @task role
*/
public function makeSystemAgentUser(PhabricatorUser $user, $system_agent) {
$actor = $this->requireActor();
if (!$user->getID()) {
throw new Exception("User has not been created yet!");
}
$user->openTransaction();
$user->beginWriteLocking();
$user->reload();
if ($user->getIsSystemAgent() == $system_agent) {
$user->endWriteLocking();
$user->killTransaction();
return $this;
}
$log = PhabricatorUserLog::initializeNewLog(
$actor,
$user->getPHID(),
PhabricatorUserLog::ACTION_SYSTEM_AGENT);
$log->setOldValue($user->getIsSystemAgent());
$log->setNewValue($system_agent);
$user->setIsSystemAgent((int)$system_agent);
$user->save();
$log->save();
$user->endWriteLocking();
$user->saveTransaction();
return $this;
}
/**
* @task role
*/
public function disableUser(PhabricatorUser $user, $disable) {
$actor = $this->requireActor();
if (!$user->getID()) {
throw new Exception("User has not been created yet!");
}
$user->openTransaction();
$user->beginWriteLocking();
$user->reload();
if ($user->getIsDisabled() == $disable) {
$user->endWriteLocking();
$user->killTransaction();
return $this;
}
$log = PhabricatorUserLog::initializeNewLog(
$actor,
$user->getPHID(),
PhabricatorUserLog::ACTION_DISABLE);
$log->setOldValue($user->getIsDisabled());
$log->setNewValue($disable);
$user->setIsDisabled((int)$disable);
$user->save();
$log->save();
$user->endWriteLocking();
$user->saveTransaction();
return $this;
}
/**
* @task role
*/
public function approveUser(PhabricatorUser $user, $approve) {
$actor = $this->requireActor();
if (!$user->getID()) {
throw new Exception("User has not been created yet!");
}
$user->openTransaction();
$user->beginWriteLocking();
$user->reload();
if ($user->getIsApproved() == $approve) {
$user->endWriteLocking();
$user->killTransaction();
return $this;
}
$log = PhabricatorUserLog::initializeNewLog(
$actor,
$user->getPHID(),
PhabricatorUserLog::ACTION_APPROVE);
$log->setOldValue($user->getIsApproved());
$log->setNewValue($approve);
$user->setIsApproved($approve);
$user->save();
$log->save();
$user->endWriteLocking();
$user->saveTransaction();
return $this;
}
/* -( Adding, Removing and Changing Email )-------------------------------- */
/**
* @task email
*/
public function addEmail(
PhabricatorUser $user,
PhabricatorUserEmail $email) {
$actor = $this->requireActor();
if (!$user->getID()) {
throw new Exception("User has not been created yet!");
}
if ($email->getID()) {
throw new Exception("Email has already been created!");
}
// Use changePrimaryEmail() to change primary email.
$email->setIsPrimary(0);
$email->setUserPHID($user->getPHID());
$this->willAddEmail($email);
$user->openTransaction();
$user->beginWriteLocking();
$user->reload();
try {
$email->save();
} catch (AphrontQueryDuplicateKeyException $ex) {
$user->endWriteLocking();
$user->killTransaction();
throw $ex;
}
$log = PhabricatorUserLog::initializeNewLog(
$actor,
$user->getPHID(),
PhabricatorUserLog::ACTION_EMAIL_ADD);
$log->setNewValue($email->getAddress());
$log->save();
$user->endWriteLocking();
$user->saveTransaction();
return $this;
}
/**
* @task email
*/
public function removeEmail(
PhabricatorUser $user,
PhabricatorUserEmail $email) {
$actor = $this->requireActor();
if (!$user->getID()) {
throw new Exception("User has not been created yet!");
}
if (!$email->getID()) {
throw new Exception("Email has not been created yet!");
}
$user->openTransaction();
$user->beginWriteLocking();
$user->reload();
$email->reload();
if ($email->getIsPrimary()) {
throw new Exception("Can't remove primary email!");
}
if ($email->getUserPHID() != $user->getPHID()) {
throw new Exception("Email not owned by user!");
}
$email->delete();
$log = PhabricatorUserLog::initializeNewLog(
$actor,
$user->getPHID(),
PhabricatorUserLog::ACTION_EMAIL_REMOVE);
$log->setOldValue($email->getAddress());
$log->save();
$user->endWriteLocking();
$user->saveTransaction();
return $this;
}
/**
* @task email
*/
public function changePrimaryEmail(
PhabricatorUser $user,
PhabricatorUserEmail $email) {
$actor = $this->requireActor();
if (!$user->getID()) {
throw new Exception("User has not been created yet!");
}
if (!$email->getID()) {
throw new Exception("Email has not been created yet!");
}
$user->openTransaction();
$user->beginWriteLocking();
$user->reload();
$email->reload();
if ($email->getUserPHID() != $user->getPHID()) {
throw new Exception("User does not own email!");
}
if ($email->getIsPrimary()) {
throw new Exception("Email is already primary!");
}
if (!$email->getIsVerified()) {
throw new Exception("Email is not verified!");
}
$old_primary = $user->loadPrimaryEmail();
if ($old_primary) {
$old_primary->setIsPrimary(0);
$old_primary->save();
}
$email->setIsPrimary(1);
$email->save();
$log = PhabricatorUserLog::initializeNewLog(
$actor,
$user->getPHID(),
PhabricatorUserLog::ACTION_EMAIL_PRIMARY);
$log->setOldValue($old_primary ? $old_primary->getAddress() : null);
$log->setNewValue($email->getAddress());
$log->save();
$user->endWriteLocking();
$user->saveTransaction();
if ($old_primary) {
$old_primary->sendOldPrimaryEmail($user, $email);
}
$email->sendNewPrimaryEmail($user);
return $this;
}
+ /**
+ * Verify a user's email address.
+ *
+ * This verifies an individual email address. If the address is the user's
+ * primary address and their account was not previously verified, their
+ * account is marked as email verified.
+ *
+ * @task email
+ */
+ public function verifyEmail(
+ PhabricatorUser $user,
+ PhabricatorUserEmail $email) {
+ $actor = $this->requireActor();
+
+ if (!$user->getID()) {
+ throw new Exception('User has not been created yet!');
+ }
+ if (!$email->getID()) {
+ throw new Exception('Email has not been created yet!');
+ }
+
+ $user->openTransaction();
+ $user->beginWriteLocking();
+
+ $user->reload();
+ $email->reload();
+
+ if ($email->getUserPHID() != $user->getPHID()) {
+ throw new Exception(pht('User does not own email!'));
+ }
+
+ if (!$email->getIsVerified()) {
+ $email->setIsVerified(1);
+ $email->save();
+
+ $log = PhabricatorUserLog::initializeNewLog(
+ $actor,
+ $user->getPHID(),
+ PhabricatorUserLog::ACTION_EMAIL_VERIFY);
+ $log->setNewValue($email->getAddress());
+ $log->save();
+ }
+
+ if (!$user->getIsEmailVerified()) {
+ // If the user just verified their primary email address, mark their
+ // account as email verified.
+ $user_primary = $user->loadPrimaryEmail();
+ if ($user_primary->getID() == $email->getID()) {
+ $user->setIsEmailVerified(1);
+ $user->save();
+ }
+ }
+
+ $user->endWriteLocking();
+ $user->saveTransaction();
+
+ }
+
+
/* -( Internals )---------------------------------------------------------- */
/**
* @task internal
*/
private function willAddEmail(PhabricatorUserEmail $email) {
// Hard check before write to prevent creation of disallowed email
// addresses. Normally, the application does checks and raises more
// user friendly errors for us, but we omit the courtesy checks on some
// pathways like administrative scripts for simplicity.
if (!PhabricatorUserEmail::isValidAddress($email->getAddress())) {
throw new Exception(PhabricatorUserEmail::describeValidAddresses());
}
if (!PhabricatorUserEmail::isAllowedAddress($email->getAddress())) {
throw new Exception(PhabricatorUserEmail::describeAllowedAddresses());
}
}
}
diff --git a/src/applications/people/storage/PhabricatorUserLog.php b/src/applications/people/storage/PhabricatorUserLog.php
index 5a0dfdfc39..4dcc888880 100644
--- a/src/applications/people/storage/PhabricatorUserLog.php
+++ b/src/applications/people/storage/PhabricatorUserLog.php
@@ -1,178 +1,180 @@
<?php
final class PhabricatorUserLog extends PhabricatorUserDAO
implements PhabricatorPolicyInterface {
const ACTION_LOGIN = 'login';
const ACTION_LOGIN_PARTIAL = 'login-partial';
const ACTION_LOGIN_FULL = 'login-full';
const ACTION_LOGOUT = 'logout';
const ACTION_LOGIN_FAILURE = 'login-fail';
const ACTION_RESET_PASSWORD = 'reset-pass';
const ACTION_CREATE = 'create';
const ACTION_EDIT = 'edit';
const ACTION_ADMIN = 'admin';
const ACTION_SYSTEM_AGENT = 'system-agent';
const ACTION_DISABLE = 'disable';
const ACTION_APPROVE = 'approve';
const ACTION_DELETE = 'delete';
const ACTION_CONDUIT_CERTIFICATE = 'conduit-cert';
const ACTION_CONDUIT_CERTIFICATE_FAILURE = 'conduit-cert-fail';
const ACTION_EMAIL_PRIMARY = 'email-primary';
const ACTION_EMAIL_REMOVE = 'email-remove';
const ACTION_EMAIL_ADD = 'email-add';
+ const ACTION_EMAIL_VERIFY = 'email-verify';
const ACTION_CHANGE_PASSWORD = 'change-password';
const ACTION_CHANGE_USERNAME = 'change-username';
const ACTION_ENTER_HISEC = 'hisec-enter';
const ACTION_EXIT_HISEC = 'hisec-exit';
const ACTION_FAIL_HISEC = 'hisec-fail';
const ACTION_MULTI_ADD = 'multi-add';
const ACTION_MULTI_REMOVE = 'multi-remove';
protected $actorPHID;
protected $userPHID;
protected $action;
protected $oldValue;
protected $newValue;
protected $details = array();
protected $remoteAddr;
protected $session;
public static function getActionTypeMap() {
return array(
self::ACTION_LOGIN => pht('Login'),
self::ACTION_LOGIN_PARTIAL => pht('Login: Partial Login'),
self::ACTION_LOGIN_FULL => pht('Login: Upgrade to Full'),
self::ACTION_LOGIN_FAILURE => pht('Login: Failure'),
self::ACTION_LOGOUT => pht('Logout'),
self::ACTION_RESET_PASSWORD => pht('Reset Password'),
self::ACTION_CREATE => pht('Create Account'),
self::ACTION_EDIT => pht('Edit Account'),
self::ACTION_ADMIN => pht('Add/Remove Administrator'),
self::ACTION_SYSTEM_AGENT => pht('Add/Remove System Agent'),
self::ACTION_DISABLE => pht('Enable/Disable'),
self::ACTION_APPROVE => pht('Approve Registration'),
self::ACTION_DELETE => pht('Delete User'),
self::ACTION_CONDUIT_CERTIFICATE
=> pht('Conduit: Read Certificate'),
self::ACTION_CONDUIT_CERTIFICATE_FAILURE
=> pht('Conduit: Read Certificate Failure'),
self::ACTION_EMAIL_PRIMARY => pht('Email: Change Primary'),
self::ACTION_EMAIL_ADD => pht('Email: Add Address'),
self::ACTION_EMAIL_REMOVE => pht('Email: Remove Address'),
+ self::ACTION_EMAIL_VERIFY => pht('Email: Verify'),
self::ACTION_CHANGE_PASSWORD => pht('Change Password'),
self::ACTION_CHANGE_USERNAME => pht('Change Username'),
self::ACTION_ENTER_HISEC => pht('Hisec: Enter'),
self::ACTION_EXIT_HISEC => pht('Hisec: Exit'),
self::ACTION_FAIL_HISEC => pht('Hisec: Failed Attempt'),
self::ACTION_MULTI_ADD => pht('Multi-Factor: Add Factor'),
self::ACTION_MULTI_REMOVE => pht('Multi-Factor: Remove Factor'),
);
}
public static function initializeNewLog(
PhabricatorUser $actor = null,
$object_phid,
$action) {
$log = new PhabricatorUserLog();
if ($actor) {
$log->setActorPHID($actor->getPHID());
if ($actor->hasSession()) {
$session = $actor->getSession();
// NOTE: This is a hash of the real session value, so it's safe to
// store it directly in the logs.
$log->setSession($session->getSessionKey());
}
}
$log->setUserPHID((string)$object_phid);
$log->setAction($action);
$log->remoteAddr = idx($_SERVER, 'REMOTE_ADDR', '');
return $log;
}
public static function loadRecentEventsFromThisIP($action, $timespan) {
return id(new PhabricatorUserLog())->loadAllWhere(
'action = %s AND remoteAddr = %s AND dateCreated > %d
ORDER BY dateCreated DESC',
$action,
idx($_SERVER, 'REMOTE_ADDR'),
time() - $timespan);
}
public function save() {
$this->details['host'] = php_uname('n');
$this->details['user_agent'] = AphrontRequest::getHTTPHeader('User-Agent');
return parent::save();
}
public function getConfiguration() {
return array(
self::CONFIG_SERIALIZATION => array(
'oldValue' => self::SERIALIZATION_JSON,
'newValue' => self::SERIALIZATION_JSON,
'details' => self::SERIALIZATION_JSON,
),
) + parent::getConfiguration();
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return PhabricatorPolicies::POLICY_NOONE;
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
if ($viewer->getIsAdmin()) {
return true;
}
$viewer_phid = $viewer->getPHID();
if ($viewer_phid) {
$user_phid = $this->getUserPHID();
if ($viewer_phid == $user_phid) {
return true;
}
$actor_phid = $this->getActorPHID();
if ($viewer_phid == $actor_phid) {
return true;
}
}
return false;
}
public function describeAutomaticCapability($capability) {
return array(
pht('Users can view their activity and activity that affects them.'),
pht('Administrators can always view all activity.'),
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Jan 19 2025, 21:15 (6 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1128839
Default Alt Text
(31 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment