Completed
Push — master ( a89f9a...3036b1 )
by Morris
29:19 queued 12:13
created

RequestHandlerController::addShare()   F

Complexity

Conditions 24
Paths 453

Size

Total Lines 95

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 24
nc 453
nop 11
dl 0
loc 95
rs 0.7597
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

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:

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
 * @copyright Copyright (c) 2018 Bjoern Schiessle <[email protected]>
4
 *
5
 * @author Bjoern Schiessle <[email protected]>
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License as
11
 * published by the Free Software Foundation, either version 3 of the
12
 * License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
namespace OCA\CloudFederationAPI\Controller;
25
26
use OCA\CloudFederationAPI\Config;
27
use OCP\AppFramework\Controller;
28
use OCP\AppFramework\Http;
29
use OCP\AppFramework\Http\JSONResponse;
30
use OCP\Federation\Exceptions\ActionNotSupportedException;
31
use OCP\Federation\Exceptions\AuthenticationFailedException;
32
use OCP\Federation\Exceptions\BadRequestException;
33
use OCP\Federation\Exceptions\ProviderCouldNotAddShareException;
34
use OCP\Federation\ICloudFederationFactory;
35
use OCP\Federation\ICloudFederationProviderManager;
36
use OCP\Federation\Exceptions\ProviderDoesNotExistsException;
37
use OCP\Federation\ICloudIdManager;
38
use OCP\IGroupManager;
39
use OCP\ILogger;
40
use OCP\IRequest;
41
use OCP\IURLGenerator;
42
use OCP\IUserManager;
43
use OCP\Share\Exceptions\ShareNotFound;
44
45
46
/**
47
 * Class RequestHandlerController
48
 *
49
 * handle API between different Cloud instances
50
 *
51
 * @package OCA\CloudFederationAPI\Controller
52
 */
53
class RequestHandlerController extends Controller {
54
55
	/** @var ILogger */
56
	private $logger;
57
58
	/** @var IUserManager */
59
	private $userManager;
60
61
	/** @var IGroupManager */
62
	private $groupManager;
63
64
	/** @var IURLGenerator */
65
	private $urlGenerator;
66
67
	/** @var ICloudFederationProviderManager */
68
	private $cloudFederationProviderManager;
69
70
	/** @var Config */
71
	private $config;
72
73
	/** @var ICloudFederationFactory */
74
	private $factory;
75
76
	/** @var ICloudIdManager */
77
	private $cloudIdManager;
78
79 View Code Duplication
	public function __construct($appName,
80
								IRequest $request,
81
								ILogger $logger,
82
								IUserManager $userManager,
83
								IGroupManager $groupManager,
84
								IURLGenerator $urlGenerator,
85
								ICloudFederationProviderManager $cloudFederationProviderManager,
86
								Config $config,
87
								ICloudFederationFactory $factory,
88
								ICloudIdManager $cloudIdManager
89
	) {
90
		parent::__construct($appName, $request);
91
92
		$this->logger = $logger;
93
		$this->userManager = $userManager;
94
		$this->groupManager = $groupManager;
95
		$this->urlGenerator = $urlGenerator;
96
		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
97
		$this->config = $config;
98
		$this->factory = $factory;
99
		$this->cloudIdManager = $cloudIdManager;
100
	}
101
102
	/**
103
	 * add share
104
	 *
105
	 * @NoCSRFRequired
106
	 * @PublicPage
107
	 * @BruteForceProtection(action=receiveFederatedShare)
108
	 *
109
	 * @param string $shareWith
110
	 * @param string $name resource name (e.g. document.odt)
111
	 * @param string $description share description (optional)
112
	 * @param string $providerId resource UID on the provider side
113
	 * @param string $owner provider specific UID of the user who owns the resource
114
	 * @param string $ownerDisplayName display name of the user who shared the item
115
	 * @param string $sharedBy provider specific UID of the user who shared the resource
116
	 * @param string $sharedByDisplayName display name of the user who shared the resource
117
	 * @param array $protocol (e,.g. ['name' => 'webdav', 'options' => ['username' => 'john', 'permissions' => 31]])
118
	 * @param string $shareType ('group' or 'user' share)
119
	 * @param $resourceType ('file', 'calendar',...)
120
	 * @return Http\DataResponse|JSONResponse
121
	 *
122
	 * Example: curl -H "Content-Type: application/json" -X POST -d '{"shareWith":"admin1@serve1","name":"welcome server2.txt","description":"desc","providerId":"2","owner":"admin2@http://localhost/server2","ownerDisplayName":"admin2 display","shareType":"user","resourceType":"file","protocol":{"name":"webdav","options":{"sharedSecret":"secret","permissions":"webdav-property"}}}' http://localhost/server/index.php/ocm/shares
123
	 */
124
	public function addShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $protocol, $shareType, $resourceType) {
125
126
		// check if all required parameters are set
127
		if ($shareWith === null ||
128
			$name === null ||
129
			$providerId === null ||
130
			$owner === null ||
131
			$resourceType === null ||
132
			$shareType === null ||
133
			!is_array($protocol) ||
134
			!isset($protocol['name']) ||
135
			!isset ($protocol['options']) ||
136
			!is_array($protocol['options']) ||
137
			!isset($protocol['options']['sharedSecret'])
138
		) {
139
			return new JSONResponse(
140
				['message' => 'Missing arguments'],
141
				Http::STATUS_BAD_REQUEST
142
			);
143
		}
144
145
		$supportedShareTypes = $this->config->getSupportedShareTypes($resourceType);
146
		if (!in_array($shareType, $supportedShareTypes)) {
147
			return new JSONResponse(
148
				['message' => 'Share type "' . $shareType . '" not implemented'],
149
				Http::STATUS_NOT_IMPLEMENTED
150
			);
151
		}
152
153
		$cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
154
		$shareWith = $cloudId->getUser();
155
156
		if ($shareType === 'user') {
157
			$shareWith = $this->mapUid($shareWith);
158
159
			if (!$this->userManager->userExists($shareWith)) {
160
				return new JSONResponse(
161
					['message' => 'User "' . $shareWith . '" does not exists at ' . $this->urlGenerator->getBaseUrl()],
162
					Http::STATUS_BAD_REQUEST
163
				);
164
			}
165
		}
166
167
		if ($shareType === 'group') {
168
			if(!$this->groupManager->groupExists($shareWith)) {
169
				return new JSONResponse(
170
					['message' => 'Group "' . $shareWith . '" does not exists at ' . $this->urlGenerator->getBaseUrl()],
171
					Http::STATUS_BAD_REQUEST
172
				);
173
			}
174
		}
175
176
		// if no explicit display name is given, we use the uid as display name
177
		$ownerDisplayName = $ownerDisplayName === null ? $owner : $ownerDisplayName;
178
		$sharedByDisplayName = $sharedByDisplayName === null ? $sharedBy : $sharedByDisplayName;
179
180
		// sharedBy* parameter is optional, if nothing is set we assume that it is the same user as the owner
181
		if ($sharedBy === null) {
182
			$sharedBy = $owner;
183
			$sharedByDisplayName = $ownerDisplayName;
184
		}
185
186
		try {
187
			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
188
			$share = $this->factory->getCloudFederationShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, '', $shareType, $resourceType);
189
			$share->setProtocol($protocol);
190
			$provider->shareReceived($share);
191
		} catch (ProviderDoesNotExistsException $e) {
192
			return new JSONResponse(
193
				['message' => $e->getMessage()],
194
				Http::STATUS_NOT_IMPLEMENTED
195
			);
196
		} catch (ProviderCouldNotAddShareException $e) {
197
			return new JSONResponse(
198
				['message' => $e->getMessage()],
199
				$e->getCode()
200
			);
201
		} catch (\Exception $e) {
202
			return new JSONResponse(
203
				['message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl()],
204
				Http::STATUS_BAD_REQUEST
205
			);
206
		}
207
208
		$user = $this->userManager->get($shareWith);
209
		$recipientDisplayName = '';
210
		if($user) {
211
			$recipientDisplayName = $user->getDisplayName();
212
		}
213
214
		return new JSONResponse(
215
			['recipientDisplayName' => $recipientDisplayName],
216
			Http::STATUS_CREATED);
217
218
	}
