Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Phabricator Update #2

Merged
merged 30 commits into from
Jan 29, 2020
Merged
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2adc36b
Correctly identify more SSH private key problems as "formatting" or "…
Nov 9, 2019
e86aae9
Surface edits to "Text" panels on dashboards as remarkup edits
Nov 13, 2019
1996b0c
Update the "owner can always view/edit" policy exception rule
Nov 19, 2019
de66a8e
Remove "stronger/weaker" policy color hints from object headers
Nov 19, 2019
959504a
When predicting object policies for project milestones, adjust object…
Nov 19, 2019
d58eddc
When predicting project membership during edits, predict milestones w…
Nov 19, 2019
df0f5c6
Make repository identity email address association case-insensitive
Nov 14, 2019
a2b2c39
Distinguish between "Assigned" and "Effective" identity PHIDs more cl…
Nov 14, 2019
6afbb61
Remove "PhabricatorEventType::TYPE_DIFFUSION_LOOKUPUSER" event
Nov 14, 2019
0014d04
Consolidate repository identity resolution and detection code
Nov 14, 2019
18da346
Add additional flags to "bin/repository rebuild-identities" to improv…
Nov 14, 2019
d69a736
Use DestructionEngine to destroy UserEmail objects
Nov 14, 2019
89dcf97
Give "PhabricatorUserEmail" a PHID
Nov 14, 2019
a7aca50
Update repository identities after all mutations to users and email a…
Nov 14, 2019
63d84e0
Improve use of keys when iterating over commits in "bin/audit delete"…
Nov 19, 2019
374f8b1
Add a "--dry-run" flag to "bin/repository rebuild-identities"
Nov 19, 2019
2abf292
Fix an issue where editing paths in Owners packages could raise an er…
Nov 21, 2019
eb6df7a
Remove "phlog()" of exeptions during Conduit calls
Nov 22, 2019
1667acf
Implement "PolicyInterface" on "UserEmail" so "EmailQuery" can load t…
Nov 25, 2019
33c534f
Extend Config to full-width
Nov 25, 2019
4cd333b
Use same method to get object URI as used in DifferentialTransactionE…
Dec 9, 2019
54bcbda
Fix an XSS issue with certain high-priority remarkup rules embedded i…
Dec 13, 2019
767528c
Move search query parser/compiler classes to Phabricator
Jan 14, 2020
db6b4ca
Update deprecated array access syntax in Porter stemmer
Jan 14, 2020
138ba87
Guard call to "get_magic_quotes_gpc()" with "@" to silence PHP 7.4+ w…
Jan 14, 2020
f806528
Allow the Herald Rule Editor to apply generic "Edge" transactions
Jan 15, 2020
d0b01a4
Fix two issues with missing whitespace when elements stack on top of …
Jan 15, 2020
6ccb6a6
Update "git rev-parse" invocation to work in Git 2.25.0
Jan 16, 2020
6c45000
Add "Project tags added" and "Project tags removed" fields in Herald
Jan 21, 2020
b38449c
Implement an "Author's packages" Herald field for Differential
Jan 21, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update repository identities after all mutations to users and email a…
…ddresses

Summary:
Ref T13444. Currently, many mutations to users and email addresses (particularly: user creation; and user and address destruction) do not propagate properly to repository identities.

Add hooks to all mutation workflows so repository identities get rebuilt properly when users are created, email addresses are removed, users or email addresses are destroyed, or email addresses are reassigned.

Test Plan:
- Added random email address to account, removed it.
- Added unassociated email address to account, saw identity update (and associate).
  - Removed it, saw identity update (and disassociate).
- Registered an account with an unassociated email address, saw identity update (and associate).
  - Destroyed the account, saw identity update (and disassociate).
- Added address X to account A, unverified.
  - Invited address X.
  - Clicked invite link as account B.
  - Confirmed desire to steal address.
  - Saw identity update and reassociate.

Maniphest Tasks: T13444

Differential Revision: https://secure.phabricator.com/D20914
  • Loading branch information
