mirror of
https://github.com/flarum/framework.git
synced 2025-02-02 21:27:17 +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
9b013a4136
commit
0e5c3aff1a
|
@ -100,10 +100,6 @@ class ListNotificationsController extends AbstractListController
|
||||||
$areMoreResults ? null : 0
|
$areMoreResults ? null : 0
|
||||||
);
|
);
|
||||||
|
|
||||||
$notifications = array_filter($notifications, function ($notification) {
|
|
||||||
return ! $notification->subjectModel || $notification->subject;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (in_array('subject.discussion', $include)) {
|
if (in_array('subject.discussion', $include)) {
|
||||||
$this->loadSubjectDiscussions($notifications);
|
$this->loadSubjectDiscussions($notifications);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,9 @@ namespace Flarum\Notification;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Flarum\Database\AbstractModel;
|
use Flarum\Database\AbstractModel;
|
||||||
|
use Flarum\Event\ScopeModelVisibility;
|
||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Models a notification record in the database.
|
* Models a notification record in the database.
|
||||||
|
@ -135,6 +137,38 @@ class Notification extends AbstractModel
|
||||||
return $this->morphTo('subject', 'subjectModel');
|
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.
|
* Get the type-to-subject-model map.
|
||||||
*
|
*
|
||||||
|
|
|
@ -33,6 +33,7 @@ class NotificationRepository
|
||||||
->where('user_id', $user->id)
|
->where('user_id', $user->id)
|
||||||
->whereIn('type', $user->getAlertableNotificationTypes())
|
->whereIn('type', $user->getAlertableNotificationTypes())
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
|
->whereSubjectVisibleTo($user)
|
||||||
->groupBy('type', 'subject_id')
|
->groupBy('type', 'subject_id')
|
||||||
->orderByRaw('MAX(created_at) DESC')
|
->orderByRaw('MAX(created_at) DESC')
|
||||||
->skip($offset)
|
->skip($offset)
|
||||||
|
|
|
@ -437,6 +437,7 @@ class User extends AbstractModel
|
||||||
->whereIn('type', $this->getAlertableNotificationTypes())
|
->whereIn('type', $this->getAlertableNotificationTypes())
|
||||||
->whereNull('read_at')
|
->whereNull('read_at')
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
|
->whereSubjectVisibleTo($this)
|
||||||
->get();
|
->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user