Fix errors with Webhooks and error templates.
This commit is contained in:
parent
33a1c84b5a
commit
3068f7c4e7
|
@ -9,6 +9,7 @@ use App\Environment;
|
|||
use App\Exception;
|
||||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Service\ServiceControl;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
final class LogsAction
|
||||
|
@ -16,7 +17,8 @@ final class LogsAction
|
|||
use HasLogViewer;
|
||||
|
||||
public function __construct(
|
||||
private readonly Environment $environment
|
||||
private readonly Environment $environment,
|
||||
private readonly ServiceControl $serviceControl,
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -78,37 +80,19 @@ final class LogsAction
|
|||
];
|
||||
|
||||
if ($this->environment->isDocker()) {
|
||||
$langServiceLog = __('%s Service Log');
|
||||
$logPaths['service_mariadb'] = [
|
||||
'name' => sprintf($langServiceLog, __('MariaDB')),
|
||||
'path' => $tempDir . '/service_mariadb.log',
|
||||
'tail' => true,
|
||||
];
|
||||
$logPaths['service_redis'] = [
|
||||
'name' => sprintf($langServiceLog, __('Redis')),
|
||||
'path' => $tempDir . '/service_redis.log',
|
||||
'tail' => true,
|
||||
];
|
||||
$logPaths['service_beanstalkd'] = [
|
||||
'name' => sprintf($langServiceLog, __('Beanstalkd')),
|
||||
'path' => $tempDir . '/service_beanstalkd.log',
|
||||
'tail' => true,
|
||||
];
|
||||
$logPaths['service_cron'] = [
|
||||
'name' => sprintf($langServiceLog, __('Cron')),
|
||||
'path' => $tempDir . '/service_crond.log',
|
||||
'tail' => true,
|
||||
];
|
||||
$logPaths['service_nginx'] = [
|
||||
'name' => sprintf($langServiceLog, __('Nginx')),
|
||||
'path' => $tempDir . '/service_nginx.log',
|
||||
'tail' => true,
|
||||
];
|
||||
$logPaths['service_sftpgo'] = [
|
||||
'name' => sprintf($langServiceLog, __('SFTPGo')),
|
||||
'path' => $tempDir . '/service_sftpgo.log',
|
||||
'tail' => true,
|
||||
];
|
||||
$langServiceLog = __('Service Log: %s (%s)');
|
||||
|
||||
foreach ($this->serviceControl->getServiceNames() as $serviceKey => $serviceName) {
|
||||
$logPath = $tempDir . '/service_' . $serviceKey . '.log';
|
||||
|
||||
if (is_file($logPath)) {
|
||||
$logPaths['service_' . $serviceKey] = [
|
||||
'name' => sprintf($langServiceLog, $serviceKey, $serviceName),
|
||||
'path' => $logPath,
|
||||
'tail' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$logPaths['nginx_access'] = [
|
||||
'name' => __('Nginx Access Log'),
|
||||
|
|
|
@ -10,10 +10,13 @@ use App\Entity;
|
|||
use App\Enums\SupportedLocales;
|
||||
use App\Enums\SupportedThemes;
|
||||
use App\Http\ServerRequest;
|
||||
use App\Traits\RequestAwareTrait;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
final class Customization
|
||||
{
|
||||
use RequestAwareTrait;
|
||||
|
||||
private ?Entity\User $user = null;
|
||||
|
||||
private Entity\Settings $settings;
|
||||
|
@ -28,22 +31,34 @@ final class Customization
|
|||
|
||||
public function __construct(
|
||||
private readonly Environment $environment,
|
||||
Entity\Repository\SettingsRepository $settingsRepo,
|
||||
ServerRequestInterface $request
|
||||
Entity\Repository\SettingsRepository $settingsRepo
|
||||
) {
|
||||
$this->settings = $settingsRepo->readSettings();
|
||||
|
||||
$this->instanceName = $this->settings->getInstanceName() ?? '';
|
||||
|
||||
// Register current user
|
||||
$this->user = $request->getAttribute(ServerRequest::ATTR_USER);
|
||||
$this->user = null;
|
||||
$this->theme = SupportedThemes::default();
|
||||
$this->publicTheme = $this->settings->getPublicThemeEnum();
|
||||
|
||||
// Register current theme
|
||||
$this->theme = $this->determineTheme($request);
|
||||
$this->publicTheme = $this->determineTheme($request, true);
|
||||
$this->locale = SupportedLocales::default();
|
||||
}
|
||||
|
||||
// Register locale
|
||||
$this->locale = SupportedLocales::createFromRequest($this->environment, $request);
|
||||
public function setRequest(?ServerRequestInterface $request): void
|
||||
{
|
||||
$this->request = $request;
|
||||
|
||||
if (null !== $request) {
|
||||
// Register current user
|
||||
$this->user = $request->getAttribute(ServerRequest::ATTR_USER);
|
||||
|
||||
// Register current theme
|
||||
$this->theme = $this->determineTheme($request);
|
||||
$this->publicTheme = $this->determineTheme($request, true);
|
||||
|
||||
// Register locale
|
||||
$this->locale = SupportedLocales::createFromRequest($this->environment, $request);
|
||||
}
|
||||
}
|
||||
|
||||
private function determineTheme(
|
||||
|
|
|
@ -13,7 +13,6 @@ use App\Exception\PermissionDeniedException;
|
|||
use App\Middleware\InjectSession;
|
||||
use App\Session\Flash;
|
||||
use App\View;
|
||||
use DI\FactoryInterface;
|
||||
use Mezzio\Session\Session;
|
||||
use Monolog\Logger;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
@ -34,7 +33,7 @@ final class ErrorHandler extends \Slim\Handlers\ErrorHandler
|
|||
private string $loggerLevel = LogLevel::ERROR;
|
||||
|
||||
public function __construct(
|
||||
private readonly FactoryInterface $factory,
|
||||
private readonly View $view,
|
||||
private readonly Router $router,
|
||||
private readonly InjectSession $injectSession,
|
||||
private readonly Environment $environment,
|
||||
|
@ -142,14 +141,9 @@ final class ErrorHandler extends \Slim\Handlers\ErrorHandler
|
|||
return $response->withJson($apiResponse);
|
||||
}
|
||||
|
||||
try {
|
||||
$view = $this->factory->make(
|
||||
View::class,
|
||||
[
|
||||
'request' => $this->request,
|
||||
]
|
||||
);
|
||||
$view = $this->view->withRequest($this->request);
|
||||
|
||||
try {
|
||||
return $view->renderToResponse(
|
||||
$response,
|
||||
'system/error_http',
|
||||
|
@ -247,14 +241,9 @@ final class ErrorHandler extends \Slim\Handlers\ErrorHandler
|
|||
return $response->write($run->handleException($this->exception));
|
||||
}
|
||||
|
||||
try {
|
||||
$view = $this->factory->make(
|
||||
View::class,
|
||||
[
|
||||
'request' => $this->request,
|
||||
]
|
||||
);
|
||||
$view = $this->view->withRequest($this->request);
|
||||
|
||||
try {
|
||||
return $view->renderToResponse(
|
||||
$response,
|
||||
'system/error_general',
|
||||
|
|
|
@ -17,20 +17,16 @@ use Psr\Http\Server\RequestHandlerInterface;
|
|||
abstract class AbstractAuth implements MiddlewareInterface
|
||||
{
|
||||
public function __construct(
|
||||
protected Entity\Repository\SettingsRepository $settingsRepo,
|
||||
protected Environment $environment,
|
||||
protected Acl $acl
|
||||
protected readonly Entity\Repository\UserRepository $userRepo,
|
||||
protected readonly Environment $environment,
|
||||
protected readonly Acl $acl,
|
||||
protected readonly Customization $customization
|
||||
) {
|
||||
}
|
||||
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
// Initialize Customization (timezones, locales, etc) based on the current logged in user.
|
||||
$customization = new Customization(
|
||||
environment: $this->environment,
|
||||
settingsRepo: $this->settingsRepo,
|
||||
request: $request
|
||||
);
|
||||
$customization = $this->customization->withRequest($request);
|
||||
|
||||
// Initialize ACL (can only be initialized after Customization as it contains localizations).
|
||||
$acl = $this->acl->withRequest($request);
|
||||
|
|
|
@ -6,6 +6,7 @@ namespace App\Middleware\Auth;
|
|||
|
||||
use App\Acl;
|
||||
use App\Auth;
|
||||
use App\Customization;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Exception\CsrfValidationException;
|
||||
|
@ -21,13 +22,13 @@ final class ApiAuth extends AbstractAuth
|
|||
public const API_CSRF_NAMESPACE = 'api';
|
||||
|
||||
public function __construct(
|
||||
protected Entity\Repository\UserRepository $userRepo,
|
||||
protected Entity\Repository\ApiKeyRepository $apiKeyRepo,
|
||||
Entity\Repository\SettingsRepository $settingsRepo,
|
||||
Entity\Repository\UserRepository $userRepo,
|
||||
Environment $environment,
|
||||
Acl $acl
|
||||
Acl $acl,
|
||||
Customization $customization
|
||||
) {
|
||||
parent::__construct($settingsRepo, $environment, $acl);
|
||||
parent::__construct($userRepo, $environment, $acl, $customization);
|
||||
}
|
||||
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
|
|
|
@ -4,10 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Middleware\Auth;
|
||||
|
||||
use App\Acl;
|
||||
use App\Auth;
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use App\Http\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
@ -15,15 +12,6 @@ use Psr\Http\Server\RequestHandlerInterface;
|
|||
|
||||
final class StandardAuth extends AbstractAuth
|
||||
{
|
||||
public function __construct(
|
||||
private readonly Entity\Repository\UserRepository $userRepo,
|
||||
Entity\Repository\SettingsRepository $settingsRepo,
|
||||
Environment $environment,
|
||||
Acl $acl
|
||||
) {
|
||||
parent::__construct($settingsRepo, $environment, $acl);
|
||||
}
|
||||
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
// Initialize the Auth for this request.
|
||||
|
|
|
@ -22,9 +22,9 @@ final class GetCurrentUser implements MiddlewareInterface
|
|||
{
|
||||
public function __construct(
|
||||
private readonly Entity\Repository\UserRepository $userRepo,
|
||||
private readonly Entity\Repository\SettingsRepository $settingsRepo,
|
||||
private readonly Environment $environment,
|
||||
private readonly Acl $acl
|
||||
private readonly Acl $acl,
|
||||
private readonly Customization $customization
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -44,11 +44,7 @@ final class GetCurrentUser implements MiddlewareInterface
|
|||
->withAttribute('is_logged_in', (null !== $user));
|
||||
|
||||
// Initialize Customization (timezones, locales, etc) based on the current logged in user.
|
||||
$customization = new Customization(
|
||||
environment: $this->environment,
|
||||
settingsRepo: $this->settingsRepo,
|
||||
request: $request
|
||||
);
|
||||
$customization = $this->customization->withRequest($request);
|
||||
|
||||
// Initialize ACL (can only be initialized after Customization as it contains localizations).
|
||||
$acl = $this->acl->withRequest($request);
|
||||
|
|
32
src/View.php
32
src/View.php
|
@ -24,6 +24,7 @@ final class View extends Engine
|
|||
private readonly GlobalSections $sections;
|
||||
|
||||
public function __construct(
|
||||
Customization $customization,
|
||||
Environment $environment,
|
||||
EventDispatcherInterface $dispatcher,
|
||||
Version $version,
|
||||
|
@ -37,6 +38,7 @@ final class View extends Engine
|
|||
$this->addData(
|
||||
[
|
||||
'sections' => $this->sections,
|
||||
'customization' => $customization,
|
||||
'environment' => $environment,
|
||||
'version' => $version,
|
||||
'router' => $router,
|
||||
|
@ -99,17 +101,25 @@ final class View extends Engine
|
|||
$this->request = $request;
|
||||
|
||||
if (null !== $request) {
|
||||
$this->addData(
|
||||
[
|
||||
'request' => $request,
|
||||
'router' => $request->getAttribute(ServerRequest::ATTR_ROUTER),
|
||||
'auth' => $request->getAttribute(ServerRequest::ATTR_AUTH),
|
||||
'acl' => $request->getAttribute(ServerRequest::ATTR_ACL),
|
||||
'customization' => $request->getAttribute(ServerRequest::ATTR_CUSTOMIZATION),
|
||||
'flash' => $request->getAttribute(ServerRequest::ATTR_SESSION_FLASH),
|
||||
'user' => $request->getAttribute(ServerRequest::ATTR_USER),
|
||||
]
|
||||
);
|
||||
$requestData = [
|
||||
'request' => $request,
|
||||
'auth' => $request->getAttribute(ServerRequest::ATTR_AUTH),
|
||||
'acl' => $request->getAttribute(ServerRequest::ATTR_ACL),
|
||||
'flash' => $request->getAttribute(ServerRequest::ATTR_SESSION_FLASH),
|
||||
'user' => $request->getAttribute(ServerRequest::ATTR_USER),
|
||||
];
|
||||
|
||||
$router = $request->getAttribute(ServerRequest::ATTR_ROUTER);
|
||||
if (null !== $router) {
|
||||
$requestData['router'] = $router;
|
||||
}
|
||||
|
||||
$customization = $request->getAttribute(ServerRequest::ATTR_CUSTOMIZATION);
|
||||
if (null !== $customization) {
|
||||
$requestData['customization'] = $customization;
|
||||
}
|
||||
|
||||
$this->addData($requestData);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -115,12 +115,12 @@ abstract class AbstractConnector implements ConnectorInterface
|
|||
return (preg_match($pattern, $url)) ? $url : null;
|
||||
}
|
||||
|
||||
protected function incompleteConfigException(): \InvalidArgumentException
|
||||
protected function incompleteConfigException(string $name): \InvalidArgumentException
|
||||
{
|
||||
return new \InvalidArgumentException(
|
||||
sprintf(
|
||||
'Webhook %s is missing necessary configuration. Skipping...',
|
||||
static::NAME
|
||||
$name
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ final class Discord extends AbstractConnector
|
|||
$webhook_url = $this->getValidUrl($config['webhook_url'] ?? '');
|
||||
|
||||
if (empty($webhook_url)) {
|
||||
throw $this->incompleteConfigException();
|
||||
throw $this->incompleteConfigException(self::NAME);
|
||||
}
|
||||
|
||||
$raw_vars = [
|
||||
|
|
|
@ -40,7 +40,7 @@ final class Email extends AbstractConnector
|
|||
$emailBody = $config['message'];
|
||||
|
||||
if (empty($emailTo) || empty($emailSubject) || empty($emailBody)) {
|
||||
throw $this->incompleteConfigException();
|
||||
throw $this->incompleteConfigException(self::NAME);
|
||||
}
|
||||
|
||||
$email = $this->mail->createMessage();
|
||||
|
|
|
@ -24,7 +24,7 @@ final class Generic extends AbstractConnector
|
|||
$webhook_url = $this->getValidUrl($config['webhook_url'] ?? '');
|
||||
|
||||
if (empty($webhook_url)) {
|
||||
throw $this->incompleteConfigException();
|
||||
throw $this->incompleteConfigException(self::NAME);
|
||||
}
|
||||
|
||||
$request_options = [
|
||||
|
|
|
@ -34,7 +34,7 @@ final class GoogleAnalytics extends AbstractConnector
|
|||
): void {
|
||||
$config = $webhook->getConfig();
|
||||
if (empty($config['tracking_id'])) {
|
||||
throw $this->incompleteConfigException();
|
||||
throw $this->incompleteConfigException(self::NAME);
|
||||
}
|
||||
|
||||
// Get listen URLs for each mount point.
|
||||
|
|
|
@ -34,7 +34,7 @@ final class Mastodon extends AbstractConnector
|
|||
$accessToken = trim($config['access_token'] ?? '');
|
||||
|
||||
if (empty($instanceUrl) || empty($accessToken)) {
|
||||
throw $this->incompleteConfigException();
|
||||
throw $this->incompleteConfigException(self::NAME);
|
||||
}
|
||||
|
||||
$messages = $this->replaceVariables(
|
||||
|
|
|
@ -36,7 +36,7 @@ final class MatomoAnalytics extends AbstractConnector
|
|||
$config = $webhook->getConfig();
|
||||
|
||||
if (empty($config['matomo_url']) || empty($config['site_id'])) {
|
||||
throw $this->incompleteConfigException();
|
||||
throw $this->incompleteConfigException(self::NAME);
|
||||
}
|
||||
|
||||
// Get listen URLs for each mount point.
|
||||
|
|
|
@ -30,7 +30,7 @@ final class Telegram extends AbstractConnector
|
|||
$chat_id = trim($config['chat_id'] ?? '');
|
||||
|
||||
if (empty($bot_token) || empty($chat_id)) {
|
||||
throw $this->incompleteConfigException();
|
||||
throw $this->incompleteConfigException(self::NAME);
|
||||
}
|
||||
|
||||
$messages = $this->replaceVariables(
|
||||
|
|
|
@ -27,7 +27,7 @@ final class TuneIn extends AbstractConnector
|
|||
$config = $webhook->getConfig();
|
||||
|
||||
if (empty($config['partner_id']) || empty($config['partner_key']) || empty($config['station_id'])) {
|
||||
throw $this->incompleteConfigException();
|
||||
throw $this->incompleteConfigException(self::NAME);
|
||||
}
|
||||
|
||||
$this->logger->debug('Dispatching TuneIn AIR API call...');
|
||||
|
|
|
@ -47,7 +47,7 @@ final class Twitter extends AbstractConnector
|
|||
|| empty($config['token'])
|
||||
|| empty($config['token_secret'])
|
||||
) {
|
||||
throw $this->incompleteConfigException();
|
||||
throw $this->incompleteConfigException(self::NAME);
|
||||
}
|
||||
|
||||
// Set up Twitter OAuth
|
||||
|
|
|
@ -51,7 +51,16 @@ final class Dispatcher
|
|||
$triggers = $message->triggers;
|
||||
|
||||
// Always dispatch the special "local" updater task.
|
||||
$this->localHandler->dispatch($station, $np);
|
||||
try {
|
||||
$this->localHandler->dispatch($station, $np);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error(
|
||||
sprintf('%s L%d: %s', $e->getFile(), $e->getLine(), $e->getMessage()),
|
||||
[
|
||||
'exception' => $e,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->environment->isTesting()) {
|
||||
$this->logger->notice('In testing mode; no webhooks dispatched.');
|
||||
|
@ -74,18 +83,12 @@ final class Dispatcher
|
|||
$this->logger->debug(sprintf('Dispatching connector "%s".', $webhook->getType()));
|
||||
|
||||
try {
|
||||
if ($connectorObj->dispatch($station, $webhook, $np, $triggers)) {
|
||||
$webhook->updateLastSentTimestamp();
|
||||
$this->em->persist($webhook);
|
||||
}
|
||||
$connectorObj->dispatch($station, $webhook, $np, $triggers);
|
||||
$webhook->updateLastSentTimestamp();
|
||||
$this->em->persist($webhook);
|
||||
} catch (\Throwable $e) {
|
||||
$this->logger->error(
|
||||
sprintf(
|
||||
'%s L%d: %s',
|
||||
$e->getFile(),
|
||||
$e->getLine(),
|
||||
$e->getMessage()
|
||||
),
|
||||
sprintf('%s L%d: %s', $e->getFile(), $e->getLine(), $e->getMessage()),
|
||||
[
|
||||
'exception' => $e,
|
||||
]
|
||||
|
|
|
@ -6,7 +6,6 @@ namespace App\Webhook;
|
|||
|
||||
use App\Entity;
|
||||
use App\Environment;
|
||||
use GuzzleHttp\Client;
|
||||
use Monolog\Logger;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
|
@ -18,7 +17,6 @@ final class LocalWebhookHandler
|
|||
|
||||
public function __construct(
|
||||
private readonly Logger $logger,
|
||||
private readonly Client $httpClient,
|
||||
private readonly Environment $environment,
|
||||
) {
|
||||
}
|
||||
|
|
|
@ -10,11 +10,11 @@ $this->layout('minimal', [
|
|||
<div class="card-body">
|
||||
<h2 class="display-1 mt-2">500</h2>
|
||||
<p>
|
||||
<?=$exception->getMessage() ?><br>
|
||||
<?=basename($exception->getFile()) ?> : <?=$exception->getLine() ?>
|
||||
<?= $exception->getMessage() ?><br>
|
||||
<?= basename($exception->getFile()) ?> : <?= $exception->getLine() ?>
|
||||
</p>
|
||||
|
||||
<a role="button" title="<?=__('Dashboard') ?>" class="btn btn-login btn-primary btn-float" href="<?=$router->named('home') ?>">
|
||||
<a role="button" title="<?= __('Dashboard') ?>" class="btn btn-login btn-primary btn-float" href="/">
|
||||
<i class="material-icons" aria-hidden="true">home</i>
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -15,7 +15,7 @@ $this->layout('minimal', [
|
|||
<p><?=$exception->getDescription()?></p>
|
||||
|
||||
<a role="button" title="<?=__('Dashboard')?>" class="btn btn-login btn-primary btn-float"
|
||||
href="<?=$router->named('home')?>">
|
||||
href="/">
|
||||
<i class="material-icons" aria-hidden="true">home</i>
|
||||
</a>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue