Completed
Pull Request — master (#32218)
by Thomas
50:41 queued 37:30
created

RequestHandlerController::createShare()   B

Complexity

Conditions 7
Paths 61

Size

Total Lines 76

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 61
nop 0
dl 0
loc 76
rs 7.5903
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @author Arthur Schiwon <[email protected]>
4
 * @author Björn Schießle <[email protected]>
5
 * @author Joas Schilling <[email protected]>
6
 * @author Lukas Reschke <[email protected]>
7
 * @author Morris Jobke <[email protected]>
8
 * @author Thomas Müller <[email protected]>
9
 *
10
 * @copyright Copyright (c) 2018, ownCloud GmbH
11
 * @license AGPL-3.0
12
 *
13
 * This code is free software: you can redistribute it and/or modify
14
 * it under the terms of the GNU Affero General Public License, version 3,
15
 * as published by the Free Software Foundation.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
 * GNU Affero General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License, version 3,
23
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
24
 *
25
 */
26
27
namespace OCA\FederatedFileSharing\Controller;
28
29
use OC\OCS\Result;
30
use OCA\FederatedFileSharing\AddressHandler;
31
use OCA\FederatedFileSharing\Exception\NotSupportedException;
32
use OCA\FederatedFileSharing\Exception\InvalidShareException;
33
use OCA\FederatedFileSharing\FederatedShareProvider;
34
use OCA\FederatedFileSharing\FedShareManager;
35
use OCP\App\IAppManager;
36
use OCP\AppFramework\Http;
37
use OCP\AppFramework\OCSController;
38
use OCP\Constants;
39
use OCP\IRequest;
40
use OCP\IUserManager;
41
use OCP\Share;
42
use OCP\Share\IShare;
43
44
/**
45
 * Class RequestHandlerController
46
 *
47
 * Handles OCS Request to the federated share API
48
 *
49
 * @package OCA\FederatedFileSharing\API
50
 */
51
class RequestHandlerController extends OCSController {
52
53
	/** @var FederatedShareProvider */
54
	private $federatedShareProvider;
55
56
	/** @var IAppManager */
57
	private $appManager;
58
59
	/** @var IUserManager */
60
	private $userManager;
61
62
	/** @var AddressHandler */
63
	private $addressHandler;
64
65
	/** @var  FedShareManager */
66
	private $fedShareManager;
67
68
	/**
69
	 * Server2Server constructor.
70
	 *
71
	 * @param string $appName
72
	 * @param IRequest $request
73
	 * @param FederatedShareProvider $federatedShareProvider
74
	 * @param IAppManager $appManager
75
	 * @param IUserManager $userManager
76
	 * @param AddressHandler $addressHandler
77
	 * @param FedShareManager $fedShareManager
78
	 */
79
	public function __construct($appName,
80
								IRequest $request,
81
								FederatedShareProvider $federatedShareProvider,
82
								IAppManager $appManager,
83
								IUserManager $userManager,
84
								AddressHandler $addressHandler,
85
								FedShareManager $fedShareManager
86
	) {
87
		parent::__construct($appName, $request);
88
89
		$this->federatedShareProvider = $federatedShareProvider;
90
		$this->appManager = $appManager;
91
		$this->userManager = $userManager;
92
		$this->addressHandler = $addressHandler;
93
		$this->fedShareManager = $fedShareManager;
94
	}
95
96
	/**
97
	 * @NoCSRFRequired
98
	 * @PublicPage
99
	 *
100
	 * create a new share
101
	 *
102
	 * @return Result
103
	 */
104
	public function createShare() {
105
		try {
106
			$this->assertIncomingSharingEnabled();
107
			$remote = $this->request->getParam('remote', null);
108
			$token = $this->request->getParam('token', null);
109
			$name = $this->request->getParam('name', null);
110
			$owner = $this->request->getParam('owner', null);
111
			$sharedBy = $this->request->getParam('sharedBy', null);
112
			$shareWith = $this->request->getParam('shareWith', null);
113
			$remoteId = $this->request->getParam('remoteId', null);
114
			$sharedByFederatedId = $this->request->getParam(
115
				'sharedByFederatedId',
116
				null
117
			);
118
			$ownerFederatedId = $this->request->getParam('ownerFederatedId', null);
119
			$hasMissingParams = $this->hasNull(
120
				[$remote, $token, $name, $owner, $remoteId, $shareWith]
121
			);
122
			if ($hasMissingParams) {
123
				throw new InvalidShareException(
124
					'server can not add remote share, missing parameter'
125
				);
126
			}
127
			if (!\OCP\Util::isValidFileName($name)) {
128
				throw new InvalidShareException(
129
					'The mountpoint name contains invalid characters.'
130
				);
131
			}
132
			// FIXME this should be a method in the user management instead
133
			\OCP\Util::writeLog('files_sharing', 'shareWith before, ' . $shareWith, \OCP\Util::DEBUG);
134
			\OCP\Util::emitHook(
135
				'\OCA\Files_Sharing\API\Server2Server',
136
				'preLoginNameUsedAsUserName',
137
				['uid' => &$shareWith]
138
			);
139
			\OCP\Util::writeLog('files_sharing', 'shareWith after, ' . $shareWith, \OCP\Util::DEBUG);
140
			if (!$this->userManager->userExists($shareWith)) {
141
				throw new InvalidShareException('User does not exist');
142
			}
143
			$this->fedShareManager->createShare(
144
				$shareWith,
145
				$remote,
146
				$remoteId,
147
				$owner,
148
				$name,
149
				$ownerFederatedId,
150
				$sharedByFederatedId,
151
				$sharedBy,
152
				$token
153
			);
154
		} catch (InvalidShareException $e) {
155
			return new Result(
156
				null,
157
				Http::STATUS_BAD_REQUEST,
158
				$e->getMessage()
159
			);
160
		} catch (NotSupportedException $e) {
161
			return new Result(
162
				null,
163
				Http::STATUS_SERVICE_UNAVAILABLE,
164
				'Server does not support federated cloud sharing'
165
			);
166
		} catch (\Exception $e) {
167
			\OCP\Util::writeLog(
168
				'files_sharing',
169
				'server can not add remote share, ' . $e->getMessage(),
170
				\OCP\Util::ERROR
171
			);
172
			return new Result(
173
				null,
174
				Http::STATUS_INTERNAL_SERVER_ERROR,
175
				'internal server error, was not able to add share from ' . $remote
0 ignored issues
show
Bug introduced by
The variable $remote does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
176
			);
177
		}
178
		return new Result();
179
	}
180
181
	/**
182
	 * @NoCSRFRequired
183
	 * @PublicPage
184
	 *
185
	 * create re-share on behalf of another user
186
	 *
187
	 * @param int $id
188
	 *
189
	 * @return Result
190
	 */
191
	public function reShare($id) {
192
		$token = $this->request->getParam('token', null);
193
		$shareWith = $this->request->getParam('shareWith', null);
194
		$permission = $this->request->getParam('permission', null);
195
		$remoteId = $this->request->getParam('remoteId', null);
196
197
		if ($this->hasNull([$id, $token, $shareWith, $permission, $remoteId])) {
198
			return new Result(null, Http::STATUS_BAD_REQUEST);
199
		}
200
201
		try {
202
			$permission = (int) $permission;
203
			$remoteId = (int) $remoteId;
204
			$share = $this->getValidShare($id);
205
206
			// don't allow to share a file back to the owner
207
			list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
208
			$owner = $share->getShareOwner();
209
			$currentServer = $this->addressHandler->generateRemoteURL();
210
			if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
211
				return new Result(null, Http::STATUS_FORBIDDEN);
212
			}
213
214
			$reSharingAllowed = $share->getPermissions() & Constants::PERMISSION_SHARE;
215
			if (!$reSharingAllowed) {
216
				return new Result(null, Http::STATUS_BAD_REQUEST);
217
			}
218
			$result = $this->fedShareManager->reShare(
219
				$share,
220
				$remoteId,
221
				$shareWith,
222
				$permission
223
			);
224
		} catch (Share\Exceptions\ShareNotFound $e) {
225
			return new Result(null, Http::STATUS_NOT_FOUND);
226
		} catch (InvalidShareException $e) {
227
			return new Result(null, Http::STATUS_FORBIDDEN);
228
		} catch (\Exception $e) {
229
			return new Result(null, Http::STATUS_BAD_REQUEST);
230
		}
231
232
		return new Result(
233
			[
234
				'token' => $result->getToken(),
235
				'remoteId' => $result->getId()
236
			]
237
		);
238
	}
239
240
	/**
241
	 * @NoCSRFRequired
242
	 * @PublicPage
243
	 *
244
	 * accept server-to-server share
245
	 *
246
	 * @param int $id
247
	 *
248
	 * @return Result
249
	 */
250 View Code Duplication
	public function acceptShare($id) {
251
		try {
252
			$this->assertOutgoingSharingEnabled();
253
			$share = $this->getValidShare($id);
254
			$this->fedShareManager->acceptShare($share);
255
		} catch (NotSupportedException $e) {
256
			return new Result(
257
				null,
258
				Http::STATUS_SERVICE_UNAVAILABLE,
259
				'Server does not support federated cloud sharing'
260
			);
261
		} catch (Share\Exceptions\ShareNotFound $e) {
262
			// pass
263
		}
264
		return new Result();
265
	}
266
267
	/**
268
	 * @NoCSRFRequired
269
	 * @PublicPage
270
	 *
271
	 * decline server-to-server share
272
	 *
273
	 * @param int $id
274
	 *
275
	 * @return Result
276
	 */
277 View Code Duplication
	public function declineShare($id) {
278
		try {
279
			$this->assertOutgoingSharingEnabled();
280
			$share = $this->getValidShare($id);
281
			$this->fedShareManager->declineShare($share);
282
		} catch (NotSupportedException $e) {
283
			return new Result(
284
				null,
285
				Http::STATUS_SERVICE_UNAVAILABLE,
286
				'Server does not support federated cloud sharing'
287
			);
288
		} catch (Share\Exceptions\ShareNotFound $e) {
289
			// pass
290
		}
291
292
		return new Result();
293
	}
294
295
	/**
296
	 * @NoCSRFRequired
297
	 * @PublicPage
298
	 *
299
	 * remove server-to-server share if it was unshared by the owner
300
	 *
301
	 * @param int $id
302
	 *
303
	 * @return Result
304
	 */
305
	public function unshare($id) {
306
		try {
307
			$this->assertOutgoingSharingEnabled();
308
			$token = $this->request->getParam('token', null);
309
			if ($token && $id) {
310
				$this->fedShareManager->unshare($id, $token);
311
			}
312
		} catch (NotSupportedException $e) {
313
			return new Result(
314
				null,
315
				Http::STATUS_SERVICE_UNAVAILABLE,
316
				'Server does not support federated cloud sharing'
317
			);
318
		} catch (\Exception $e) {
319
			// pass
320
		}
321
		return new Result();
322
	}
323
324
	/**
325
	 * @NoCSRFRequired
326
	 * @PublicPage
327
	 *
328
	 * federated share was revoked, either by the owner or the re-sharer
329
	 *
330
	 * @param int $id
331
	 *
332
	 * @return Result
333
	 */
334
	public function revoke($id) {
335
		try {
336
			$share = $this->getValidShare($id);
337
			$this->fedShareManager->revoke($share);
338
		} catch (\Exception $e) {
339
			return new Result(null, Http::STATUS_BAD_REQUEST);
340
		}
341
342
		return new Result();
343
	}
344
345
	/**
346
	 * @NoCSRFRequired
347
	 * @PublicPage
348
	 *
349
	 * update share information to keep federated re-shares in sync
350
	 *
351
	 * @param int $id
352
	 *
353
	 * @return Result
354
	 */
355
	public function updatePermissions($id) {
356
		try {
357
			$permissions = $this->request->getParam('permissions', null);
358
359
			$share = $this->getValidShare($id);
360
			$validPermission = \ctype_digit((string)$permissions);
361
			if (!$validPermission) {
362
				throw new \Exception();
363
			}
364
			$this->fedShareManager->updatePermissions($share, (int)$permissions);
365
		} catch (\Exception $e) {
366
			return new Result(null, Http::STATUS_BAD_REQUEST);
367
		}
368
369
		return new Result();
370
	}
371
372
	/**
373
	 * Get share by id, validate it's type and token
374
	 *
375
	 * @param int $id
376
	 *
377
	 * @return IShare
378
	 *
379
	 * @throws Share\Exceptions\ShareNotFound
380
	 * @throws InvalidShareException
381
	 */
382
	protected function getValidShare($id) {
383
		$share = $this->federatedShareProvider->getShareById($id);
384
		$token = $this->request->getParam('token', null);
385
		if ($share->getShareType() !== FederatedShareProvider::SHARE_TYPE_REMOTE
386
			|| $share->getToken() !== $token
387
		) {
388
			throw new InvalidShareException();
389
		}
390
		return $share;
391
	}
392
393
	/**
394
	 * Make sure that incoming shares are enabled
395
	 *
396
	 * @return void
397
	 *
398
	 * @throws NotSupportedException
399
	 */
400
	protected function assertIncomingSharingEnabled() {
401
		if (!$this->appManager->isEnabledForUser('files_sharing')
402
			|| !$this->federatedShareProvider->isIncomingServer2serverShareEnabled()
403
		) {
404
			throw new NotSupportedException();
405
		}
406
	}
407
	
408
	/**
409
	 * Make sure that outgoing shares are enabled
410
	 *
411
	 * @return void
412
	 *
413
	 * @throws NotSupportedException
414
	 */
415
	protected function assertOutgoingSharingEnabled() {
416
		if (!$this->appManager->isEnabledForUser('files_sharing')
417
			|| !$this->federatedShareProvider->isOutgoingServer2serverShareEnabled()
418
		) {
419
			throw new NotSupportedException();
420
		}
421
	}
422
423
	/**
424
	 * Check if value is null or an array has any null item
425
	 *
426
	 * @param mixed $param
427
	 *
428
	 * @return bool
429
	 */
430
	protected function hasNull($param) {
431
		if (\is_array($param)) {
432
			return \in_array(null, $param, true);
433
		} else {
434
			return $param === null;
435
		}
436
	}
437
}
438