From 5100f13dd8ab50a131f3987f2ae82cd6c3c2a985 Mon Sep 17 00:00:00 2001 From: Mani <12898705+Maniload@users.noreply.github.com> Date: Tue, 16 Apr 2024 17:52:53 +0200 Subject: [PATCH] feat: Added permission for revalidating pages (#654) * Added permissions as allowed include path. * Added tracks and playlists as allowed include paths to videos --- app/Enums/Auth/SpecialPermission.php | 2 ++ app/Http/Api/Schema/Auth/RoleSchema.php | 4 +++- app/Http/Api/Schema/Auth/User/MySchema.php | 1 + app/Http/Api/Schema/Wiki/AnimeSchema.php | 2 ++ app/Http/Api/Schema/Wiki/VideoSchema.php | 2 ++ app/Models/Auth/User.php | 1 + app/Models/Wiki/Video.php | 5 +++- tests/Unit/Models/Wiki/VideoTest.php | 27 +++++++++++++++++++--- 8 files changed, 39 insertions(+), 5 deletions(-) diff --git a/app/Enums/Auth/SpecialPermission.php b/app/Enums/Auth/SpecialPermission.php index abf8d348a..c1cc9825b 100644 --- a/app/Enums/Auth/SpecialPermission.php +++ b/app/Enums/Auth/SpecialPermission.php @@ -18,4 +18,6 @@ enum SpecialPermission: string case VIEW_NOVA = 'view nova'; case VIEW_TELESCOPE = 'view telescope'; + + case REVALIDATE_PAGES = 'revalidate pages'; } diff --git a/app/Http/Api/Schema/Auth/RoleSchema.php b/app/Http/Api/Schema/Auth/RoleSchema.php index 45aa8b3b3..5e95a2eb5 100644 --- a/app/Http/Api/Schema/Auth/RoleSchema.php +++ b/app/Http/Api/Schema/Auth/RoleSchema.php @@ -40,7 +40,9 @@ class RoleSchema extends EloquentSchema */ public function allowedIncludes(): array { - return []; + return [ + new AllowedInclude(new PermissionSchema(), Role::RELATION_PERMISSIONS), + ]; } /** diff --git a/app/Http/Api/Schema/Auth/User/MySchema.php b/app/Http/Api/Schema/Auth/User/MySchema.php index c8802d02d..4714b3947 100644 --- a/app/Http/Api/Schema/Auth/User/MySchema.php +++ b/app/Http/Api/Schema/Auth/User/MySchema.php @@ -44,6 +44,7 @@ class MySchema extends EloquentSchema new AllowedInclude(new PermissionSchema(), User::RELATION_PERMISSIONS), new AllowedInclude(new PlaylistSchema(), User::RELATION_PLAYLISTS), new AllowedInclude(new RoleSchema(), User::RELATION_ROLES), + new AllowedInclude(new PermissionSchema(), User::RELATION_ROLES_PERMISSIONS), ]; } diff --git a/app/Http/Api/Schema/Wiki/AnimeSchema.php b/app/Http/Api/Schema/Wiki/AnimeSchema.php index 1ae0c3669..d7db1f8df 100644 --- a/app/Http/Api/Schema/Wiki/AnimeSchema.php +++ b/app/Http/Api/Schema/Wiki/AnimeSchema.php @@ -16,6 +16,7 @@ use App\Http\Api\Field\Wiki\Anime\AnimeSynopsisField; use App\Http\Api\Field\Wiki\Anime\AnimeYearField; use App\Http\Api\Include\AllowedInclude; use App\Http\Api\Schema\EloquentSchema; +use App\Http\Api\Schema\List\PlaylistSchema; use App\Http\Api\Schema\Pivot\Wiki\AnimeResourceSchema; use App\Http\Api\Schema\Wiki\Anime\SynonymSchema; use App\Http\Api\Schema\Wiki\Anime\Theme\EntrySchema; @@ -82,6 +83,7 @@ class AnimeSchema extends EloquentSchema implements InteractsWithPivots, Searcha new AllowedInclude(new ExternalResourceSchema(), 'animethemes.animethemeentries.videos.animethemeentries.animetheme.song.resources'), new AllowedInclude(new ExternalResourceSchema(), 'animethemes.song.resources'), new AllowedInclude(new ImageSchema(), 'animethemes.song.artists.images'), + new AllowedInclude(new PlaylistSchema(), 'animethemes.animethemeentries.videos.tracks.playlist'), ]; } diff --git a/app/Http/Api/Schema/Wiki/VideoSchema.php b/app/Http/Api/Schema/Wiki/VideoSchema.php index ce9aae5eb..9559d51ab 100644 --- a/app/Http/Api/Schema/Wiki/VideoSchema.php +++ b/app/Http/Api/Schema/Wiki/VideoSchema.php @@ -25,6 +25,7 @@ use App\Http\Api\Field\Wiki\Video\VideoUncenField; use App\Http\Api\Field\Wiki\Video\VideoViewCountField; use App\Http\Api\Include\AllowedInclude; use App\Http\Api\Schema\EloquentSchema; +use App\Http\Api\Schema\List\Playlist\TrackSchema; use App\Http\Api\Schema\Wiki\Anime\Theme\EntrySchema; use App\Http\Api\Schema\Wiki\Anime\ThemeSchema; use App\Http\Api\Schema\Wiki\Video\ScriptSchema; @@ -59,6 +60,7 @@ class VideoSchema extends EloquentSchema implements SearchableSchema new AllowedInclude(new EntrySchema(), Video::RELATION_ANIMETHEMEENTRIES), new AllowedInclude(new ScriptSchema(), Video::RELATION_SCRIPT), new AllowedInclude(new ThemeSchema(), Video::RELATION_ANIMETHEME), + new AllowedInclude(new TrackSchema(), Video::RELATION_TRACKS), // Undocumented paths needed for client builds new AllowedInclude(new SongSchema(), 'animethemeentries.animetheme.song'), diff --git a/app/Models/Auth/User.php b/app/Models/Auth/User.php index d51d487b2..fa8ac7cef 100644 --- a/app/Models/Auth/User.php +++ b/app/Models/Auth/User.php @@ -73,6 +73,7 @@ class User extends Authenticatable implements MustVerifyEmail, Nameable final public const RELATION_PERMISSIONS = 'permissions'; final public const RELATION_PLAYLISTS = 'playlists'; final public const RELATION_ROLES = 'roles'; + final public const RELATION_ROLES_PERMISSIONS = 'roles.permissions'; /** * The attributes that are mass assignable. diff --git a/app/Models/Wiki/Video.php b/app/Models/Wiki/Video.php index dc2e8dd22..18780e5db 100644 --- a/app/Models/Wiki/Video.php +++ b/app/Models/Wiki/Video.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace App\Models\Wiki; use App\Contracts\Models\Streamable; +use App\Enums\Models\List\PlaylistVisibility; use App\Enums\Models\Wiki\VideoOverlap; use App\Enums\Models\Wiki\VideoSource; use App\Events\Wiki\Video\VideoCreated; @@ -13,6 +14,7 @@ use App\Events\Wiki\Video\VideoRestored; use App\Events\Wiki\Video\VideoUpdated; use App\Http\Resources\Pivot\Wiki\Resource\AnimeThemeEntryVideoResource; use App\Models\BaseModel; +use App\Models\List\Playlist; use App\Models\List\Playlist\PlaylistTrack; use App\Models\Wiki\Anime\Theme\AnimeThemeEntry; use App\Models\Wiki\Video\VideoScript; @@ -349,6 +351,7 @@ class Video extends BaseModel implements Streamable, Viewable */ public function tracks(): HasMany { - return $this->hasMany(PlaylistTrack::class, PlaylistTrack::ATTRIBUTE_VIDEO); + return $this->hasMany(PlaylistTrack::class, PlaylistTrack::ATTRIBUTE_VIDEO) + ->whereRelation(PlaylistTrack::RELATION_PLAYLIST, Playlist::ATTRIBUTE_VISIBILITY, PlaylistVisibility::PUBLIC->value); } } diff --git a/tests/Unit/Models/Wiki/VideoTest.php b/tests/Unit/Models/Wiki/VideoTest.php index e08126091..5f7cce37a 100644 --- a/tests/Unit/Models/Wiki/VideoTest.php +++ b/tests/Unit/Models/Wiki/VideoTest.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Tests\Unit\Models\Wiki; +use App\Enums\Models\List\PlaylistVisibility; use App\Enums\Models\Wiki\VideoOverlap; use App\Enums\Models\Wiki\VideoSource; use App\Models\List\Playlist; @@ -316,16 +317,17 @@ class VideoTest extends TestCase } /** - * Video shall have a one-to-many relationship with the type PlaylistTrack. + * Video shall have a one-to-many relationship with the type PlaylistTrack, but only if the playlist is public. * * @return void */ - public function testTracks(): void + public function testTracksPublic(): void { $trackCount = $this->faker->randomDigitNotNull(); + $playlist = Playlist::factory()->createOne([ Playlist::ATTRIBUTE_VISIBILITY => PlaylistVisibility::PUBLIC ]); $video = Video::factory() - ->has(PlaylistTrack::factory()->for(Playlist::factory())->count($trackCount), Video::RELATION_TRACKS) + ->has(PlaylistTrack::factory()->for($playlist)->count($trackCount), Video::RELATION_TRACKS) ->createOne(); static::assertInstanceOf(HasMany::class, $video->tracks()); @@ -333,6 +335,25 @@ class VideoTest extends TestCase static::assertInstanceOf(PlaylistTrack::class, $video->tracks()->first()); } + /** + * Video shall have a one-to-many relationship with the type PlaylistTrack, but only if the playlist is public. + * + * @return void + */ + public function testTracksNotPublic(): void + { + $trackCount = $this->faker->randomDigitNotNull(); + + $visibility = Arr::random([ PlaylistVisibility::PRIVATE, PlaylistVisibility::UNLISTED ]); + $playlist = Playlist::factory()->createOne([ Playlist::ATTRIBUTE_VISIBILITY => $visibility ]); + $video = Video::factory() + ->has(PlaylistTrack::factory()->for($playlist)->count($trackCount), Video::RELATION_TRACKS) + ->createOne(); + + static::assertInstanceOf(HasMany::class, $video->tracks()); + static::assertNotEquals($trackCount, $video->tracks()->count()); + } + /** * Video shall have a one-to-one relationship with the type Script. *