mirror of
https://github.com/flarum/framework.git
synced 2024-11-30 21:44:12 +08:00
Perform visibility checks on notification subjects at the query level
This will prevent a notification from being seen by a user if its subject is deleted or undergoes some kind of permission change (eg. a discussion is moved into a private tag) ref #1380
This commit is contained in:
parent
17fdc0ebe0
commit
6d14d0c39b
|
@ -100,10 +100,6 @@ class ListNotificationsController extends AbstractListController
|
|||
$areMoreResults ? null : 0
|
||||
);
|
||||
|
||||
$notifications = array_filter($notifications, function ($notification) {
|
||||
return ! $notification->subjectModel || $notification->subject;
|
||||
});
|
||||
|
||||
if (in_array('subject.discussion', $include)) {
|
||||
$this->loadSubjectDiscussions($notifications);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,9 @@ namespace Flarum\Notification;
|
|||
|
||||
use Carbon\Carbon;
|
||||
use Flarum\Database\AbstractModel;
|
||||
use Flarum\Event\ScopeModelVisibility;
|
||||
use Flarum\User\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
/**
|
||||
* Models a notification record in the database.
|
||||
|
@ -135,6 +137,38 @@ class Notification extends AbstractModel
|
|||
return $this->morphTo('subject', 'subjectModel');
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope the query to include only notifications whose subjects are visible
|
||||
* to the given user.
|
||||
*
|
||||
* @param Builder $query
|
||||
*/
|
||||
public function scopeWhereSubjectVisibleTo(Builder $query, User $actor)
|
||||
{
|
||||
$query->where(function ($query) use ($actor) {
|
||||
$classes = [];
|
||||
|
||||
foreach (static::$subjectModels as $type => $class) {
|
||||
$classes[$class][] = $type;
|
||||
}
|
||||
|
||||
foreach ($classes as $class => $types) {
|
||||
$query->orWhere(function ($query) use ($types, $class, $actor) {
|
||||
$query->whereIn('type', $types)
|
||||
->whereExists(function ($query) use ($class, $actor) {
|
||||
$query->selectRaw(1)
|
||||
->from((new $class)->getTable())
|
||||
->whereColumn('id', 'subject_id');
|
||||
|
||||
static::$dispatcher->dispatch(
|
||||
new ScopeModelVisibility($class::query()->setQuery($query), $actor, 'view')
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type-to-subject-model map.
|
||||
*
|
||||
|
|
|
@ -33,6 +33,7 @@ class NotificationRepository
|
|||
->where('user_id', $user->id)
|
||||
->whereIn('type', $user->getAlertableNotificationTypes())
|
||||
->where('is_deleted', false)
|
||||
->whereSubjectVisibleTo($user)
|
||||
->groupBy('type', 'subject_id')
|
||||
->orderByRaw('MAX(created_at) DESC')
|
||||
->skip($offset)
|
||||
|
|
|
@ -437,6 +437,7 @@ class User extends AbstractModel
|
|||
->whereIn('type', $this->getAlertableNotificationTypes())
|
||||
->whereNull('read_at')
|
||||
->where('is_deleted', false)
|
||||
->whereSubjectVisibleTo($this)
|
||||
->get();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user