Page MenuHomePhabricator

D9199.id21861.diff
No OneTemporary

D9199.id21861.diff

diff --git a/src/applications/phriction/controller/PhrictionDocumentController.php b/src/applications/phriction/controller/PhrictionDocumentController.php
--- a/src/applications/phriction/controller/PhrictionDocumentController.php
+++ b/src/applications/phriction/controller/PhrictionDocumentController.php
@@ -1,8 +1,5 @@
<?php
-/**
- * @group phriction
- */
final class PhrictionDocumentController
extends PhrictionController {
@@ -118,7 +115,7 @@
$new_doc = id(new PhrictionDocumentQuery())
->setViewer($user)
->withIDs(array($new_doc_id))
- ->exectueOne();
+ ->executeOne();
$slug_uri = PhrictionDocument::getSlugURI($new_doc->getSlug());
diff --git a/src/applications/phriction/phid/PhrictionPHIDTypeDocument.php b/src/applications/phriction/phid/PhrictionPHIDTypeDocument.php
--- a/src/applications/phriction/phid/PhrictionPHIDTypeDocument.php
+++ b/src/applications/phriction/phid/PhrictionPHIDTypeDocument.php
@@ -25,8 +25,8 @@
array $phids) {
return id(new PhrictionDocumentQuery())
- ->needContent(true)
- ->withPHIDs($phids);
+ ->withPHIDs($phids)
+ ->needContent(true);
}
public function loadHandles(
diff --git a/src/applications/phriction/query/PhrictionDocumentQuery.php b/src/applications/phriction/query/PhrictionDocumentQuery.php
--- a/src/applications/phriction/query/PhrictionDocumentQuery.php
+++ b/src/applications/phriction/query/PhrictionDocumentQuery.php
@@ -49,21 +49,97 @@
}
protected function loadPage() {
- $document = new PhrictionDocument();
- $conn_r = $document->establishConnection('r');
+ $table = new PhrictionDocument();
+ $conn_r = $table->establishConnection('r');
$rows = queryfx_all(
$conn_r,
'SELECT * FROM %T %Q %Q %Q',
- $document->getTableName(),
+ $table->getTableName(),
$this->buildWhereClause($conn_r),
$this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
- return $document->loadAllFromArray($rows);
+ $documents = $table->loadAllFromArray($rows);
+
+ if ($documents) {
+ $ancestor_slugs = array();
+ foreach ($documents as $key => $document) {
+ $document_slug = $document->getSlug();
+ foreach (PhabricatorSlug::getAncestry($document_slug) as $ancestor) {
+ $ancestor_slugs[$ancestor][] = $key;
+ }
+ }
+
+ if ($ancestor_slugs) {
+ $ancestors = queryfx_all(
+ $conn_r,
+ 'SELECT * FROM %T WHERE slug IN (%Ls)',
+ $document->getTableName(),
+ array_keys($ancestor_slugs));
+ $ancestors = $table->loadAllFromArray($ancestors);
+ $ancestors = mpull($ancestors, null, 'getSlug');
+
+ foreach ($ancestor_slugs as $ancestor_slug => $document_keys) {
+ $ancestor = idx($ancestors, $ancestor_slug);
+ foreach ($document_keys as $document_key) {
+ $documents[$document_key]->attachAncestor(
+ $ancestor_slug,
+ $ancestor);
+ }
+ }
+ }
+ }
+
+ return $documents;
}
protected function willFilterPage(array $documents) {
+ // To view a Phriction document, you must also be able to view all of the
+ // ancestor documents. Filter out documents which have ancestors that are
+ // not visible.
+
+ $document_map = array();
+ foreach ($documents as $document) {
+ $document_map[$document->getSlug()] = $document;
+ foreach ($document->getAncestors() as $key => $ancestor) {
+ if ($ancestor) {
+ $document_map[$key] = $ancestor;
+ }
+ }
+ }
+
+ $filtered_map = $this->applyPolicyFilter(
+ $document_map,
+ array(PhabricatorPolicyCapability::CAN_VIEW));
+
+ // Filter all of the documents where a parent is not visible.
+ foreach ($documents as $document_key => $document) {
+ // If the document itself is not visible, filter it.
+ if (!isset($filtered_map[$document->getSlug()])) {
+ $this->didRejectResult($documents[$document_key]);
+ unset($documents[$document_key]);
+ continue;
+ }
+
+ // If an ancestor exists but is not visible, filter the document.
+ foreach ($document->getAncestors() as $ancestor_key => $ancestor) {
+ if (!$ancestor) {
+ continue;
+ }
+
+ if (!isset($filtered_map[$ancestor_key])) {
+ $this->didRejectResult($documents[$document_key]);
+ unset($documents[$document_key]);
+ break;
+ }
+ }
+ }
+
+ if (!$documents) {
+ return $documents;
+ }
+
if ($this->needContent) {
$contents = id(new PhrictionContent())->loadAllWhere(
'id IN (%Ld)',
diff --git a/src/applications/phriction/storage/PhrictionDocument.php b/src/applications/phriction/storage/PhrictionDocument.php
--- a/src/applications/phriction/storage/PhrictionDocument.php
+++ b/src/applications/phriction/storage/PhrictionDocument.php
@@ -1,8 +1,5 @@
<?php
-/**
- * @group phriction
- */
final class PhrictionDocument extends PhrictionDAO
implements
PhabricatorPolicyInterface,
@@ -16,6 +13,7 @@
protected $status;
private $contentObject = self::ATTACHABLE;
+ private $ancestors = array();
// TODO: This should be `self::ATTACHABLE`, but there are still a lot of call
// sites which load PhrictionDocuments directly.
@@ -84,6 +82,19 @@
return (bool)$this->getProject();
}
+ public function getAncestors() {
+ return $this->ancestors;
+ }
+
+ public function getAncestor($slug) {
+ return $this->assertAttachedKey($this->ancestors, $slug);
+ }
+
+ public function attachAncestor($slug, $ancestor) {
+ $this->ancestors[$slug] = $ancestor;
+ return $this;
+ }
+
public static function isProjectSlug($slug) {
$slug = PhabricatorSlug::normalize($slug);
$prefix = 'projects/';
@@ -119,6 +130,7 @@
if ($this->hasProject()) {
return $this->getProject()->getPolicy($capability);
}
+
return PhabricatorPolicies::POLICY_USER;
}
@@ -134,6 +146,14 @@
return pht(
"This is a project wiki page, and inherits the project's policies.");
}
+
+ switch ($capability) {
+ case PhabricatorPolicyCapability::CAN_VIEW:
+ return pht(
+ 'To view a wiki document, you must also be able to view all '.
+ 'of its parents.');
+ }
+
return null;
}
diff --git a/src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php b/src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php
--- a/src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php
+++ b/src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php
@@ -302,19 +302,32 @@
private function getPolicyFilter() {
$filter = new PhabricatorPolicyFilter();
$filter->setViewer($this->viewer);
- if (!$this->capabilities) {
- $capabilities = array(
- PhabricatorPolicyCapability::CAN_VIEW,
- );
- } else {
- $capabilities = $this->capabilities;
- }
+ $capabilities = $this->getRequiredCapabilities();
$filter->requireCapabilities($capabilities);
$filter->raisePolicyExceptions($this->shouldRaisePolicyExceptions());
return $filter;
}
+ protected function getRequiredCapabilities() {
+ if ($this->capabilities) {
+ return $this->capabilities;
+ }
+
+ return array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ );
+ }
+
+ protected function applyPolicyFilter(array $objects, array $capabilities) {
+ if ($this->shouldDisablePolicyFiltering()) {
+ return $objects;
+ }
+ $filter = $this->getPolicyFilter();
+ $filter->requireCapabilities($capabilities);
+ return $filter->apply($objects);
+ }
+
protected function didRejectResult(PhabricatorPolicyInterface $object) {
$this->getPolicyFilter()->rejectObject(
$object,

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 9, 11:06 AM (1 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6743890
Default Alt Text
D9199.id21861.diff (7 KB)

Event Timeline