2024-01-09 18:34:40 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Tests\Feature\KoelPlus;
|
|
|
|
|
|
|
|
use App\Models\Song;
|
2024-10-24 10:45:45 +00:00
|
|
|
use PHPUnit\Framework\Attributes\Test;
|
2024-01-18 11:13:05 +00:00
|
|
|
use Tests\PlusTestCase;
|
2024-01-09 18:34:40 +00:00
|
|
|
|
2024-01-11 12:41:33 +00:00
|
|
|
use function Tests\create_user;
|
|
|
|
|
2024-01-18 11:13:05 +00:00
|
|
|
class SongTest extends PlusTestCase
|
2024-01-09 18:34:40 +00:00
|
|
|
{
|
2024-10-24 10:45:45 +00:00
|
|
|
#[Test]
|
|
|
|
public function withOwnSongsOnlyOptionOn(): void
|
2024-01-15 22:26:50 +00:00
|
|
|
{
|
|
|
|
$user = create_user();
|
|
|
|
|
|
|
|
Song::factory(2)->public()->create();
|
2024-01-22 22:33:16 +00:00
|
|
|
|
2024-01-15 22:26:50 +00:00
|
|
|
$ownSongs = Song::factory(3)->for($user, 'owner')->create();
|
|
|
|
|
|
|
|
$this->getAs('api/songs?own_songs_only=true', $user)
|
|
|
|
->assertSuccessful()
|
|
|
|
->assertJsonCount(3, 'data')
|
|
|
|
->assertJsonFragment(['id' => $ownSongs[0]->id])
|
|
|
|
->assertJsonFragment(['id' => $ownSongs[1]->id])
|
|
|
|
->assertJsonFragment(['id' => $ownSongs[2]->id]);
|
|
|
|
}
|
|
|
|
|
2024-10-24 10:45:45 +00:00
|
|
|
#[Test]
|
|
|
|
public function withOwnSongsOnlyOptionOffOrMissing(): void
|
2024-01-15 22:26:50 +00:00
|
|
|
{
|
|
|
|
$user = create_user();
|
|
|
|
|
|
|
|
Song::factory(2)->public()->create();
|
|
|
|
Song::factory(3)->for($user, 'owner')->create();
|
|
|
|
|
|
|
|
$this->getAs('api/songs?own_songs_only=false', $user)
|
|
|
|
->assertSuccessful()
|
|
|
|
->assertJsonCount(5, 'data');
|
|
|
|
|
|
|
|
$this->getAs('api/songs', $user)
|
|
|
|
->assertSuccessful()
|
|
|
|
->assertJsonCount(5, 'data');
|
|
|
|
}
|
|
|
|
|
2024-10-24 10:45:45 +00:00
|
|
|
#[Test]
|
|
|
|
public function showSongPolicy(): void
|
2024-01-09 18:34:40 +00:00
|
|
|
{
|
2024-01-11 12:41:33 +00:00
|
|
|
$user = create_user();
|
2024-01-09 18:34:40 +00:00
|
|
|
|
|
|
|
/** @var Song $publicSong */
|
|
|
|
$publicSong = Song::factory()->public()->create();
|
|
|
|
|
|
|
|
// We can access public songs.
|
2024-11-09 14:56:48 +00:00
|
|
|
$this->getAs("api/songs/{$publicSong->id}", $user)->assertSuccessful();
|
2024-01-09 18:34:40 +00:00
|
|
|
|
|
|
|
/** @var Song $ownPrivateSong */
|
|
|
|
$ownPrivateSong = Song::factory()->for($user, 'owner')->private()->create();
|
|
|
|
|
|
|
|
// We can access our own private songs.
|
2024-11-09 14:56:48 +00:00
|
|
|
$this->getAs("api/songs/{$ownPrivateSong->id}", $user)->assertSuccessful();
|
2024-01-09 18:34:40 +00:00
|
|
|
|
2024-01-10 23:25:22 +00:00
|
|
|
/** @var Song $externalUnownedSong */
|
2024-01-09 23:26:16 +00:00
|
|
|
$externalUnownedSong = Song::factory()->private()->create();
|
2024-01-09 18:34:40 +00:00
|
|
|
|
|
|
|
// But we can't access private songs that are not ours.
|
2024-11-09 14:56:48 +00:00
|
|
|
$this->getAs("api/songs/{$externalUnownedSong->id}", $user)->assertForbidden();
|
2024-01-09 18:34:40 +00:00
|
|
|
}
|
|
|
|
|
2024-10-24 10:45:45 +00:00
|
|
|
#[Test]
|
|
|
|
public function editSongsPolicy(): void
|
2024-01-09 18:34:40 +00:00
|
|
|
{
|
2024-01-11 12:41:33 +00:00
|
|
|
$currentUser = create_user();
|
|
|
|
$anotherUser = create_user();
|
2024-01-09 18:34:40 +00:00
|
|
|
|
2024-01-09 23:26:16 +00:00
|
|
|
$externalUnownedSongs = Song::factory(3)->for($anotherUser, 'owner')->private()->create();
|
2024-01-09 18:34:40 +00:00
|
|
|
|
|
|
|
// We can't edit songs that are not ours.
|
|
|
|
$this->putAs('api/songs', [
|
2024-11-09 14:56:48 +00:00
|
|
|
'songs' => $externalUnownedSongs->modelKeys(),
|
2024-01-09 18:34:40 +00:00
|
|
|
'data' => [
|
|
|
|
'title' => 'New Title',
|
|
|
|
],
|
|
|
|
], $currentUser)->assertForbidden();
|
|
|
|
|
|
|
|
// Even if some of the songs are owned by us, we still can't edit them.
|
2024-01-09 23:26:16 +00:00
|
|
|
$mixedSongs = $externalUnownedSongs->merge(Song::factory(2)->for($currentUser, 'owner')->create());
|
2024-01-09 18:34:40 +00:00
|
|
|
|
|
|
|
$this->putAs('api/songs', [
|
2024-11-09 14:56:48 +00:00
|
|
|
'songs' => $mixedSongs->modelKeys(),
|
2024-01-09 18:34:40 +00:00
|
|
|
'data' => [
|
|
|
|
'title' => 'New Title',
|
|
|
|
],
|
|
|
|
], $currentUser)->assertForbidden();
|
|
|
|
|
|
|
|
// But we can edit our own songs.
|
|
|
|
$ownSongs = Song::factory(3)->for($currentUser, 'owner')->create();
|
|
|
|
|
|
|
|
$this->putAs('api/songs', [
|
2024-11-09 14:56:48 +00:00
|
|
|
'songs' => $ownSongs->modelKeys(),
|
2024-01-09 18:34:40 +00:00
|
|
|
'data' => [
|
|
|
|
'title' => 'New Title',
|
|
|
|
],
|
|
|
|
], $currentUser)->assertSuccessful();
|
|
|
|
}
|
|
|
|
|
2024-10-24 10:45:45 +00:00
|
|
|
#[Test]
|
|
|
|
public function deleteSongsPolicy(): void
|
2024-01-09 18:34:40 +00:00
|
|
|
{
|
2024-01-11 12:41:33 +00:00
|
|
|
$currentUser = create_user();
|
|
|
|
$anotherUser = create_user();
|
2024-01-09 18:34:40 +00:00
|
|
|
|
2024-01-09 23:26:16 +00:00
|
|
|
$externalUnownedSongs = Song::factory(3)->for($anotherUser, 'owner')->private()->create();
|
2024-01-09 18:34:40 +00:00
|
|
|
|
|
|
|
// We can't delete songs that are not ours.
|
2024-11-09 14:56:48 +00:00
|
|
|
$this->deleteAs('api/songs', ['songs' => $externalUnownedSongs->modelKeys()], $currentUser)
|
2024-01-09 18:34:40 +00:00
|
|
|
->assertForbidden();
|
|
|
|
|
|
|
|
// Even if some of the songs are owned by us, we still can't delete them.
|
2024-01-09 23:26:16 +00:00
|
|
|
$mixedSongs = $externalUnownedSongs->merge(Song::factory(2)->for($currentUser, 'owner')->create());
|
2024-01-09 18:34:40 +00:00
|
|
|
|
2024-11-09 14:56:48 +00:00
|
|
|
$this->deleteAs('api/songs', ['songs' => $mixedSongs->modelKeys()], $currentUser)
|
2024-01-09 18:34:40 +00:00
|
|
|
->assertForbidden();
|
|
|
|
|
|
|
|
// But we can delete our own songs.
|
|
|
|
$ownSongs = Song::factory(3)->for($currentUser, 'owner')->create();
|
|
|
|
|
2024-11-09 14:56:48 +00:00
|
|
|
$this->deleteAs('api/songs', ['songs' => $ownSongs->modelKeys()], $currentUser)
|
2024-01-09 18:34:40 +00:00
|
|
|
->assertSuccessful();
|
|
|
|
}
|
2024-01-16 21:14:14 +00:00
|
|
|
|
2024-10-24 10:45:45 +00:00
|
|
|
#[Test]
|
2024-11-09 14:56:48 +00:00
|
|
|
public function markSongsAsPublic(): void
|
2024-01-16 21:14:14 +00:00
|
|
|
{
|
|
|
|
$user = create_user();
|
|
|
|
|
|
|
|
$songs = Song::factory(3)->for($user, 'owner')->private()->create();
|
|
|
|
|
2024-11-09 14:56:48 +00:00
|
|
|
$this->putAs('api/songs/publicize', ['songs' => $songs->modelKeys()], $user)
|
2024-01-16 21:14:14 +00:00
|
|
|
->assertSuccessful();
|
|
|
|
|
|
|
|
$songs->each(static function (Song $song): void {
|
|
|
|
$song->refresh();
|
|
|
|
self::assertTrue($song->is_public);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-10-24 10:45:45 +00:00
|
|
|
#[Test]
|
2024-11-09 14:56:48 +00:00
|
|
|
public function markSongsAsPrivate(): void
|
2024-01-16 21:14:14 +00:00
|
|
|
{
|
|
|
|
$user = create_user();
|
|
|
|
|
|
|
|
$songs = Song::factory(3)->for($user, 'owner')->public()->create();
|
|
|
|
|
2024-11-09 14:56:48 +00:00
|
|
|
$this->putAs('api/songs/privatize', ['songs' => $songs->modelKeys()], $user)
|
2024-01-16 21:14:14 +00:00
|
|
|
->assertSuccessful();
|
|
|
|
|
|
|
|
$songs->each(static function (Song $song): void {
|
|
|
|
$song->refresh();
|
|
|
|
self::assertFalse($song->is_public);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-10-24 10:45:45 +00:00
|
|
|
#[Test]
|
|
|
|
public function publicizingOrPrivatizingSongsRequiresOwnership(): void
|
2024-01-16 21:14:14 +00:00
|
|
|
{
|
|
|
|
$songs = Song::factory(3)->public()->create();
|
|
|
|
|
2024-11-09 14:56:48 +00:00
|
|
|
$this->putAs('api/songs/privatize', ['songs' => $songs->modelKeys()])
|
2024-01-16 21:14:14 +00:00
|
|
|
->assertForbidden();
|
|
|
|
|
|
|
|
$otherSongs = Song::factory(3)->private()->create();
|
|
|
|
|
2024-11-09 14:56:48 +00:00
|
|
|
$this->putAs('api/songs/publicize', ['songs' => $otherSongs->modelKeys()])
|
2024-01-16 21:14:14 +00:00
|
|
|
->assertForbidden();
|
|
|
|
}
|
2024-01-09 18:34:40 +00:00
|
|
|
}
|