Handle private streams better (failed to show profile before)
authorMikael Nordfeldth <mmn@hethane.se>
Sun, 3 Jan 2016 18:05:49 +0000 (19:05 +0100)
committerMikael Nordfeldth <mmn@hethane.se>
Sun, 3 Jan 2016 18:16:29 +0000 (19:16 +0100)
classes/Profile.php
lib/noticestreamaction.php
lib/privatestreamexception.php [new file with mode: 0644]
lib/profilenoticestream.php

index a45511fe54b60a1a02d87258cb61656e2f9d1010..1c8dbcc2525e14b45c7de055fde0844535f9dfb2 100644 (file)
@@ -761,6 +761,17 @@ class Profile extends Managed_DataObject
         return Subscription::exists($this, $other);
     }
 
+    function readableBy(Profile $other=null)
+    {
+        // If it's not a private stream, it's readable by anyone
+        if (!$this->isPrivateStream()) {
+            return true;
+        }
+
+        // If it's a private stream, $other must be a subscriber to $this
+        return is_null($other) ? false : $other->isSubscribed($this);
+    }
+
     /**
      * Check if a pending subscription request is outstanding for this...
      *
index bf09b637805b94c515debcdb311c2141dac0704c..fb592915a7cd3ac9defdbbc7ba519021b3e04a5a 100644 (file)
@@ -13,8 +13,13 @@ abstract class NoticestreamAction extends ProfileAction
         $this->doStreamPreparation();
 
         // fetch the actual stream stuff
-        $stream = $this->getStream();
-        $this->notice = $stream->getNotices(($this->page-1) * NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
+        try {
+            $stream = $this->getStream();
+            $this->notice = $stream->getNotices(($this->page-1) * NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1);
+        } catch (PrivateStreamException $e) {
+            $this->notice = new Notice();
+            $this->notice->whereAdd('FALSE');
+        }
 
         if ($this->page > 1 && $this->notice->N == 0) {
             // TRANS: Client error when page not found (404).
diff --git a/lib/privatestreamexception.php b/lib/privatestreamexception.php
new file mode 100644 (file)
index 0000000..ed9f3e0
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+/**
+ * An exception for private streams
+ *
+ * @category  Exception
+ * @package   GNUsocial
+ * @author    Mikael Nordfeldth <mmn@hethane.se>
+ * @copyright 2016 Free Software Foundation, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ */
+
+class PrivateStreamException extends AuthorizationException
+{
+    var $owner = null;  // owner of the private stream
+    var $reader = null; // reader, may be null if not logged in
+
+    public function __construct(Profile $owner, Profile $reader=null)
+    {
+        $this->owner = $owner;
+        $this->reader = $reader;
+
+        // TRANS: Message when a private stream attemps to be read by unauthorized third party.
+        $msg = sprintf(_m('This stream is protected and only authorized subscribers may see its contents.'));
+
+        // If $reader is a profile, authentication has been made but still not accepted (403),
+        // otherwise authentication may give access to this resource (401).
+        parent::__construct($msg, ($reader instanceof Profile ? 403 : 401));
+    }
+}
index 1fa795d32090a55866c49f9221757ab7c089fdcb..3c8de05855bb014eeade3f4f7708d137075be186 100644 (file)
@@ -74,7 +74,7 @@ class ProfileNoticeStream extends ScopingNoticeStream
     function getNotices($offset, $limit, $since_id=null, $max_id=null)
     {
         if ($this->impossibleStream()) {
-            return new ArrayWrapper(array());
+            throw new PrivateStreamException($this->streamProfile, $this->userProfile);
         } else {
             return parent::getNotices($offset, $limit, $since_id, $max_id);
         }
@@ -82,12 +82,8 @@ class ProfileNoticeStream extends ScopingNoticeStream
 
     function impossibleStream() 
     {
-        $user = User::getKV('id', $this->streamProfile->id);
-
-        // If it's a private stream, and no user or not a subscriber
-
-        if (!empty($user) && $user->private_stream && 
-            (empty($this->userProfile) || !$this->userProfile->isSubscribed($this->streamProfile))) {
+        if (!$this->streamProfile->readableBy($this->userProfile)) {
+            // cannot read because it's a private stream and either noone's logged in or they are not subscribers
             return true;
         }