Files
wallabag/src/Guzzle/AuthenticatorSubscriber.php

122 lines
3.4 KiB
PHP
Raw Normal View History

<?php
2024-02-19 01:30:12 +01:00
namespace Wallabag\Guzzle;
use GuzzleHttp\Event\BeforeEvent;
use GuzzleHttp\Event\CompleteEvent;
use GuzzleHttp\Event\SubscriberInterface;
use GuzzleHttp\Message\RequestInterface;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Wallabag\SiteConfig\Authenticator\Authenticator;
2024-02-19 01:30:12 +01:00
use Wallabag\SiteConfig\SiteConfig;
use Wallabag\SiteConfig\SiteConfigBuilder;
class AuthenticatorSubscriber implements SubscriberInterface, LoggerAwareInterface
{
// avoid loop when login failed which can just be a bad login/password
// after 2 attempts, we skip the login
public const MAX_RETRIES = 2;
private int $retries = 0;
/** @var SiteConfigBuilder */
private $configBuilder;
/** @var Authenticator */
private $authenticator;
/** @var LoggerInterface */
private $logger;
/**
* AuthenticatorSubscriber constructor.
*/
public function __construct(SiteConfigBuilder $configBuilder, Authenticator $authenticator)
{
$this->configBuilder = $configBuilder;
$this->authenticator = $authenticator;
$this->logger = new NullLogger();
}
public function setLogger(LoggerInterface $logger): void
{
$this->logger = $logger;
}
public function getEvents(): array
{
return [
'before' => ['loginIfRequired'],
'complete' => ['loginIfRequested'],
];
}
public function loginIfRequired(BeforeEvent $event)
{
$config = $this->buildSiteConfig($event->getRequest());
if (false === $config || !$config->requiresLogin()) {
$this->logger->debug('loginIfRequired> will not require login');
return;
}
$client = $event->getClient();
if (!$this->authenticator->isLoggedIn($config, $client)) {
$this->logger->debug('loginIfRequired> user is not logged in, attach authenticator');
$emitter = $client->getEmitter();
$emitter->detach($this);
$this->authenticator->login($config, $client);
$emitter->attach($this);
}
}
public function loginIfRequested(CompleteEvent $event)
{
$config = $this->buildSiteConfig($event->getRequest());
if (false === $config || !$config->requiresLogin()) {
$this->logger->debug('loginIfRequested> will not require login');
return;
}
$body = $event->getResponse()->getBody();
if (
null === $body
|| '' === $body->getContents()
) {
$this->logger->debug('loginIfRequested> empty body, ignoring');
return;
}
$isLoginRequired = $this->authenticator->isLoginRequired($config, $body);
$this->logger->debug('loginIfRequested> retry #' . $this->retries . ' with login ' . ($isLoginRequired ? '' : 'not ') . 'required');
if ($isLoginRequired && $this->retries < self::MAX_RETRIES) {
$client = $event->getClient();
$emitter = $client->getEmitter();
$emitter->detach($this);
$this->authenticator->login($config, $client);
$emitter->attach($this);
$event->retry();
++$this->retries;
}
}
/**
* @return SiteConfig|false
*/
private function buildSiteConfig(RequestInterface $request)
{
return $this->configBuilder->buildForHost($request->getHost());
}
}