Completed
Pull Request — master (#9345)
by Björn
57:07 queued 34:19
created
apps/federatedfilesharing/lib/Controller/RequestHandlerController.php 1 patch
Indentation   +427 added lines, -427 removed lines patch added patch discarded remove patch
@@ -52,431 +52,431 @@
 block discarded – undo
52 52
 
53 53
 class RequestHandlerController extends OCSController {
54 54
 
55
-	/** @var FederatedShareProvider */
56
-	private $federatedShareProvider;
57
-
58
-	/** @var IDBConnection */
59
-	private $connection;
60
-
61
-	/** @var Share\IManager */
62
-	private $shareManager;
63
-
64
-	/** @var Notifications */
65
-	private $notifications;
66
-
67
-	/** @var AddressHandler */
68
-	private $addressHandler;
69
-
70
-	/** @var  IUserManager */
71
-	private $userManager;
72
-
73
-	/** @var string */
74
-	private $shareTable = 'share';
75
-
76
-	/** @var ICloudIdManager */
77
-	private $cloudIdManager;
78
-
79
-	/** @var ILogger */
80
-	private $logger;
81
-
82
-	/** @var ICloudFederationFactory */
83
-	private $cloudFederationFactory;
84
-
85
-	/** @var ICloudFederationProviderManager */
86
-	private $cloudFederationProviderManager;
87
-
88
-	/**
89
-	 * Server2Server constructor.
90
-	 *
91
-	 * @param string $appName
92
-	 * @param IRequest $request
93
-	 * @param FederatedShareProvider $federatedShareProvider
94
-	 * @param IDBConnection $connection
95
-	 * @param Share\IManager $shareManager
96
-	 * @param Notifications $notifications
97
-	 * @param AddressHandler $addressHandler
98
-	 * @param IUserManager $userManager
99
-	 * @param ICloudIdManager $cloudIdManager
100
-	 * @param ILogger $logger
101
-	 * @param ICloudFederationFactory $cloudFederationFactory
102
-	 * @param ICloudFederationProviderManager $cloudFederationProviderManager
103
-	 */
104
-	public function __construct($appName,
105
-								IRequest $request,
106
-								FederatedShareProvider $federatedShareProvider,
107
-								IDBConnection $connection,
108
-								Share\IManager $shareManager,
109
-								Notifications $notifications,
110
-								AddressHandler $addressHandler,
111
-								IUserManager $userManager,
112
-								ICloudIdManager $cloudIdManager,
113
-								ILogger $logger,
114
-								ICloudFederationFactory $cloudFederationFactory,
115
-								ICloudFederationProviderManager $cloudFederationProviderManager
116
-	) {
117
-		parent::__construct($appName, $request);
118
-
119
-		$this->federatedShareProvider = $federatedShareProvider;
120
-		$this->connection = $connection;
121
-		$this->shareManager = $shareManager;
122
-		$this->notifications = $notifications;
123
-		$this->addressHandler = $addressHandler;
124
-		$this->userManager = $userManager;
125
-		$this->cloudIdManager = $cloudIdManager;
126
-		$this->logger = $logger;
127
-		$this->cloudFederationFactory = $cloudFederationFactory;
128
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
129
-	}
130
-
131
-	/**
132
-	 * @NoCSRFRequired
133
-	 * @PublicPage
134
-	 *
135
-	 * create a new share
136
-	 *
137
-	 * @return Http\DataResponse
138
-	 * @throws OCSException
139
-	 */
140
-	public function createShare() {
141
-
142
-		$remote = isset($_POST['remote']) ? $_POST['remote'] : null;
143
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
144
-		$name = isset($_POST['name']) ? $_POST['name'] : null;
145
-		$owner = isset($_POST['owner']) ? $_POST['owner'] : null;
146
-		$sharedBy = isset($_POST['sharedBy']) ? $_POST['sharedBy'] : null;
147
-		$shareWith = isset($_POST['shareWith']) ? $_POST['shareWith'] : null;
148
-		$remoteId = isset($_POST['remoteId']) ? (int)$_POST['remoteId'] : null;
149
-		$sharedByFederatedId = isset($_POST['sharedByFederatedId']) ? $_POST['sharedByFederatedId'] : null;
150
-		$ownerFederatedId = isset($_POST['ownerFederatedId']) ? $_POST['ownerFederatedId'] : null;
151
-
152
-		if ($ownerFederatedId === null) {
153
-			$ownerFederatedId = $this->cloudIdManager->getCloudId($owner, $this->cleanupRemote($remote))->getId();
154
-		}
155
-		// if the owner of the share and the initiator are the same user
156
-		// we also complete the federated share ID for the initiator
157
-		if ($sharedByFederatedId === null && $owner === $sharedBy) {
158
-			$sharedByFederatedId = $ownerFederatedId;
159
-		}
160
-
161
-		$share = $this->cloudFederationFactory->getCloudFederationShare(
162
-			$shareWith,
163
-			$name,
164
-			'',
165
-			$remoteId,
166
-			$ownerFederatedId,
167
-			$owner,
168
-			$sharedByFederatedId,
169
-			$sharedBy,
170
-			$token,
171
-			'user',
172
-			'file'
173
-		);
174
-
175
-		try {
176
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
177
-			$provider->shareReceived($share);
178
-		} catch (ProviderDoesNotExistsException $e) {
179
-			throw new OCSException('Server does not support federated cloud sharing', 503);
180
-		} catch (ProviderCouldNotAddShareException $e) {
181
-			throw new OCSException($e->getMessage(), 400);
182
-		} catch (\Exception $e) {
183
-			throw new OCSException('internal server error, was not able to add share from ' . $remote, 500);
184
-		}
185
-
186
-		return new Http\DataResponse();
187
-	}
188
-
189
-	/**
190
-	 * @NoCSRFRequired
191
-	 * @PublicPage
192
-	 *
193
-	 * create re-share on behalf of another user
194
-	 *
195
-	 * @param int $id
196
-	 * @return Http\DataResponse
197
-	 * @throws OCSBadRequestException
198
-	 * @throws OCSException
199
-	 * @throws OCSForbiddenException
200
-	 */
201
-	public function reShare($id) {
202
-
203
-		$token = $this->request->getParam('token', null);
204
-		$shareWith = $this->request->getParam('shareWith', null);
205
-		$permission = (int)$this->request->getParam('permission', null);
206
-		$remoteId = (int)$this->request->getParam('remoteId', null);
207
-
208
-		if ($id === null ||
209
-			$token === null ||
210
-			$shareWith === null ||
211
-			$permission === null ||
212
-			$remoteId === null
213
-		) {
214
-			throw new OCSBadRequestException();
215
-		}
216
-
217
-		$notification = [
218
-			'sharedSecret' => $token,
219
-			'shareWith' => $shareWith,
220
-			'senderId' => $remoteId,
221
-			'message' => 'Recipient of a share ask the owner to reshare the file'
222
-		];
223
-
224
-		try {
225
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
226
-			list($newToken, $localId) = $provider->notificationReceived('REQUEST_RESHARE', $id, $notification);
227
-			return new Http\DataResponse([
228
-				'token' => $newToken,
229
-				'remoteId' => $localId
230
-			]);
231
-		} catch (ProviderDoesNotExistsException $e) {
232
-			throw new OCSException('Server does not support federated cloud sharing', 503);
233
-		} catch (ShareNotFound $e) {
234
-			$this->logger->debug('Share not found: ' . $e->getMessage());
235
-		} catch (\Exception $e) {
236
-			$this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
237
-		}
238
-
239
-		throw new OCSBadRequestException();
240
-	}
241
-
242
-
243
-	/**
244
-	 * @NoCSRFRequired
245
-	 * @PublicPage
246
-	 *
247
-	 * accept server-to-server share
248
-	 *
249
-	 * @param int $id
250
-	 * @return Http\DataResponse
251
-	 * @throws OCSException
252
-	 * @throws ShareNotFound
253
-	 * @throws \OC\HintException
254
-	 */
255
-	public function acceptShare($id) {
256
-
257
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
258
-
259
-		$notification = [
260
-			'sharedSecret' => $token,
261
-			'message' => 'Recipient accept the share'
262
-		];
263
-
264
-		try {
265
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
266
-			$provider->notificationReceived('SHARE_ACCEPTED', $id, $notification);
267
-		} catch (ProviderDoesNotExistsException $e) {
268
-			throw new OCSException('Server does not support federated cloud sharing', 503);
269
-		} catch (ShareNotFound $e) {
270
-			$this->logger->debug('Share not found: ' . $e->getMessage());
271
-		} catch (\Exception $e) {
272
-			$this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
273
-		}
274
-
275
-		return new Http\DataResponse();
276
-	}
277
-
278
-	/**
279
-	 * @NoCSRFRequired
280
-	 * @PublicPage
281
-	 *
282
-	 * decline server-to-server share
283
-	 *
284
-	 * @param int $id
285
-	 * @return Http\DataResponse
286
-	 * @throws OCSException
287
-	 */
288
-	public function declineShare($id) {
289
-
290
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
291
-
292
-		$notification = [
293
-			'sharedSecret' => $token,
294
-			'message' => 'Recipient declined the share'
295
-		];
296
-
297
-		try {
298
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
299
-			$provider->notificationReceived('SHARE_DECLINED', $id, $notification);
300
-		} catch (ProviderDoesNotExistsException $e) {
301
-			throw new OCSException('Server does not support federated cloud sharing', 503);
302
-		} catch (ShareNotFound $e) {
303
-			$this->logger->debug('Share not found: ' . $e->getMessage());
304
-		} catch (\Exception $e) {
305
-			$this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
306
-		}
307
-
308
-		return new Http\DataResponse();
309
-	}
310
-
311
-	/**
312
-	 * @NoCSRFRequired
313
-	 * @PublicPage
314
-	 *
315
-	 * remove server-to-server share if it was unshared by the owner
316
-	 *
317
-	 * @param int $id
318
-	 * @return Http\DataResponse
319
-	 * @throws OCSException
320
-	 */
321
-	public function unshare($id) {
322
-
323
-		if (!$this->isS2SEnabled()) {
324
-			throw new OCSException('Server does not support federated cloud sharing', 503);
325
-		}
326
-
327
-		$token = isset($_POST['token']) ? $_POST['token'] : null;
328
-
329
-		try {
330
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
331
-			$notification = ['sharedSecret' => $token];
332
-			$provider->notificationReceived('SHARE_UNSHARED', $id, $notification);
333
-		} catch (\Exception $e) {
334
-			$this->logger->debug('processing unshare notification failed: ' . $e->getMessage());
335
-		}
336
-
337
-		return new Http\DataResponse();
338
-	}
339
-
340
-	private function cleanupRemote($remote) {
341
-		$remote = substr($remote, strpos($remote, '://') + 3);
342
-
343
-		return rtrim($remote, '/');
344
-	}
345
-
346
-
347
-	/**
348
-	 * @NoCSRFRequired
349
-	 * @PublicPage
350
-	 *
351
-	 * federated share was revoked, either by the owner or the re-sharer
352
-	 *
353
-	 * @param int $id
354
-	 * @return Http\DataResponse
355
-	 * @throws OCSBadRequestException
356
-	 */
357
-	public function revoke($id) {
358
-
359
-		$token = $this->request->getParam('token');
360
-
361
-		try {
362
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
363
-			$notification = ['sharedSecret' => $token];
364
-			$provider->notificationReceived('RESHARE_UNDO', $id, $notification);
365
-			return new Http\DataResponse();
366
-		} catch (\Exception $e) {
367
-			throw new OCSBadRequestException();
368
-		}
369
-
370
-	}
371
-
372
-	/**
373
-	 * check if server-to-server sharing is enabled
374
-	 *
375
-	 * @param bool $incoming
376
-	 * @return bool
377
-	 */
378
-	private function isS2SEnabled($incoming = false) {
379
-
380
-		$result = \OCP\App::isEnabled('files_sharing');
381
-
382
-		if ($incoming) {
383
-			$result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
384
-		} else {
385
-			$result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
386
-		}
387
-
388
-		return $result;
389
-	}
390
-
391
-	/**
392
-	 * @NoCSRFRequired
393
-	 * @PublicPage
394
-	 *
395
-	 * update share information to keep federated re-shares in sync
396
-	 *
397
-	 * @param int $id
398
-	 * @return Http\DataResponse
399
-	 * @throws OCSBadRequestException
400
-	 */
401
-	public function updatePermissions($id) {
402
-		$token = $this->request->getParam('token', null);
403
-		$ncPermissions = $this->request->getParam('permissions', null);
404
-
405
-		try {
406
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
407
-			$ocmPermissions = $this->ncPermissions2ocmPermissions((int)$ncPermissions);
408
-			$notification = ['sharedSecret' => $token, 'permission' => $ocmPermissions];
409
-			$provider->notificationReceived('RESHARE_CHANGE_PERMISSION', $id, $notification);
410
-		} catch (\Exception $e) {
411
-			$this->logger->debug($e->getMessage());
412
-			throw new OCSBadRequestException();
413
-		}
414
-
415
-		return new Http\DataResponse();
416
-	}
417
-
418
-	/**
419
-	 * translate Nextcloud permissions to OCM Permissions
420
-	 *
421
-	 * @param $ncPermissions
422
-	 * @return array
423
-	 */
424
-	protected function ncPermissions2ocmPermissions($ncPermissions) {
425
-
426
-		$ocmPermissions = [];
427
-
428
-		if ($ncPermissions & Constants::PERMISSION_SHARE) {
429
-			$ocmPermissions[] = 'share';
430
-		}
431
-
432
-		if ($ncPermissions & Constants::PERMISSION_READ) {
433
-			$ocmPermissions[] = 'read';
434
-		}
435
-
436
-		if (($ncPermissions & Constants::PERMISSION_CREATE) ||
437
-			($ncPermissions & Constants::PERMISSION_UPDATE)) {
438
-			$ocmPermissions[] = 'write';
439
-		}
440
-
441
-		return $ocmPermissions;
442
-
443
-	}
444
-
445
-	/**
446
-	 * @NoCSRFRequired
447
-	 * @PublicPage
448
-	 *
449
-	 * change the owner of a server-to-server share
450
-	 *
451
-	 * @param int $id
452
-	 * @return Http\DataResponse
453
-	 * @throws \InvalidArgumentException
454
-	 * @throws OCSException
455
-	 */
456
-	public function move($id) {
457
-
458
-		if (!$this->isS2SEnabled()) {
459
-			throw new OCSException('Server does not support federated cloud sharing', 503);
460
-		}
461
-
462
-		$token = $this->request->getParam('token');
463
-		$remote = $this->request->getParam('remote');
464
-		$newRemoteId = $this->request->getParam('remote_id', $id);
465
-		$cloudId = $this->cloudIdManager->resolveCloudId($remote);
466
-
467
-		$qb = $this->connection->getQueryBuilder();
468
-		$query = $qb->update('share_external')
469
-			->set('remote', $qb->createNamedParameter($cloudId->getRemote()))
470
-			->set('owner', $qb->createNamedParameter($cloudId->getUser()))
471
-			->set('remote_id', $qb->createNamedParameter($newRemoteId))
472
-			->where($qb->expr()->eq('remote_id', $qb->createNamedParameter($id)))
473
-			->andWhere($qb->expr()->eq('share_token', $qb->createNamedParameter($token)));
474
-		$affected = $query->execute();
475
-
476
-		if ($affected > 0) {
477
-			return new Http\DataResponse(['remote' => $cloudId->getRemote(), 'owner' => $cloudId->getUser()]);
478
-		} else {
479
-			throw new OCSBadRequestException('Share not found or token invalid');
480
-		}
481
-	}
55
+    /** @var FederatedShareProvider */
56
+    private $federatedShareProvider;
57
+
58
+    /** @var IDBConnection */
59
+    private $connection;
60
+
61
+    /** @var Share\IManager */
62
+    private $shareManager;
63
+
64
+    /** @var Notifications */
65
+    private $notifications;
66
+
67
+    /** @var AddressHandler */
68
+    private $addressHandler;
69
+
70
+    /** @var  IUserManager */
71
+    private $userManager;
72
+
73
+    /** @var string */
74
+    private $shareTable = 'share';
75
+
76
+    /** @var ICloudIdManager */
77
+    private $cloudIdManager;
78
+
79
+    /** @var ILogger */
80
+    private $logger;
81
+
82
+    /** @var ICloudFederationFactory */
83
+    private $cloudFederationFactory;
84
+
85
+    /** @var ICloudFederationProviderManager */
86
+    private $cloudFederationProviderManager;
87
+
88
+    /**
89
+     * Server2Server constructor.
90
+     *
91
+     * @param string $appName
92
+     * @param IRequest $request
93
+     * @param FederatedShareProvider $federatedShareProvider
94
+     * @param IDBConnection $connection
95
+     * @param Share\IManager $shareManager
96
+     * @param Notifications $notifications
97
+     * @param AddressHandler $addressHandler
98
+     * @param IUserManager $userManager
99
+     * @param ICloudIdManager $cloudIdManager
100
+     * @param ILogger $logger
101
+     * @param ICloudFederationFactory $cloudFederationFactory
102
+     * @param ICloudFederationProviderManager $cloudFederationProviderManager
103
+     */
104
+    public function __construct($appName,
105
+                                IRequest $request,
106
+                                FederatedShareProvider $federatedShareProvider,
107
+                                IDBConnection $connection,
108
+                                Share\IManager $shareManager,
109
+                                Notifications $notifications,
110
+                                AddressHandler $addressHandler,
111
+                                IUserManager $userManager,
112
+                                ICloudIdManager $cloudIdManager,
113
+                                ILogger $logger,
114
+                                ICloudFederationFactory $cloudFederationFactory,
115
+                                ICloudFederationProviderManager $cloudFederationProviderManager
116
+    ) {
117
+        parent::__construct($appName, $request);
118
+
119
+        $this->federatedShareProvider = $federatedShareProvider;
120
+        $this->connection = $connection;
121
+        $this->shareManager = $shareManager;
122
+        $this->notifications = $notifications;
123
+        $this->addressHandler = $addressHandler;
124
+        $this->userManager = $userManager;
125
+        $this->cloudIdManager = $cloudIdManager;
126
+        $this->logger = $logger;
127
+        $this->cloudFederationFactory = $cloudFederationFactory;
128
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
129
+    }
130
+
131
+    /**
132
+     * @NoCSRFRequired
133
+     * @PublicPage
134
+     *
135
+     * create a new share
136
+     *
137
+     * @return Http\DataResponse
138
+     * @throws OCSException
139
+     */
140
+    public function createShare() {
141
+
142
+        $remote = isset($_POST['remote']) ? $_POST['remote'] : null;
143
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
144
+        $name = isset($_POST['name']) ? $_POST['name'] : null;
145
+        $owner = isset($_POST['owner']) ? $_POST['owner'] : null;
146
+        $sharedBy = isset($_POST['sharedBy']) ? $_POST['sharedBy'] : null;
147
+        $shareWith = isset($_POST['shareWith']) ? $_POST['shareWith'] : null;
148
+        $remoteId = isset($_POST['remoteId']) ? (int)$_POST['remoteId'] : null;
149
+        $sharedByFederatedId = isset($_POST['sharedByFederatedId']) ? $_POST['sharedByFederatedId'] : null;
150
+        $ownerFederatedId = isset($_POST['ownerFederatedId']) ? $_POST['ownerFederatedId'] : null;
151
+
152
+        if ($ownerFederatedId === null) {
153
+            $ownerFederatedId = $this->cloudIdManager->getCloudId($owner, $this->cleanupRemote($remote))->getId();
154
+        }
155
+        // if the owner of the share and the initiator are the same user
156
+        // we also complete the federated share ID for the initiator
157
+        if ($sharedByFederatedId === null && $owner === $sharedBy) {
158
+            $sharedByFederatedId = $ownerFederatedId;
159
+        }
160
+
161
+        $share = $this->cloudFederationFactory->getCloudFederationShare(
162
+            $shareWith,
163
+            $name,
164
+            '',
165
+            $remoteId,
166
+            $ownerFederatedId,
167
+            $owner,
168
+            $sharedByFederatedId,
169
+            $sharedBy,
170
+            $token,
171
+            'user',
172
+            'file'
173
+        );
174
+
175
+        try {
176
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
177
+            $provider->shareReceived($share);
178
+        } catch (ProviderDoesNotExistsException $e) {
179
+            throw new OCSException('Server does not support federated cloud sharing', 503);
180
+        } catch (ProviderCouldNotAddShareException $e) {
181
+            throw new OCSException($e->getMessage(), 400);
182
+        } catch (\Exception $e) {
183
+            throw new OCSException('internal server error, was not able to add share from ' . $remote, 500);
184
+        }
185
+
186
+        return new Http\DataResponse();
187
+    }
188
+
189
+    /**
190
+     * @NoCSRFRequired
191
+     * @PublicPage
192
+     *
193
+     * create re-share on behalf of another user
194
+     *
195
+     * @param int $id
196
+     * @return Http\DataResponse
197
+     * @throws OCSBadRequestException
198
+     * @throws OCSException
199
+     * @throws OCSForbiddenException
200
+     */
201
+    public function reShare($id) {
202
+
203
+        $token = $this->request->getParam('token', null);
204
+        $shareWith = $this->request->getParam('shareWith', null);
205
+        $permission = (int)$this->request->getParam('permission', null);
206
+        $remoteId = (int)$this->request->getParam('remoteId', null);
207
+
208
+        if ($id === null ||
209
+            $token === null ||
210
+            $shareWith === null ||
211
+            $permission === null ||
212
+            $remoteId === null
213
+        ) {
214
+            throw new OCSBadRequestException();
215
+        }
216
+
217
+        $notification = [
218
+            'sharedSecret' => $token,
219
+            'shareWith' => $shareWith,
220
+            'senderId' => $remoteId,
221
+            'message' => 'Recipient of a share ask the owner to reshare the file'
222
+        ];
223
+
224
+        try {
225
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
226
+            list($newToken, $localId) = $provider->notificationReceived('REQUEST_RESHARE', $id, $notification);
227
+            return new Http\DataResponse([
228
+                'token' => $newToken,
229
+                'remoteId' => $localId
230
+            ]);
231
+        } catch (ProviderDoesNotExistsException $e) {
232
+            throw new OCSException('Server does not support federated cloud sharing', 503);
233
+        } catch (ShareNotFound $e) {
234
+            $this->logger->debug('Share not found: ' . $e->getMessage());
235
+        } catch (\Exception $e) {
236
+            $this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
237
+        }
238
+
239
+        throw new OCSBadRequestException();
240
+    }
241
+
242
+
243
+    /**
244
+     * @NoCSRFRequired
245
+     * @PublicPage
246
+     *
247
+     * accept server-to-server share
248
+     *
249
+     * @param int $id
250
+     * @return Http\DataResponse
251
+     * @throws OCSException
252
+     * @throws ShareNotFound
253
+     * @throws \OC\HintException
254
+     */
255
+    public function acceptShare($id) {
256
+
257
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
258
+
259
+        $notification = [
260
+            'sharedSecret' => $token,
261
+            'message' => 'Recipient accept the share'
262
+        ];
263
+
264
+        try {
265
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
266
+            $provider->notificationReceived('SHARE_ACCEPTED', $id, $notification);
267
+        } catch (ProviderDoesNotExistsException $e) {
268
+            throw new OCSException('Server does not support federated cloud sharing', 503);
269
+        } catch (ShareNotFound $e) {
270
+            $this->logger->debug('Share not found: ' . $e->getMessage());
271
+        } catch (\Exception $e) {
272
+            $this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
273
+        }
274
+
275
+        return new Http\DataResponse();
276
+    }
277
+
278
+    /**
279
+     * @NoCSRFRequired
280
+     * @PublicPage
281
+     *
282
+     * decline server-to-server share
283
+     *
284
+     * @param int $id
285
+     * @return Http\DataResponse
286
+     * @throws OCSException
287
+     */
288
+    public function declineShare($id) {
289
+
290
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
291
+
292
+        $notification = [
293
+            'sharedSecret' => $token,
294
+            'message' => 'Recipient declined the share'
295
+        ];
296
+
297
+        try {
298
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
299
+            $provider->notificationReceived('SHARE_DECLINED', $id, $notification);
300
+        } catch (ProviderDoesNotExistsException $e) {
301
+            throw new OCSException('Server does not support federated cloud sharing', 503);
302
+        } catch (ShareNotFound $e) {
303
+            $this->logger->debug('Share not found: ' . $e->getMessage());
304
+        } catch (\Exception $e) {
305
+            $this->logger->debug('internal server error, can not process notification: ' . $e->getMessage());
306
+        }
307
+
308
+        return new Http\DataResponse();
309
+    }
310
+
311
+    /**
312
+     * @NoCSRFRequired
313
+     * @PublicPage
314
+     *
315
+     * remove server-to-server share if it was unshared by the owner
316
+     *
317
+     * @param int $id
318
+     * @return Http\DataResponse
319
+     * @throws OCSException
320
+     */
321
+    public function unshare($id) {
322
+
323
+        if (!$this->isS2SEnabled()) {
324
+            throw new OCSException('Server does not support federated cloud sharing', 503);
325
+        }
326
+
327
+        $token = isset($_POST['token']) ? $_POST['token'] : null;
328
+
329
+        try {
330
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
331
+            $notification = ['sharedSecret' => $token];
332
+            $provider->notificationReceived('SHARE_UNSHARED', $id, $notification);
333
+        } catch (\Exception $e) {
334
+            $this->logger->debug('processing unshare notification failed: ' . $e->getMessage());
335
+        }
336
+
337
+        return new Http\DataResponse();
338
+    }
339
+
340
+    private function cleanupRemote($remote) {
341
+        $remote = substr($remote, strpos($remote, '://') + 3);
342
+
343
+        return rtrim($remote, '/');
344
+    }
345
+
346
+
347
+    /**
348
+     * @NoCSRFRequired
349
+     * @PublicPage
350
+     *
351
+     * federated share was revoked, either by the owner or the re-sharer
352
+     *
353
+     * @param int $id
354
+     * @return Http\DataResponse
355
+     * @throws OCSBadRequestException
356
+     */
357
+    public function revoke($id) {
358
+
359
+        $token = $this->request->getParam('token');
360
+
361
+        try {
362
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
363
+            $notification = ['sharedSecret' => $token];
364
+            $provider->notificationReceived('RESHARE_UNDO', $id, $notification);
365
+            return new Http\DataResponse();
366
+        } catch (\Exception $e) {
367
+            throw new OCSBadRequestException();
368
+        }
369
+
370
+    }
371
+
372
+    /**
373
+     * check if server-to-server sharing is enabled
374
+     *
375
+     * @param bool $incoming
376
+     * @return bool
377
+     */
378
+    private function isS2SEnabled($incoming = false) {
379
+
380
+        $result = \OCP\App::isEnabled('files_sharing');
381
+
382
+        if ($incoming) {
383
+            $result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
384
+        } else {
385
+            $result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
386
+        }
387
+
388
+        return $result;
389
+    }
390
+
391
+    /**
392
+     * @NoCSRFRequired
393
+     * @PublicPage
394
+     *
395
+     * update share information to keep federated re-shares in sync
396
+     *
397
+     * @param int $id
398
+     * @return Http\DataResponse
399
+     * @throws OCSBadRequestException
400
+     */
401
+    public function updatePermissions($id) {
402
+        $token = $this->request->getParam('token', null);
403
+        $ncPermissions = $this->request->getParam('permissions', null);
404
+
405
+        try {
406
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider('file');
407
+            $ocmPermissions = $this->ncPermissions2ocmPermissions((int)$ncPermissions);
408
+            $notification = ['sharedSecret' => $token, 'permission' => $ocmPermissions];
409
+            $provider->notificationReceived('RESHARE_CHANGE_PERMISSION', $id, $notification);
410
+        } catch (\Exception $e) {
411
+            $this->logger->debug($e->getMessage());
412
+            throw new OCSBadRequestException();
413
+        }
414
+
415
+        return new Http\DataResponse();
416
+    }
417
+
418
+    /**
419
+     * translate Nextcloud permissions to OCM Permissions
420
+     *
421
+     * @param $ncPermissions
422
+     * @return array
423
+     */
424
+    protected function ncPermissions2ocmPermissions($ncPermissions) {
425
+
426
+        $ocmPermissions = [];
427
+
428
+        if ($ncPermissions & Constants::PERMISSION_SHARE) {
429
+            $ocmPermissions[] = 'share';
430
+        }
431
+
432
+        if ($ncPermissions & Constants::PERMISSION_READ) {
433
+            $ocmPermissions[] = 'read';
434
+        }
435
+
436
+        if (($ncPermissions & Constants::PERMISSION_CREATE) ||
437
+            ($ncPermissions & Constants::PERMISSION_UPDATE)) {
438
+            $ocmPermissions[] = 'write';
439
+        }
440
+
441
+        return $ocmPermissions;
442
+
443
+    }
444
+
445
+    /**
446
+     * @NoCSRFRequired
447
+     * @PublicPage
448
+     *
449
+     * change the owner of a server-to-server share
450
+     *
451
+     * @param int $id
452
+     * @return Http\DataResponse
453
+     * @throws \InvalidArgumentException
454
+     * @throws OCSException
455
+     */
456
+    public function move($id) {
457
+
458
+        if (!$this->isS2SEnabled()) {
459
+            throw new OCSException('Server does not support federated cloud sharing', 503);
460
+        }
461
+
462
+        $token = $this->request->getParam('token');
463
+        $remote = $this->request->getParam('remote');
464
+        $newRemoteId = $this->request->getParam('remote_id', $id);
465
+        $cloudId = $this->cloudIdManager->resolveCloudId($remote);
466
+
467
+        $qb = $this->connection->getQueryBuilder();
468
+        $query = $qb->update('share_external')
469
+            ->set('remote', $qb->createNamedParameter($cloudId->getRemote()))
470
+            ->set('owner', $qb->createNamedParameter($cloudId->getUser()))
471
+            ->set('remote_id', $qb->createNamedParameter($newRemoteId))
472
+            ->where($qb->expr()->eq('remote_id', $qb->createNamedParameter($id)))
473
+            ->andWhere($qb->expr()->eq('share_token', $qb->createNamedParameter($token)));
474
+        $affected = $query->execute();
475
+
476
+        if ($affected > 0) {
477
+            return new Http\DataResponse(['remote' => $cloudId->getRemote(), 'owner' => $cloudId->getUser()]);
478
+        } else {
479
+            throw new OCSBadRequestException('Share not found or token invalid');
480
+        }
481
+    }
482 482
 }
Please login to merge, or discard this patch.
apps/cloud_federation_api/lib/Config.php 1 patch
Indentation   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -34,33 +34,33 @@
 block discarded – undo
34 34
  */
35 35
 class Config {
36 36
 
37
-	/** @var IGsConfig  */
38
-	private $gsConfig;
37
+    /** @var IGsConfig  */
38
+    private $gsConfig;
39 39
 
40
-	/** @var IConfig */
41
-	private $config;
40
+    /** @var IConfig */
41
+    private $config;
42 42
 
43
-	public function __construct(IGsConfig $globalScaleConfig, IConfig $config) {
44
-		$this->gsConfig = $globalScaleConfig;
45
-		$this->config = $config;
46
-	}
43
+    public function __construct(IGsConfig $globalScaleConfig, IConfig $config) {
44
+        $this->gsConfig = $globalScaleConfig;
45
+        $this->config = $config;
46
+    }
47 47
 
48
-	public function incomingRequestsEnabled() {
49
-		if ($this->gsConfig->onlyInternalFederation()) {
50
-			return false;
51
-		}
52
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
53
-		return ($result === 'yes');
54
-	}
48
+    public function incomingRequestsEnabled() {
49
+        if ($this->gsConfig->onlyInternalFederation()) {
50
+            return false;
51
+        }
52
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
53
+        return ($result === 'yes');
54
+    }
55 55
 
56
-	public function outgoingRequestsEnabled() {
56
+    public function outgoingRequestsEnabled() {
57 57
 
58
-		if ($this->gsConfig->onlyInternalFederation()) {
59
-			return false;
60
-		}
61
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
62
-		return ($result === 'yes');
58
+        if ($this->gsConfig->onlyInternalFederation()) {
59
+            return false;
60
+        }
61
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
62
+        return ($result === 'yes');
63 63
 
64
-	}
64
+    }
65 65
 
66 66
 }
Please login to merge, or discard this patch.
apps/cloud_federation_api/lib/Controller/RequestHandlerController.php 1 patch
Indentation   +233 added lines, -233 removed lines patch added patch discarded remove patch
@@ -51,238 +51,238 @@
 block discarded – undo
51 51
  */
52 52
 class RequestHandlerController extends Controller {
53 53
 
54
-	/** @var ILogger */
55
-	private $logger;
56
-
57
-	/** @var IUserManager */
58
-	private $userManager;
59
-
60
-	/** @var IURLGenerator */
61
-	private $urlGenerator;
62
-
63
-	/** @var ICloudFederationProviderManager */
64
-	private $cloudFederationProviderManager;
65
-
66
-	/** @var Config */
67
-	private $config;
68
-
69
-	/** @var ICloudFederationFactory */
70
-	private $factory;
71
-
72
-	/** @var ICloudIdManager */
73
-	private $cloudIdManager;
74
-
75
-	public function __construct($appName,
76
-								IRequest $request,
77
-								ILogger $logger,
78
-								IUserManager $userManager,
79
-								IURLGenerator $urlGenerator,
80
-								ICloudFederationProviderManager $cloudFederationProviderManager,
81
-								Config $config,
82
-								ICloudFederationFactory $factory,
83
-								ICloudIdManager $cloudIdManager
84
-	) {
85
-		parent::__construct($appName, $request);
86
-
87
-		$this->logger = $logger;
88
-		$this->userManager = $userManager;
89
-		$this->urlGenerator = $urlGenerator;
90
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
91
-		$this->config = $config;
92
-		$this->factory = $factory;
93
-		$this->cloudIdManager = $cloudIdManager;
94
-	}
95
-
96
-	/**
97
-	 * add share
98
-	 *
99
-	 * @NoCSRFRequired
100
-	 * @PublicPage
101
-	 * @BruteForceProtection(action=receiveFederatedShare)
102
-	 *
103
-	 * @param string $shareWith
104
-	 * @param string $name resource name (e.g. document.odt)
105
-	 * @param string $description share description (optional)
106
-	 * @param string $providerId resource UID on the provider side
107
-	 * @param string $owner provider specific UID of the user who owns the resource
108
-	 * @param string $ownerDisplayName display name of the user who shared the item
109
-	 * @param string $sharedBy provider specific UID of the user who shared the resource
110
-	 * @param string $sharedByDisplayName display name of the user who shared the resource
111
-	 * @param array $protocol (e,.g. ['name' => 'webdav', 'options' => ['username' => 'john', 'permissions' => 31]])
112
-	 * @param string $shareType ('group' or 'user' share)
113
-	 * @param $resourceType ('file', 'calendar',...)
114
-	 * @return Http\DataResponse|JSONResponse
115
-	 *
116
-	 * 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
117
-	 */
118
-	public function addShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $protocol, $shareType, $resourceType) {
119
-
120
-		if (!$this->config->incomingRequestsEnabled()) {
121
-			return new JSONResponse(
122
-				['message' => 'This server doesn\'t support outgoing federated shares'],
123
-			Http::STATUS_NOT_IMPLEMENTED
124
-			);
125
-		}
126
-
127
-		// check if all required parameters are set
128
-		if ($shareWith === null ||
129
-			$name === null ||
130
-			$providerId === null ||
131
-			$owner === null ||
132
-			$resourceType === null ||
133
-			$shareType === null ||
134
-			!is_array($protocol) ||
135
-			!isset($protocol['name']) ||
136
-			!isset ($protocol['options']) ||
137
-			!is_array($protocol['options']) ||
138
-			!isset($protocol['options']['sharedSecret'])
139
-		) {
140
-			return new JSONResponse(
141
-				['message' => 'Missing arguments'],
142
-				Http::STATUS_BAD_REQUEST
143
-			);
144
-		}
145
-
146
-		$cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
147
-		$shareWithLocalId = $cloudId->getUser();
148
-		$shareWith = $this->mapUid($shareWithLocalId);
149
-
150
-		if (!$this->userManager->userExists($shareWith)) {
151
-			return new JSONResponse(
152
-				['message' => 'User "' . $shareWith . '" does not exists at ' . $this->urlGenerator->getBaseUrl()],
153
-				Http::STATUS_BAD_REQUEST
154
-			);
155
-		}
156
-
157
-		// if no explicit display name is given, we use the uid as display name
158
-		$ownerDisplayName = $ownerDisplayName === null ? $owner : $ownerDisplayName;
159
-		$sharedByDisplayName = $sharedByDisplayName === null ? $sharedBy : $sharedByDisplayName;
160
-
161
-		// sharedBy* parameter is optional, if nothing is set we assume that it is the same user as the owner
162
-		if ($sharedBy === null) {
163
-			$sharedBy = $owner;
164
-			$sharedByDisplayName = $ownerDisplayName;
165
-		}
166
-
167
-		try {
168
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
169
-			$share = $this->factory->getCloudFederationShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, '', $shareType, $resourceType);
170
-			$share->setProtocol($protocol);
171
-			$id = $provider->shareReceived($share);
172
-		} catch (ProviderDoesNotExistsException $e) {
173
-			return new JSONResponse(
174
-				['message' => $e->getMessage()],
175
-				Http::STATUS_NOT_IMPLEMENTED
176
-			);
177
-		} catch (ProviderCouldNotAddShareException $e) {
178
-			return new JSONResponse(
179
-				['message' => $e->getMessage()],
180
-				$e->getCode()
181
-			);
182
-		} catch (\Exception $e) {
183
-			return new JSONResponse(
184
-				['message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl()],
185
-				Http::STATUS_BAD_REQUEST
186
-			);
187
-		}
188
-
189
-		$user = $this->userManager->get($shareWithLocalId);
190
-		$recipientDisplayName = '';
191
-		if($user) {
192
-			$recipientDisplayName = $user->getDisplayName();
193
-		}
194
-
195
-		return new JSONResponse(
196
-			['recipientDisplayName' => $recipientDisplayName],
197
-			Http::STATUS_CREATED);
198
-
199
-	}
200
-
201
-	/**
202
-	 * receive notification about existing share
203
-	 *
204
-	 * @NoCSRFRequired
205
-	 * @PublicPage
206
-	 * @BruteForceProtection(action=receiveFederatedShareNotification)
207
-	 *
208
-	 * @param string $notificationType (notification type, e.g. SHARE_ACCEPTED)
209
-	 * @param string $resourceType (calendar, file, contact,...)
210
-	 * @param string $providerId id of the share
211
-	 * @param array $notification the actual payload of the notification
212
-	 * @return JSONResponse
213
-	 */
214
-	public function receiveNotification($notificationType, $resourceType, $providerId, array $notification) {
215
-		if (!$this->config->incomingRequestsEnabled()) {
216
-			return new JSONResponse(
217
-				['message' => 'This server doesn\'t support outgoing federated shares'],
218
-				Http::STATUS_NOT_IMPLEMENTED
219
-			);
220
-		}
221
-
222
-		// check if all required parameters are set
223
-		if ($notificationType === null ||
224
-			$resourceType === null ||
225
-			$providerId === null ||
226
-			!is_array($notification)
227
-		) {
228
-			return new JSONResponse(
229
-				['message' => 'Missing arguments'],
230
-				Http::STATUS_BAD_REQUEST
231
-			);
232
-		}
233
-
234
-		try {
235
-			$provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
236
-			$result = $provider->notificationReceived($notificationType, $providerId, $notification);
237
-		} catch (ProviderDoesNotExistsException $e) {
238
-			return new JSONResponse(
239
-				['message' => $e->getMessage()],
240
-				Http::STATUS_BAD_REQUEST
241
-			);
242
-		} catch (ShareNotFound $e) {
243
-			return new JSONResponse(
244
-				['message' => $e->getMessage()],
245
-				Http::STATUS_BAD_REQUEST
246
-			);
247
-		} catch (ActionNotSupportedException $e) {
248
-			return new JSONResponse(
249
-				['message' => $e->getMessage()],
250
-				Http::STATUS_NOT_IMPLEMENTED
251
-			);
252
-		} catch (BadRequestException $e) {
253
-			return new JSONResponse($e->getReturnMessage(), Http::STATUS_BAD_REQUEST);
254
-		} catch (AuthenticationFailedException $e) {
255
-			return new JSONResponse(["message" => "RESOURCE_NOT_FOUND"], Http::STATUS_FORBIDDEN);
256
-		}
257
-		catch (\Exception $e) {
258
-			return new JSONResponse(
259
-				['message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl()],
260
-				Http::STATUS_BAD_REQUEST
261
-			);
262
-		}
263
-
264
-		return new JSONResponse($result,Http::STATUS_CREATED);
265
-
266
-	}
267
-
268
-	/**
269
-	 * map login name to internal LDAP UID if a LDAP backend is in use
270
-	 *
271
-	 * @param string $uid
272
-	 * @return string mixed
273
-	 */
274
-	private function mapUid($uid) {
275
-		\OC::$server->getURLGenerator()->linkToDocs('key');
276
-		// FIXME this should be a method in the user management instead
277
-		$this->logger->debug('shareWith before, ' . $uid, ['app' => $this->appName]);
278
-		\OCP\Util::emitHook(
279
-			'\OCA\Files_Sharing\API\Server2Server',
280
-			'preLoginNameUsedAsUserName',
281
-			array('uid' => &$uid)
282
-		);
283
-		$this->logger->debug('shareWith after, ' . $uid, ['app' => $this->appName]);
284
-
285
-		return $uid;
286
-	}
54
+    /** @var ILogger */
55
+    private $logger;
56
+
57
+    /** @var IUserManager */
58
+    private $userManager;
59
+
60
+    /** @var IURLGenerator */
61
+    private $urlGenerator;
62
+
63
+    /** @var ICloudFederationProviderManager */
64
+    private $cloudFederationProviderManager;
65
+
66
+    /** @var Config */
67
+    private $config;
68
+
69
+    /** @var ICloudFederationFactory */
70
+    private $factory;
71
+
72
+    /** @var ICloudIdManager */
73
+    private $cloudIdManager;
74
+
75
+    public function __construct($appName,
76
+                                IRequest $request,
77
+                                ILogger $logger,
78
+                                IUserManager $userManager,
79
+                                IURLGenerator $urlGenerator,
80
+                                ICloudFederationProviderManager $cloudFederationProviderManager,
81
+                                Config $config,
82
+                                ICloudFederationFactory $factory,
83
+                                ICloudIdManager $cloudIdManager
84
+    ) {
85
+        parent::__construct($appName, $request);
86
+
87
+        $this->logger = $logger;
88
+        $this->userManager = $userManager;
89
+        $this->urlGenerator = $urlGenerator;
90
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
91
+        $this->config = $config;
92
+        $this->factory = $factory;
93
+        $this->cloudIdManager = $cloudIdManager;
94
+    }
95
+
96
+    /**
97
+     * add share
98
+     *
99
+     * @NoCSRFRequired
100
+     * @PublicPage
101
+     * @BruteForceProtection(action=receiveFederatedShare)
102
+     *
103
+     * @param string $shareWith
104
+     * @param string $name resource name (e.g. document.odt)
105
+     * @param string $description share description (optional)
106
+     * @param string $providerId resource UID on the provider side
107
+     * @param string $owner provider specific UID of the user who owns the resource
108
+     * @param string $ownerDisplayName display name of the user who shared the item
109
+     * @param string $sharedBy provider specific UID of the user who shared the resource
110
+     * @param string $sharedByDisplayName display name of the user who shared the resource
111
+     * @param array $protocol (e,.g. ['name' => 'webdav', 'options' => ['username' => 'john', 'permissions' => 31]])
112
+     * @param string $shareType ('group' or 'user' share)
113
+     * @param $resourceType ('file', 'calendar',...)
114
+     * @return Http\DataResponse|JSONResponse
115
+     *
116
+     * 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
117
+     */
118
+    public function addShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, $protocol, $shareType, $resourceType) {
119
+
120
+        if (!$this->config->incomingRequestsEnabled()) {
121
+            return new JSONResponse(
122
+                ['message' => 'This server doesn\'t support outgoing federated shares'],
123
+            Http::STATUS_NOT_IMPLEMENTED
124
+            );
125
+        }
126
+
127
+        // check if all required parameters are set
128
+        if ($shareWith === null ||
129
+            $name === null ||
130
+            $providerId === null ||
131
+            $owner === null ||
132
+            $resourceType === null ||
133
+            $shareType === null ||
134
+            !is_array($protocol) ||
135
+            !isset($protocol['name']) ||
136
+            !isset ($protocol['options']) ||
137
+            !is_array($protocol['options']) ||
138
+            !isset($protocol['options']['sharedSecret'])
139
+        ) {
140
+            return new JSONResponse(
141
+                ['message' => 'Missing arguments'],
142
+                Http::STATUS_BAD_REQUEST
143
+            );
144
+        }
145
+
146
+        $cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
147
+        $shareWithLocalId = $cloudId->getUser();
148
+        $shareWith = $this->mapUid($shareWithLocalId);
149
+
150
+        if (!$this->userManager->userExists($shareWith)) {
151
+            return new JSONResponse(
152
+                ['message' => 'User "' . $shareWith . '" does not exists at ' . $this->urlGenerator->getBaseUrl()],
153
+                Http::STATUS_BAD_REQUEST
154
+            );
155
+        }
156
+
157
+        // if no explicit display name is given, we use the uid as display name
158
+        $ownerDisplayName = $ownerDisplayName === null ? $owner : $ownerDisplayName;
159
+        $sharedByDisplayName = $sharedByDisplayName === null ? $sharedBy : $sharedByDisplayName;
160
+
161
+        // sharedBy* parameter is optional, if nothing is set we assume that it is the same user as the owner
162
+        if ($sharedBy === null) {
163
+            $sharedBy = $owner;
164
+            $sharedByDisplayName = $ownerDisplayName;
165
+        }
166
+
167
+        try {
168
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
169
+            $share = $this->factory->getCloudFederationShare($shareWith, $name, $description, $providerId, $owner, $ownerDisplayName, $sharedBy, $sharedByDisplayName, '', $shareType, $resourceType);
170
+            $share->setProtocol($protocol);
171
+            $id = $provider->shareReceived($share);
172
+        } catch (ProviderDoesNotExistsException $e) {
173
+            return new JSONResponse(
174
+                ['message' => $e->getMessage()],
175
+                Http::STATUS_NOT_IMPLEMENTED
176
+            );
177
+        } catch (ProviderCouldNotAddShareException $e) {
178
+            return new JSONResponse(
179
+                ['message' => $e->getMessage()],
180
+                $e->getCode()
181
+            );
182
+        } catch (\Exception $e) {
183
+            return new JSONResponse(
184
+                ['message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl()],
185
+                Http::STATUS_BAD_REQUEST
186
+            );
187
+        }
188
+
189
+        $user = $this->userManager->get($shareWithLocalId);
190
+        $recipientDisplayName = '';
191
+        if($user) {
192
+            $recipientDisplayName = $user->getDisplayName();
193
+        }
194
+
195
+        return new JSONResponse(
196
+            ['recipientDisplayName' => $recipientDisplayName],
197
+            Http::STATUS_CREATED);
198
+
199
+    }
200
+
201
+    /**
202
+     * receive notification about existing share
203
+     *
204
+     * @NoCSRFRequired
205
+     * @PublicPage
206
+     * @BruteForceProtection(action=receiveFederatedShareNotification)
207
+     *
208
+     * @param string $notificationType (notification type, e.g. SHARE_ACCEPTED)
209
+     * @param string $resourceType (calendar, file, contact,...)
210
+     * @param string $providerId id of the share
211
+     * @param array $notification the actual payload of the notification
212
+     * @return JSONResponse
213
+     */
214
+    public function receiveNotification($notificationType, $resourceType, $providerId, array $notification) {
215
+        if (!$this->config->incomingRequestsEnabled()) {
216
+            return new JSONResponse(
217
+                ['message' => 'This server doesn\'t support outgoing federated shares'],
218
+                Http::STATUS_NOT_IMPLEMENTED
219
+            );
220
+        }
221
+
222
+        // check if all required parameters are set
223
+        if ($notificationType === null ||
224
+            $resourceType === null ||
225
+            $providerId === null ||
226
+            !is_array($notification)
227
+        ) {
228
+            return new JSONResponse(
229
+                ['message' => 'Missing arguments'],
230
+                Http::STATUS_BAD_REQUEST
231
+            );
232
+        }
233
+
234
+        try {
235
+            $provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
236
+            $result = $provider->notificationReceived($notificationType, $providerId, $notification);
237
+        } catch (ProviderDoesNotExistsException $e) {
238
+            return new JSONResponse(
239
+                ['message' => $e->getMessage()],
240
+                Http::STATUS_BAD_REQUEST
241
+            );
242
+        } catch (ShareNotFound $e) {
243
+            return new JSONResponse(
244
+                ['message' => $e->getMessage()],
245
+                Http::STATUS_BAD_REQUEST
246
+            );
247
+        } catch (ActionNotSupportedException $e) {
248
+            return new JSONResponse(
249
+                ['message' => $e->getMessage()],
250
+                Http::STATUS_NOT_IMPLEMENTED
251
+            );
252
+        } catch (BadRequestException $e) {
253
+            return new JSONResponse($e->getReturnMessage(), Http::STATUS_BAD_REQUEST);
254
+        } catch (AuthenticationFailedException $e) {
255
+            return new JSONResponse(["message" => "RESOURCE_NOT_FOUND"], Http::STATUS_FORBIDDEN);
256
+        }
257
+        catch (\Exception $e) {
258
+            return new JSONResponse(
259
+                ['message' => 'Internal error at ' . $this->urlGenerator->getBaseUrl()],
260
+                Http::STATUS_BAD_REQUEST
261
+            );
262
+        }
263
+
264
+        return new JSONResponse($result,Http::STATUS_CREATED);
265
+
266
+    }
267
+
268
+    /**
269
+     * map login name to internal LDAP UID if a LDAP backend is in use
270
+     *
271
+     * @param string $uid
272
+     * @return string mixed
273
+     */
274
+    private function mapUid($uid) {
275
+        \OC::$server->getURLGenerator()->linkToDocs('key');
276
+        // FIXME this should be a method in the user management instead
277
+        $this->logger->debug('shareWith before, ' . $uid, ['app' => $this->appName]);
278
+        \OCP\Util::emitHook(
279
+            '\OCA\Files_Sharing\API\Server2Server',
280
+            'preLoginNameUsedAsUserName',
281
+            array('uid' => &$uid)
282
+        );
283
+        $this->logger->debug('shareWith after, ' . $uid, ['app' => $this->appName]);
284
+
285
+        return $uid;
286
+    }
287 287
 
288 288
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/ocm/CloudFederationProviderFiles.php 1 patch
Indentation   +712 added lines, -712 removed lines patch added patch discarded remove patch
@@ -50,718 +50,718 @@
 block discarded – undo
50 50
 
51 51
 class CloudFederationProviderFiles implements ICloudFederationProvider {
52 52
 
53
-	/** @var IAppManager */
54
-	private $appManager;
55
-
56
-	/** @var FederatedShareProvider */
57
-	private $federatedShareProvider;
58
-
59
-	/** @var AddressHandler */
60
-	private $addressHandler;
61
-
62
-	/** @var ILogger */
63
-	private $logger;
64
-
65
-	/** @var IUserManager */
66
-	private $userManager;
67
-
68
-	/** @var ICloudIdManager */
69
-	private $cloudIdManager;
70
-
71
-	/** @var IActivityManager */
72
-	private $activityManager;
73
-
74
-	/** @var INotificationManager */
75
-	private $notificationManager;
76
-
77
-	/** @var IURLGenerator */
78
-	private $urlGenerator;
79
-
80
-	/** @var ICloudFederationFactory */
81
-	private $cloudFederationFactory;
82
-
83
-	/** @var ICloudFederationProviderManager */
84
-	private $cloudFederationProviderManager;
85
-
86
-	/** @var IDBConnection */
87
-	private $connection;
88
-
89
-	/**
90
-	 * CloudFederationProvider constructor.
91
-	 *
92
-	 * @param IAppManager $appManager
93
-	 * @param FederatedShareProvider $federatedShareProvider
94
-	 * @param AddressHandler $addressHandler
95
-	 * @param ILogger $logger
96
-	 * @param IUserManager $userManager
97
-	 * @param ICloudIdManager $cloudIdManager
98
-	 * @param IActivityManager $activityManager
99
-	 * @param INotificationManager $notificationManager
100
-	 * @param IURLGenerator $urlGenerator
101
-	 * @param ICloudFederationFactory $cloudFederationFactory
102
-	 * @param ICloudFederationProviderManager $cloudFederationProviderManager
103
-	 * @param IDBConnection $connection
104
-	 */
105
-	public function __construct(IAppManager $appManager,
106
-								FederatedShareProvider $federatedShareProvider,
107
-								AddressHandler $addressHandler,
108
-								ILogger $logger,
109
-								IUserManager $userManager,
110
-								ICloudIdManager $cloudIdManager,
111
-								IActivityManager $activityManager,
112
-								INotificationManager $notificationManager,
113
-								IURLGenerator $urlGenerator,
114
-								ICloudFederationFactory $cloudFederationFactory,
115
-								ICloudFederationProviderManager $cloudFederationProviderManager,
116
-								IDBConnection $connection
117
-	) {
118
-		$this->appManager = $appManager;
119
-		$this->federatedShareProvider = $federatedShareProvider;
120
-		$this->addressHandler = $addressHandler;
121
-		$this->logger = $logger;
122
-		$this->userManager = $userManager;
123
-		$this->cloudIdManager = $cloudIdManager;
124
-		$this->activityManager = $activityManager;
125
-		$this->notificationManager = $notificationManager;
126
-		$this->urlGenerator = $urlGenerator;
127
-		$this->cloudFederationFactory = $cloudFederationFactory;
128
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
129
-		$this->connection = $connection;
130
-	}
131
-
132
-
133
-
134
-	/**
135
-	 * @return string
136
-	 */
137
-	public function getShareType() {
138
-		return 'file';
139
-	}
140
-
141
-	/**
142
-	 * share received from another server
143
-	 *
144
-	 * @param ICloudFederationShare $share
145
-	 * @return string provider specific unique ID of the share
146
-	 *
147
-	 * @throws ProviderCouldNotAddShareException
148
-	 * @throws \OCP\AppFramework\QueryException
149
-	 * @throws \OC\HintException
150
-	 * @since 14.0.0
151
-	 */
152
-	public function shareReceived(ICloudFederationShare $share) {
153
-
154
-		if (!$this->isS2SEnabled(true)) {
155
-			throw new ProviderCouldNotAddShareException('Server does not support federated cloud sharing', '', Http::STATUS_SERVICE_UNAVAILABLE);
156
-		}
157
-
158
-		$protocol = $share->getProtocol();
159
-		if ($protocol['name'] !== 'webdav') {
160
-			throw new ProviderCouldNotAddShareException('Unsupported protocol for data exchange.', '', Http::STATUS_NOT_IMPLEMENTED);
161
-		}
162
-
163
-		list($ownerUid, $remote) = $this->addressHandler->splitUserRemote($share->getOwner());
164
-		// for backward compatibility make sure that the remote url stored in the
165
-		// database ends with a trailing slash
166
-		if (substr($remote, -1) !== '/') {
167
-			$remote = $remote . '/';
168
-		}
169
-
170
-		$token = $share->getShareSecret();
171
-		$name = $share->getResourceName();
172
-		$owner = $share->getOwnerDisplayName();
173
-		$sharedBy = $share->getSharedByDisplayName();
174
-		$shareWith = $share->getShareWith();
175
-		$remoteId = $share->getProviderId();
176
-		$sharedByFederatedId = $share->getSharedBy();
177
-		$ownerFederatedId = $share->getOwner();
178
-
179
-		// if no explicit information about the person who created the share was send
180
-		// we assume that the share comes from the owner
181
-		if ($sharedByFederatedId === null) {
182
-			$sharedBy = $owner;
183
-			$sharedByFederatedId = $ownerFederatedId;
184
-		}
185
-
186
-		if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
187
-
188
-			if (!Util::isValidFileName($name)) {
189
-				throw new ProviderCouldNotAddShareException('The mountpoint name contains invalid characters.', '', Http::STATUS_BAD_REQUEST);
190
-			}
191
-
192
-			// FIXME this should be a method in the user management instead
193
-			$this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
194
-			Util::emitHook(
195
-				'\OCA\Files_Sharing\API\Server2Server',
196
-				'preLoginNameUsedAsUserName',
197
-				array('uid' => &$shareWith)
198
-			);
199
-			$this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
200
-
201
-			if (!$this->userManager->userExists($shareWith)) {
202
-				throw new ProviderCouldNotAddShareException('User does not exists', '',Http::STATUS_BAD_REQUEST);
203
-			}
204
-
205
-			\OC_Util::setupFS($shareWith);
206
-
207
-			$externalManager = new \OCA\Files_Sharing\External\Manager(
208
-				\OC::$server->getDatabaseConnection(),
209
-				Filesystem::getMountManager(),
210
-				Filesystem::getLoader(),
211
-				\OC::$server->getHTTPClientService(),
212
-				\OC::$server->getNotificationManager(),
213
-				\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
214
-				\OC::$server->getCloudFederationProviderManager(),
215
-				\OC::$server->getCloudFederationFactory(),
216
-				$shareWith
217
-			);
218
-
219
-			try {
220
-				$externalManager->addShare($remote, $token, '', $name, $owner, false, $shareWith, $remoteId);
221
-				$shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external');
222
-
223
-				$event = $this->activityManager->generateEvent();
224
-				$event->setApp('files_sharing')
225
-					->setType('remote_share')
226
-					->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
227
-					->setAffectedUser($shareWith)
228
-					->setObject('remote_share', (int)$shareId, $name);
229
-				\OC::$server->getActivityManager()->publish($event);
230
-
231
-				$notification = $this->notificationManager->createNotification();
232
-				$notification->setApp('files_sharing')
233
-					->setUser($shareWith)
234
-					->setDateTime(new \DateTime())
235
-					->setObject('remote_share', $shareId)
236
-					->setSubject('remote_share', [$ownerFederatedId, $sharedByFederatedId, trim($name, '/')]);
237
-
238
-				$declineAction = $notification->createAction();
239
-				$declineAction->setLabel('decline')
240
-					->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
241
-				$notification->addAction($declineAction);
242
-
243
-				$acceptAction = $notification->createAction();
244
-				$acceptAction->setLabel('accept')
245
-					->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
246
-				$notification->addAction($acceptAction);
247
-
248
-				$this->notificationManager->notify($notification);
249
-
250
-				return $shareId;
251
-			} catch (\Exception $e) {
252
-				$this->logger->logException($e, [
253
-					'message' => 'Server can not add remote share.',
254
-					'level' => ILogger::ERROR,
255
-					'app' => 'files_sharing'
256
-				]);
257
-				throw new ProviderCouldNotAddShareException('internal server error, was not able to add share from ' . $remote, '', HTTP::STATUS_INTERNAL_SERVER_ERROR);
258
-			}
259
-		}
260
-
261
-		throw new ProviderCouldNotAddShareException('server can not add remote share, missing parameter', '', HTTP::STATUS_BAD_REQUEST);
262
-
263
-	}
264
-
265
-	/**
266
-	 * notification received from another server
267
-	 *
268
-	 * @param string $notificationType (e.g. SHARE_ACCEPTED)
269
-	 * @param string $providerId id of the share
270
-	 * @param array $notification payload of the notification
271
-	 * @return array data send back to the sender
272
-	 *
273
-	 * @throws ActionNotSupportedException
274
-	 * @throws AuthenticationFailedException
275
-	 * @throws BadRequestException
276
-	 * @throws \OC\HintException
277
-	 * @since 14.0.0
278
-	 */
279
-	public function notificationReceived($notificationType, $providerId, array $notification) {
280
-
281
-		switch ($notificationType) {
282
-			case 'SHARE_ACCEPTED':
283
-				return $this->shareAccepted($providerId, $notification);
284
-			case 'SHARE_DECLINED':
285
-				return $this->shareDeclined($providerId, $notification);
286
-			case 'SHARE_UNSHARED':
287
-				return $this->unshare($providerId, $notification);
288
-			case 'REQUEST_RESHARE':
289
-				return $this->reshareRequested($providerId, $notification);
290
-			case 'RESHARE_UNDO':
291
-				return $this->undoReshare($providerId, $notification);
292
-			case 'RESHARE_CHANGE_PERMISSION':
293
-				return $this->updateResharePermissions($providerId, $notification);
294
-		}
295
-
296
-
297
-		throw new BadRequestException([$notificationType]);
298
-	}
299
-
300
-	/**
301
-	 * process notification that the recipient accepted a share
302
-	 *
303
-	 * @param string $id
304
-	 * @param array $notification
305
-	 * @return array
306
-	 * @throws ActionNotSupportedException
307
-	 * @throws AuthenticationFailedException
308
-	 * @throws BadRequestException
309
-	 * @throws \OC\HintException
310
-	 */
311
-	private function shareAccepted($id, array $notification) {
312
-
313
-		if (!$this->isS2SEnabled()) {
314
-			throw new ActionNotSupportedException('Server does not support federated cloud sharing');
315
-		}
316
-
317
-		if (!isset($notification['sharedSecret'])) {
318
-			throw new BadRequestException(['sharedSecret']);
319
-		}
320
-
321
-		$token = $notification['sharedSecret'];
322
-
323
-		$share = $this->federatedShareProvider->getShareById($id);
324
-
325
-		$this->verifyShare($share, $token);
326
-		$this->executeAcceptShare($share);
327
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
328
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
329
-			$remoteId = $this->federatedShareProvider->getRemoteId($share);
330
-			$notification = $this->cloudFederationFactory->getCloudFederationNotification();
331
-			$notification->setMessage(
332
-				'SHARE_ACCEPTED',
333
-				'file',
334
-				$remoteId,
335
-				[
336
-					'sharedSecret' => $token,
337
-					'message' => 'Recipient accepted the re-share'
338
-				]
339
-
340
-			);
341
-			$this->cloudFederationProviderManager->sendNotification($remote, $notification);
342
-
343
-		}
344
-
345
-		return [];
346
-	}
347
-
348
-	/**
349
-	 * @param IShare $share
350
-	 * @throws ShareNotFound
351
-	 */
352
-	protected function executeAcceptShare(IShare $share) {
353
-		try {
354
-			$fileId = (int)$share->getNode()->getId();
355
-			list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
356
-		} catch (\Exception $e) {
357
-			throw new ShareNotFound();
358
-		}
359
-
360
-		$event = $this->activityManager->generateEvent();
361
-		$event->setApp('files_sharing')
362
-			->setType('remote_share')
363
-			->setAffectedUser($this->getCorrectUid($share))
364
-			->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_ACCEPTED, [$share->getSharedWith(), [$fileId => $file]])
365
-			->setObject('files', $fileId, $file)
366
-			->setLink($link);
367
-		$this->activityManager->publish($event);
368
-	}
369
-
370
-	/**
371
-	 * process notification that the recipient declined a share
372
-	 *
373
-	 * @param string $id
374
-	 * @param array $notification
375
-	 * @return array
376
-	 * @throws ActionNotSupportedException
377
-	 * @throws AuthenticationFailedException
378
-	 * @throws BadRequestException
379
-	 * @throws ShareNotFound
380
-	 * @throws \OC\HintException
381
-	 *
382
-	 */
383
-	protected function shareDeclined($id, array $notification) {
384
-
385
-		if (!$this->isS2SEnabled()) {
386
-			throw new ActionNotSupportedException('Server does not support federated cloud sharing');
387
-		}
388
-
389
-		if (!isset($notification['sharedSecret'])) {
390
-			throw new BadRequestException(['sharedSecret']);
391
-		}
392
-
393
-		$token = $notification['sharedSecret'];
394
-
395
-		$share = $this->federatedShareProvider->getShareById($id);
396
-
397
-		$this->verifyShare($share, $token);
398
-
399
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
400
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
401
-			$remoteId = $this->federatedShareProvider->getRemoteId($share);
402
-			$notification = $this->cloudFederationFactory->getCloudFederationNotification();
403
-			$notification->setMessage(
404
-				'SHARE_DECLINED',
405
-				'file',
406
-				$remoteId,
407
-				[
408
-					'sharedSecret' => $token,
409
-					'message' => 'Recipient declined the re-share'
410
-				]
411
-
412
-			);
413
-			$this->cloudFederationProviderManager->sendNotification($remote, $notification);
414
-		}
415
-
416
-		$this->executeDeclineShare($share);
417
-
418
-		return [];
419
-
420
-	}
421
-
422
-	/**
423
-	 * delete declined share and create a activity
424
-	 *
425
-	 * @param IShare $share
426
-	 * @throws ShareNotFound
427
-	 */
428
-	protected function executeDeclineShare(IShare $share) {
429
-		$this->federatedShareProvider->removeShareFromTable($share);
430
-
431
-		try {
432
-			$fileId = (int)$share->getNode()->getId();
433
-			list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
434
-		} catch (\Exception $e) {
435
-			throw new ShareNotFound();
436
-		}
437
-
438
-		$event = $this->activityManager->generateEvent();
439
-		$event->setApp('files_sharing')
440
-			->setType('remote_share')
441
-			->setAffectedUser($this->getCorrectUid($share))
442
-			->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_DECLINED, [$share->getSharedWith(), [$fileId => $file]])
443
-			->setObject('files', $fileId, $file)
444
-			->setLink($link);
445
-		$this->activityManager->publish($event);
446
-
447
-	}
448
-
449
-	/**
450
-	 * received the notification that the owner unshared a file from you
451
-	 *
452
-	 * @param string $id
453
-	 * @param array $notification
454
-	 * @return array
455
-	 * @throws AuthenticationFailedException
456
-	 * @throws BadRequestException
457
-	 */
458
-	private function undoReshare($id, array $notification) {
459
-		if (!isset($notification['sharedSecret'])) {
460
-			throw new BadRequestException(['sharedSecret']);
461
-		}
462
-		$token = $notification['sharedSecret'];
463
-
464
-		$share = $this->federatedShareProvider->getShareById($id);
465
-
466
-		$this->verifyShare($share, $token);
467
-		$this->federatedShareProvider->removeShareFromTable($share);
468
-		return [];
469
-	}
470
-
471
-	/**
472
-	 * unshare file from self
473
-	 *
474
-	 * @param string $id
475
-	 * @param array $notification
476
-	 * @return array
477
-	 * @throws ActionNotSupportedException
478
-	 * @throws BadRequestException
479
-	 */
480
-	private function unshare($id, array $notification) {
481
-
482
-		if (!$this->isS2SEnabled(true)) {
483
-			throw new ActionNotSupportedException("incoming shares disabled!");
484
-		}
485
-
486
-		if (!isset($notification['sharedSecret'])) {
487
-			throw new BadRequestException(['sharedSecret']);
488
-		}
489
-		$token = $notification['sharedSecret'];
490
-
491
-		$qb = $this->connection->getQueryBuilder();
492
-		$qb->select('*')
493
-			->from('share_external')
494
-			->where(
495
-				$qb->expr()->andX(
496
-					$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
497
-					$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
498
-				)
499
-			);
500
-
501
-		$result = $qb->execute();
502
-		$share = $result->fetch();
503
-		$result->closeCursor();
504
-
505
-		if ($token && $id && !empty($share)) {
506
-
507
-			$remote = $this->cleanupRemote($share['remote']);
508
-
509
-			$owner = $this->cloudIdManager->getCloudId($share['owner'], $remote);
510
-			$mountpoint = $share['mountpoint'];
511
-			$user = $share['user'];
512
-
513
-			$qb = $this->connection->getQueryBuilder();
514
-			$qb->delete('share_external')
515
-				->where(
516
-					$qb->expr()->andX(
517
-						$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
518
-						$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
519
-					)
520
-				);
521
-
522
-			$qb->execute();
523
-
524
-			if ($share['accepted']) {
525
-				$path = trim($mountpoint, '/');
526
-			} else {
527
-				$path = trim($share['name'], '/');
528
-			}
529
-
530
-			$notification = $this->notificationManager->createNotification();
531
-			$notification->setApp('files_sharing')
532
-				->setUser($share['user'])
533
-				->setObject('remote_share', (int)$share['id']);
534
-			$this->notificationManager->markProcessed($notification);
535
-
536
-			$event = $this->activityManager->generateEvent();
537
-			$event->setApp('files_sharing')
538
-				->setType('remote_share')
539
-				->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
540
-				->setAffectedUser($user)
541
-				->setObject('remote_share', (int)$share['id'], $path);
542
-			\OC::$server->getActivityManager()->publish($event);
543
-		}
544
-
545
-		return [];
546
-	}
547
-
548
-	private function cleanupRemote($remote) {
549
-		$remote = substr($remote, strpos($remote, '://') + 3);
550
-
551
-		return rtrim($remote, '/');
552
-	}
553
-
554
-	/**
555
-	 * recipient of a share request to re-share the file with another user
556
-	 *
557
-	 * @param string $id
558
-	 * @param array $notification
559
-	 * @return array
560
-	 * @throws AuthenticationFailedException
561
-	 * @throws BadRequestException
562
-	 * @throws ProviderCouldNotAddShareException
563
-	 * @throws ShareNotFound
564
-	 */
565
-	protected function reshareRequested($id, array $notification) {
566
-
567
-		if (!isset($notification['sharedSecret'])) {
568
-			throw new BadRequestException(['sharedSecret']);
569
-		}
570
-		$token = $notification['sharedSecret'];
571
-
572
-		if (!isset($notification['shareWith'])) {
573
-			throw new BadRequestException(['shareWith']);
574
-		}
575
-		$shareWith = $notification['shareWith'];
576
-
577
-		if (!isset($notification['senderId'])) {
578
-			throw new BadRequestException(['senderId']);
579
-		}
580
-		$senderId = $notification['senderId'];
581
-
582
-		$share = $this->federatedShareProvider->getShareById($id);
583
-		// don't allow to share a file back to the owner
584
-		try {
585
-			list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
586
-			$owner = $share->getShareOwner();
587
-			$currentServer = $this->addressHandler->generateRemoteURL();
588
-			if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
589
-				throw new ProviderCouldNotAddShareException('Resharing back to the owner is not allowed: ' . $id);
590
-			}
591
-		} catch (\Exception $e) {
592
-			throw new ProviderCouldNotAddShareException($e->getMessage());
593
-		}
594
-
595
-		$this->verifyShare($share, $token);
596
-
597
-		// check if re-sharing is allowed
598
-		if ($share->getPermissions() & Constants::PERMISSION_SHARE) {
599
-			// the recipient of the initial share is now the initiator for the re-share
600
-			$share->setSharedBy($share->getSharedWith());
601
-			$share->setSharedWith($shareWith);
602
-			$result = $this->federatedShareProvider->create($share);
603
-			$this->federatedShareProvider->storeRemoteId((int)$result->getId(), $senderId);
604
-			return ['token' => $result->getToken(), 'providerId' => $result->getId()];
605
-		} else {
606
-			throw new ProviderCouldNotAddShareException('resharing not allowed for share: ' . $id);
607
-		}
608
-
609
-	}
610
-
611
-	/**
612
-	 * update permission of a re-share so that the share dialog shows the right
613
-	 * permission if the owner or the sender changes the permission
614
-	 *
615
-	 * @param string $id
616
-	 * @param array $notification
617
-	 * @return array
618
-	 * @throws AuthenticationFailedException
619
-	 * @throws BadRequestException
620
-	 */
621
-	protected function updateResharePermissions($id, array $notification) {
622
-
623
-		if (!isset($notification['sharedSecret'])) {
624
-			throw new BadRequestException(['sharedSecret']);
625
-		}
626
-		$token = $notification['sharedSecret'];
627
-
628
-		if (!isset($notification['permission'])) {
629
-			throw new BadRequestException(['permission']);
630
-		}
631
-		$ocmPermissions = $notification['permission'];
632
-
633
-		$share = $this->federatedShareProvider->getShareById($id);
634
-
635
-		$ncPermission = $this->ocmPermissions2ncPermissions($ocmPermissions);
636
-
637
-		$this->verifyShare($share, $token);
638
-		$this->updatePermissionsInDatabase($share, $ncPermission);
639
-
640
-		return [];
641
-	}
642
-
643
-	/**
644
-	 * translate OCM Permissions to Nextcloud permissions
645
-	 *
646
-	 * @param array $ocmPermissions
647
-	 * @return int
648
-	 * @throws BadRequestException
649
-	 */
650
-	protected function ocmPermissions2ncPermissions(array $ocmPermissions) {
651
-		$ncPermissions = 0;
652
-		foreach($ocmPermissions as $permission) {
653
-			switch (strtolower($permission)) {
654
-				case 'read':
655
-					$ncPermissions += Constants::PERMISSION_READ;
656
-					break;
657
-				case 'write':
658
-					$ncPermissions += Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE;
659
-					break;
660
-				case 'share':
661
-					$ncPermissions += Constants::PERMISSION_SHARE;
662
-					break;
663
-				default:
664
-					throw new BadRequestException(['permission']);
665
-			}
666
-
667
-			error_log("new permissions: " . $ncPermissions);
668
-		}
669
-
670
-		return $ncPermissions;
671
-	}
672
-
673
-	/**
674
-	 * update permissions in database
675
-	 *
676
-	 * @param IShare $share
677
-	 * @param int $permissions
678
-	 */
679
-	protected function updatePermissionsInDatabase(IShare $share, $permissions) {
680
-		$query = $this->connection->getQueryBuilder();
681
-		$query->update('share')
682
-			->where($query->expr()->eq('id', $query->createNamedParameter($share->getId())))
683
-			->set('permissions', $query->createNamedParameter($permissions))
684
-			->execute();
685
-	}
686
-
687
-
688
-	/**
689
-	 * get file
690
-	 *
691
-	 * @param string $user
692
-	 * @param int $fileSource
693
-	 * @return array with internal path of the file and a absolute link to it
694
-	 */
695
-	private function getFile($user, $fileSource) {
696
-		\OC_Util::setupFS($user);
697
-
698
-		try {
699
-			$file = Filesystem::getPath($fileSource);
700
-		} catch (NotFoundException $e) {
701
-			$file = null;
702
-		}
703
-		$args = Filesystem::is_dir($file) ? array('dir' => $file) : array('dir' => dirname($file), 'scrollto' => $file);
704
-		$link = Util::linkToAbsolute('files', 'index.php', $args);
705
-
706
-		return [$file, $link];
707
-
708
-	}
709
-
710
-	/**
711
-	 * check if we are the initiator or the owner of a re-share and return the correct UID
712
-	 *
713
-	 * @param IShare $share
714
-	 * @return string
715
-	 */
716
-	protected function getCorrectUid(IShare $share) {
717
-		if ($this->userManager->userExists($share->getShareOwner())) {
718
-			return $share->getShareOwner();
719
-		}
720
-
721
-		return $share->getSharedBy();
722
-	}
723
-
724
-
725
-
726
-	/**
727
-	 * check if we got the right share
728
-	 *
729
-	 * @param IShare $share
730
-	 * @param string $token
731
-	 * @return bool
732
-	 * @throws AuthenticationFailedException
733
-	 */
734
-	protected function verifyShare(IShare $share, $token) {
735
-		if (
736
-			$share->getShareType() === FederatedShareProvider::SHARE_TYPE_REMOTE &&
737
-			$share->getToken() === $token
738
-		) {
739
-			return true;
740
-		}
741
-
742
-		throw new AuthenticationFailedException();
743
-	}
744
-
745
-
746
-
747
-	/**
748
-	 * check if server-to-server sharing is enabled
749
-	 *
750
-	 * @param bool $incoming
751
-	 * @return bool
752
-	 */
753
-	private function isS2SEnabled($incoming = false) {
754
-
755
-		$result = $this->appManager->isEnabledForUser('files_sharing');
756
-
757
-		if ($incoming) {
758
-			$result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
759
-		} else {
760
-			$result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
761
-		}
762
-
763
-		return $result;
764
-	}
53
+    /** @var IAppManager */
54
+    private $appManager;
55
+
56
+    /** @var FederatedShareProvider */
57
+    private $federatedShareProvider;
58
+
59
+    /** @var AddressHandler */
60
+    private $addressHandler;
61
+
62
+    /** @var ILogger */
63
+    private $logger;
64
+
65
+    /** @var IUserManager */
66
+    private $userManager;
67
+
68
+    /** @var ICloudIdManager */
69
+    private $cloudIdManager;
70
+
71
+    /** @var IActivityManager */
72
+    private $activityManager;
73
+
74
+    /** @var INotificationManager */
75
+    private $notificationManager;
76
+
77
+    /** @var IURLGenerator */
78
+    private $urlGenerator;
79
+
80
+    /** @var ICloudFederationFactory */
81
+    private $cloudFederationFactory;
82
+
83
+    /** @var ICloudFederationProviderManager */
84
+    private $cloudFederationProviderManager;
85
+
86
+    /** @var IDBConnection */
87
+    private $connection;
88
+
89
+    /**
90
+     * CloudFederationProvider constructor.
91
+     *
92
+     * @param IAppManager $appManager
93
+     * @param FederatedShareProvider $federatedShareProvider
94
+     * @param AddressHandler $addressHandler
95
+     * @param ILogger $logger
96
+     * @param IUserManager $userManager
97
+     * @param ICloudIdManager $cloudIdManager
98
+     * @param IActivityManager $activityManager
99
+     * @param INotificationManager $notificationManager
100
+     * @param IURLGenerator $urlGenerator
101
+     * @param ICloudFederationFactory $cloudFederationFactory
102
+     * @param ICloudFederationProviderManager $cloudFederationProviderManager
103
+     * @param IDBConnection $connection
104
+     */
105
+    public function __construct(IAppManager $appManager,
106
+                                FederatedShareProvider $federatedShareProvider,
107
+                                AddressHandler $addressHandler,
108
+                                ILogger $logger,
109
+                                IUserManager $userManager,
110
+                                ICloudIdManager $cloudIdManager,
111
+                                IActivityManager $activityManager,
112
+                                INotificationManager $notificationManager,
113
+                                IURLGenerator $urlGenerator,
114
+                                ICloudFederationFactory $cloudFederationFactory,
115
+                                ICloudFederationProviderManager $cloudFederationProviderManager,
116
+                                IDBConnection $connection
117
+    ) {
118
+        $this->appManager = $appManager;
119
+        $this->federatedShareProvider = $federatedShareProvider;
120
+        $this->addressHandler = $addressHandler;
121
+        $this->logger = $logger;
122
+        $this->userManager = $userManager;
123
+        $this->cloudIdManager = $cloudIdManager;
124
+        $this->activityManager = $activityManager;
125
+        $this->notificationManager = $notificationManager;
126
+        $this->urlGenerator = $urlGenerator;
127
+        $this->cloudFederationFactory = $cloudFederationFactory;
128
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
129
+        $this->connection = $connection;
130
+    }
131
+
132
+
133
+
134
+    /**
135
+     * @return string
136
+     */
137
+    public function getShareType() {
138
+        return 'file';
139
+    }
140
+
141
+    /**
142
+     * share received from another server
143
+     *
144
+     * @param ICloudFederationShare $share
145
+     * @return string provider specific unique ID of the share
146
+     *
147
+     * @throws ProviderCouldNotAddShareException
148
+     * @throws \OCP\AppFramework\QueryException
149
+     * @throws \OC\HintException
150
+     * @since 14.0.0
151
+     */
152
+    public function shareReceived(ICloudFederationShare $share) {
153
+
154
+        if (!$this->isS2SEnabled(true)) {
155
+            throw new ProviderCouldNotAddShareException('Server does not support federated cloud sharing', '', Http::STATUS_SERVICE_UNAVAILABLE);
156
+        }
157
+
158
+        $protocol = $share->getProtocol();
159
+        if ($protocol['name'] !== 'webdav') {
160
+            throw new ProviderCouldNotAddShareException('Unsupported protocol for data exchange.', '', Http::STATUS_NOT_IMPLEMENTED);
161
+        }
162
+
163
+        list($ownerUid, $remote) = $this->addressHandler->splitUserRemote($share->getOwner());
164
+        // for backward compatibility make sure that the remote url stored in the
165
+        // database ends with a trailing slash
166
+        if (substr($remote, -1) !== '/') {
167
+            $remote = $remote . '/';
168
+        }
169
+
170
+        $token = $share->getShareSecret();
171
+        $name = $share->getResourceName();
172
+        $owner = $share->getOwnerDisplayName();
173
+        $sharedBy = $share->getSharedByDisplayName();
174
+        $shareWith = $share->getShareWith();
175
+        $remoteId = $share->getProviderId();
176
+        $sharedByFederatedId = $share->getSharedBy();
177
+        $ownerFederatedId = $share->getOwner();
178
+
179
+        // if no explicit information about the person who created the share was send
180
+        // we assume that the share comes from the owner
181
+        if ($sharedByFederatedId === null) {
182
+            $sharedBy = $owner;
183
+            $sharedByFederatedId = $ownerFederatedId;
184
+        }
185
+
186
+        if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
187
+
188
+            if (!Util::isValidFileName($name)) {
189
+                throw new ProviderCouldNotAddShareException('The mountpoint name contains invalid characters.', '', Http::STATUS_BAD_REQUEST);
190
+            }
191
+
192
+            // FIXME this should be a method in the user management instead
193
+            $this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
194
+            Util::emitHook(
195
+                '\OCA\Files_Sharing\API\Server2Server',
196
+                'preLoginNameUsedAsUserName',
197
+                array('uid' => &$shareWith)
198
+            );
199
+            $this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
200
+
201
+            if (!$this->userManager->userExists($shareWith)) {
202
+                throw new ProviderCouldNotAddShareException('User does not exists', '',Http::STATUS_BAD_REQUEST);
203
+            }
204
+
205
+            \OC_Util::setupFS($shareWith);
206
+
207
+            $externalManager = new \OCA\Files_Sharing\External\Manager(
208
+                \OC::$server->getDatabaseConnection(),
209
+                Filesystem::getMountManager(),
210
+                Filesystem::getLoader(),
211
+                \OC::$server->getHTTPClientService(),
212
+                \OC::$server->getNotificationManager(),
213
+                \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
214
+                \OC::$server->getCloudFederationProviderManager(),
215
+                \OC::$server->getCloudFederationFactory(),
216
+                $shareWith
217
+            );
218
+
219
+            try {
220
+                $externalManager->addShare($remote, $token, '', $name, $owner, false, $shareWith, $remoteId);
221
+                $shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external');
222
+
223
+                $event = $this->activityManager->generateEvent();
224
+                $event->setApp('files_sharing')
225
+                    ->setType('remote_share')
226
+                    ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
227
+                    ->setAffectedUser($shareWith)
228
+                    ->setObject('remote_share', (int)$shareId, $name);
229
+                \OC::$server->getActivityManager()->publish($event);
230
+
231
+                $notification = $this->notificationManager->createNotification();
232
+                $notification->setApp('files_sharing')
233
+                    ->setUser($shareWith)
234
+                    ->setDateTime(new \DateTime())
235
+                    ->setObject('remote_share', $shareId)
236
+                    ->setSubject('remote_share', [$ownerFederatedId, $sharedByFederatedId, trim($name, '/')]);
237
+
238
+                $declineAction = $notification->createAction();
239
+                $declineAction->setLabel('decline')
240
+                    ->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
241
+                $notification->addAction($declineAction);
242
+
243
+                $acceptAction = $notification->createAction();
244
+                $acceptAction->setLabel('accept')
245
+                    ->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
246
+                $notification->addAction($acceptAction);
247
+
248
+                $this->notificationManager->notify($notification);
249
+
250
+                return $shareId;
251
+            } catch (\Exception $e) {
252
+                $this->logger->logException($e, [
253
+                    'message' => 'Server can not add remote share.',
254
+                    'level' => ILogger::ERROR,
255
+                    'app' => 'files_sharing'
256
+                ]);
257
+                throw new ProviderCouldNotAddShareException('internal server error, was not able to add share from ' . $remote, '', HTTP::STATUS_INTERNAL_SERVER_ERROR);
258
+            }
259
+        }
260
+
261
+        throw new ProviderCouldNotAddShareException('server can not add remote share, missing parameter', '', HTTP::STATUS_BAD_REQUEST);
262
+
263
+    }
264
+
265
+    /**
266
+     * notification received from another server
267
+     *
268
+     * @param string $notificationType (e.g. SHARE_ACCEPTED)
269
+     * @param string $providerId id of the share
270
+     * @param array $notification payload of the notification
271
+     * @return array data send back to the sender
272
+     *
273
+     * @throws ActionNotSupportedException
274
+     * @throws AuthenticationFailedException
275
+     * @throws BadRequestException
276
+     * @throws \OC\HintException
277
+     * @since 14.0.0
278
+     */
279
+    public function notificationReceived($notificationType, $providerId, array $notification) {
280
+
281
+        switch ($notificationType) {
282
+            case 'SHARE_ACCEPTED':
283
+                return $this->shareAccepted($providerId, $notification);
284
+            case 'SHARE_DECLINED':
285
+                return $this->shareDeclined($providerId, $notification);
286
+            case 'SHARE_UNSHARED':
287
+                return $this->unshare($providerId, $notification);
288
+            case 'REQUEST_RESHARE':
289
+                return $this->reshareRequested($providerId, $notification);
290
+            case 'RESHARE_UNDO':
291
+                return $this->undoReshare($providerId, $notification);
292
+            case 'RESHARE_CHANGE_PERMISSION':
293
+                return $this->updateResharePermissions($providerId, $notification);
294
+        }
295
+
296
+
297
+        throw new BadRequestException([$notificationType]);
298
+    }
299
+
300
+    /**
301
+     * process notification that the recipient accepted a share
302
+     *
303
+     * @param string $id
304
+     * @param array $notification
305
+     * @return array
306
+     * @throws ActionNotSupportedException
307
+     * @throws AuthenticationFailedException
308
+     * @throws BadRequestException
309
+     * @throws \OC\HintException
310
+     */
311
+    private function shareAccepted($id, array $notification) {
312
+
313
+        if (!$this->isS2SEnabled()) {
314
+            throw new ActionNotSupportedException('Server does not support federated cloud sharing');
315
+        }
316
+
317
+        if (!isset($notification['sharedSecret'])) {
318
+            throw new BadRequestException(['sharedSecret']);
319
+        }
320
+
321
+        $token = $notification['sharedSecret'];
322
+
323
+        $share = $this->federatedShareProvider->getShareById($id);
324
+
325
+        $this->verifyShare($share, $token);
326
+        $this->executeAcceptShare($share);
327
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
328
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
329
+            $remoteId = $this->federatedShareProvider->getRemoteId($share);
330
+            $notification = $this->cloudFederationFactory->getCloudFederationNotification();
331
+            $notification->setMessage(
332
+                'SHARE_ACCEPTED',
333
+                'file',
334
+                $remoteId,
335
+                [
336
+                    'sharedSecret' => $token,
337
+                    'message' => 'Recipient accepted the re-share'
338
+                ]
339
+
340
+            );
341
+            $this->cloudFederationProviderManager->sendNotification($remote, $notification);
342
+
343
+        }
344
+
345
+        return [];
346
+    }
347
+
348
+    /**
349
+     * @param IShare $share
350
+     * @throws ShareNotFound
351
+     */
352
+    protected function executeAcceptShare(IShare $share) {
353
+        try {
354
+            $fileId = (int)$share->getNode()->getId();
355
+            list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
356
+        } catch (\Exception $e) {
357
+            throw new ShareNotFound();
358
+        }
359
+
360
+        $event = $this->activityManager->generateEvent();
361
+        $event->setApp('files_sharing')
362
+            ->setType('remote_share')
363
+            ->setAffectedUser($this->getCorrectUid($share))
364
+            ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_ACCEPTED, [$share->getSharedWith(), [$fileId => $file]])
365
+            ->setObject('files', $fileId, $file)
366
+            ->setLink($link);
367
+        $this->activityManager->publish($event);
368
+    }
369
+
370
+    /**
371
+     * process notification that the recipient declined a share
372
+     *
373
+     * @param string $id
374
+     * @param array $notification
375
+     * @return array
376
+     * @throws ActionNotSupportedException
377
+     * @throws AuthenticationFailedException
378
+     * @throws BadRequestException
379
+     * @throws ShareNotFound
380
+     * @throws \OC\HintException
381
+     *
382
+     */
383
+    protected function shareDeclined($id, array $notification) {
384
+
385
+        if (!$this->isS2SEnabled()) {
386
+            throw new ActionNotSupportedException('Server does not support federated cloud sharing');
387
+        }
388
+
389
+        if (!isset($notification['sharedSecret'])) {
390
+            throw new BadRequestException(['sharedSecret']);
391
+        }
392
+
393
+        $token = $notification['sharedSecret'];
394
+
395
+        $share = $this->federatedShareProvider->getShareById($id);
396
+
397
+        $this->verifyShare($share, $token);
398
+
399
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
400
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
401
+            $remoteId = $this->federatedShareProvider->getRemoteId($share);
402
+            $notification = $this->cloudFederationFactory->getCloudFederationNotification();
403
+            $notification->setMessage(
404
+                'SHARE_DECLINED',
405
+                'file',
406
+                $remoteId,
407
+                [
408
+                    'sharedSecret' => $token,
409
+                    'message' => 'Recipient declined the re-share'
410
+                ]
411
+
412
+            );
413
+            $this->cloudFederationProviderManager->sendNotification($remote, $notification);
414
+        }
415
+
416
+        $this->executeDeclineShare($share);
417
+
418
+        return [];
419
+
420
+    }
421
+
422
+    /**
423
+     * delete declined share and create a activity
424
+     *
425
+     * @param IShare $share
426
+     * @throws ShareNotFound
427
+     */
428
+    protected function executeDeclineShare(IShare $share) {
429
+        $this->federatedShareProvider->removeShareFromTable($share);
430
+
431
+        try {
432
+            $fileId = (int)$share->getNode()->getId();
433
+            list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
434
+        } catch (\Exception $e) {
435
+            throw new ShareNotFound();
436
+        }
437
+
438
+        $event = $this->activityManager->generateEvent();
439
+        $event->setApp('files_sharing')
440
+            ->setType('remote_share')
441
+            ->setAffectedUser($this->getCorrectUid($share))
442
+            ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_DECLINED, [$share->getSharedWith(), [$fileId => $file]])
443
+            ->setObject('files', $fileId, $file)
444
+            ->setLink($link);
445
+        $this->activityManager->publish($event);
446
+
447
+    }
448
+
449
+    /**
450
+     * received the notification that the owner unshared a file from you
451
+     *
452
+     * @param string $id
453
+     * @param array $notification
454
+     * @return array
455
+     * @throws AuthenticationFailedException
456
+     * @throws BadRequestException
457
+     */
458
+    private function undoReshare($id, array $notification) {
459
+        if (!isset($notification['sharedSecret'])) {
460
+            throw new BadRequestException(['sharedSecret']);
461
+        }
462
+        $token = $notification['sharedSecret'];
463
+
464
+        $share = $this->federatedShareProvider->getShareById($id);
465
+
466
+        $this->verifyShare($share, $token);
467
+        $this->federatedShareProvider->removeShareFromTable($share);
468
+        return [];
469
+    }
470
+
471
+    /**
472
+     * unshare file from self
473
+     *
474
+     * @param string $id
475
+     * @param array $notification
476
+     * @return array
477
+     * @throws ActionNotSupportedException
478
+     * @throws BadRequestException
479
+     */
480
+    private function unshare($id, array $notification) {
481
+
482
+        if (!$this->isS2SEnabled(true)) {
483
+            throw new ActionNotSupportedException("incoming shares disabled!");
484
+        }
485
+
486
+        if (!isset($notification['sharedSecret'])) {
487
+            throw new BadRequestException(['sharedSecret']);
488
+        }
489
+        $token = $notification['sharedSecret'];
490
+
491
+        $qb = $this->connection->getQueryBuilder();
492
+        $qb->select('*')
493
+            ->from('share_external')
494
+            ->where(
495
+                $qb->expr()->andX(
496
+                    $qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
497
+                    $qb->expr()->eq('share_token', $qb->createNamedParameter($token))
498
+                )
499
+            );
500
+
501
+        $result = $qb->execute();
502
+        $share = $result->fetch();
503
+        $result->closeCursor();
504
+
505
+        if ($token && $id && !empty($share)) {
506
+
507
+            $remote = $this->cleanupRemote($share['remote']);
508
+
509
+            $owner = $this->cloudIdManager->getCloudId($share['owner'], $remote);
510
+            $mountpoint = $share['mountpoint'];
511
+            $user = $share['user'];
512
+
513
+            $qb = $this->connection->getQueryBuilder();
514
+            $qb->delete('share_external')
515
+                ->where(
516
+                    $qb->expr()->andX(
517
+                        $qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
518
+                        $qb->expr()->eq('share_token', $qb->createNamedParameter($token))
519
+                    )
520
+                );
521
+
522
+            $qb->execute();
523
+
524
+            if ($share['accepted']) {
525
+                $path = trim($mountpoint, '/');
526
+            } else {
527
+                $path = trim($share['name'], '/');
528
+            }
529
+
530
+            $notification = $this->notificationManager->createNotification();
531
+            $notification->setApp('files_sharing')
532
+                ->setUser($share['user'])
533
+                ->setObject('remote_share', (int)$share['id']);
534
+            $this->notificationManager->markProcessed($notification);
535
+
536
+            $event = $this->activityManager->generateEvent();
537
+            $event->setApp('files_sharing')
538
+                ->setType('remote_share')
539
+                ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
540
+                ->setAffectedUser($user)
541
+                ->setObject('remote_share', (int)$share['id'], $path);
542
+            \OC::$server->getActivityManager()->publish($event);
543
+        }
544
+
545
+        return [];
546
+    }
547
+
548
+    private function cleanupRemote($remote) {
549
+        $remote = substr($remote, strpos($remote, '://') + 3);
550
+
551
+        return rtrim($remote, '/');
552
+    }
553
+
554
+    /**
555
+     * recipient of a share request to re-share the file with another user
556
+     *
557
+     * @param string $id
558
+     * @param array $notification
559
+     * @return array
560
+     * @throws AuthenticationFailedException
561
+     * @throws BadRequestException
562
+     * @throws ProviderCouldNotAddShareException
563
+     * @throws ShareNotFound
564
+     */
565
+    protected function reshareRequested($id, array $notification) {
566
+
567
+        if (!isset($notification['sharedSecret'])) {
568
+            throw new BadRequestException(['sharedSecret']);
569
+        }
570
+        $token = $notification['sharedSecret'];
571
+
572
+        if (!isset($notification['shareWith'])) {
573
+            throw new BadRequestException(['shareWith']);
574
+        }
575
+        $shareWith = $notification['shareWith'];
576
+
577
+        if (!isset($notification['senderId'])) {
578
+            throw new BadRequestException(['senderId']);
579
+        }
580
+        $senderId = $notification['senderId'];
581
+
582
+        $share = $this->federatedShareProvider->getShareById($id);
583
+        // don't allow to share a file back to the owner
584
+        try {
585
+            list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
586
+            $owner = $share->getShareOwner();
587
+            $currentServer = $this->addressHandler->generateRemoteURL();
588
+            if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
589
+                throw new ProviderCouldNotAddShareException('Resharing back to the owner is not allowed: ' . $id);
590
+            }
591
+        } catch (\Exception $e) {
592
+            throw new ProviderCouldNotAddShareException($e->getMessage());
593
+        }
594
+
595
+        $this->verifyShare($share, $token);
596
+
597
+        // check if re-sharing is allowed
598
+        if ($share->getPermissions() & Constants::PERMISSION_SHARE) {
599
+            // the recipient of the initial share is now the initiator for the re-share
600
+            $share->setSharedBy($share->getSharedWith());
601
+            $share->setSharedWith($shareWith);
602
+            $result = $this->federatedShareProvider->create($share);
603
+            $this->federatedShareProvider->storeRemoteId((int)$result->getId(), $senderId);
604
+            return ['token' => $result->getToken(), 'providerId' => $result->getId()];
605
+        } else {
606
+            throw new ProviderCouldNotAddShareException('resharing not allowed for share: ' . $id);
607
+        }
608
+
609
+    }
610
+
611
+    /**
612
+     * update permission of a re-share so that the share dialog shows the right
613
+     * permission if the owner or the sender changes the permission
614
+     *
615
+     * @param string $id
616
+     * @param array $notification
617
+     * @return array
618
+     * @throws AuthenticationFailedException
619
+     * @throws BadRequestException
620
+     */
621
+    protected function updateResharePermissions($id, array $notification) {
622
+
623
+        if (!isset($notification['sharedSecret'])) {
624
+            throw new BadRequestException(['sharedSecret']);
625
+        }
626
+        $token = $notification['sharedSecret'];
627
+
628
+        if (!isset($notification['permission'])) {
629
+            throw new BadRequestException(['permission']);
630
+        }
631
+        $ocmPermissions = $notification['permission'];
632
+
633
+        $share = $this->federatedShareProvider->getShareById($id);
634
+
635
+        $ncPermission = $this->ocmPermissions2ncPermissions($ocmPermissions);
636
+
637
+        $this->verifyShare($share, $token);
638
+        $this->updatePermissionsInDatabase($share, $ncPermission);
639
+
640
+        return [];
641
+    }
642
+
643
+    /**
644
+     * translate OCM Permissions to Nextcloud permissions
645
+     *
646
+     * @param array $ocmPermissions
647
+     * @return int
648
+     * @throws BadRequestException
649
+     */
650
+    protected function ocmPermissions2ncPermissions(array $ocmPermissions) {
651
+        $ncPermissions = 0;
652
+        foreach($ocmPermissions as $permission) {
653
+            switch (strtolower($permission)) {
654
+                case 'read':
655
+                    $ncPermissions += Constants::PERMISSION_READ;
656
+                    break;
657
+                case 'write':
658
+                    $ncPermissions += Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE;
659
+                    break;
660
+                case 'share':
661
+                    $ncPermissions += Constants::PERMISSION_SHARE;
662
+                    break;
663
+                default:
664
+                    throw new BadRequestException(['permission']);
665
+            }
666
+
667
+            error_log("new permissions: " . $ncPermissions);
668
+        }
669
+
670
+        return $ncPermissions;
671
+    }
672
+
673
+    /**
674
+     * update permissions in database
675
+     *
676
+     * @param IShare $share
677
+     * @param int $permissions
678
+     */
679
+    protected function updatePermissionsInDatabase(IShare $share, $permissions) {
680
+        $query = $this->connection->getQueryBuilder();
681
+        $query->update('share')
682
+            ->where($query->expr()->eq('id', $query->createNamedParameter($share->getId())))
683
+            ->set('permissions', $query->createNamedParameter($permissions))
684
+            ->execute();
685
+    }
686
+
687
+
688
+    /**
689
+     * get file
690
+     *
691
+     * @param string $user
692
+     * @param int $fileSource
693
+     * @return array with internal path of the file and a absolute link to it
694
+     */
695
+    private function getFile($user, $fileSource) {
696
+        \OC_Util::setupFS($user);
697
+
698
+        try {
699
+            $file = Filesystem::getPath($fileSource);
700
+        } catch (NotFoundException $e) {
701
+            $file = null;
702
+        }
703
+        $args = Filesystem::is_dir($file) ? array('dir' => $file) : array('dir' => dirname($file), 'scrollto' => $file);
704
+        $link = Util::linkToAbsolute('files', 'index.php', $args);
705
+
706
+        return [$file, $link];
707
+
708
+    }
709
+
710
+    /**
711
+     * check if we are the initiator or the owner of a re-share and return the correct UID
712
+     *
713
+     * @param IShare $share
714
+     * @return string
715
+     */
716
+    protected function getCorrectUid(IShare $share) {
717
+        if ($this->userManager->userExists($share->getShareOwner())) {
718
+            return $share->getShareOwner();
719
+        }
720
+
721
+        return $share->getSharedBy();
722
+    }
723
+
724
+
725
+
726
+    /**
727
+     * check if we got the right share
728
+     *
729
+     * @param IShare $share
730
+     * @param string $token
731
+     * @return bool
732
+     * @throws AuthenticationFailedException
733
+     */
734
+    protected function verifyShare(IShare $share, $token) {
735
+        if (
736
+            $share->getShareType() === FederatedShareProvider::SHARE_TYPE_REMOTE &&
737
+            $share->getToken() === $token
738
+        ) {
739
+            return true;
740
+        }
741
+
742
+        throw new AuthenticationFailedException();
743
+    }
744
+
745
+
746
+
747
+    /**
748
+     * check if server-to-server sharing is enabled
749
+     *
750
+     * @param bool $incoming
751
+     * @return bool
752
+     */
753
+    private function isS2SEnabled($incoming = false) {
754
+
755
+        $result = $this->appManager->isEnabledForUser('files_sharing');
756
+
757
+        if ($incoming) {
758
+            $result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
759
+        } else {
760
+            $result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
761
+        }
762
+
763
+        return $result;
764
+    }
765 765
 
766 766
 
767 767
 }
Please login to merge, or discard this patch.