219
220
	/**
221
	 * receive notification about existing share
222
	 *
223
	 * @NoCSRFRequired
224
	 * @PublicPage
225
	 * @BruteForceProtection(action=receiveFederatedShareNotification)
226
	 *
227
	 * @param string $notificationType (notification type, e.g. SHARE_ACCEPTED)
228
	 * @param string $resourceType (calendar, file, contact,...)
229
	 * @param string $providerId id of the share
230
	 * @param array $notification the actual payload of the notification
231
	 * @return JSONResponse
232
	 */
233
	public function receiveNotification($notificationType, $resourceType, $providerId, array $notification) {
234
235
		// check if all required parameters are set
236
		if ($notificationType === null ||
237
			$resourceType === null ||
238
			$providerId === null ||
239
			!is_array($notification)
240
		) {
241
			return new JSONResponse(
242
				['message' => 'Missing arguments'],
243
				Http::STATUS_BAD_REQUEST
244
			);
245
		}
246
247
		try {
248
			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
249
			$result = $provider->notificationReceived($notificationType, $providerId, $notification);
250
		} catch (ProviderDoesNotExistsException $e) {
251
			return new JSONResponse(
252
				['message' => $e->getMessage()],
253
				Http::STATUS_BAD_REQUEST
254
			);
255
		} catch (ShareNotFound $e) {
256
			return new JSONResponse(
257
				['message' => $e->getMessage()],
258
				Http::STATUS_BAD_REQUEST
259
			);
260
		} catch (ActionNotSupportedException $e) {
261
			return new JSONResponse(
262
				['message' => $e->getMessage()],
263
				Http::STATUS_NOT_IMPLEMENTED
264
			);
265
		} catch (BadRequestException $e) {
266
			return new JSONResponse($e->getReturnMessage(), Http::STATUS_BAD_REQUEST);
267
		} catch (AuthenticationFailedException $e) {
268
			return new JSONResponse(["message" => "RESOURCE_NOT_FOUND"], Http::STATUS_FORBIDDEN);
269
		}
270
		catch (\Exception $e) {
271
			return new JSONResponse(
272
				['message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl()],
273
				Http::STATUS_BAD_REQUEST
274
			);
275
		}
276
277
		return new JSONResponse($result,Http::STATUS_CREATED);
278
279
	}
280
281
	/**
282
	 * map login name to internal LDAP UID if a LDAP backend is in use
283
	 *
284
	 * @param string $uid
285
	 * @return string mixed
286
	 */
287
	private function mapUid($uid) {
288
		// FIXME this should be a method in the user management instead
289
		$this->logger->debug('shareWith before, ' . $uid, ['app' => $this->appName]);
290
		\OCP\Util::emitHook(
291
			'\OCA\Files_Sharing\API\Server2Server',
292
			'preLoginNameUsedAsUserName',
293
			array('uid' => &$uid)
294
		);
295
		$this->logger->debug('shareWith after, ' . $uid, ['app' => $this->appName]);
296
297
		return $uid;
298
	}
299
300
}
301