Compare commits
2 Commits
v0.34.15
...
dev-config
| Author | SHA1 | Date | |
|---|---|---|---|
| 14739500f4 | |||
| 0aee4ae7df |
8
.env
8
.env
@@ -51,3 +51,11 @@ OIDC_CLIENT_ID="Enter your OIDC client id"
|
|||||||
OIDC_CLIENT_SECRET="Enter your OIDC client secret"
|
OIDC_CLIENT_SECRET="Enter your OIDC client secret"
|
||||||
OIDC_BYPASS_FORM_LOGIN=false
|
OIDC_BYPASS_FORM_LOGIN=false
|
||||||
###< drenso/symfony-oidc-bundle ###
|
###< drenso/symfony-oidc-bundle ###
|
||||||
|
|
||||||
|
|
||||||
|
SMTP_HOST=
|
||||||
|
SMTP_USER=
|
||||||
|
SMTP_PASS=
|
||||||
|
SMTP_PORT=
|
||||||
|
SMTP_FROM=
|
||||||
|
SMTP_FROM_NAME=""
|
||||||
@@ -43,6 +43,7 @@
|
|||||||
"symfony/mailer": "7.3.*",
|
"symfony/mailer": "7.3.*",
|
||||||
"symfony/mercure-bundle": "^0.3.9",
|
"symfony/mercure-bundle": "^0.3.9",
|
||||||
"symfony/messenger": "7.3.*",
|
"symfony/messenger": "7.3.*",
|
||||||
|
"symfony/monolog-bundle": "^3.10",
|
||||||
"symfony/runtime": "7.3.*",
|
"symfony/runtime": "7.3.*",
|
||||||
"symfony/scheduler": "7.3.*",
|
"symfony/scheduler": "7.3.*",
|
||||||
"symfony/security-bundle": "7.3.*",
|
"symfony/security-bundle": "7.3.*",
|
||||||
|
|||||||
264
composer.lock
generated
264
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "0f98dada0a01d471cebf4eb1b51b9006",
|
"content-hash": "cf9a5b3cdb6e21e270da6c4efee09005",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "1tomany/rich-bundle",
|
"name": "1tomany/rich-bundle",
|
||||||
@@ -2681,6 +2681,109 @@
|
|||||||
},
|
},
|
||||||
"time": "2025-02-06T08:48:15+00:00"
|
"time": "2025-02-06T08:48:15+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "monolog/monolog",
|
||||||
|
"version": "3.9.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Seldaek/monolog.git",
|
||||||
|
"reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6",
|
||||||
|
"reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.1",
|
||||||
|
"psr/log": "^2.0 || ^3.0"
|
||||||
|
},
|
||||||
|
"provide": {
|
||||||
|
"psr/log-implementation": "3.0.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"aws/aws-sdk-php": "^3.0",
|
||||||
|
"doctrine/couchdb": "~1.0@dev",
|
||||||
|
"elasticsearch/elasticsearch": "^7 || ^8",
|
||||||
|
"ext-json": "*",
|
||||||
|
"graylog2/gelf-php": "^1.4.2 || ^2.0",
|
||||||
|
"guzzlehttp/guzzle": "^7.4.5",
|
||||||
|
"guzzlehttp/psr7": "^2.2",
|
||||||
|
"mongodb/mongodb": "^1.8",
|
||||||
|
"php-amqplib/php-amqplib": "~2.4 || ^3",
|
||||||
|
"php-console/php-console": "^3.1.8",
|
||||||
|
"phpstan/phpstan": "^2",
|
||||||
|
"phpstan/phpstan-deprecation-rules": "^2",
|
||||||
|
"phpstan/phpstan-strict-rules": "^2",
|
||||||
|
"phpunit/phpunit": "^10.5.17 || ^11.0.7",
|
||||||
|
"predis/predis": "^1.1 || ^2",
|
||||||
|
"rollbar/rollbar": "^4.0",
|
||||||
|
"ruflin/elastica": "^7 || ^8",
|
||||||
|
"symfony/mailer": "^5.4 || ^6",
|
||||||
|
"symfony/mime": "^5.4 || ^6"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
|
||||||
|
"doctrine/couchdb": "Allow sending log messages to a CouchDB server",
|
||||||
|
"elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
|
||||||
|
"ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
|
||||||
|
"ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
|
||||||
|
"ext-mbstring": "Allow to work properly with unicode symbols",
|
||||||
|
"ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
|
||||||
|
"ext-openssl": "Required to send log messages using SSL",
|
||||||
|
"ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
|
||||||
|
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
|
||||||
|
"mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
|
||||||
|
"php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
|
||||||
|
"rollbar/rollbar": "Allow sending log messages to Rollbar",
|
||||||
|
"ruflin/elastica": "Allow sending log messages to an Elastic Search server"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-main": "3.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Monolog\\": "src/Monolog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Jordi Boggiano",
|
||||||
|
"email": "j.boggiano@seld.be",
|
||||||
|
"homepage": "https://seld.be"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Sends your logs to files, sockets, inboxes, databases and various web services",
|
||||||
|
"homepage": "https://github.com/Seldaek/monolog",
|
||||||
|
"keywords": [
|
||||||
|
"log",
|
||||||
|
"logging",
|
||||||
|
"psr-3"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/Seldaek/monolog/issues",
|
||||||
|
"source": "https://github.com/Seldaek/monolog/tree/3.9.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/Seldaek",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-03-24T10:02:05+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "nesbot/carbon",
|
"name": "nesbot/carbon",
|
||||||
"version": "3.10.0",
|
"version": "3.10.0",
|
||||||
@@ -7578,6 +7681,165 @@
|
|||||||
],
|
],
|
||||||
"time": "2025-02-19T08:51:26+00:00"
|
"time": "2025-02-19T08:51:26+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/monolog-bridge",
|
||||||
|
"version": "v7.3.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/monolog-bridge.git",
|
||||||
|
"reference": "1b188c8abbbef25b111da878797514b7a8d33990"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/1b188c8abbbef25b111da878797514b7a8d33990",
|
||||||
|
"reference": "1b188c8abbbef25b111da878797514b7a8d33990",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"monolog/monolog": "^3",
|
||||||
|
"php": ">=8.2",
|
||||||
|
"symfony/http-kernel": "^6.4|^7.0",
|
||||||
|
"symfony/service-contracts": "^2.5|^3"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/console": "<6.4",
|
||||||
|
"symfony/http-foundation": "<6.4",
|
||||||
|
"symfony/security-core": "<6.4"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/console": "^6.4|^7.0",
|
||||||
|
"symfony/http-client": "^6.4|^7.0",
|
||||||
|
"symfony/mailer": "^6.4|^7.0",
|
||||||
|
"symfony/messenger": "^6.4|^7.0",
|
||||||
|
"symfony/mime": "^6.4|^7.0",
|
||||||
|
"symfony/security-core": "^6.4|^7.0",
|
||||||
|
"symfony/var-dumper": "^6.4|^7.0"
|
||||||
|
},
|
||||||
|
"type": "symfony-bridge",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Bridge\\Monolog\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Provides integration for Monolog with various Symfony components",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/monolog-bridge/tree/v7.3.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-03-21T12:17:46+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/monolog-bundle",
|
||||||
|
"version": "v3.10.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/monolog-bundle.git",
|
||||||
|
"reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181",
|
||||||
|
"reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"monolog/monolog": "^1.25.1 || ^2.0 || ^3.0",
|
||||||
|
"php": ">=7.2.5",
|
||||||
|
"symfony/config": "^5.4 || ^6.0 || ^7.0",
|
||||||
|
"symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0",
|
||||||
|
"symfony/http-kernel": "^5.4 || ^6.0 || ^7.0",
|
||||||
|
"symfony/monolog-bridge": "^5.4 || ^6.0 || ^7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/console": "^5.4 || ^6.0 || ^7.0",
|
||||||
|
"symfony/phpunit-bridge": "^6.3 || ^7.0",
|
||||||
|
"symfony/yaml": "^5.4 || ^6.0 || ^7.0"
|
||||||
|
},
|
||||||
|
"type": "symfony-bundle",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "3.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Bundle\\MonologBundle\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Symfony MonologBundle",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"keywords": [
|
||||||
|
"log",
|
||||||
|
"logging"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/symfony/monolog-bundle/issues",
|
||||||
|
"source": "https://github.com/symfony/monolog-bundle/tree/v3.10.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2023-11-06T17:08:13+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/options-resolver",
|
"name": "symfony/options-resolver",
|
||||||
"version": "v7.3.0",
|
"version": "v7.3.0",
|
||||||
|
|||||||
@@ -23,4 +23,5 @@ return [
|
|||||||
SymfonyCasts\Bundle\ResetPassword\SymfonyCastsResetPasswordBundle::class => ['all' => true],
|
SymfonyCasts\Bundle\ResetPassword\SymfonyCastsResetPasswordBundle::class => ['all' => true],
|
||||||
Drenso\OidcBundle\DrensoOidcBundle::class => ['all' => true],
|
Drenso\OidcBundle\DrensoOidcBundle::class => ['all' => true],
|
||||||
SpomkyLabs\PwaBundle\SpomkyLabsPwaBundle::class => ['all' => true],
|
SpomkyLabs\PwaBundle\SpomkyLabsPwaBundle::class => ['all' => true],
|
||||||
|
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||||
];
|
];
|
||||||
|
|||||||
78
config/packages/monolog.yaml
Normal file
78
config/packages/monolog.yaml
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
monolog:
|
||||||
|
channels:
|
||||||
|
- deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
|
||||||
|
- monitor
|
||||||
|
|
||||||
|
when@dev:
|
||||||
|
monolog:
|
||||||
|
handlers:
|
||||||
|
main:
|
||||||
|
type: stream
|
||||||
|
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||||
|
level: debug
|
||||||
|
channels: ["!event"]
|
||||||
|
# uncomment to get logging in your browser
|
||||||
|
# you may have to allow bigger header sizes in your Web server configuration
|
||||||
|
#firephp:
|
||||||
|
# type: firephp
|
||||||
|
# level: info
|
||||||
|
#chromephp:
|
||||||
|
# type: chromephp
|
||||||
|
# level: info
|
||||||
|
console:
|
||||||
|
type: console
|
||||||
|
process_psr_3_messages: false
|
||||||
|
channels: ["!event", "!doctrine", "!console"]
|
||||||
|
monitor:
|
||||||
|
type: stream
|
||||||
|
action_level: debug
|
||||||
|
path: "%kernel.logs_dir%/monitors.log"
|
||||||
|
channels: [monitor]
|
||||||
|
|
||||||
|
when@test:
|
||||||
|
monolog:
|
||||||
|
handlers:
|
||||||
|
main:
|
||||||
|
type: fingers_crossed
|
||||||
|
action_level: error
|
||||||
|
handler: nested
|
||||||
|
excluded_http_codes: [404, 405]
|
||||||
|
channels: ["!event"]
|
||||||
|
nested:
|
||||||
|
type: stream
|
||||||
|
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||||
|
level: debug
|
||||||
|
monitor:
|
||||||
|
type: stream
|
||||||
|
action_level: info
|
||||||
|
path: "%kernel.logs_dir%/monitors.log"
|
||||||
|
channels: [monitor]
|
||||||
|
|
||||||
|
when@prod:
|
||||||
|
monolog:
|
||||||
|
handlers:
|
||||||
|
main:
|
||||||
|
type: fingers_crossed
|
||||||
|
action_level: error
|
||||||
|
handler: nested
|
||||||
|
excluded_http_codes: [404, 405]
|
||||||
|
buffer_size: 50 # How many messages should be saved? Prevent memory leaks
|
||||||
|
nested:
|
||||||
|
type: stream
|
||||||
|
path: php://stderr
|
||||||
|
level: debug
|
||||||
|
formatter: monolog.formatter.json
|
||||||
|
console:
|
||||||
|
type: console
|
||||||
|
process_psr_3_messages: false
|
||||||
|
channels: ["!event", "!doctrine"]
|
||||||
|
deprecation:
|
||||||
|
type: stream
|
||||||
|
channels: [deprecation]
|
||||||
|
path: php://stderr
|
||||||
|
formatter: monolog.formatter.json
|
||||||
|
monitor:
|
||||||
|
type: stream
|
||||||
|
action_level: info
|
||||||
|
path: "%kernel.logs_dir%/monitors.log"
|
||||||
|
channels: [monitor]
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
parameters:
|
parameters:
|
||||||
# App
|
# App
|
||||||
app.url: '%env(APP_URL)%'
|
app.url: '%env(APP_URL)%'
|
||||||
|
app.env: '%env(default:app.default.env:APP_ENV)%'
|
||||||
app.version: '%env(default:app.default.version:APP_VERSION)%'
|
app.version: '%env(default:app.default.version:APP_VERSION)%'
|
||||||
|
|
||||||
# Debrid Services
|
# Debrid Services
|
||||||
@@ -32,6 +33,7 @@ parameters:
|
|||||||
app.cache.redis.host.default: 'redis://redis'
|
app.cache.redis.host.default: 'redis://redis'
|
||||||
|
|
||||||
# Various configs
|
# Various configs
|
||||||
|
app.default.env: 'prod'
|
||||||
app.default.version: '0.dev'
|
app.default.version: '0.dev'
|
||||||
app.default.timezone: 'America/Chicago'
|
app.default.timezone: 'America/Chicago'
|
||||||
|
|
||||||
|
|||||||
105
src/Base/Config/AppConfig.php
Normal file
105
src/Base/Config/AppConfig.php
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Base\Config;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
|
|
||||||
|
class AppConfig implements ConfigInterface
|
||||||
|
{
|
||||||
|
private array $messages = [];
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
#[Autowire(param: 'app.env')]
|
||||||
|
private readonly ?string $appEnv = null,
|
||||||
|
|
||||||
|
#[Autowire(param: 'app.url')]
|
||||||
|
private readonly ?string $appUrl = null,
|
||||||
|
|
||||||
|
#[Autowire(param: 'app.debrid.real_debrid.key')]
|
||||||
|
private readonly ?string $realDebridApiKey = null,
|
||||||
|
|
||||||
|
#[Autowire(param: 'app.meta_provider.tmdb.key')]
|
||||||
|
private readonly ?string $tmdbApiKey = null,
|
||||||
|
|
||||||
|
#[Autowire(param: 'media.movies_path')]
|
||||||
|
private readonly ?string $moviesPath = null,
|
||||||
|
|
||||||
|
#[Autowire(param: 'media.tvshows_path')]
|
||||||
|
private readonly ?string $tvshowsPath = null,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function isValid(): bool
|
||||||
|
{
|
||||||
|
$valid = true;
|
||||||
|
|
||||||
|
if (false === $this->isVariableValid('APP_ENV', $this->appEnv)) {
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $this->isVariableValid('APP_URL', $this->appUrl)) {
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $this->isVariableValid('REAL_DEBRID_KEY', $this->realDebridApiKey)) {
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $this->isVariableValid('TMDB_API', $this->tmdbApiKey)) {
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $this->isVariableValid('MOVIES_PATH', $this->moviesPath)) {
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $this->isVariableValid('TVSHOWS_PATH', $this->tvshowsPath)) {
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMessages(): array
|
||||||
|
{
|
||||||
|
return $this->messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isVariableValid($key, $value): bool
|
||||||
|
{
|
||||||
|
if ("" === $value || null === $value) {
|
||||||
|
$this->messages[] = "Your system is misconfigured. Please set the $key environment variable appropriately.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAppEnv(): ?string
|
||||||
|
{
|
||||||
|
return $this->appEnv;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAppUrl(): ?string
|
||||||
|
{
|
||||||
|
return $this->appUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRealDebridApiKey(): ?string
|
||||||
|
{
|
||||||
|
return $this->realDebridApiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTmdbApiKey(): ?string
|
||||||
|
{
|
||||||
|
return $this->tmdbApiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMoviesPath(): ?string
|
||||||
|
{
|
||||||
|
return $this->moviesPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTvshowsPath(): ?string
|
||||||
|
{
|
||||||
|
return $this->tvshowsPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
88
src/Base/Config/Auth/OidcConfig.php
Normal file
88
src/Base/Config/Auth/OidcConfig.php
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Base\Config\Auth;
|
||||||
|
|
||||||
|
use App\Base\Config\ConfigInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
|
|
||||||
|
class OidcConfig implements ConfigInterface
|
||||||
|
{
|
||||||
|
private array $messages = [];
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
#[Autowire(param: 'auth.method')]
|
||||||
|
private readonly ?string $authMethod = null,
|
||||||
|
|
||||||
|
#[Autowire(param: 'auth.oidc.well_known_url')]
|
||||||
|
private readonly ?string $wellKnownUrl = null,
|
||||||
|
|
||||||
|
#[Autowire(param: 'auth.oidc.client_id')]
|
||||||
|
private readonly ?string $clientId = null,
|
||||||
|
|
||||||
|
#[Autowire(param: 'auth.oidc.client_secret')]
|
||||||
|
private readonly ?string $clientSecret = null,
|
||||||
|
|
||||||
|
#[Autowire(param: 'auth.oidc.bypass_form_login')]
|
||||||
|
private readonly ?bool $bypassFormLogin = null,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function isEnabled(): bool
|
||||||
|
{
|
||||||
|
return "oidc" === strtolower($this->authMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isValid(): bool
|
||||||
|
{
|
||||||
|
$valid = true;
|
||||||
|
|
||||||
|
if (true === $this->isEnabled()) {
|
||||||
|
if (false === $this->isVariableValid("OIDC_CLIENT_ID", $this->clientId)) {
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $this->isVariableValid("OIDC_CLIENT_SECRET", $this->clientSecret)) {
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $this->isVariableValid("OIDC_WELL_KNOWN_URL", $this->wellKnownUrl)) {
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getWellKnownUrl(): ?string
|
||||||
|
{
|
||||||
|
return $this->wellKnownUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClientId(): ?string
|
||||||
|
{
|
||||||
|
return $this->clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getClientSecret(): ?string
|
||||||
|
{
|
||||||
|
return $this->clientSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBypassFormLogin(): ?bool
|
||||||
|
{
|
||||||
|
return $this->bypassFormLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMessages(): array
|
||||||
|
{
|
||||||
|
return $this->messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isVariableValid(string $key, mixed $value): bool
|
||||||
|
{
|
||||||
|
if ("" === $value || null === $value) {
|
||||||
|
$this->messages[] = "Your OIDC is misconfigured. Please set the $key environment variable to the required value.";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
62
src/Base/Config/AuthConfig.php
Normal file
62
src/Base/Config/AuthConfig.php
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Base\Config;
|
||||||
|
|
||||||
|
use App\Base\Config\Auth\OidcConfig;
|
||||||
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
|
|
||||||
|
class AuthConfig implements ConfigInterface
|
||||||
|
{
|
||||||
|
const AUTH_METHODS = ['form_login', 'oidc'];
|
||||||
|
|
||||||
|
private array $messages = [];
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
#[Autowire(param: 'auth.method')]
|
||||||
|
private readonly ?string $authMethod,
|
||||||
|
private readonly OidcConfig $oidcConfig,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function isMethod(string $method): bool
|
||||||
|
{
|
||||||
|
return $this->getAuthMethod() === strtolower($method);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAuthMethod(): string
|
||||||
|
{
|
||||||
|
return strtolower($this->authMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOidcConfig(): OidcConfig
|
||||||
|
{
|
||||||
|
return $this->oidcConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isValid(): bool
|
||||||
|
{
|
||||||
|
$valid = true;
|
||||||
|
if (null === $this->getAuthMethod() || "" === $this->getAuthMethod()) {
|
||||||
|
$this->messages[] = "Your auth method is missing. Please set the AUTH_METHOD environment variable to your desired value. Valid options: [form_login, oidc].";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_array($this->getAuthMethod(), self::AUTH_METHODS, true)) {
|
||||||
|
$this->messages[] = "Your auth method is incorrect. Please set the AUTH_METHOD environment variable to your desired value. Valid options: [form_login, oidc].";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("oidc" === $this->getAuthMethod()) {
|
||||||
|
if (false === $this->oidcConfig->isValid()) {
|
||||||
|
$this->messages += $this->oidcConfig->getMessages();
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMessages(): array
|
||||||
|
{
|
||||||
|
return $this->messages;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/Base/Config/ConfigInterface.php
Normal file
12
src/Base/Config/ConfigInterface.php
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Base\Config;
|
||||||
|
|
||||||
|
interface ConfigInterface
|
||||||
|
{
|
||||||
|
/** Validates the config values are present and as expected */
|
||||||
|
public function isValid(): bool;
|
||||||
|
|
||||||
|
/** Holds the error messages so they can be logged */
|
||||||
|
public function getMessages(): array;
|
||||||
|
}
|
||||||
113
src/Base/Config/SmtpConfig.php
Normal file
113
src/Base/Config/SmtpConfig.php
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Base\Config;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
|
|
||||||
|
class SmtpConfig implements ConfigInterface
|
||||||
|
{
|
||||||
|
private array $messages = [];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SMTP is considered enabled if any of
|
||||||
|
* the parameters are set. If none are set,
|
||||||
|
* then the User must not need it.
|
||||||
|
*/
|
||||||
|
private bool $isEnabled = false;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
#[Autowire(env: 'SMTP_HOST')]
|
||||||
|
private readonly ?string $smtpHost,
|
||||||
|
#[Autowire(env: 'SMTP_USER')]
|
||||||
|
private readonly ?string $smtpUser,
|
||||||
|
#[Autowire(env: 'SMTP_PASS')]
|
||||||
|
private readonly ?string $smtpPass,
|
||||||
|
#[Autowire(env: 'SMTP_PORT')]
|
||||||
|
private readonly ?string $smtpPort,
|
||||||
|
#[Autowire(env: 'SMTP_FROM')]
|
||||||
|
private readonly ?string $smtpFrom,
|
||||||
|
#[Autowire(env: 'SMTP_FROM_NAME')]
|
||||||
|
private readonly ?string $smtpFromName,
|
||||||
|
) {
|
||||||
|
foreach (func_get_args() as $key => $value) {
|
||||||
|
if ("" !== $value && $value !== null) {
|
||||||
|
$this->isEnabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isEnabled(): bool
|
||||||
|
{
|
||||||
|
return $this->isEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMessages(): array
|
||||||
|
{
|
||||||
|
return $this->messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isValid(): bool
|
||||||
|
{
|
||||||
|
if (false === $this->isEnabled) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$valid = true;
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
'SMTP_HOST' => $this->smtpHost,
|
||||||
|
'SMTP_USER' => $this->smtpUser,
|
||||||
|
'SMTP_PASS' => $this->smtpPass,
|
||||||
|
'SMTP_PORT' => $this->smtpPort,
|
||||||
|
'SMTP_FROM' => $this->smtpFrom,
|
||||||
|
'SMTP_FROM_NAME' => $this->smtpFromName,
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($params as $key => $value) {
|
||||||
|
if (false === $this->isVariableValid($key, $value)) {
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isVariableValid($key, $value): bool
|
||||||
|
{
|
||||||
|
if ("" === $value || null === $value) {
|
||||||
|
$this->messages[] = "Your SMTP is misconfigured. Please set the $key environment variable appropriately.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSmtpHost(): ?string
|
||||||
|
{
|
||||||
|
return $this->smtpHost;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSmtpUser(): ?string
|
||||||
|
{
|
||||||
|
return $this->smtpUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSmtpPass(): ?string
|
||||||
|
{
|
||||||
|
return $this->smtpPass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSmtpPort(): ?string
|
||||||
|
{
|
||||||
|
return $this->smtpPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSmtpFrom(): ?string
|
||||||
|
{
|
||||||
|
return $this->smtpFrom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSmtpFromName(): ?string
|
||||||
|
{
|
||||||
|
return $this->smtpFromName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,58 +2,60 @@
|
|||||||
|
|
||||||
namespace App\Base;
|
namespace App\Base;
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
use App\Base\Config\AppConfig;
|
||||||
|
use App\Base\Config\AuthConfig;
|
||||||
|
use App\Base\Config\SmtpConfig;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Symfony\Contracts\Cache\TagAwareCacheInterface;
|
||||||
|
|
||||||
final class ConfigResolver
|
final class ConfigResolver
|
||||||
{
|
{
|
||||||
private array $messages = [];
|
private array $messages = [];
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#[Autowire(param: 'app.url')]
|
private readonly LoggerInterface $logger,
|
||||||
private readonly ?string $appUrl = null,
|
private readonly TagAwareCacheInterface $cache,
|
||||||
|
private readonly AuthConfig $authConfig,
|
||||||
#[Autowire(param: 'app.debrid.real_debrid.key')]
|
private readonly SmtpConfig $smtpConfig,
|
||||||
private readonly ?string $realDebridApiKey = null,
|
private readonly AppConfig $appConfig,
|
||||||
|
|
||||||
#[Autowire(param: 'app.meta_provider.tmdb.key')]
|
|
||||||
private readonly ?string $tmdbApiKey = null,
|
|
||||||
|
|
||||||
#[Autowire(param: 'media.movies_path')]
|
|
||||||
private readonly ?string $moviesPath = null,
|
|
||||||
|
|
||||||
#[Autowire(param: 'media.tvshows.path')]
|
|
||||||
private readonly ?string $tvshowsPath = null,
|
|
||||||
|
|
||||||
#[Autowire(param: 'auth.method')]
|
|
||||||
private readonly ?string $authMethod = null,
|
|
||||||
|
|
||||||
#[Autowire(param: 'auth.oidc.well_known_url')]
|
|
||||||
private readonly ?string $authOidcWellKnownUrl = null,
|
|
||||||
|
|
||||||
#[Autowire(param: 'auth.oidc.client_id')]
|
|
||||||
private readonly ?string $authOidcClientId = null,
|
|
||||||
|
|
||||||
#[Autowire(param: 'auth.oidc.client_secret')]
|
|
||||||
private readonly ?string $authOidcClientSecret = null,
|
|
||||||
|
|
||||||
#[Autowire(param: 'auth.oidc.bypass_form_login')]
|
|
||||||
private ?bool $authOidcBypassFormLogin = null,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function validate(): bool
|
public function validate(): bool
|
||||||
|
{
|
||||||
|
if ("prod" === strtolower($this->appConfig->getAppEnv())) {
|
||||||
|
return $this->cache->get('app.valid_config', function () {
|
||||||
|
return $this->doValidate();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return $this->doValidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function doValidate(): bool
|
||||||
{
|
{
|
||||||
$valid = true;
|
$valid = true;
|
||||||
|
|
||||||
if (null === $this->realDebridApiKey || "" === $this->realDebridApiKey) {
|
if (false === $this->appConfig->isValid()) {
|
||||||
$this->messages[] = "Your Real Debrid API key is missing. Please set it to the 'REAL_DEBRID_KEY' environment variable.";
|
$this->messages += $this->appConfig->getMessages();
|
||||||
$valid = false;
|
$valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null === $this->tmdbApiKey || "" === $this->tmdbApiKey) {
|
if (false === $this->authConfig->isValid()) {
|
||||||
$this->messages[] = "Your TMDB API key is missing. Please set it to the 'TMDB_API' environment variable.";
|
$this->messages += $this->authConfig->getMessages();
|
||||||
$valid = false;
|
$valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (false === $this->smtpConfig->isValid()) {
|
||||||
|
$this->messages += $this->smtpConfig->getMessages();
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $valid) {
|
||||||
|
foreach ($this->messages as $message) {
|
||||||
|
$this->logger->error('> [ConfigResolver] ' . $message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $valid;
|
return $valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,34 +64,18 @@ final class ConfigResolver
|
|||||||
return $this->messages;
|
return $this->messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAuthConfig(): AuthConfig
|
||||||
|
{
|
||||||
|
return $this->authConfig;
|
||||||
|
}
|
||||||
|
|
||||||
public function authIs(string $method): bool
|
public function authIs(string $method): bool
|
||||||
{
|
{
|
||||||
if (strtolower($method) === strtolower($this->getAuthMethod())) {
|
return $this->authConfig->isMethod($method);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAuthMethod(): string
|
public function getAuthMethod(): string
|
||||||
{
|
{
|
||||||
return strtolower($this->authMethod);
|
return $this->authConfig->getAuthMethod();
|
||||||
}
|
|
||||||
|
|
||||||
public function bypassFormLogin(): bool
|
|
||||||
{
|
|
||||||
return $this->authOidcBypassFormLogin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAuthConfig(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'method' => $this->authMethod,
|
|
||||||
'oidc' => [
|
|
||||||
'well_known_url' => $this->authOidcWellKnownUrl,
|
|
||||||
'client_id' => $this->authOidcClientId,
|
|
||||||
'client_secret' => $this->authOidcClientSecret,
|
|
||||||
'bypass_form_login' => $this->authOidcBypassFormLogin,
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Base\Framework\EventListener;
|
||||||
|
|
||||||
|
use App\Base\ConfigResolver;
|
||||||
|
use App\Base\Service\Broadcaster;
|
||||||
|
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
|
||||||
|
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||||
|
|
||||||
|
final class KernelRequestValidateConfig
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly ConfigResolver $configResolver,
|
||||||
|
private readonly Broadcaster $broadcaster,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
#[AsEventListener(event: 'kernel.request', priority: 20)]
|
||||||
|
public function validateConfig(RequestEvent $event): void
|
||||||
|
{
|
||||||
|
if (false === $this->configResolver->validate()) {
|
||||||
|
$this->broadcaster->systemAlert('Ruh-roh', 'It looks like your system is misconfigured. Please search the application logs for strings starting with "[error] > [ConfigResolver]" to find more information.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,8 @@ readonly class Broadcaster
|
|||||||
private Environment $renderer,
|
private Environment $renderer,
|
||||||
private HubInterface $hub,
|
private HubInterface $hub,
|
||||||
private RequestStack $requestStack,
|
private RequestStack $requestStack,
|
||||||
) {}
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
public function alert(string $title, string $message, string $type = "success"): void
|
public function alert(string $title, string $message, string $type = "success"): void
|
||||||
{
|
{
|
||||||
@@ -31,4 +32,18 @@ readonly class Broadcaster
|
|||||||
);
|
);
|
||||||
$this->hub->publish($update);
|
$this->hub->publish($update);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function systemAlert(string $title, string $message, string $type = "warning"): void
|
||||||
|
{
|
||||||
|
$update = new Update(
|
||||||
|
'system_alerts',
|
||||||
|
$this->renderer->render('broadcast/Alert.stream.html.twig', [
|
||||||
|
'alert_id' => uniqid(),
|
||||||
|
'title' => $title,
|
||||||
|
'message' => $message,
|
||||||
|
'type' => $type,
|
||||||
|
])
|
||||||
|
);
|
||||||
|
$this->hub->publish($update);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Monitor\Action\Handler;
|
|
||||||
|
|
||||||
use App\Download\Action\Command\DownloadMediaCommand;
|
|
||||||
use App\Monitor\Action\Command\MonitorMovieCommand;
|
|
||||||
use App\Monitor\Action\Result\MonitorMovieResult;
|
|
||||||
use App\Monitor\Framework\Entity\Monitor;
|
|
||||||
use App\Monitor\Framework\Repository\MonitorRepository;
|
|
||||||
use App\Monitor\Service\MonitorOptionEvaluator;
|
|
||||||
use App\Torrentio\Action\Command\GetMovieOptionsCommand;
|
|
||||||
use App\Torrentio\Action\Handler\GetMovieOptionsHandler;
|
|
||||||
use DateTimeImmutable;
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
|
||||||
use OneToMany\RichBundle\Contract\CommandInterface;
|
|
||||||
use OneToMany\RichBundle\Contract\HandlerInterface;
|
|
||||||
use OneToMany\RichBundle\Contract\ResultInterface;
|
|
||||||
use Psr\Log\LoggerInterface;
|
|
||||||
use Symfony\Bundle\SecurityBundle\Security;
|
|
||||||
use Symfony\Component\Messenger\MessageBusInterface;
|
|
||||||
|
|
||||||
/** @implements HandlerInterface<MonitorMovieCommand> */
|
|
||||||
readonly class MonitorMovieHandler implements HandlerInterface
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
private MonitorRepository $movieMonitorRepository,
|
|
||||||
private GetMovieOptionsHandler $getMovieOptionsHandler,
|
|
||||||
private EntityManagerInterface $entityManager,
|
|
||||||
private MessageBusInterface $bus,
|
|
||||||
private LoggerInterface $logger,
|
|
||||||
private Security $security,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public function handle(CommandInterface $command): ResultInterface
|
|
||||||
{
|
|
||||||
$this->logger->info('> [MonitorMovieHandler] Executing MonitorMovieHandler');
|
|
||||||
/** @var Monitor $monitor */
|
|
||||||
$monitor = $this->movieMonitorRepository->find($command->movieMonitorId);
|
|
||||||
$monitor->setStatus('In Progress');
|
|
||||||
|
|
||||||
$this->logger->info('> [MonitorMovieHandler] Searching for "' . $monitor->getTitle() . '" download options');
|
|
||||||
$results = $this->getMovieOptionsHandler->handle(
|
|
||||||
new GetMovieOptionsCommand($monitor->getTmdbId(), $monitor->getImdbId())
|
|
||||||
);
|
|
||||||
$this->logger->info('> [MonitorMovieHandler] Found ' . count($results->results) . ' download options');
|
|
||||||
|
|
||||||
$result = $this->monitorOptionEvaluator->evaluateOptions($monitor, $results->results);
|
|
||||||
|
|
||||||
if (null !== $result) {
|
|
||||||
$this->logger->info('> [MonitorMovieHandler] 1 result found: dispatching DownloadMediaCommand for "' . $result->title . '"');
|
|
||||||
$this->bus->dispatch(new DownloadMediaCommand(
|
|
||||||
$result->url,
|
|
||||||
$monitor->getTitle(),
|
|
||||||
$result->filename,
|
|
||||||
'movies',
|
|
||||||
$monitor->getImdbId(),
|
|
||||||
$monitor->getUser()->getId(),
|
|
||||||
));
|
|
||||||
$monitor->setStatus('Complete');
|
|
||||||
$monitor->setDownloadedAt(new DateTimeIMmutable());
|
|
||||||
} else {
|
|
||||||
$monitor->setStatus('Active');
|
|
||||||
}
|
|
||||||
|
|
||||||
$monitor->setLastSearch(new DateTimeImmutable());
|
|
||||||
$monitor->incrementSearchCount();
|
|
||||||
$this->entityManager->flush();
|
|
||||||
|
|
||||||
return new MonitorMovieResult(
|
|
||||||
status: 'OK',
|
|
||||||
result: [
|
|
||||||
'monitor' => $monitor,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,6 @@ namespace App\Monitor\Action\Handler;
|
|||||||
use App\Base\Util\EpisodeId;
|
use App\Base\Util\EpisodeId;
|
||||||
use App\Download\Action\Command\DownloadMediaCommand;
|
use App\Download\Action\Command\DownloadMediaCommand;
|
||||||
use App\Download\DownloadOptionEvaluator;
|
use App\Download\DownloadOptionEvaluator;
|
||||||
use App\Download\Framework\Entity\Download;
|
|
||||||
use App\Download\Framework\Repository\DownloadRepository;
|
use App\Download\Framework\Repository\DownloadRepository;
|
||||||
use App\Monitor\Action\Command\MonitorMovieCommand;
|
use App\Monitor\Action\Command\MonitorMovieCommand;
|
||||||
use App\Monitor\Action\Result\MonitorTvEpisodeResult;
|
use App\Monitor\Action\Result\MonitorTvEpisodeResult;
|
||||||
@@ -16,7 +15,6 @@ use App\Torrentio\Action\Handler\GetTvShowOptionsHandler;
|
|||||||
use App\User\Dto\UserPreferencesFactory;
|
use App\User\Dto\UserPreferencesFactory;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
|
||||||
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;
|
||||||
@@ -29,7 +27,6 @@ readonly class MonitorTvEpisodeHandler implements HandlerInterface
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
private GetTvShowOptionsHandler $getTvShowOptionsHandler,
|
private GetTvShowOptionsHandler $getTvShowOptionsHandler,
|
||||||
private DownloadOptionEvaluator $downloadOptionEvaluator,
|
private DownloadOptionEvaluator $downloadOptionEvaluator,
|
||||||
private EntityManagerInterface $entityManager,
|
|
||||||
private MessageBusInterface $bus,
|
private MessageBusInterface $bus,
|
||||||
private LoggerInterface $logger,
|
private LoggerInterface $logger,
|
||||||
private MonitorRepository $monitorRepository,
|
private MonitorRepository $monitorRepository,
|
||||||
|
|||||||
@@ -18,19 +18,22 @@ 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\Component\DependencyInjection\Attribute\Target;
|
||||||
|
|
||||||
/** @implements HandlerInterface<MonitorMovieCommand> */
|
/** @implements HandlerInterface<MonitorMovieCommand> */
|
||||||
readonly class MonitorTvShowHandler implements HandlerInterface
|
readonly class MonitorTvShowHandler implements HandlerInterface
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
#[Target('monitorLogger')]
|
||||||
|
private LoggerInterface $logger,
|
||||||
private MonitorRepository $monitorRepository,
|
private MonitorRepository $monitorRepository,
|
||||||
private EntityManagerInterface $entityManager,
|
private EntityManagerInterface $entityManager,
|
||||||
private MonitorTvEpisodeHandler $monitorTvEpisodeHandler,
|
private MonitorTvEpisodeHandler $monitorTvEpisodeHandler,
|
||||||
private MediaFiles $mediaFiles,
|
private MediaFiles $mediaFiles,
|
||||||
private LoggerInterface $logger,
|
|
||||||
private Tmdb $tmdb,
|
private Tmdb $tmdb,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|
||||||
public function handle(CommandInterface $command): ResultInterface
|
public function handle(CommandInterface $command): ResultInterface
|
||||||
{
|
{
|
||||||
$this->logger->info('> [MonitorTvShowHandler] Executing MonitorTvShowHandler');
|
$this->logger->info('> [MonitorTvShowHandler] Executing MonitorTvShowHandler');
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use App\Monitor\Action\Command\MonitorTvShowCommand;
|
|||||||
use App\Monitor\Framework\Repository\MonitorRepository;
|
use App\Monitor\Framework\Repository\MonitorRepository;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\Attribute\Target;
|
||||||
use Symfony\Component\Messenger\MessageBusInterface;
|
use Symfony\Component\Messenger\MessageBusInterface;
|
||||||
use Symfony\Component\Scheduler\Attribute\AsCronTask;
|
use Symfony\Component\Scheduler\Attribute\AsCronTask;
|
||||||
|
|
||||||
@@ -16,13 +17,14 @@ use Symfony\Component\Scheduler\Attribute\AsCronTask;
|
|||||||
class MonitorDispatcher
|
class MonitorDispatcher
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
#[Target('monitorLogger')]
|
||||||
private readonly LoggerInterface $logger,
|
private readonly LoggerInterface $logger,
|
||||||
private readonly MonitorRepository $monitorRepository,
|
private readonly MonitorRepository $monitorRepository,
|
||||||
private readonly MessageBusInterface $bus,
|
private readonly MessageBusInterface $bus,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function __invoke() {
|
public function __invoke() {
|
||||||
$this->logger->info('[MonitorDispatcher] Executing MonitorDispatcher');
|
$this->logger->info('[MonitorDispatcher] > Executing MonitorDispatcher');
|
||||||
|
|
||||||
$this->cleanupStuckMonitors();
|
$this->cleanupStuckMonitors();
|
||||||
|
|
||||||
@@ -34,15 +36,19 @@ class MonitorDispatcher
|
|||||||
];
|
];
|
||||||
|
|
||||||
$monitors = $this->monitorRepository->findBy(['status' => ['New', 'Active']]);
|
$monitors = $this->monitorRepository->findBy(['status' => ['New', 'Active']]);
|
||||||
|
$this->logger->info('[MonitorDispatcher] ' . count($monitors) . ' monitors found');
|
||||||
|
|
||||||
foreach ($monitors as $monitor) {
|
foreach ($monitors as $monitor) {
|
||||||
|
$this->logger->info('[MonitorDispatcher] - Evaluating monitor ' . $monitor->getId() . ' for "' . $monitor->getTitle() . '"');
|
||||||
$monitor->setStatus('In Progress');
|
$monitor->setStatus('In Progress');
|
||||||
$this->monitorRepository->getEntityManager()->flush();
|
$this->monitorRepository->getEntityManager()->flush();
|
||||||
|
|
||||||
$command = $monitorHandlers[$monitor->getMonitorType()];
|
$command = $monitorHandlers[$monitor->getMonitorType()];
|
||||||
$this->logger->info('[MonitorDispatcher] Dispatching ' . $command . ' for ' . $monitor->getTitle());
|
$this->logger->info('[MonitorDispatcher] Dispatching ' . $command . ' for ' . $monitor->getTitle());
|
||||||
$this->bus->dispatch(new $command($monitor->getId()));
|
$this->bus->dispatch(new $command($monitor->getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->logger->info('[MonitorDispatcher] < Complete');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function cleanupStuckMonitors(): void
|
private function cleanupStuckMonitors(): void
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class LoginController extends AbstractController
|
|||||||
return $this->redirectToRoute('app_getting_started');
|
return $this->redirectToRoute('app_getting_started');
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($config->authIs('oidc') && $config->bypassFormLogin()) {
|
if ($config->authIs('oidc') && true === $config->getAuthConfig()->getOidcConfig()->getBypassFormLogin()) {
|
||||||
return $this->redirectToRoute('app_login_oidc');
|
return $this->redirectToRoute('app_login_oidc');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace App\User\Framework\Controller\Web;
|
namespace App\User\Framework\Controller\Web;
|
||||||
|
|
||||||
use App\Base\ConfigResolver;
|
use App\Base\ConfigResolver;
|
||||||
|
use App\Base\Service\Broadcaster;
|
||||||
use Drenso\OidcBundle\OidcClientInterface;
|
use Drenso\OidcBundle\OidcClientInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Bundle\SecurityBundle\Security;
|
use Symfony\Bundle\SecurityBundle\Security;
|
||||||
@@ -15,13 +16,15 @@ class LoginOidcController extends AbstractController
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private ConfigResolver $configResolver,
|
private ConfigResolver $configResolver,
|
||||||
|
private Broadcaster $broadcaster,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
#[Route('/login/oidc', name: 'app_login_oidc')]
|
#[Route('/login/oidc', name: 'app_login_oidc')]
|
||||||
public function oidcStart(OidcClientInterface $oidcClient): RedirectResponse
|
public function oidcStart(OidcClientInterface $oidcClient): RedirectResponse
|
||||||
{
|
{
|
||||||
if (false === $this->configResolver->authIs('oidc')) {
|
if (false === $this->configResolver->authIs('oidc')) {
|
||||||
throw new \Exception('You must configure the OIDC environment variables before logging in at this route.');
|
$this->broadcaster->systemAlert('Your authentication must be set to "oidc" in order to login with OIDC.', 'warning');
|
||||||
|
return $this->redirectToRoute('app_login');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect to authorization @ OIDC provider
|
// Redirect to authorization @ OIDC provider
|
||||||
|
|||||||
@@ -4,13 +4,9 @@ namespace App\User\Framework\Security;
|
|||||||
|
|
||||||
use App\User\Framework\Entity\User;
|
use App\User\Framework\Entity\User;
|
||||||
use App\User\Framework\Repository\UserRepository;
|
use App\User\Framework\Repository\UserRepository;
|
||||||
use Drenso\OidcBundle\Exception\OidcException;
|
|
||||||
use Drenso\OidcBundle\Model\OidcTokens;
|
use Drenso\OidcBundle\Model\OidcTokens;
|
||||||
use Drenso\OidcBundle\Model\OidcUserData;
|
use Drenso\OidcBundle\Model\OidcUserData;
|
||||||
use Drenso\OidcBundle\Security\UserProvider\OidcUserProviderInterface;
|
use Drenso\OidcBundle\Security\UserProvider\OidcUserProviderInterface;
|
||||||
use Symfony\Component\PasswordHasher\PasswordHasherInterface;
|
|
||||||
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
|
|
||||||
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
|
||||||
use Symfony\Component\Security\Core\User\OidcUser;
|
use Symfony\Component\Security\Core\User\OidcUser;
|
||||||
use Symfony\Component\Security\Core\User\UserInterface;
|
use Symfony\Component\Security\Core\User\UserInterface;
|
||||||
|
|
||||||
@@ -47,7 +43,7 @@ class OidcUserProvider implements OidcUserProviderInterface
|
|||||||
|
|
||||||
public function supportsClass(string $class): bool
|
public function supportsClass(string $class): bool
|
||||||
{
|
{
|
||||||
return User::class === $class || OidcUser::class === $class;
|
return User::class === $class || OidcUser::class === $class || is_subclass_of($class, User::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadUserByIdentifier(string $identifier): UserInterface
|
public function loadUserByIdentifier(string $identifier): UserInterface
|
||||||
|
|||||||
12
symfony.lock
12
symfony.lock
@@ -217,6 +217,18 @@
|
|||||||
"config/packages/messenger.yaml"
|
"config/packages/messenger.yaml"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"symfony/monolog-bundle": {
|
||||||
|
"version": "3.10",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "main",
|
||||||
|
"version": "3.7",
|
||||||
|
"ref": "aff23899c4440dd995907613c1dd709b6f59503f"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/monolog.yaml"
|
||||||
|
]
|
||||||
|
},
|
||||||
"symfony/property-info": {
|
"symfony/property-info": {
|
||||||
"version": "7.3",
|
"version": "7.3",
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
|||||||
@@ -23,5 +23,17 @@
|
|||||||
<span class="text-sm">v{{ version }}</span>
|
<span class="text-sm">v{{ version }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div {{ turbo_stream_listen('system_alerts') }} class="fixed z-40 top-10 right-10">
|
||||||
|
<div class="z-40">
|
||||||
|
<ul id="alert_list" class="flex flex-col gap-2">
|
||||||
|
{% for message in app.flashes('warning') %}
|
||||||
|
<twig:Alert :title="'Warning'" :message="message" :alert_id="''" type="warning" data-controller="alert" />
|
||||||
|
{% endfor %}
|
||||||
|
{% for message in app.flashes('success') %}
|
||||||
|
<twig:Alert :title="'Success'" :message="message" :alert_id="''" type="warning" data-controller="alert" />
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -26,6 +26,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div {{ turbo_stream_listen('system_alerts') }} class="fixed z-40 top-10 right-10">
|
||||||
|
<div class="z-40">
|
||||||
|
<ul id="alert_list" class="flex flex-col gap-2">
|
||||||
|
{% for message in app.flashes('system_warning') %}
|
||||||
|
<twig:Alert :title="'Warning'" :message="message" :alert_id="''" type="warning" data-controller="alert" />
|
||||||
|
{% endfor %}
|
||||||
|
{% for message in app.flashes('system_success') %}
|
||||||
|
<twig:Alert :title="'Success'" :message="message" :alert_id="''" type="warning" data-controller="alert" />
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div {{ turbo_stream_listen(app.session.get('mercure_alert_topic')) }} class="fixed z-40 top-10 right-10">
|
<div {{ turbo_stream_listen(app.session.get('mercure_alert_topic')) }} class="fixed z-40 top-10 right-10">
|
||||||
<div class="z-40">
|
<div class="z-40">
|
||||||
<ul id="alert_list" class="flex flex-col gap-2">
|
<ul id="alert_list" class="flex flex-col gap-2">
|
||||||
|
|||||||
Reference in New Issue
Block a user