Completed
Pull Request — master (#32303)
by Victor
16:45
created

Notifications::sendPreOcmRemoteShare()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 3
nop 8
dl 0
loc 30
rs 8.8177
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * @author Björn Schießle <[email protected]>
4
 * @author Joas Schilling <[email protected]>
5
 * @author Lukas Reschke <[email protected]>
6
 * @author Thomas Müller <[email protected]>
7
 * @author Vincent Petry <[email protected]>
8
 *
9
 * @copyright Copyright (c) 2018, ownCloud GmbH
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
namespace OCA\FederatedFileSharing;
27
28
use OCP\AppFramework\Http;
29
use OCP\BackgroundJob\IJobList;
30
use OCP\Http\Client\IClientService;
31
use OCP\IConfig;
32
33
class Notifications {
34
	const RESPONSE_FORMAT = 'json'; // default response format for ocs calls
35
36
	/** @var AddressHandler */
37
	private $addressHandler;
38
39
	/** @var IClientService */
40
	private $httpClientService;
41
42
	/** @var DiscoveryManager */
43
	private $discoveryManager;
44
45 1
	/** @var IJobList  */
46
	private $jobList;
47
48
	/** @var IConfig */
49 1
	private $config;
50 1
51 1
	/**
52
	 * @param AddressHandler $addressHandler
53
	 * @param IClientService $httpClientService
54
	 * @param DiscoveryManager $discoveryManager
55
	 * @param IJobList $jobList
56
	 * @param IConfig $config
57
	 */
58
	public function __construct(
59
		AddressHandler $addressHandler,
60
		IClientService $httpClientService,
61
		DiscoveryManager $discoveryManager,
62
		IJobList $jobList,
63
		IConfig $config
64
	) {
65
		$this->addressHandler = $addressHandler;
66
		$this->httpClientService = $httpClientService;
67
		$this->discoveryManager = $discoveryManager;
68
		$this->jobList = $jobList;
69
		$this->config = $config;
70
	}
71
72
	/**
73
	 * send server-to-server share to remote server
74
	 *
75
	 * @param string $token
76
	 * @param string $shareWith
77
	 * @param string $name
78
	 * @param int $remote_id
79
	 * @param string $owner
80
	 * @param string $ownerFederatedId
81
	 * @param string $sharedBy
82
	 * @param string $sharedByFederatedId
83
	 * @return bool
84
	 * @throws \OC\HintException
85
	 * @throws \OC\ServerNotAvailableException
86
	 */
87
	public function sendRemoteShare($token, $shareWith, $name, $remote_id, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId) {
88
		$ocmRemoteShareSuccess = $this->sendOcmRemoteShare($token, $shareWith, $name, $remote_id, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId);
89
		if (!$ocmRemoteShareSuccess) {
90
			return $this->sendPreOcmRemoteShare($token, $shareWith, $name, $remote_id, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId);
91
		}
92
	}
93
94
	/**
95
	 * ask owner to re-share the file with the given user
96
	 *
97
	 * @param string $token
98
	 * @param int $id remote Id
99
	 * @param int $shareId internal share Id
100
	 * @param string $remote remote address of the owner
101
	 * @param string $shareWith
102
	 * @param int $permission
103
	 * @return bool
104
	 * @throws \Exception
105
	 */
106
	public function requestReShare($token, $id, $shareId, $remote, $shareWith, $permission) {
107
		$fields = [
108
			'shareWith' => $shareWith,
109
			'token' => $token,
110
			'permission' => $permission,
111
			'remoteId' => $shareId
112
		];
113
114
		$url = $this->addressHandler->removeProtocolFromUrl($remote);
115
		$result = $this->tryHttpPostToShareEndpoint(\rtrim($url, '/'), '/' . $id . '/reshare', $fields);
116
		$status = \json_decode($result['result'], true);
117
118
		$httpRequestSuccessful = $result['success'];
119
		$ocsCallSuccessful = $status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200;
120
		$validToken = isset($status['ocs']['data']['token']) && \is_string($status['ocs']['data']['token']);
121
		$validRemoteId = isset($status['ocs']['data']['remoteId']);
122
123
		if ($httpRequestSuccessful && $ocsCallSuccessful && $validToken && $validRemoteId) {
124
			return [
125
				$status['ocs']['data']['token'],
126
				(int)$status['ocs']['data']['remoteId']
127
			];
128
		}
129
130
		return false;
131
	}
132
133
	/**
134
	 * send server-to-server unshare to remote server
135
	 *
136
	 * @param string $remote url
137
	 * @param int $id share id
138
	 * @param string $token
139
	 * @return bool
140
	 */
141
	public function sendRemoteUnShare($remote, $id, $token) {
142
		return $this->sendUpdateToRemote($remote, $id, $token, 'unshare');
143
	}
144
145
	/**
146
	 * send server-to-server unshare to remote server
147
	 *
148
	 * @param string $remote url
149
	 * @param int $id share id
150
	 * @param string $token
151
	 * @return bool
152
	 */
153
	public function sendRevokeShare($remote, $id, $token) {
154
		return $this->sendUpdateToRemote($remote, $id, $token, 'revoke');
155
	}
156
157
	/**
158
	 * send notification to remote server if the permissions was changed
159
	 *
160
	 * @param string $remote
161
	 * @param int $remoteId
162
	 * @param string $token
163
	 * @param int $permissions
164
	 * @return bool
165
	 */
166
	public function sendPermissionChange($remote, $remoteId, $token, $permissions) {
167
		return $this->sendUpdateToRemote($remote, $remoteId, $token, 'permissions', ['permissions' => $permissions]);
168
	}
169
170
	/**
171
	 * forward accept reShare to remote server
172
	 *
173
	 * @param string $remote
174
	 * @param int $remoteId
175
	 * @param string $token
176
	 */
177
	public function sendAcceptShare($remote, $remoteId, $token) {
178
		$this->sendUpdateToRemote($remote, $remoteId, $token, 'accept');
179
	}
180
181
	/**
182
	 * forward decline reShare to remote server
183
	 *
184
	 * @param string $remote
185
	 * @param int $remoteId
186
	 * @param string $token
187
	 */
188
	public function sendDeclineShare($remote, $remoteId, $token) {
189
		$this->sendUpdateToRemote($remote, $remoteId, $token, 'decline');
190
	}
191
192
	/**
193
	 * inform remote server whether server-to-server share was accepted/declined
194
	 *
195
	 * @param string $remote
196
	 * @param string $token
197
	 * @param int $remoteId Share id on the remote host
198
	 * @param string $action possible actions: accept, decline, unshare, revoke, permissions
199
	 * @param array $data
200
	 * @param int $try
201
	 * @return boolean
202
	 * @throws \Exception
203
	 */
204
	public function sendUpdateToRemote($remote, $remoteId, $token, $action, $data = [], $try = 0) {
205
		$fields = ['token' => $token];
206
		foreach ($data as $key => $value) {
207
			$fields[$key] = $value;
208
		}
209
210
		$url = $this->addressHandler->removeProtocolFromUrl($remote);
211
		$result = $this->tryHttpPostToShareEndpoint(\rtrim($url, '/'), '/' . $remoteId . '/' . $action, $fields);
212
		$status = \json_decode($result['result'], true);
213
214
		if ($result['success'] &&
215
			($status['ocs']['meta']['statuscode'] === 100 ||
216
				$status['ocs']['meta']['statuscode'] === 200
217
			)
218
		) {
219
			return true;
220
		} elseif ($try === 0) {
221
			// only add new job on first try
222
			$this->jobList->add('OCA\FederatedFileSharing\BackgroundJob\RetryJob',
223
				[
224
					'remote' => $remote,
225
					'remoteId' => $remoteId,
226
					'token' => $token,
227
					'action' => $action,
228
					'data' => \json_encode($data),
229
					'try' => $try,
230
					'lastRun' => $this->getTimestamp()
231
				]
232
			);
233
		}
234
235
		return false;
236
	}
237
238
	/**
239
	 * return current timestamp
240
	 *
241
	 * @return int
242
	 */
243
	protected function getTimestamp() {
244
		return \time();
245
	}
246
247
	/**
248
	 * try http post first with https and then with http as a fallback
249
	 *
250
	 * @param string $remoteDomain
251
	 * @param string $urlSuffix
252
	 * @param array $fields post parameters
253
	 * @return array
254
	 * @throws \Exception
255
	 */
256
	protected function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields, $useOcm = false) {
257
		$client = $this->httpClientService->newClient();
258
		$protocol = 'https://';
259
		$result = [
260
			'success' => false,
261
			'result' => '',
262
		];
263
		$try = 0;
264
265
		while ($result['success'] === false && $try < 2) {
266
			if ($useOcm) {
267
				$endpoint = $this->discoveryManager->getOcmShareEndpoint($protocol . $remoteDomain);
268
			} else {
269
				$endpoint = $this->discoveryManager->getShareEndpoint($protocol . $remoteDomain);
270
			}
271
272
			try {
273
				$response = $client->post($protocol . $remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT, [
274
					'body' => $fields,
275
					'timeout' => 10,
276
					'connect_timeout' => 10,
277
				]);
278
				$result['result'] = $response->getBody();
279
				$result['statusCode'] = $response->getStatusCode();
280
				$result['success'] = true;
281
				break;
282
			} catch (\Exception $e) {
283
				// if flat re-sharing is not supported by the remote server
284
				// we re-throw the exception and fall back to the old behaviour.
285
				// (flat re-shares has been introduced in ownCloud 9.1)
286
				if ($e->getCode() === Http::STATUS_INTERNAL_SERVER_ERROR) {
287
					throw $e;
288
				}
289
				$allowHttpFallback = $this->config->getSystemValue('sharing.federation.allowHttpFallback', false) === true;
290
				if (!$allowHttpFallback) {
291
					break;
292
				}
293
				$try++;
294
				$protocol = 'http://';
295
			}
296
		}
297
298
		return $result;
299
	}
300
301
	protected function sendOcmRemoteShare($token, $shareWith, $name, $remote_id, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId) {
0 ignored issues
show
Unused Code introduced by
The parameter $owner is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $sharedBy is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
302
		list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
303
		if ($user && $remote) {
304
			$fields = [
305
				'shareWith' => $shareWith,
306
				'name' => $name,
307
				'providerId' => $remote_id,
308
				'owner' => $ownerFederatedId,
309
				'ownerDisplayName' => '',
310
				'sender' => $sharedByFederatedId,
311
				'senderDisplayName' => '',
312
				'token' => $token,
313
				'shareType' => 'user',
314
				'resourceType' => 'file',
315
				'protocol' => [
316
					'name' => 'webdav',
317
					'options' => [
318
						'sharedSecret' => $token
319
					]
320
				]
321
			];
322
323
			$url = $this->addressHandler->removeProtocolFromUrl($remote);
324
			$result = $this->tryHttpPostToShareEndpoint($url, '', $fields, true);
325
326
			if (isset($result['statusCode']) && $result['statusCode'] === 201) {
327
				\OC_Hook::emit('OCP\Share', 'federated_share_added', ['server' => $remote]);
328
				return true;
329
			}
330
		}
331
		return false;
332
	}
333
334
	protected function sendPreOcmRemoteShare($token, $shareWith, $name, $remote_id, $owner, $ownerFederatedId, $sharedBy, $sharedByFederatedId) {
335
		list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
336
337
		if ($user && $remote) {
338
			$url = $remote;
339
			$local = $this->addressHandler->generateRemoteURL();
340
341
			$fields = [
342
				'shareWith' => $user,
343
				'token' => $token,
344
				'name' => $name,
345
				'remoteId' => $remote_id,
346
				'owner' => $owner,
347
				'ownerFederatedId' => $ownerFederatedId,
348
				'sharedBy' => $sharedBy,
349
				'sharedByFederatedId' => $sharedByFederatedId,
350
				'remote' => $local,
351
			];
352
353
			$url = $this->addressHandler->removeProtocolFromUrl($url);
354
			$result = $this->tryHttpPostToShareEndpoint($url, '', $fields);
355
			$status = \json_decode($result['result'], true);
356
357
			if ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200)) {
358
				\OC_Hook::emit('OCP\Share', 'federated_share_added', ['server' => $remote]);
359
				return true;
360
			}
361
		}
362
		return false;
363
	}
364
}
365