fix: scopes downloads and monitors to users

This commit is contained in:
2025-05-11 16:27:53 -05:00
parent 6817bd8c80
commit 8aba35fee1
13 changed files with 34 additions and 40 deletions

View File

@@ -26,7 +26,7 @@ export default class extends Controller {
title: this.element.dataset['title'], title: this.element.dataset['title'],
filename: this.filenameValue, filename: this.filenameValue,
mediaType: this.mediaTypeValue, mediaType: this.mediaTypeValue,
imdbId: this.imdbIdValue imdbId: this.imdbIdValue,
}) })
}) })
.then(res => res.json()) .then(res => res.json())

View File

@@ -6,6 +6,7 @@ use App\Download\Action\Input\DownloadMediaInput;
use App\Download\Framework\Repository\DownloadRepository; use App\Download\Framework\Repository\DownloadRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mercure\HubInterface;
use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
@@ -21,6 +22,7 @@ class DownloadController extends AbstractController
DownloadMediaInput $input, DownloadMediaInput $input,
): Response { ): Response {
$download = $this->downloadRepository->insert( $download = $this->downloadRepository->insert(
$this->getUser(),
$input->url, $input->url,
$input->title, $input->title,
$input->filename, $input->filename,

View File

@@ -15,6 +15,7 @@ class DownloadMediaCommand implements CommandInterface
public string $filename, public string $filename,
public string $mediaType, public string $mediaType,
public string $imdbId, public string $imdbId,
public int $userId,
public ?int $downloadId = null, public ?int $downloadId = null,
) {} ) {}
} }

View File

@@ -6,6 +6,7 @@ use App\Download\Action\Command\DownloadMediaCommand;
use App\Download\Action\Result\DownloadMediaResult; use App\Download\Action\Result\DownloadMediaResult;
use App\Download\Framework\Repository\DownloadRepository; use App\Download\Framework\Repository\DownloadRepository;
use App\Download\Downloader\DownloaderInterface; use App\Download\Downloader\DownloaderInterface;
use App\User\Framework\Repository\UserRepository;
use OneToMany\RichBundle\Contract\CommandInterface; use OneToMany\RichBundle\Contract\CommandInterface;
use OneToMany\RichBundle\Contract\HandlerInterface; use OneToMany\RichBundle\Contract\HandlerInterface;
use OneToMany\RichBundle\Contract\ResultInterface; use OneToMany\RichBundle\Contract\ResultInterface;
@@ -17,12 +18,14 @@ readonly class DownloadMediaHandler implements HandlerInterface
public function __construct( public function __construct(
private DownloaderInterface $downloader, private DownloaderInterface $downloader,
private DownloadRepository $downloadRepository, private DownloadRepository $downloadRepository,
private UserRepository $userRepository,
) {} ) {}
public function handle(CommandInterface $command): ResultInterface public function handle(CommandInterface $command): ResultInterface
{ {
if (null === $command->downloadId) { if (null === $command->downloadId) {
$download = $this->downloadRepository->insert( $download = $this->downloadRepository->insert(
$this->userRepository->find($command->userId),
$command->url, $command->url,
$command->title, $command->title,
$command->filename, $command->filename,
@@ -34,7 +37,6 @@ readonly class DownloadMediaHandler implements HandlerInterface
$download = $this->downloadRepository->find($command->downloadId); $download = $this->downloadRepository->find($command->downloadId);
} }
try { try {
$this->downloadRepository->updateStatus($download->getId(), 'In Progress'); $this->downloadRepository->updateStatus($download->getId(), 'In Progress');

View File

@@ -26,6 +26,8 @@ class DownloadMediaInput implements InputInterface
#[SourceRequest('imdbId')] #[SourceRequest('imdbId')]
public string $imdbId, public string $imdbId,
public ?int $userId = null,
public ?int $downloadId = null, public ?int $downloadId = null,
) {} ) {}
@@ -38,6 +40,7 @@ class DownloadMediaInput implements InputInterface
$this->mediaType, $this->mediaType,
$this->imdbId, $this->imdbId,
$this->downloadId, $this->downloadId,
$this->userId
); );
} }
} }

View File

@@ -3,11 +3,12 @@
namespace App\Download\Framework\Repository; namespace App\Download\Framework\Repository;
use App\Download\Framework\Entity\Download; use App\Download\Framework\Entity\Download;
use App\ValueObject\DownloadRequest; use App\User\Framework\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
use Knp\Component\Pager\Paginator; use Knp\Component\Pager\Paginator;
use Knp\Component\Pager\PaginatorInterface; use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\Security\Core\User\UserInterface;
/** /**
* @extends ServiceEntityRepository<Download> * @extends ServiceEntityRepository<Download>
@@ -51,6 +52,7 @@ class DownloadRepository extends ServiceEntityRepository
} }
public function insert( public function insert(
UserInterface $user,
string $url, string $url,
string $title, string $title,
string $filename, string $filename,
@@ -59,7 +61,9 @@ class DownloadRepository extends ServiceEntityRepository
string $batchId, string $batchId,
string $status = 'New' string $status = 'New'
): Download { ): Download {
/** @var User $user */
$download = (new Download()) $download = (new Download())
->setUser($user)
->setUrl($url) ->setUrl($url)
->setTitle($title) ->setTitle($title)
->setFilename($filename) ->setFilename($filename)
@@ -75,22 +79,6 @@ class DownloadRepository extends ServiceEntityRepository
return $download; return $download;
} }
public function insertFromDownloadRequest(DownloadRequest $request): Download
{
$download = (new Download())
->setUrl($request->downloadUrl)
->setTitle($request->seriesName)
->setFilename($request->filename)
->setImdbId($request->imdbCode)
->setMediaType($request->mediaType)
->setStatus('New');
$this->getEntityManager()->persist($download);
$this->getEntityManager()->flush();
return $download;
}
public function updateStatus(int $id, string $status): Download public function updateStatus(int $id, string $status): Download
{ {
$download = $this->find($id); $download = $this->find($id);
@@ -106,18 +94,6 @@ class DownloadRepository extends ServiceEntityRepository
$this->getEntityManager()->flush(); $this->getEntityManager()->flush();
} }
public function getPendingByBatchId(string $batchId): ?array
{
$query = $this->createQueryBuilder('d')
->andWhere('d.status IN (:statuses)')
->andWhere('d.batchId = :batchId')
->setParameter('statuses', ['New', 'In Progress'])
->setParameter('batchId', $batchId)
->getQuery();
return $query->getResult();
}
public function latest(int $limit = 1) public function latest(int $limit = 1)
{ {
return $this->createQueryBuilder('d') return $this->createQueryBuilder('d')

View File

@@ -7,7 +7,7 @@ use OneToMany\RichBundle\Contract\CommandInterface;
class AddMonitorCommand implements CommandInterface class AddMonitorCommand implements CommandInterface
{ {
public function __construct( public function __construct(
public string $userEmail, public string $userId,
public string $title, public string $title,
public string $imdbId, public string $imdbId,
public string $tmdbId, public string $tmdbId,

View File

@@ -22,7 +22,7 @@ readonly class AddMonitorHandler implements HandlerInterface
public function handle(CommandInterface $command): ResultInterface public function handle(CommandInterface $command): ResultInterface
{ {
$user = $this->userRepository->findOneBy(['email' => $command->userEmail]); $user = $this->userRepository->find($command->userId);
$monitor = (new Monitor()) $monitor = (new Monitor())
->setUser($user) ->setUser($user)
->setTmdbId($command->tmdbId) ->setTmdbId($command->tmdbId)

View File

@@ -2,9 +2,10 @@
namespace App\Monitor\Action\Handler; namespace App\Monitor\Action\Handler;
use App\Monitor\Action\Command\DownloadMediaCommand; use App\Download\Action\Command\DownloadMediaCommand;
use App\Monitor\Action\Command\MonitorMovieCommand; use App\Monitor\Action\Command\MonitorMovieCommand;
use App\Monitor\Action\Result\MonitorMovieResult; use App\Monitor\Action\Result\MonitorMovieResult;
use App\Monitor\Framework\Entity\Monitor;
use App\Monitor\Framework\Repository\MonitorRepository; use App\Monitor\Framework\Repository\MonitorRepository;
use App\Monitor\Service\MonitorOptionEvaluator; use App\Monitor\Service\MonitorOptionEvaluator;
use App\Torrentio\Action\Command\GetMovieOptionsCommand; use App\Torrentio\Action\Command\GetMovieOptionsCommand;
@@ -15,6 +16,7 @@ use OneToMany\RichBundle\Contract\CommandInterface;
use OneToMany\RichBundle\Contract\HandlerInterface; use OneToMany\RichBundle\Contract\HandlerInterface;
use OneToMany\RichBundle\Contract\ResultInterface; use OneToMany\RichBundle\Contract\ResultInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\MessageBusInterface;
/** @implements HandlerInterface<MonitorMovieCommand> */ /** @implements HandlerInterface<MonitorMovieCommand> */
@@ -27,11 +29,13 @@ readonly class MonitorMovieHandler implements HandlerInterface
private EntityManagerInterface $entityManager, private EntityManagerInterface $entityManager,
private MessageBusInterface $bus, private MessageBusInterface $bus,
private LoggerInterface $logger, private LoggerInterface $logger,
private Security $security,
) {} ) {}
public function handle(CommandInterface $command): ResultInterface public function handle(CommandInterface $command): ResultInterface
{ {
$this->logger->info('> [MonitorMovieHandler] Executing MonitorMovieHandler'); $this->logger->info('> [MonitorMovieHandler] Executing MonitorMovieHandler');
/** @var Monitor $monitor */
$monitor = $this->movieMonitorRepository->find($command->movieMonitorId); $monitor = $this->movieMonitorRepository->find($command->movieMonitorId);
$monitor->setStatus('In Progress'); $monitor->setStatus('In Progress');
@@ -51,6 +55,7 @@ readonly class MonitorMovieHandler implements HandlerInterface
$result->filename, $result->filename,
'movies', 'movies',
$monitor->getImdbId(), $monitor->getImdbId(),
$monitor->getUser()->getId(),
)); ));
$monitor->setStatus('Complete'); $monitor->setStatus('Complete');
$monitor->setDownloadedAt(new DateTimeIMmutable()); $monitor->setDownloadedAt(new DateTimeIMmutable());
@@ -59,7 +64,7 @@ readonly class MonitorMovieHandler implements HandlerInterface
} }
$monitor->setLastSearch(new DateTimeImmutable()); $monitor->setLastSearch(new DateTimeImmutable());
$monitor->setSearchCount($monitor->getSearchCount() + 1); $monitor->incrementSearchCount();
$this->entityManager->flush(); $this->entityManager->flush();
return new MonitorMovieResult( return new MonitorMovieResult(

View File

@@ -58,6 +58,7 @@ readonly class MonitorTvEpisodeHandler implements HandlerInterface
$result->filename, $result->filename,
'tvshows', 'tvshows',
$monitor->getImdbId(), $monitor->getImdbId(),
$monitor->getUser()->getId(),
)); ));
$monitor->setStatus('Complete'); $monitor->setStatus('Complete');
$monitor->setDownloadedAt(new DateTimeImmutable()); $monitor->setDownloadedAt(new DateTimeImmutable());

