Completed
Push — master ( dccb89...31024b )
by Morris
12:39
created

GetSharedSecret::parentExecute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Björn Schießle <[email protected]>
6
 * @author Joas Schilling <[email protected]>
7
 * @author Robin Appelman <[email protected]>
8
 * @author Thomas Müller <[email protected]>
9
 *
10
 * @license AGPL-3.0
11
 *
12
 * This code is free software: you can redistribute it and/or modify
13
 * it under the terms of the GNU Affero General Public License, version 3,
14
 * as published by the Free Software Foundation.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License, version 3,
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
23
 *
24
 */
25
26
27
namespace OCA\Federation\BackgroundJob;
28
29
use GuzzleHttp\Exception\ClientException;
30
use OC\BackgroundJob\JobList;
31
use OC\BackgroundJob\Job;
32
use OCA\Federation\DbHandler;
33
use OCA\Federation\TrustedServers;
34
use OCP\AppFramework\Http;
35
use OCP\BackgroundJob\IJobList;
36
use OCP\Http\Client\IClient;
37
use OCP\Http\Client\IResponse;
38
use OCP\ILogger;
39
use OCP\IURLGenerator;
40
use OCP\OCS\IDiscoveryService;
41
42
/**
43
 * Class GetSharedSecret
44
 *
45
 * request shared secret from remote Nextcloud
46
 *
47
 * @package OCA\Federation\Backgroundjob
48
 */
