Skip to content

Commit

Permalink
fix(subscriptions): post notifications not getting access checked
Browse files Browse the repository at this point in the history
Signed-off-by: Sami Mazouz <[email protected]>
  • Loading branch information
SychO9 committed Jan 10, 2023
1 parent 02556c6 commit e5f0516
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 1 deletion.
4 changes: 3 additions & 1 deletion extensions/subscriptions/extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use Flarum\Post\Event\Restored;
use Flarum\Subscriptions\HideIgnoredFromAllDiscussionsPage;
use Flarum\Subscriptions\Listener;
use Flarum\Subscriptions\Notification\FilterVisiblePostsBeforeSending;
use Flarum\Subscriptions\Notification\NewPostBlueprint;
use Flarum\Subscriptions\Query\SubscriptionFilterGambit;

Expand All @@ -36,7 +37,8 @@
->namespace('flarum-subscriptions', __DIR__.'/views'),

(new Extend\Notification())
->type(NewPostBlueprint::class, BasicDiscussionSerializer::class, ['alert', 'email']),
->type(NewPostBlueprint::class, BasicDiscussionSerializer::class, ['alert', 'email'])
->beforeSending(FilterVisiblePostsBeforeSending::class),

(new Extend\ApiSerializer(DiscussionSerializer::class))
->attribute('subscription', function (DiscussionSerializer $serializer, Discussion $discussion) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Flarum\Subscriptions\Notification;

use Flarum\Notification\Blueprint\BlueprintInterface;

class FilterVisiblePostsBeforeSending
{
public function __invoke(BlueprintInterface $blueprint, array $recipients): array
{
if ($blueprint instanceof NewPostBlueprint) {
$newRecipients = [];

// Flarum has built-in access control for the notification subject,
// but subscriptions post notifications has the discussion as the subject.
// We'll add a post visibility check so that users can't get access to hidden replies by subscribing.
foreach ($recipients as $recipient) {
if ($blueprint->post->isVisibleTo($recipient)) {
$newRecipients[] = $recipient;
}
}

return $newRecipients;
}

return $recipients;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
namespace Flarum\Subscriptions\tests\integration\api\discussions;

use Carbon\Carbon;
use Flarum\Extend\ModelVisibility;
use Flarum\Group\Group;
use Flarum\Post\Post;
use Flarum\Testing\integration\RetrievesAuthorizedUsers;
use Flarum\Testing\integration\TestCase;
use Flarum\User\User;
Expand Down Expand Up @@ -278,4 +280,47 @@ public function approving_reply_sends_reply_notification()

$this->assertEquals(1, $mainUser->getUnreadNotificationCount());
}

/** @test */
public function replying_to_a_discussion_with_a_restricted_post_only_sends_notifications_to_allowed_users()
{
// Add visibility scoper to only allow admin
// to see expected new post with content containing 'restricted-test-post'.
$this->extend(
(new ModelVisibility(Post::class))
->scope(function (User $actor, $query) {
if (! $actor->isAdmin()) {
$query->where('content', 'not like', '%restricted-test-post%');
}
})
);

$this->app();

/** @var User $allowedUser */
$allowedUser = User::query()->find(1);
$normalUser = User::query()->find(2);

$this->assertEquals(0, $allowedUser->getUnreadNotificationCount());
$this->assertEquals(0, $normalUser->getUnreadNotificationCount());

$this->send(
$this->request('POST', '/api/posts', [
'authenticatedAs' => 3,
'json' => [
'data' => [
'attributes' => [
'content' => 'restricted-test-post',
],
'relationships' => [
'discussion' => ['data' => ['id' => 1]],
],
],
],
])
);

$this->assertEquals(1, $allowedUser->getUnreadNotificationCount());
$this->assertEquals(0, $normalUser->getUnreadNotificationCount());
}
}

0 comments on commit e5f0516

Please sign in to comment.