epriestley committed Nov 19, 2019
commit a7aca500bcd1b46eeafd47bd21d07bc7b70746db
2 changes: 2 additions & 0 deletions src/__phutil_library_map__.php
Original file line number Diff line number Diff line change
@@ -984,6 +984,7 @@
'DiffusionRepositoryEditUpdateController' => 'applications/diffusion/controller/DiffusionRepositoryEditUpdateController.php',
'DiffusionRepositoryFunctionDatasource' => 'applications/diffusion/typeahead/DiffusionRepositoryFunctionDatasource.php',
'DiffusionRepositoryHistoryManagementPanel' => 'applications/diffusion/management/DiffusionRepositoryHistoryManagementPanel.php',
'DiffusionRepositoryIdentityDestructionEngineExtension' => 'applications/diffusion/identity/DiffusionRepositoryIdentityDestructionEngineExtension.php',
'DiffusionRepositoryIdentityEditor' => 'applications/diffusion/editor/DiffusionRepositoryIdentityEditor.php',
'DiffusionRepositoryIdentityEngine' => 'applications/diffusion/identity/DiffusionRepositoryIdentityEngine.php',
'DiffusionRepositoryIdentitySearchEngine' => 'applications/diffusion/query/DiffusionRepositoryIdentitySearchEngine.php',
@@ -6968,6 +6969,7 @@
'DiffusionRepositoryEditUpdateController' => 'DiffusionRepositoryManageController',
'DiffusionRepositoryFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'DiffusionRepositoryHistoryManagementPanel' => 'DiffusionRepositoryManagementPanel',
'DiffusionRepositoryIdentityDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension',
'DiffusionRepositoryIdentityEditor' => 'PhabricatorApplicationTransactionEditor',
'DiffusionRepositoryIdentityEngine' => 'Phobject',
'DiffusionRepositoryIdentitySearchEngine' => 'PhabricatorApplicationSearchEngine',
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

final class DiffusionRepositoryIdentityDestructionEngineExtension
extends PhabricatorDestructionEngineExtension {

const EXTENSIONKEY = 'repository-identities';

public function getExtensionName() {
return pht('Repository Identities');
}

public function didDestroyObject(
PhabricatorDestructionEngine $engine,
$object) {

// When users or email addresses are destroyed, queue a task to update
// any repository identities that are associated with them. See T13444.

$related_phids = array();
$email_addresses = array();

if ($object instanceof PhabricatorUser) {
$related_phids[] = $object->getPHID();
}

if ($object instanceof PhabricatorUserEmail) {
$email_addresses[] = $object->getAddress();
}

if ($related_phids || $email_addresses) {
PhabricatorWorker::scheduleTask(
'PhabricatorRepositoryIdentityChangeWorker',
array(
'relatedPHIDs' => $related_phids,
'emailAddresses' => $email_addresses,
));
}
}

}
Original file line number Diff line number Diff line change
@@ -95,4 +95,12 @@ private function updateIdentity(PhabricatorRepositoryIdentity $identity) {
return $identity;
}

public function didUpdateEmailAddress($raw_address) {
PhabricatorWorker::scheduleTask(
'PhabricatorRepositoryIdentityChangeWorker',
array(
'emailAddresses' => array($raw_address),
));
}

}
18 changes: 11 additions & 7 deletions src/applications/people/editor/PhabricatorUserEditor.php
Original file line number Diff line number Diff line change
@@ -89,6 +89,9 @@ public function createNewUser(
$this->didVerifyEmail($user, $email);
}

id(new DiffusionRepositoryIdentityEngine())
->didUpdateEmailAddress($email->getAddress());

return $this;
}

@@ -202,11 +205,8 @@ public function addEmail(
$user->endWriteLocking();
$user->saveTransaction();

// Try and match this new address against unclaimed `RepositoryIdentity`s
PhabricatorWorker::scheduleTask(
'PhabricatorRepositoryIdentityChangeWorker',
array('userPHID' => $user->getPHID()),
array('objectPHID' => $user->getPHID()));
id(new DiffusionRepositoryIdentityEngine())
->didUpdateEmailAddress($email->getAddress());

return $this;
}
@@ -241,7 +241,8 @@ public function removeEmail(
throw new Exception(pht('Email not owned by user!'));
}

id(new PhabricatorDestructionEngine())
$destruction_engine = id(new PhabricatorDestructionEngine())
->setWaitToFinalizeDestruction(true)
->destroyObject($email);