49
class GetSharedSecret extends Job{
50
51
	/** @var IClient */
52
	private $httpClient;
53
54
	/** @var IJobList */
55
	private $jobList;
56
57
	/** @var IURLGenerator */
58
	private $urlGenerator;
59
60
	/** @var TrustedServers  */
61
	private $trustedServers;
62
63
	/** @var DbHandler */
64
	private $dbHandler;
65
66
	/** @var IDiscoveryService  */
67
	private $ocsDiscoveryService;
68
69
	/** @var ILogger */
70
	private $logger;
71
72
	/** @var bool */
73
	protected $retainJob = false;
74
75
	private $format = '?format=json';
76
77
	private $defaultEndPoint = '/ocs/v2.php/apps/federation/api/v1/shared-secret';
78
79
	/**
80
	 * RequestSharedSecret constructor.
81
	 *
82
	 * @param IClient $httpClient
83
	 * @param IURLGenerator $urlGenerator
84
	 * @param IJobList $jobList
85
	 * @param TrustedServers $trustedServers
86
	 * @param ILogger $logger
87
	 * @param DbHandler $dbHandler
88
	 * @param IDiscoveryService $ocsDiscoveryService
89
	 */
90
	public function __construct(
91
		IClient $httpClient = null,
92
		IURLGenerator $urlGenerator = null,
93
		IJobList $jobList = null,
94
		TrustedServers $trustedServers = null,
95
		ILogger $logger = null,
96
		DbHandler $dbHandler = null,
97
		IDiscoveryService $ocsDiscoveryService = null
98
	) {
99
		$this->logger = $logger ? $logger : \OC::$server->getLogger();
100
		$this->httpClient = $httpClient ? $httpClient : \OC::$server->getHTTPClientService()->newClient();
101
		$this->jobList = $jobList ? $jobList : \OC::$server->getJobList();
102
		$this->urlGenerator = $urlGenerator ? $urlGenerator : \OC::$server->getURLGenerator();
103
		$this->dbHandler = $dbHandler ? $dbHandler : new DbHandler(\OC::$server->getDatabaseConnection(), \OC::$server->getL10N('federation'));
104
		$this->ocsDiscoveryService = $ocsDiscoveryService ? $ocsDiscoveryService : \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
105 View Code Duplication
		if ($trustedServers) {
106
			$this->trustedServers = $trustedServers;
107
		} else {
108
			$this->trustedServers = new TrustedServers(
109
				$this->dbHandler,
110
				\OC::$server->getHTTPClientService(),
111
				$this->logger,
112
				$this->jobList,
113
				\OC::$server->getSecureRandom(),
114
				\OC::$server->getConfig(),
115
				\OC::$server->getEventDispatcher()
116
			);
117
		}
118
	}
119
120
	/**
121
	 * run the job, then remove it from the joblist
122
	 *
123
	 * @param JobList $jobList
124
	 * @param ILogger $logger
125
	 */
126 View Code Duplication
	public function execute($jobList, ILogger $logger = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
127
		$target = $this->argument['url'];
128
		// only execute if target is still in the list of trusted domains
129
		if ($this->trustedServers->isTrustedServer($target)) {
130
			$this->parentExecute($jobList, $logger);
131
		}
132
133
		if (!$this->retainJob) {
134
			$jobList->remove($this, $this->argument);
135
		}
136
	}
137
138
	/**
139
	 * call execute() method of parent
140
	 *
141
	 * @param JobList $jobList
142
	 * @param ILogger $logger
143
	 */
144
	protected function parentExecute($jobList, $logger = null) {
145
		parent::execute($jobList, $logger);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (execute() instead of parentExecute()). Are you sure this is correct? If so, you might want to change this to $this->execute().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
146
	}
147
148
	protected function run($argument) {
149
		$target = $argument['url'];
150
		$source = $this->urlGenerator->getAbsoluteURL('/');
151
		$source = rtrim($source, '/');
152
		$token = $argument['token'];
153
154
		$endPoints = $this->ocsDiscoveryService->discover($target, 'FEDERATED_SHARING');
155
		$endPoint = isset($endPoints['shared-secret']) ? $endPoints['shared-secret'] : $this->defaultEndPoint;
156
157
		// make sure that we have a well formated url
158
		$url = rtrim($target, '/') . '/' . trim($endPoint, '/') . $this->format;
159
160
		$result = null;
161
		try {
162
			$result = $this->httpClient->get(
163
				$url,
164
				[
165
					'query' =>
166
						[
167
							'url' => $source,
168
							'token' => $token
169
						],
170
					'timeout' => 3,
171
					'connect_timeout' => 3,
172
				]
173
			);
174
175
			$status = $result->getStatusCode();
176
177
		} catch (ClientException $e) {
0 ignored issues
show
Bug introduced by
The class GuzzleHttp\Exception\ClientException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
178
			$status = $e->getCode();
179 View Code Duplication
			if ($status === Http::STATUS_FORBIDDEN) {
180
				$this->logger->info($target . ' refused to exchange a shared secret with you.', ['app' => 'federation']);
181
			} else {
182
				$this->logger->logException($e, ['app' => 'federation']);
183
			}
184
		} catch (\Exception $e) {
185
			$status = Http::STATUS_INTERNAL_SERVER_ERROR;
186
			$this->logger->logException($e, ['app' => 'federation']);
187
		}
188
189
		// if we received a unexpected response we try again later
190
		if (
191
			$status !== Http::STATUS_OK
192
			&& $status !== Http::STATUS_FORBIDDEN
193
		) {
194
			$this->retainJob = true;
195
		}  else {
196
			// reset token if we received a valid response
197
			$this->dbHandler->addToken($target, '');
198
		}
199
200
		if ($status === Http::STATUS_OK && $result instanceof IResponse) {
201
			$body = $result->getBody();
202
			$result = json_decode($body, true);
203
			if (isset($result['ocs']['data']['sharedSecret'])) {
204
				$this->trustedServers->addSharedSecret(
205
						$target,
206
						$result['ocs']['data']['sharedSecret']
207
				);
208
			} else {
209
				$this->logger->error(
210
						'remote server "' . $target . '"" does not return a valid shared secret',
211
						['app' => 'federation']
212
				);
213
				$this->trustedServers->setServerStatus($target, TrustedServers::STATUS_FAILURE);
214
			}
215
		}
216
217
	}
218
}
219