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\DiscoveryManager; |
32
|
|
|
use OCA\FederatedFileSharing\FederatedShareProvider; |
33
|
|
|
use OCA\FederatedFileSharing\FedShareManager; |
34
|
|
|
use OCA\FederatedFileSharing\Notifications; |
35
|
|
|
use OCA\Files_Sharing\Activity; |
36
|
|
|
use OCP\AppFramework\Http; |
37
|
|
|
use OCP\AppFramework\OCSController; |
38
|
|
|
use OCP\Constants; |
39
|
|
|
use OCP\IDBConnection; |
40
|
|
|
use OCP\IRequest; |
41
|
|
|
use OCP\Share; |
42
|
|
|
use OCP\Share\IShare; |
43
|
|
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
44
|
|
|
use Symfony\Component\EventDispatcher\GenericEvent; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Class RequestHandlerController |
48
|
|
|
* |
49
|
|
|
* Handles OCS Request to the federated share API |
50
|
|
|
* |
51
|
|
|
* @package OCA\FederatedFileSharing\API |
52
|
|
|
*/ |
53
|
|
|
class RequestHandlerController extends OCSController { |
54
|
|
|
|
55
|
|
|
/** @var FederatedShareProvider */ |
56
|
|
|
private $federatedShareProvider; |
57
|
|
|
|
58
|
|
|
/** @var IDBConnection */ |
59
|
|
|
private $connection; |
60
|
|
|
|
61
|
|
|
/** @var Notifications */ |
62
|
|
|
private $notifications; |
63
|
|
|
|
64
|
|
|
/** @var AddressHandler */ |
65
|
|
|
private $addressHandler; |
66
|
|
|
|
67
|
|
|
/** @var FedShareManager */ |
68
|
|
|
private $fedShareManager; |
69
|
|
|
|
70
|
|
|
/** @var EventDispatcherInterface */ |
71
|
|
|
private $eventDispatcher; |
72
|
|
|
|
73
|
|
|
/** @var string */ |
74
|
|
|
private $shareTable = 'share'; |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* Server2Server constructor. |
78
|
|
|
* |
79
|
|
|
* @param string $appName |
80
|
|
|
* @param IRequest $request |
81
|
|
|
* @param FederatedShareProvider $federatedShareProvider |
82
|
|
|
* @param IDBConnection $connection |
83
|
|
|
* @param Notifications $notifications |
84
|
|
|
* @param AddressHandler $addressHandler |
85
|
|
|
* @param FedShareManager $fedShareManager |
86
|
|
|
* @param EventDispatcherInterface $eventDispatcher |
87
|
|
|
*/ |
88
|
|
|
public function __construct($appName, |
89
|
|
|
IRequest $request, |
90
|
|
|
FederatedShareProvider $federatedShareProvider, |
91
|
|
|
IDBConnection $connection, |
92
|
|
|
Notifications $notifications, |
93
|
|
|
AddressHandler $addressHandler, |
94
|
|
|
FedShareManager $fedShareManager, |
95
|
|
|
EventDispatcherInterface $eventDispatcher |
96
|
|
|
) { |
97
|
|
|
parent::__construct($appName, $request); |
98
|
|
|
|
99
|
|
|
$this->federatedShareProvider = $federatedShareProvider; |
100
|
|
|
$this->connection = $connection; |
101
|
|
|
$this->notifications = $notifications; |
102
|
|
|
$this->addressHandler = $addressHandler; |
103
|
|
|
$this->fedShareManager = $fedShareManager; |
104
|
|
|
$this->eventDispatcher = $eventDispatcher; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @NoCSRFRequired |
109
|
|
|
* @PublicPage |
110
|
|
|
* |
111
|
|
|
* create a new share |
112
|
|
|
* |
113
|
|
|
* @return Result |
114
|
|
|
*/ |
115
|
|
|
public function createShare() { |
116
|
|
|
if (!$this->isS2SEnabled(true)) { |
117
|
|
|
return new Result(null, 503, 'Server does not support federated cloud sharing'); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
$remote = isset($_POST['remote']) ? $_POST['remote'] : null; |
121
|
|
|
$token = isset($_POST['token']) ? $_POST['token'] : null; |
122
|
|
|
$name = isset($_POST['name']) ? $_POST['name'] : null; |
123
|
|
|
$owner = isset($_POST['owner']) ? $_POST['owner'] : null; |
124
|
|
|
$sharedBy = isset($_POST['sharedBy']) ? $_POST['sharedBy'] : null; |
125
|
|
|
$shareWith = isset($_POST['shareWith']) ? $_POST['shareWith'] : null; |
126
|
|
|
$remoteId = isset($_POST['remoteId']) ? (int)$_POST['remoteId'] : null; |
127
|
|
|
$sharedByFederatedId = isset($_POST['sharedByFederatedId']) ? $_POST['sharedByFederatedId'] : null; |
128
|
|
|
$ownerFederatedId = isset($_POST['ownerFederatedId']) ? $_POST['ownerFederatedId'] : null; |
129
|
|
|
|
130
|
|
View Code Duplication |
if ($this->hasNull([$remote, $token, $name, $owner, $remoteId, $shareWith])) { |
|
|
|
|
131
|
|
|
return new Result(null, 400, 'server can not add remote share, missing parameter'); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
if (!\OCP\Util::isValidFileName($name)) { |
135
|
|
|
return new Result(null, 400, 'The mountpoint name contains invalid characters.'); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
// FIXME this should be a method in the user management instead |
139
|
|
|
\OCP\Util::writeLog('files_sharing', 'shareWith before, ' . $shareWith, \OCP\Util::DEBUG); |
140
|
|
|
\OCP\Util::emitHook( |
141
|
|
|
'\OCA\Files_Sharing\API\Server2Server', |
142
|
|
|
'preLoginNameUsedAsUserName', |
143
|
|
|
['uid' => &$shareWith] |
144
|
|
|
); |
145
|
|
|
\OCP\Util::writeLog('files_sharing', 'shareWith after, ' . $shareWith, \OCP\Util::DEBUG); |
146
|
|
|
|
147
|
|
|
if (!\OCP\User::userExists($shareWith)) { |
148
|
|
|
return new Result(null, 400, 'User does not exist'); |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
\OC_Util::setupFS($shareWith); |
152
|
|
|
|
153
|
|
|
$discoveryManager = new DiscoveryManager( |
154
|
|
|
\OC::$server->getMemCacheFactory(), |
155
|
|
|
\OC::$server->getHTTPClientService() |
156
|
|
|
); |
157
|
|
|
$externalManager = new \OCA\Files_Sharing\External\Manager( |
158
|
|
|
\OC::$server->getDatabaseConnection(), |
159
|
|
|
\OC\Files\Filesystem::getMountManager(), |
160
|
|
|
\OC\Files\Filesystem::getLoader(), |
161
|
|
|
\OC::$server->getNotificationManager(), |
162
|
|
|
\OC::$server->getEventDispatcher(), |
163
|
|
|
$shareWith |
164
|
|
|
); |
165
|
|
|
|
166
|
|
|
try { |
167
|
|
|
$externalManager->addShare($remote, $token, '', $name, $owner, false, $shareWith, $remoteId); |
168
|
|
|
$shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external'); |
169
|
|
|
if ($ownerFederatedId === null) { |
170
|
|
|
$ownerFederatedId = $owner . '@' . $this->cleanupRemote($remote); |
171
|
|
|
} |
172
|
|
|
// if the owner of the share and the initiator are the same user |
173
|
|
|
// we also complete the federated share ID for the initiator |
174
|
|
|
if ($sharedByFederatedId === null && $owner === $sharedBy) { |
175
|
|
|
$sharedByFederatedId = $ownerFederatedId; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
$event = new GenericEvent( |
179
|
|
|
null, |
180
|
|
|
[ |
181
|
|
|
'name' => $name, |
182
|
|
|
'targetuser' => $sharedByFederatedId, |
183
|
|
|
'owner' => $owner, |
184
|
|
|
'sharewith' => $shareWith, |
185
|
|
|
'sharedby' => $sharedBy, |
186
|
|
|
'remoteid' => $remoteId |
187
|
|
|
] |
188
|
|
|
); |
189
|
|
|
$this->eventDispatcher->dispatch('\OCA\FederatedFileSharing::remote_shareReceived', $event); |
190
|
|
|
\OC::$server->getActivityManager()->publishActivity( |
191
|
|
|
Activity::FILES_SHARING_APP, Activity::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, \trim($name, '/')], '', [], |
192
|
|
|
'', '', $shareWith, Activity::TYPE_REMOTE_SHARE, Activity::PRIORITY_LOW |
193
|
|
|
); |
194
|
|
|
|
195
|
|
|
$urlGenerator = \OC::$server->getURLGenerator(); |
196
|
|
|
|
197
|
|
|
$notificationManager = \OC::$server->getNotificationManager(); |
198
|
|
|
$notification = $notificationManager->createNotification(); |
199
|
|
|
$notification->setApp('files_sharing') |
200
|
|
|
->setUser($shareWith) |
201
|
|
|
->setDateTime(new \DateTime()) |
202
|
|
|
->setObject('remote_share', $shareId) |
203
|
|
|
->setSubject('remote_share', [$ownerFederatedId, $sharedByFederatedId, \trim($name, '/')]) |
204
|
|
|
->setMessage('remote_share', [$ownerFederatedId, $sharedByFederatedId, \trim($name, '/')]); |
205
|
|
|
|
206
|
|
|
$declineAction = $notification->createAction(); |
207
|
|
|
$declineAction->setLabel('decline') |
208
|
|
|
->setLink($urlGenerator->getAbsoluteURL($urlGenerator->linkTo('', 'ocs/v1.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE'); |
209
|
|
|
$notification->addAction($declineAction); |
210
|
|
|
|
211
|
|
|
$acceptAction = $notification->createAction(); |
212
|
|
|
$acceptAction->setLabel('accept') |
213
|
|
|
->setLink($urlGenerator->getAbsoluteURL($urlGenerator->linkTo('', 'ocs/v1.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST'); |
214
|
|
|
$notification->addAction($acceptAction); |
215
|
|
|
|
216
|
|
|
$notificationManager->notify($notification); |
217
|
|
|
} catch (\Exception $e) { |
218
|
|
|
\OCP\Util::writeLog('files_sharing', 'server can not add remote share, ' . $e->getMessage(), \OCP\Util::ERROR); |
219
|
|
|
return new Result(null, 500, 'internal server error, was not able to add share from ' . $remote); |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
return new Result(); |
223
|
|
|
} |
224
|
|
|
|
225
|
|
|
/** |
226
|
|
|
* @NoCSRFRequired |
227
|
|
|
* @PublicPage |
228
|
|
|
* |
229
|
|
|
* create re-share on behalf of another user |
230
|
|
|
* |
231
|
|
|
* @param int $id |
232
|
|
|
* |
233
|
|
|
* @return Result |
234
|
|
|
*/ |
235
|
|
|
public function reShare($id) { |
236
|
|
|
$token = $this->request->getParam('token', null); |
237
|
|
|
$shareWith = $this->request->getParam('shareWith', null); |
238
|
|
|
$permission = (int)$this->request->getParam('permission', null); |
239
|
|
|
$remoteId = (int)$this->request->getParam('remoteId', null); |
240
|
|
|
|
241
|
|
View Code Duplication |
if ($this->hasNull([$id, $token, $shareWith, $permission, $remoteId])) { |
|
|
|
|
242
|
|
|
return new Result(null, Http::STATUS_BAD_REQUEST); |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
try { |
246
|
|
|
$share = $this->federatedShareProvider->getShareById($id); |
247
|
|
|
|
248
|
|
|
// don't allow to share a file back to the owner |
249
|
|
|
list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith); |
250
|
|
|
$owner = $share->getShareOwner(); |
251
|
|
|
$currentServer = $this->addressHandler->generateRemoteURL(); |
252
|
|
|
if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer) |
253
|
|
|
|| !$this->verifyShare($share, $token) |
254
|
|
|
) { |
255
|
|
|
return new Result(null, Http::STATUS_FORBIDDEN); |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
// check if re-sharing is allowed |
259
|
|
|
if (!$share->getPermissions() | ~Constants::PERMISSION_SHARE) { |
260
|
|
|
return new Result(null, Http::STATUS_BAD_REQUEST); |
261
|
|
|
} |
262
|
|
|
$share->setPermissions($share->getPermissions() & $permission); |
263
|
|
|
// the recipient of the initial share is now the initiator for the re-share |
264
|
|
|
$share->setSharedBy($share->getSharedWith()); |
265
|
|
|
$share->setSharedWith($shareWith); |
266
|
|
|
|
267
|
|
|
$result = $this->federatedShareProvider->create($share); |
268
|
|
|
$this->federatedShareProvider->storeRemoteId((int)$result->getId(), $remoteId); |
269
|
|
|
} catch (Share\Exceptions\ShareNotFound $e) { |
270
|
|
|
return new Result(null, Http::STATUS_NOT_FOUND); |
271
|
|
|
} catch (\Exception $e) { |
272
|
|
|
return new Result(null, Http::STATUS_BAD_REQUEST); |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
return new Result(['token' => $result->getToken(), 'remoteId' => $result->getId()]); |
276
|
|
|
} |
277
|
|
|
|
278
|
|
|
/** |
279
|
|
|
* @NoCSRFRequired |
280
|
|
|
* @PublicPage |
281
|
|
|
* |
282
|
|
|
* accept server-to-server share |
283
|
|
|
* |
284
|
|
|
* @param int $id |
285
|
|
|
* |
286
|
|
|
* @return Result |
287
|
|
|
*/ |
288
|
|
View Code Duplication |
public function acceptShare($id) { |
289
|
|
|
if (!$this->isS2SEnabled()) { |
290
|
|
|
return new Result(null, 503, 'Server does not support federated cloud sharing'); |
291
|
|
|
} |
292
|
|
|
|
293
|
|
|
$token = isset($_POST['token']) ? $_POST['token'] : null; |
294
|
|
|
|
295
|
|
|
try { |
296
|
|
|
$share = $this->federatedShareProvider->getShareById($id); |
297
|
|
|
if ($this->verifyShare($share, $token)) { |
298
|
|
|
$this->fedShareManager->acceptShare($share); |
299
|
|
|
if ($share->getShareOwner() !== $share->getSharedBy()) { |
300
|
|
|
list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy()); |
301
|
|
|
$remoteId = $this->federatedShareProvider->getRemoteId($share); |
302
|
|
|
$this->notifications->sendAcceptShare($remote, $remoteId, $share->getToken()); |
303
|
|
|
} |
304
|
|
|
} |
305
|
|
|
} catch (Share\Exceptions\ShareNotFound $e) { |
306
|
|
|
// pass |
307
|
|
|
} |
308
|
|
|
return new Result(); |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
/** |
312
|
|
|
* @NoCSRFRequired |
313
|
|
|
* @PublicPage |
314
|
|
|
* |
315
|
|
|
* decline server-to-server share |
316
|
|
|
* |
317
|
|
|
* @param int $id |
318
|
|
|
* |
319
|
|
|
* @return Result |
320
|
|
|
*/ |
321
|
|
View Code Duplication |
public function declineShare($id) { |
322
|
|
|
if (!$this->isS2SEnabled()) { |
323
|
|
|
return new Result(null, 503, 'Server does not support federated cloud sharing'); |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
$token = isset($_POST['token']) ? $_POST['token'] : null; |
327
|
|
|
|
328
|
|
|
try { |
329
|
|
|
$share = $this->federatedShareProvider->getShareById($id); |
330
|
|
|
if ($this->verifyShare($share, $token)) { |
331
|
|
|
if ($share->getShareOwner() !== $share->getSharedBy()) { |
332
|
|
|
list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy()); |
333
|
|
|
$remoteId = $this->federatedShareProvider->getRemoteId($share); |
334
|
|
|
$this->notifications->sendDeclineShare($remote, $remoteId, $share->getToken()); |
335
|
|
|
} |
336
|
|
|
$this->fedShareManager->declineShare($share); |
337
|
|
|
} |
338
|
|
|
} catch (Share\Exceptions\ShareNotFound $e) { |
339
|
|
|
// pass |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
return new Result(); |
343
|
|
|
} |
344
|
|
|
|
345
|
|
|
/** |
346
|
|
|
* @NoCSRFRequired |
347
|
|
|
* @PublicPage |
348
|
|
|
* |
349
|
|
|
* remove server-to-server share if it was unshared by the owner |
350
|
|
|
* |
351
|
|
|
* @param int $id |
352
|
|
|
* |
353
|
|
|
* @return Result |
354
|
|
|
*/ |
355
|
|
|
public function unshare($id) { |
356
|
|
|
if (!$this->isS2SEnabled()) { |
357
|
|
|
return new Result(null, 503, 'Server does not support federated cloud sharing'); |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
$token = isset($_POST['token']) ? $_POST['token'] : null; |
361
|
|
|
|
362
|
|
|
$query = \OCP\DB::prepare('SELECT * FROM `*PREFIX*share_external` WHERE `remote_id` = ? AND `share_token` = ?'); |
363
|
|
|
$query->execute([$id, $token]); |
364
|
|
|
$share = $query->fetchRow(); |
365
|
|
|
|
366
|
|
|
if ($token && $id && !empty($share)) { |
367
|
|
|
$remote = $this->cleanupRemote($share['remote']); |
368
|
|
|
|
369
|
|
|
$owner = $share['owner'] . '@' . $remote; |
370
|
|
|
$mountpoint = $share['mountpoint']; |
371
|
|
|
$user = $share['user']; |
372
|
|
|
|
373
|
|
|
$query = \OCP\DB::prepare('DELETE FROM `*PREFIX*share_external` WHERE `remote_id` = ? AND `share_token` = ?'); |
374
|
|
|
$query->execute([$id, $token]); |
375
|
|
|
|
376
|
|
|
if ($share['accepted']) { |
377
|
|
|
$path = \trim($mountpoint, '/'); |
378
|
|
|
} else { |
379
|
|
|
$path = \trim($share['name'], '/'); |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
$notificationManager = \OC::$server->getNotificationManager(); |
383
|
|
|
$notification = $notificationManager->createNotification(); |
384
|
|
|
$notification->setApp('files_sharing') |
385
|
|
|
->setUser($share['user']) |
386
|
|
|
->setObject('remote_share', (int) $share['id']); |
387
|
|
|
$notificationManager->markProcessed($notification); |
388
|
|
|
|
389
|
|
|
\OC::$server->getActivityManager()->publishActivity( |
390
|
|
|
Activity::FILES_SHARING_APP, Activity::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner, $path], '', [], |
391
|
|
|
'', '', $user, Activity::TYPE_REMOTE_SHARE, Activity::PRIORITY_MEDIUM); |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
return new Result(); |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
private function cleanupRemote($remote) { |
398
|
|
|
$remote = \substr($remote, \strpos($remote, '://') + 3); |
399
|
|
|
|
400
|
|
|
return \rtrim($remote, '/'); |
401
|
|
|
} |
402
|
|
|
|
403
|
|
|
/** |
404
|
|
|
* @NoCSRFRequired |
405
|
|
|
* @PublicPage |
406
|
|
|
* |
407
|
|
|
* federated share was revoked, either by the owner or the re-sharer |
408
|
|
|
* |
409
|
|
|
* @param int $id |
410
|
|
|
* |
411
|
|
|
* @return Result |
412
|
|
|
*/ |
413
|
|
|
public function revoke($id) { |
414
|
|
|
$token = $this->request->getParam('token'); |
415
|
|
|
|
416
|
|
|
$share = $this->federatedShareProvider->getShareById($id); |
417
|
|
|
if (!$this->verifyShare($share, $token)) { |
418
|
|
|
return new Result(null, Http::STATUS_BAD_REQUEST); |
419
|
|
|
} |
420
|
|
|
|
421
|
|
|
$this->federatedShareProvider->removeShareFromTable($share); |
422
|
|
|
return new Result(); |
423
|
|
|
} |
424
|
|
|
|
425
|
|
|
/** |
426
|
|
|
* get share |
427
|
|
|
* |
428
|
|
|
* @param int $id |
429
|
|
|
* @param string $token |
430
|
|
|
* |
431
|
|
|
* @return array|bool |
432
|
|
|
*/ |
433
|
|
|
protected function getShare($id, $token) { |
434
|
|
|
$query = $this->connection->getQueryBuilder(); |
435
|
|
|
$query->select('*')->from($this->shareTable) |
436
|
|
|
->where($query->expr()->eq('token', $query->createNamedParameter($token))) |
437
|
|
|
->andWhere($query->expr()->eq('share_type', $query->createNamedParameter(FederatedShareProvider::SHARE_TYPE_REMOTE))) |
438
|
|
|
->andWhere($query->expr()->eq('id', $query->createNamedParameter($id))); |
439
|
|
|
|
440
|
|
|
$result = $query->execute()->fetchAll(); |
441
|
|
|
|
442
|
|
|
if (!empty($result) && isset($result[0])) { |
443
|
|
|
return $result[0]; |
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
return false; |
447
|
|
|
} |
448
|
|
|
|
449
|
|
|
/** |
450
|
|
|
* check if server-to-server sharing is enabled |
451
|
|
|
* |
452
|
|
|
* @param bool $incoming |
453
|
|
|
* |
454
|
|
|
* @return bool |
455
|
|
|
*/ |
456
|
|
|
private function isS2SEnabled($incoming = false) { |
457
|
|
|
$result = \OCP\App::isEnabled('files_sharing'); |
458
|
|
|
|
459
|
|
|
if ($incoming) { |
460
|
|
|
$result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled(); |
461
|
|
|
} else { |
462
|
|
|
$result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled(); |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
return $result; |
466
|
|
|
} |
467
|
|
|
|
468
|
|
|
/** |
469
|
|
|
* check if we got the right share |
470
|
|
|
* |
471
|
|
|
* @param Share\IShare $share |
472
|
|
|
* @param string $token |
473
|
|
|
* |
474
|
|
|
* @return bool |
475
|
|
|
*/ |
476
|
|
|
protected function verifyShare(Share\IShare $share, $token) { |
477
|
|
|
if ( |
478
|
|
|
$share->getShareType() === FederatedShareProvider::SHARE_TYPE_REMOTE && |
479
|
|
|
$share->getToken() === $token |
480
|
|
|
) { |
481
|
|
|
return true; |
482
|
|
|
} |
483
|
|
|
|
484
|
|
|
return false; |
485
|
|
|
} |
486
|
|
|
|
487
|
|
|
/** |
488
|
|
|
* @NoCSRFRequired |
489
|
|
|
* @PublicPage |
490
|
|
|
* |
491
|
|
|
* update share information to keep federated re-shares in sync |
492
|
|
|
* |
493
|
|
|
* @param array $params |
494
|
|
|
* |
495
|
|
|
* @return Result |
496
|
|
|
*/ |
497
|
|
|
public function updatePermissions($params) { |
498
|
|
|
$id = (int)$params['id']; |
499
|
|
|
$token = $this->request->getParam('token', null); |
500
|
|
|
$permissions = $this->request->getParam('permissions', null); |
501
|
|
|
|
502
|
|
|
try { |
503
|
|
|
$share = $this->federatedShareProvider->getShareById($id); |
504
|
|
|
$validPermission = \ctype_digit($permissions); |
505
|
|
|
$validToken = $this->verifyShare($share, $token); |
506
|
|
|
if (!$validPermission || !$validToken) { |
507
|
|
|
return new Result(null, Http::STATUS_BAD_REQUEST); |
508
|
|
|
} |
509
|
|
|
$this->updatePermissionsInDatabase($share, (int)$permissions); |
510
|
|
|
} catch (Share\Exceptions\ShareNotFound $e) { |
511
|
|
|
return new Result(null, Http::STATUS_BAD_REQUEST); |
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
return new Result(); |
515
|
|
|
} |
516
|
|
|
|
517
|
|
|
/** |
518
|
|
|
* update permissions in database |
519
|
|
|
* |
520
|
|
|
* @param IShare $share |
521
|
|
|
* @param int $permissions |
522
|
|
|
*/ |
523
|
|
View Code Duplication |
protected function updatePermissionsInDatabase(IShare $share, $permissions) { |
524
|
|
|
$query = $this->connection->getQueryBuilder(); |
525
|
|
|
$query->update('share') |
526
|
|
|
->where($query->expr()->eq('id', $query->createNamedParameter($share->getId()))) |
527
|
|
|
->set('permissions', $query->createNamedParameter($permissions)) |
528
|
|
|
->execute(); |
529
|
|
|
} |
530
|
|
|
|
531
|
|
|
/** |
532
|
|
|
* Check if value is null or an array has any null item |
533
|
|
|
* |
534
|
|
|
* @param mixed $param |
535
|
|
|
* |
536
|
|
|
* @return bool |
537
|
|
|
*/ |
538
|
|
|
protected function hasNull($param) { |
539
|
|
|
if (\is_array($param)) { |
540
|
|
|
return \in_array(null, $param, true); |
541
|
|
|
} else { |
542
|
|
|
return $param === null; |
543
|
|
|
} |
544
|
|
|
} |
545
|
|
|
} |
546
|
|
|
|
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.