fix: assing default user to S3-imported songs

This commit is contained in:
Phan An 2024-01-15 18:45:01 +01:00
parent 854900b9b7
commit 179faefeed
7 changed files with 51 additions and 21 deletions

View file

@ -3,7 +3,7 @@
namespace App\Console\Commands\Admin;
use App\Console\Commands\Traits\AskForPassword;
use App\Models\User;
use App\Repositories\UserRepository;
use Illuminate\Console\Command;
use Illuminate\Contracts\Hashing\Hasher as Hash;
@ -15,7 +15,7 @@ class ChangePasswordCommand extends Command
{email? : The user's email. If empty, will get the default admin user.}";
protected $description = "Change a user's password";
public function __construct(private Hash $hash)
public function __construct(private Hash $hash, private UserRepository $userRepository)
{
parent::__construct();
}
@ -24,10 +24,9 @@ class ChangePasswordCommand extends Command
{
$email = $this->argument('email');
/** @var User|null $user */
$user = $email
? User::query()->where('email', $email)->first()
: User::query()->where('is_admin', true)->first();
? $this->userRepository->findOneByEmail($email)
: $this->userRepository->getDefaultAdminUser();
if (!$user) {
$this->error('The user account cannot be found.');

View file

@ -5,6 +5,7 @@ namespace App\Console\Commands;
use App\Libraries\WatchRecord\InotifyWatchRecord;
use App\Models\Setting;
use App\Models\User;
use App\Repositories\UserRepository;
use App\Services\MediaScanner;
use App\Values\ScanConfiguration;
use App\Values\ScanResult;
@ -29,7 +30,7 @@ class ScanCommand extends Command
private ?string $mediaPath;
private ProgressBar $progressBar;
public function __construct(private MediaScanner $mediaScanner)
public function __construct(private MediaScanner $mediaScanner, private UserRepository $userRepository)
{
parent::__construct();
@ -170,8 +171,8 @@ class ScanCommand extends Command
return $user;
}
/** @var User $user */
$user = User::where('is_admin', true)->oldest()->firstOrFail();
$user = $this->userRepository->getDefaultAdminUser();
$this->components->warn(
"No song owner specified. Setting the first admin ($user->name, ID $user->id) as owner."
);

View file

@ -2,6 +2,17 @@
namespace App\Repositories;
use App\Models\User;
class UserRepository extends Repository
{
public function getDefaultAdminUser(): User
{
return User::query()->where('is_admin', true)->oldest()->firstOrFail();
}
public function findOneByEmail(string $email): ?User
{
return User::query()->where('email', $email)->first();
}
}

View file

@ -6,15 +6,6 @@ use SplFileInfo;
class Helper
{
/**
* Get a unique hash from a file path.
* This hash can then be used as the Song record's ID.
*/
public static function getFileHash(string $path): string
{
return md5(config('app.key') . $path);
}
public static function getModifiedTime(string|SplFileInfo $file): int
{
$file = is_string($file) ? new SplFileInfo($file) : $file;

View file

@ -8,6 +8,7 @@ use App\Models\Album;
use App\Models\Artist;
use App\Models\Song;
use App\Repositories\SongRepository;
use App\Repositories\UserRepository;
use Aws\S3\S3ClientInterface;
use Illuminate\Cache\Repository as Cache;
@ -18,6 +19,7 @@ class S3Service implements ObjectStorageInterface
private Cache $cache,
private MediaMetadataService $mediaMetadataService,
private SongRepository $songRepository,
private UserRepository $userRepository,
) {
}
@ -48,6 +50,7 @@ class S3Service implements ObjectStorageInterface
int $track,
string $lyrics
): Song {
$user = $this->userRepository->getDefaultAdminUser();
$path = Song::getPathFromS3BucketAndKey($bucket, $key);
$artist = Artist::getOrCreate($artistName);
@ -74,6 +77,8 @@ class S3Service implements ObjectStorageInterface
'track' => $track,
'lyrics' => $lyrics,
'mtime' => time(),
'owner_id' => $user->id,
'is_public' => true,
]);
event(new LibraryChanged());

View file

@ -5,6 +5,7 @@ namespace App\Services;
use App\Exceptions\InvitationNotFoundException;
use App\Mail\UserInvite;
use App\Models\User;
use App\Repositories\UserRepository;
use Illuminate\Contracts\Hashing\Hasher as Hash;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
@ -13,7 +14,7 @@ use Illuminate\Support\Str;
class UserInvitationService
{
public function __construct(private Hash $hash)
public function __construct(private Hash $hash, private UserRepository $userRepository)
{
}
@ -36,8 +37,7 @@ class UserInvitationService
/** @throws InvitationNotFoundException */
public function revokeByEmail(string $email): void
{
/** @var ?User $user */
$user = User::query()->where('email', $email)->first();
$user = $this->userRepository->findOneByEmail($email);
throw_unless($user?->is_prospect, new InvitationNotFoundException());
$user->delete();
}

View file

@ -5,6 +5,7 @@ namespace Tests\Unit\Services;
use App\Events\LibraryChanged;
use App\Models\Song;
use App\Repositories\SongRepository;
use App\Repositories\UserRepository;
use App\Services\MediaMetadataService;
use App\Services\S3Service;
use Aws\CommandInterface;
@ -16,11 +17,14 @@ use Mockery\LegacyMockInterface;
use Mockery\MockInterface;
use Tests\TestCase;
use function Tests\create_admin;
class S3ServiceTest extends TestCase
{
private S3ClientInterface|LegacyMockInterface|MockInterface $s3Client;
private Cache|LegacyMockInterface|MockInterface $cache;
private SongRepository|LegacyMockInterface|MockInterface $songRepository;
private UserRepository|LegacyMockInterface|MockInterface $userRepository;
private S3Service $s3Service;
public function setUp(): void
@ -32,14 +36,26 @@ class S3ServiceTest extends TestCase
$metadataService = Mockery::mock(MediaMetadataService::class);
$this->songRepository = Mockery::mock(SongRepository::class);
$this->userRepository = Mockery::mock(UserRepository::class);
$this->s3Service = new S3Service($this->s3Client, $this->cache, $metadataService, $this->songRepository);
$this->s3Service = new S3Service(
$this->s3Client,
$this->cache,
$metadataService,
$this->songRepository,
$this->userRepository
);
}
public function testCreateSongEntry(): void
{
$this->expectsEvents(LibraryChanged::class);
$user = create_admin();
$this->userRepository->shouldReceive('getDefaultAdminUser')
->once()
->andReturn($user);
$song = $this->s3Service->createSongEntry(
bucket: 'foo',
key: 'bar',
@ -60,12 +76,18 @@ class S3ServiceTest extends TestCase
self::assertSame(355.5, $song->length);
self::assertSame('Is this the real life?', $song->lyrics);
self::assertSame(1, $song->track);
self::assertSame($user->id, $song->owner_id);
}
public function testUpdateSongEntry(): void
{
$this->expectsEvents(LibraryChanged::class);
$user = create_admin();
$this->userRepository->shouldReceive('getDefaultAdminUser')
->once()
->andReturn($user);
/** @var Song $song */
$song = Song::factory()->create([
'path' => 's3://foo/bar',
@ -95,6 +117,7 @@ class S3ServiceTest extends TestCase
self::assertSame(355.5, $song->length);
self::assertSame('Is this the real life?', $song->lyrics);
self::assertSame(1, $song->track);
self::assertSame($user->id, $song->owner_id);
}
public function testDeleteSong(): void