1
0
mirror of https://github.com/flarum/core.git synced 2025-10-13 16:05:05 +02:00
Files
php-flarum/src/Core/Access/DiscussionPolicy.php
Toby Zerner 40a78d302e Fix permission logic priorities
This helps to fix a bug in flarum-ext-tags where a user could not rename or edit the tags of their own discussion if it was in a restricted tag. This was due to the order of GetPermission event listeners – the logic that determines that a user *can't* perform an action because of a restrictive tag was running before (and thus instead of) the logic that determines that a user *can* edit their own stuff.

The solution is to change the "catch-all" methods on Policies to "after" instead of "before" – that is, they will run only if the per-ability methods return null.

We also simplify the GetPermission event by passing the model as a sole "argument", as I can't imagine any cases where we'll need more than one argument.
2016-05-28 09:35:08 +09:30

117 lines
2.9 KiB
PHP

<?php
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Flarum\Core\Access;
use Carbon\Carbon;
use Flarum\Core\Discussion;
use Flarum\Core\User;
use Flarum\Event\ScopeHiddenDiscussionVisibility;
use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Database\Eloquent\Builder;
class DiscussionPolicy extends AbstractPolicy
{
/**
* {@inheritdoc}
*/
protected $model = Discussion::class;
/**
* @var SettingsRepositoryInterface
*/
protected $settings;
/**
* @var Gate
*/
protected $gate;
/**
* @var Dispatcher
*/
protected $events;
/**
* @param SettingsRepositoryInterface $settings
* @param Gate $gate
*/
public function __construct(SettingsRepositoryInterface $settings, Gate $gate, Dispatcher $events)
{
$this->settings = $settings;
$this->gate = $gate;
$this->events = $events;
}
/**
* @param User $actor
* @param string $ability
* @return bool|null
*/
public function after(User $actor, $ability)
{
if ($actor->hasPermission('discussion.'.$ability)) {
return true;
}
}
/**
* @param User $actor
* @param Builder $query
*/
public function find(User $actor, Builder $query)
{
if ($actor->cannot('viewDiscussions')) {
$query->whereRaw('FALSE');
} elseif (! $actor->hasPermission('discussion.hide')) {
$query->where(function ($query) use ($actor) {
$query->whereNull('discussions.hide_time')
->where('comments_count', '>', 0)
->orWhere('start_user_id', $actor->id);
$this->events->fire(
new ScopeHiddenDiscussionVisibility($query, $actor, 'discussion.hide')
);
});
}
}
/**
* @param User $actor
* @param Discussion $discussion
* @return bool|null
*/
public function rename(User $actor, Discussion $discussion)
{
if ($discussion->start_user_id == $actor->id) {
$allowRenaming = $this->settings->get('allow_renaming');
if ($allowRenaming === '-1'
|| ($allowRenaming === 'reply' && $discussion->participants_count <= 1)
|| ($discussion->start_time->diffInMinutes(new Carbon) < $allowRenaming)) {
return true;
}
}
}
/**
* @param User $actor
* @param Discussion $discussion
* @return bool|null
*/
public function hide(User $actor, Discussion $discussion)
{
if ($discussion->start_user_id == $actor->id && $discussion->participants_count <= 1) {
return true;
}
}
}