mirror of
https://github.com/flarum/core.git
synced 2025-08-10 10:24:46 +02:00
Update APIs
This commit is contained in:
@@ -22,4 +22,21 @@ class Tag extends Model
|
|||||||
{
|
{
|
||||||
return $this->belongsTo('Flarum\Core\Models\Discussion', 'last_discussion_id');
|
return $this->belongsTo('Flarum\Core\Models\Discussion', 'last_discussion_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getVisibleTo($user)
|
||||||
|
{
|
||||||
|
static $tags;
|
||||||
|
if (!$tags) {
|
||||||
|
$tags = static::all();
|
||||||
|
}
|
||||||
|
|
||||||
|
$ids = [];
|
||||||
|
foreach ($tags as $tag) {
|
||||||
|
if (! $tag->is_restricted || $user->hasPermission('tag'.$tag->id.'.view')) {
|
||||||
|
$ids[] = $tag->id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ids;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,21 +1,25 @@
|
|||||||
<?php namespace Flarum\Tags;
|
<?php namespace Flarum\Tags;
|
||||||
|
|
||||||
use Flarum\Support\ServiceProvider;
|
use Flarum\Support\ServiceProvider;
|
||||||
use Flarum\Extend\ForumAssets;
|
use Flarum\Extend;
|
||||||
use Flarum\Extend\EventSubscribers;
|
|
||||||
use Flarum\Extend\Relationship;
|
|
||||||
use Flarum\Extend\SerializeRelationship;
|
|
||||||
use Flarum\Extend\ApiInclude;
|
|
||||||
use Flarum\Extend\ApiLink;
|
|
||||||
use Flarum\Extend\Permission;
|
|
||||||
use Flarum\Extend\DiscussionGambit;
|
|
||||||
use Flarum\Extend\PostType;
|
|
||||||
use Flarum\Core\Models\Discussion;
|
use Flarum\Core\Models\Discussion;
|
||||||
use Flarum\Core\Models\Post;
|
|
||||||
use Flarum\Core\Models\User;
|
use Flarum\Core\Models\User;
|
||||||
|
|
||||||
class TagsServiceProvider extends ServiceProvider
|
class TagsServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Register the service provider.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
$this->app->bind(
|
||||||
|
'Flarum\Tags\TagRepositoryInterface',
|
||||||
|
'Flarum\Tags\EloquentTagRepository'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bootstrap the application events.
|
* Bootstrap the application events.
|
||||||
*
|
*
|
||||||
@@ -24,75 +28,69 @@ class TagsServiceProvider extends ServiceProvider
|
|||||||
public function boot()
|
public function boot()
|
||||||
{
|
{
|
||||||
$this->extend([
|
$this->extend([
|
||||||
new ForumAssets([
|
(new Extend\ForumClient())
|
||||||
|
->assets([
|
||||||
__DIR__.'/../js/dist/extension.js',
|
__DIR__.'/../js/dist/extension.js',
|
||||||
__DIR__.'/../less/extension.less'
|
__DIR__.'/../less/extension.less'
|
||||||
]),
|
]),
|
||||||
|
|
||||||
new EventSubscribers([
|
(new Extend\Model('Flarum\Tags\Tag'))
|
||||||
'Flarum\Tags\Handlers\DiscussionTaggedNotifier',
|
// Hide tags that the user doesn't have permission to see.
|
||||||
'Flarum\Tags\Handlers\TagSaver',
|
->scopeVisible(function ($query, User $user) {
|
||||||
'Flarum\Tags\Handlers\TagLoader'
|
$query->whereIn('id', Tag::getVisibleTo($user));
|
||||||
]),
|
})
|
||||||
|
|
||||||
new Relationship('Flarum\Core\Models\Discussion', 'tags', function ($model) {
|
// Allow the user to start discussions in tags which aren't
|
||||||
return $model->belongsToMany('Flarum\Tags\Tag', 'discussions_tags');
|
// restricted, or for which the user has explicitly been granted
|
||||||
}),
|
// permission.
|
||||||
|
->allow('startDiscussion', function (Tag $tag, User $user) {
|
||||||
new SerializeRelationship('Flarum\Api\Serializers\DiscussionBasicSerializer', 'hasMany', 'tags', 'Flarum\Tags\TagSerializer'),
|
|
||||||
|
|
||||||
new ApiInclude(['discussions.index', 'discussions.show'], 'tags', true),
|
|
||||||
|
|
||||||
new SerializeRelationship('Flarum\Api\Serializers\ForumSerializer', 'hasMany', 'tags', 'Flarum\Tags\TagSerializer'),
|
|
||||||
|
|
||||||
new ApiInclude(['forum.show'], ['tags', 'tags.lastDiscussion'], true),
|
|
||||||
new ApiLink(['forum.show'], ['tags.parent'], true),
|
|
||||||
|
|
||||||
(new Permission('discussion.tag'))
|
|
||||||
->serialize(),
|
|
||||||
// ->grant(function ($grant, $user) {
|
|
||||||
// $grant->where('start_user_id', $user->id);
|
|
||||||
// // @todo add limitations to time etc. according to a config setting
|
|
||||||
// }),
|
|
||||||
|
|
||||||
new DiscussionGambit('Flarum\Tags\TagGambit'),
|
|
||||||
|
|
||||||
new PostType('Flarum\Tags\DiscussionTaggedPost')
|
|
||||||
]);
|
|
||||||
|
|
||||||
Tag::scopeVisible(function ($query, User $user) {
|
|
||||||
$query->whereIn('id', $this->getTagsWithPermission($user, 'view'));
|
|
||||||
});
|
|
||||||
|
|
||||||
Tag::allow('startDiscussion', function (Tag $tag, User $user) {
|
|
||||||
if (! $tag->is_restricted || $user->hasPermission('tag'.$tag->id.'.startDiscussion')) {
|
if (! $tag->is_restricted || $user->hasPermission('tag'.$tag->id.'.startDiscussion')) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
}),
|
||||||
|
|
||||||
Discussion::scopeVisible(function ($query, User $user) {
|
// Expose the complete tag list to clients by adding it as a
|
||||||
|
// relationship to the /api/forum endpoint. Since the Forum model
|
||||||
|
// doesn't actually have a tags relationship, we will manually
|
||||||
|
// load and assign the tags data to it using an event listener.
|
||||||
|
(new Extend\ApiSerializer('Flarum\Api\Serializers\ForumSerializer'))
|
||||||
|
->hasMany('tags', 'Flarum\Tags\TagSerializer'),
|
||||||
|
|
||||||
|
(new Extend\ApiAction('Flarum\Api\Actions\Forum\ShowAction'))
|
||||||
|
->addInclude('tags')
|
||||||
|
->addInclude('tags.lastDiscussion')
|
||||||
|
->addLink('tags.parent'),
|
||||||
|
|
||||||
|
new Extend\EventSubscriber('Flarum\Tags\Handlers\TagLoader'),
|
||||||
|
|
||||||
|
// Extend the Discussion model and API: add the tags relationship
|
||||||
|
// and modify permissions.
|
||||||
|
(new Extend\Model('Flarum\Core\Models\Discussion'))
|
||||||
|
->belongsToMany('tags', 'Flarum\Tags\Tag', 'discussions_tags')
|
||||||
|
|
||||||
|
// Hide discussions which have tags that the user is not allowed
|
||||||
|
// to see.
|
||||||
|
->scopeVisible(function ($query, User $user) {
|
||||||
$query->whereNotExists(function ($query) use ($user) {
|
$query->whereNotExists(function ($query) use ($user) {
|
||||||
return $query->select(app('db')->raw(1))
|
return $query->select(app('db')->raw(1))
|
||||||
->from('discussions_tags')
|
->from('discussions_tags')
|
||||||
->whereNotIn('tag_id', $this->getTagsWithPermission($user, 'view'))
|
->whereNotIn('tag_id', Tag::getVisibleTo($user))
|
||||||
->whereRaw('discussion_id = discussions.id');
|
->whereRaw('discussion_id = discussions.id');
|
||||||
});
|
});
|
||||||
});
|
})
|
||||||
|
|
||||||
Discussion::allow('*', function (Discussion $discussion, User $user, $action) {
|
// Wrap all discussion permission checks with some logic
|
||||||
|
// pertaining to the discussion's tags. If the discussion has a
|
||||||
|
// tag that has been restricted, and the user has this
|
||||||
|
// permission for that tag, then they are allowed. If the
|
||||||
|
// discussion only has tags that have been restricted, then the
|
||||||
|
// user *must* have permission for at least one of them.
|
||||||
|
->allow('*', function (Discussion $discussion, User $user, $action) {
|
||||||
$tags = $discussion->getRelation('tags');
|
$tags = $discussion->getRelation('tags');
|
||||||
|
|
||||||
if (! count($tags)) {
|
if (count($tags)) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$restricted = true;
|
$restricted = true;
|
||||||
|
|
||||||
// If the discussion has a tag that has been restricted, and the user
|
|
||||||
// has this permission for that tag, then they are allowed. If the
|
|
||||||
// discussion only has tags that have been restricted, then the user
|
|
||||||
// *must* have permission for at least one of them. Otherwise, inherit
|
|
||||||
// global permissions.
|
|
||||||
foreach ($tags as $tag) {
|
foreach ($tags as $tag) {
|
||||||
if ($tag->is_restricted) {
|
if ($tag->is_restricted) {
|
||||||
if ($user->hasPermission('tag'.$tag->id.'.discussion.'.$action)) {
|
if ($user->hasPermission('tag'.$tag->id.'.discussion.'.$action)) {
|
||||||
@@ -106,37 +104,32 @@ class TagsServiceProvider extends ServiceProvider
|
|||||||
if ($restricted) {
|
if ($restricted) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
Post::allow('*', function (Post $post, User $user, $action) {
|
(new Extend\ApiSerializer('Flarum\Api\Serializers\DiscussionBasicSerializer'))
|
||||||
return $post->discussion->can($user, $action.'Posts');
|
->hasMany('tags', 'Flarum\Tags\TagSerializer')
|
||||||
});
|
->attributes(function (&$attributes, $discussion, $user) {
|
||||||
}
|
$attributes['canTag'] = $discussion->can($user, 'tag');
|
||||||
|
}),
|
||||||
|
|
||||||
protected function getTagsWithPermission($user, $permission) {
|
(new Extend\ApiAction([
|
||||||
static $tags;
|
'Flarum\Api\Actions\Discussions\IndexAction',
|
||||||
if (!$tags) $tags = Tag::all();
|
'Flarum\Api\Actions\Discussions\ShowAction'
|
||||||
|
]))
|
||||||
|
->addInclude('tags'),
|
||||||
|
|
||||||
$ids = [];
|
// Add an event subscriber so that tags data is persisted when
|
||||||
foreach ($tags as $tag) {
|
// saving a discussion.
|
||||||
if (! $tag->is_restricted || $user->hasPermission('tag'.$tag->id.'.'.$permission)) {
|
new Extend\EventSubscriber('Flarum\Tags\Handlers\TagSaver'),
|
||||||
$ids[] = $tag->id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $ids;
|
// Add a gambit that allows filtering discussions by tag(s).
|
||||||
}
|
new Extend\DiscussionGambit('Flarum\Tags\TagGambit'),
|
||||||
|
|
||||||
/**
|
// Add a new post type which indicates when a discussion's tags were
|
||||||
* Register the service provider.
|
// changed.
|
||||||
*
|
new Extend\PostType('Flarum\Tags\DiscussionTaggedPost'),
|
||||||
* @return void
|
new Extend\EventSubscriber('Flarum\Tags\Handlers\DiscussionTaggedNotifier')
|
||||||
*/
|
]);
|
||||||
public function register()
|
|
||||||
{
|
|
||||||
$this->app->bind(
|
|
||||||
'Flarum\Tags\TagRepositoryInterface',
|
|
||||||
'Flarum\Tags\EloquentTagRepository'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user