mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-25 16:22:43 +01:00
Fix an error when users receive notifications about objects they can no longer see
Summary: Ref T13623. The change in D21577 could lead to a case where we try to access stories the user can't see. Move the story-loading piece to "willFilterPage()" to make our way thorugh this. Test Plan: - Made FeedStory return nothing to simulate invisible notifications, loaded page. - Before: index access fatal. - After: clean "no notifications". - Loaded notifications normally, saw normal notifications. Maniphest Tasks: T13623 Differential Revision: https://secure.phabricator.com/D21603
This commit is contained in:
parent
4cff4dc68b
commit
0815891e42
1 changed files with 39 additions and 24 deletions
|
@ -63,25 +63,7 @@ final class PhabricatorNotificationQuery
|
||||||
$this->buildWhereClause($conn),
|
$this->buildWhereClause($conn),
|
||||||
$this->buildLimitClause($conn));
|
$this->buildLimitClause($conn));
|
||||||
|
|
||||||
// See T13623. Although most queries for notifications return unique
|
return $data;
|
||||||
// stories, this isn't a guarantee.
|
|
||||||
$story_map = ipull($data, null, 'chronologicalKey');
|
|
||||||
|
|
||||||
$stories = PhabricatorFeedStory::loadAllFromRows(
|
|
||||||
$story_map,
|
|
||||||
$this->getViewer());
|
|
||||||
$stories = mpull($stories, null, 'getChronologicalKey');
|
|
||||||
|
|
||||||
$results = array();
|
|
||||||
foreach ($data as $row) {
|
|
||||||
$story_key = $row['chronologicalKey'];
|
|
||||||
$has_viewed = $row['hasViewed'];
|
|
||||||
|
|
||||||
$results[] = id(clone $stories[$story_key])
|
|
||||||
->setHasViewed($has_viewed);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||||
|
@ -111,14 +93,47 @@ final class PhabricatorNotificationQuery
|
||||||
return $where;
|
return $where;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function willFilterPage(array $stories) {
|
protected function willFilterPage(array $rows) {
|
||||||
foreach ($stories as $key => $story) {
|
// See T13623. The policy model here is outdated and awkward.
|
||||||
if (!$story->isVisibleInNotifications()) {
|
|
||||||
unset($stories[$key]);
|
// Users may have notifications about objects they can no longer see.
|
||||||
|
// Two ways this can arise: destroy an object; or change an object's
|
||||||
|
// view policy to exclude a user.
|
||||||
|
|
||||||
|
// "PhabricatorFeedStory::loadAllFromRows()" does its own policy filtering.
|
||||||
|
// This doesn't align well with modern query sequencing, but we should be
|
||||||
|
// able to get away with it by loading here.
|
||||||
|
|
||||||
|
// See T13623. Although most queries for notifications return unique
|
||||||
|
// stories, this isn't a guarantee.
|
||||||
|
$story_map = ipull($rows, null, 'chronologicalKey');
|
||||||
|
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$stories = PhabricatorFeedStory::loadAllFromRows($story_map, $viewer);
|
||||||
|
$stories = mpull($stories, null, 'getChronologicalKey');
|
||||||
|
|
||||||
|
$results = array();
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$story_key = $row['chronologicalKey'];
|
||||||
|
$has_viewed = $row['hasViewed'];
|
||||||
|
|
||||||
|
if (!isset($stories[$story_key])) {
|
||||||
|
// NOTE: We can't call "didRejectResult()" here because we don't have
|
||||||
|
// a policy object to pass.
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$story = id(clone $stories[$story_key])
|
||||||
|
->setHasViewed($has_viewed);
|
||||||
|
|
||||||
|
if (!$story->isVisibleInNotifications()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$results[] = $story;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $stories;
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getDefaultOrderVector() {
|
protected function getDefaultOrderVector() {
|
||||||
|
|
Loading…
Reference in a new issue