$log = PhabricatorUserLog::initializeNewLog(
@@ -255,6 +256,7 @@ public function removeEmail(
$user->saveTransaction();

$this->revokePasswordResetLinks($user);
$destruction_engine->finalizeDestruction();

return $this;
}
@@ -327,7 +329,6 @@ public function changePrimaryEmail(
}
$email->sendNewPrimaryEmail($user);


$this->revokePasswordResetLinks($user);

return $this;
@@ -441,6 +442,9 @@ public function reassignEmail(

$user->endWriteLocking();
$user->saveTransaction();

id(new DiffusionRepositoryIdentityEngine())
->didUpdateEmailAddress($email->getAddress());
}


Original file line number Diff line number Diff line change
@@ -6,30 +6,54 @@ final class PhabricatorRepositoryIdentityChangeWorker
protected function doWork() {
$viewer = PhabricatorUser::getOmnipotentUser();

$task_data = $this->getTaskData();
$user_phid = idx($task_data, 'userPHID');
$related_phids = $this->getTaskDataValue('relatedPHIDs');
$email_addresses = $this->getTaskDataValue('emailAddresses');

// Retain backward compatibility with older tasks which may still be in
// queue. Previously, this worker accepted a single "userPHID". See
// T13444. This can be removed in some future version of Phabricator once
// these tasks have likely flushed out of queue.
$legacy_phid = $this->getTaskDataValue('userPHID');
if ($legacy_phid) {
if (!is_array($related_phids)) {
$related_phids = array();
}
$related_phids[] = $legacy_phid;
}

$user = id(new PhabricatorPeopleQuery())
->withPHIDs(array($user_phid))
->setViewer($viewer)
->executeOne();
// Note that we may arrive in this worker after the associated objects
// have already been destroyed, so we can't (and shouldn't) verify that
// PHIDs correspond to real objects. If you "bin/remove destroy" a user,
// we'll end up here with a now-bogus user PHID that we should
// disassociate from identities.

$emails = id(new PhabricatorUserEmail())->loadAllWhere(
'userPHID = %s',
$user->getPHID());
$identity_map = array();

$identity_engine = id(new DiffusionRepositoryIdentityEngine())
->setViewer($viewer);
if ($related_phids) {
$identities = id(new PhabricatorRepositoryIdentityQuery())
->setViewer($viewer)
->withRelatedPHIDs($related_phids)
->execute();
$identity_map += mpull($identities, null, 'getPHID');
}

foreach ($emails as $email) {
if ($email_addresses) {
$identities = id(new PhabricatorRepositoryIdentityQuery())
->setViewer($viewer)
->withEmailAddresses(array($email->getAddress()))
->withEmailAddresses($email_addresses)
->execute();
$identity_map += mpull($identities, null, 'getPHID');
}

foreach ($identities as $identity) {
$identity_engine->newUpdatedIdentity($identity);
}
// If we didn't find any related identities, we're all set.
if (!$identity_map) {
return;
}

$identity_engine = id(new DiffusionRepositoryIdentityEngine())
->setViewer($viewer);
foreach ($identity_map as $identity) {
$identity_engine->newUpdatedIdentity($identity);
}
}

51 changes: 50 additions & 1 deletion src/applications/system/engine/PhabricatorDestructionEngine.php
Original file line number Diff line number Diff line change
@@ -5,6 +5,9 @@ final class PhabricatorDestructionEngine extends Phobject {
private $rootLogID;
private $collectNotes;
private $notes = array();
private $depth = 0;
private $destroyedObjects = array();
private $waitToFinalizeDestruction = false;

public function setCollectNotes($collect_notes) {
$this->collectNotes = $collect_notes;
@@ -19,9 +22,20 @@ public function getViewer() {
return PhabricatorUser::getOmnipotentUser();
}

public function setWaitToFinalizeDestruction($wait) {
$this->waitToFinalizeDestruction = $wait;
return $this;
}

public function getWaitToFinalizeDestruction() {
return $this->waitToFinalizeDestruction;
}

public function destroyObject(PhabricatorDestructibleInterface $object) {
$this->depth++;

$log = id(new PhabricatorSystemDestructionLog())
->setEpoch(time())
->setEpoch(PhabricatorTime::getNow())
->setObjectClass(get_class($object));

if ($this->rootLogID) {
@@ -73,7 +87,42 @@ public function destroyObject(PhabricatorDestructibleInterface $object) {
foreach ($extensions as $key => $extension) {
$extension->destroyObject($this, $object);
}

$this->destroyedObjects[] = $object;
}

$this->depth--;

// If this is a root-level invocation of "destroyObject()", flush the
// queue of destroyed objects and fire "didDestroyObject()" hooks. This
// hook allows extensions to do things like queue cache updates which
// might race if we fire them during object destruction.

if (!$this->depth) {
if (!$this->getWaitToFinalizeDestruction()) {
$this->finalizeDestruction();
}
}

return $this;
}

public function finalizeDestruction() {
$extensions = PhabricatorDestructionEngineExtension::getAllExtensions();

foreach ($this->destroyedObjects as $object) {
foreach ($extensions as $extension) {
if (!$extension->canDestroyObject($this, $object)) {
continue;
}

$extension->didDestroyObject($this, $object);
}
}

$this->destroyedObjects = array();

return $this;
}

private function getObjectPHID($object) {
Original file line number Diff line number Diff line change
@@ -14,9 +14,17 @@ public function canDestroyObject(
return true;
}

abstract public function destroyObject(
public function destroyObject(
PhabricatorDestructionEngine $engine,
$object);
$object) {
return null;
}

public function didDestroyObject(
PhabricatorDestructionEngine $engine,
$object) {
return null;
}

final public static function getAllExtensions() {
return id(new PhutilClassMapQuery())