diff options
Diffstat (limited to 'apps/federation/lib/BackgroundJob/RequestSharedSecret.php')
-rw-r--r-- | apps/federation/lib/BackgroundJob/RequestSharedSecret.php | 184 |
1 files changed, 55 insertions, 129 deletions
diff --git a/apps/federation/lib/BackgroundJob/RequestSharedSecret.php b/apps/federation/lib/BackgroundJob/RequestSharedSecret.php index ad7504da7ad..4d57d1f6aef 100644 --- a/apps/federation/lib/BackgroundJob/RequestSharedSecret.php +++ b/apps/federation/lib/BackgroundJob/RequestSharedSecret.php @@ -1,52 +1,27 @@ <?php -/** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Bjoern Schiessle <bjoern@schiessle.org> - * @author Björn Schießle <bjoern@schiessle.org> - * @author Joas Schilling <coding@schilljs.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only + */ namespace OCA\Federation\BackgroundJob; - use GuzzleHttp\Exception\ClientException; -use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\RequestException; -use GuzzleHttp\Ring\Exception\RingException; -use OC\BackgroundJob\JobList; -use OC\BackgroundJob\Job; -use OCA\Federation\DbHandler; use OCA\Federation\TrustedServers; use OCP\AppFramework\Http; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\IJobList; +use OCP\BackgroundJob\Job; use OCP\Http\Client\IClient; use OCP\Http\Client\IClientService; -use OCP\ILogger; +use OCP\IConfig; use OCP\IURLGenerator; use OCP\OCS\IDiscoveryService; +use Psr\Log\LoggerInterface; /** * Class RequestSharedSecret @@ -56,85 +31,38 @@ use OCP\OCS\IDiscoveryService; * @package OCA\Federation\Backgroundjob */ class RequestSharedSecret extends Job { + private IClient $httpClient; - /** @var IClient */ - private $httpClient; - - /** @var IJobList */ - private $jobList; - - /** @var IURLGenerator */ - private $urlGenerator; - - /** @var DbHandler */ - private $dbHandler; - - /** @var TrustedServers */ - private $trustedServers; - - /** @var IDiscoveryService */ - private $ocsDiscoveryService; - - /** @var ILogger */ - private $logger; + protected bool $retainJob = false; - /** @var ITimeFactory */ - private $timeFactory; + private string $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/request-shared-secret'; - /** @var bool */ - protected $retainJob = false; + /** @var int 30 day = 2592000sec */ + private int $maxLifespan = 2592000; - private $format = '?format=json'; - - private $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/request-shared-secret'; - - /** @var int 30 day = 2592000sec */ - private $maxLifespan = 2592000; - - /** - * RequestSharedSecret constructor. - * - * @param IClientService $httpClientService - * @param IURLGenerator $urlGenerator - * @param IJobList $jobList - * @param TrustedServers $trustedServers - * @param DbHandler $dbHandler - * @param IDiscoveryService $ocsDiscoveryService - * @param ILogger $logger - * @param ITimeFactory $timeFactory - */ public function __construct( IClientService $httpClientService, - IURLGenerator $urlGenerator, - IJobList $jobList, - TrustedServers $trustedServers, - DbHandler $dbHandler, - IDiscoveryService $ocsDiscoveryService, - ILogger $logger, - ITimeFactory $timeFactory + private IURLGenerator $urlGenerator, + private IJobList $jobList, + private TrustedServers $trustedServers, + private IDiscoveryService $ocsDiscoveryService, + private LoggerInterface $logger, + ITimeFactory $timeFactory, + private IConfig $config, ) { + parent::__construct($timeFactory); $this->httpClient = $httpClientService->newClient(); - $this->jobList = $jobList; - $this->urlGenerator = $urlGenerator; - $this->dbHandler = $dbHandler; - $this->logger = $logger; - $this->ocsDiscoveryService = $ocsDiscoveryService; - $this->trustedServers = $trustedServers; - $this->timeFactory = $timeFactory; } /** * run the job, then remove it from the joblist - * - * @param JobList $jobList - * @param ILogger|null $logger */ - public function execute($jobList, ILogger $logger = null) { + public function start(IJobList $jobList): void { $target = $this->argument['url']; // only execute if target is still in the list of trusted domains if ($this->trustedServers->isTrustedServer($target)) { - $this->parentExecute($jobList, $logger); + $this->parentStart($jobList); } $jobList->remove($this, $this->argument); @@ -145,20 +73,21 @@ class RequestSharedSecret extends Job { } /** - * call execute() method of parent - * - * @param JobList $jobList - * @param ILogger $logger + * Call start() method of parent + * Useful for unit tests */ - protected function parentExecute($jobList, $logger) { - parent::execute($jobList, $logger); + protected function parentStart(IJobList $jobList): void { + parent::start($jobList); } + /** + * @param array $argument + * @return void + */ protected function run($argument) { - $target = $argument['url']; - $created = isset($argument['created']) ? (int)$argument['created'] : $this->timeFactory->getTime(); - $currentTime = $this->timeFactory->getTime(); + $created = isset($argument['created']) ? (int)$argument['created'] : $this->time->getTime(); + $currentTime = $this->time->getTime(); $source = $this->urlGenerator->getAbsoluteURL('/'); $source = rtrim($source, '/'); $token = $argument['token']; @@ -166,16 +95,17 @@ class RequestSharedSecret extends Job { // kill job after 30 days of trying $deadline = $currentTime - $this->maxLifespan; if ($created < $deadline) { + $this->logger->warning("The job to request the shared secret job is too old and gets stopped now without retention. Setting server status of '{$target}' to failure."); $this->retainJob = false; $this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE); return; } $endPoints = $this->ocsDiscoveryService->discover($target, 'FEDERATED_SHARING'); - $endPoint = isset($endPoints['shared-secret']) ? $endPoints['shared-secret'] : $this->defaultEndPoint; + $endPoint = $endPoints['shared-secret'] ?? $this->defaultEndPoint; - // make sure that we have a well formated url - $url = rtrim($target, '/') . '/' . trim($endPoint, '/') . $this->format; + // make sure that we have a well formatted url + $url = rtrim($target, '/') . '/' . trim($endPoint, '/'); try { $result = $this->httpClient->post( @@ -184,64 +114,60 @@ class RequestSharedSecret extends Job { 'body' => [ 'url' => $source, 'token' => $token, + 'format' => 'json', ], 'timeout' => 3, 'connect_timeout' => 3, + 'verify' => !$this->config->getSystemValue('sharing.federation.allowSelfSignedCertificates', false), ] ); $status = $result->getStatusCode(); - } catch (ClientException $e) { $status = $e->getCode(); if ($status === Http::STATUS_FORBIDDEN) { - $this->logger->info($target . ' refused to ask for a shared secret.', ['app' => 'federation']); + $this->logger->info($target . ' refused to ask for a shared secret.'); } else { - $this->logger->info($target . ' responded with a ' . $status . ' containing: ' . $e->getMessage(), ['app' => 'federation']); + $this->logger->info($target . ' responded with a ' . $status . ' containing: ' . $e->getMessage()); } } catch (RequestException $e) { $status = -1; // There is no status code if we could not connect - $this->logger->info('Could not connect to ' . $target, ['app' => 'federation']); - } catch (RingException $e) { - $status = -1; // There is no status code if we could not connect - $this->logger->info('Could not connect to ' . $target, ['app' => 'federation']); - } catch (\Exception $e) { + $this->logger->info('Could not connect to ' . $target); + } catch (\Throwable $e) { $status = Http::STATUS_INTERNAL_SERVER_ERROR; - $this->logger->logException($e, ['app' => 'federation']); + $this->logger->error($e->getMessage(), ['exception' => $e]); } // if we received a unexpected response we try again later if ( $status !== Http::STATUS_OK - && $status !== Http::STATUS_FORBIDDEN + && ($status !== Http::STATUS_FORBIDDEN || $this->getAttempt($argument) < 5) ) { $this->retainJob = true; } - - if ($status === Http::STATUS_FORBIDDEN) { - // clear token if remote server refuses to ask for shared secret - $this->dbHandler->addToken($target, ''); - } - } /** * re-add background job - * - * @param array $argument */ - protected function reAddJob(array $argument) { + protected function reAddJob(array $argument): void { $url = $argument['url']; - $created = isset($argument['created']) ? (int)$argument['created'] : $this->timeFactory->getTime(); + $created = isset($argument['created']) ? (int)$argument['created'] : $this->time->getTime(); $token = $argument['token']; + $attempt = $this->getAttempt($argument) + 1; $this->jobList->add( RequestSharedSecret::class, [ 'url' => $url, 'token' => $token, - 'created' => $created + 'created' => $created, + 'attempt' => $attempt ] ); } + + protected function getAttempt(array $argument): int { + return $argument['attempt'] ?? 0; + } } |