View File

@@ -12,7 +12,7 @@ class AddMonitorInput implements InputInterface
{ {
public function __construct( public function __construct(
#[SourceSecurity] #[SourceSecurity]
public string $userEmail, public int|string $userId,
#[SourceRequest('tmdbId')] #[SourceRequest('tmdbId')]
public string $tmdbId, public string $tmdbId,
@@ -36,7 +36,7 @@ class AddMonitorInput implements InputInterface
public function toCommand(): CommandInterface public function toCommand(): CommandInterface
{ {
return new AddMonitorCommand( return new AddMonitorCommand(
$this->userEmail, $this->userId,
$this->title, $this->title,
$this->imdbId, $this->imdbId,
$this->tmdbId, $this->tmdbId,

View File

@@ -5,6 +5,7 @@ namespace App\Monitor\Framework\Controller;
use App\Monitor\Action\Handler\AddMonitorHandler; use App\Monitor\Action\Handler\AddMonitorHandler;
use App\Monitor\Action\Input\AddMonitorInput; use App\Monitor\Action\Input\AddMonitorInput;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Mercure\HubInterface; use Symfony\Component\Mercure\HubInterface;
use Symfony\Component\Mercure\Update; use Symfony\Component\Mercure\Update;
@@ -17,6 +18,7 @@ class ApiController extends AbstractController
#[Autowire(service: 'twig')] #[Autowire(service: 'twig')]
private readonly Environment $renderer, private readonly Environment $renderer,
private readonly HubInterface $hub, private readonly HubInterface $hub,
private readonly Security $security,
) {} ) {}
#[Route('/api/monitor', name: 'api_monitor', methods: ['POST'])] #[Route('/api/monitor', name: 'api_monitor', methods: ['POST'])]
@@ -25,7 +27,9 @@ class ApiController extends AbstractController
AddMonitorHandler $handler, AddMonitorHandler $handler,
HubInterface $hub, HubInterface $hub,
) { ) {
$response = $handler->handle($input->toCommand()); $command = $input->toCommand();
$command->userId = $this->security->getUser()->getId();
$response = $handler->handle($command);
$hub->publish(new Update( $hub->publish(new Update(
'alerts', 'alerts',

View File

@@ -11,7 +11,7 @@ use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Scheduler\Attribute\AsCronTask; use Symfony\Component\Scheduler\Attribute\AsCronTask;
#[AsCronTask('*/10 * * * *', schedule: 'monitor')] #[AsCronTask('* * * * *', schedule: 'monitor')]
class MonitorDispatcher class MonitorDispatcher
{ {
public function __construct( public function __construct(
@@ -27,7 +27,7 @@ class MonitorDispatcher
'movie' => MonitorMovieCommand::class, 'movie' => MonitorMovieCommand::class,
'tvepisode' => MonitorTvEpisodeCommand::class, 'tvepisode' => MonitorTvEpisodeCommand::class,
'tvseason' => MonitorTvSeasonCommand::class, 'tvseason' => MonitorTvSeasonCommand::class,
'tvshow' => MonitorTvShowCommand::class, 'tvshows' => MonitorTvShowCommand::class,
]; ];
$monitors = $this->monitorRepository->findBy(['status' => ['New', 'Active']]); $monitors = $this->monitorRepository->findBy(['status' => ['New', 'Active']]);