Completed
Push — master ( 9b8394...483b13 )
by Sander
02:27
created

ShareController::createPublicShare()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 36
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 36
ccs 0
cts 23
cp 0
rs 8.439
c 0
b 0
f 0
cc 5
eloc 24
nc 6
nop 5
crap 30
1
<?php
2
/**
3
 * Nextcloud - passman
4
 *
5
 * This file is licensed under the Affero General Public License version 3 or
6
 * later. See the COPYING file.
7
 *
8
 * @author Sander Brand <[email protected]>
9
 * @copyright Sander Brand 2016
10
 */
11
12
namespace OCA\Passman\Controller;
13
14
use OCA\Passman\Db\SharingACL;
15
use OCA\Passman\Db\Vault;
16
use OCA\Passman\Service\CredentialService;
17
use OCA\Passman\Service\FileService;
18
use OCA\Passman\Service\NotificationService;
19
use OCA\Passman\Service\SettingsService;
20
use OCA\Passman\Service\ShareService;
21
use OCA\Passman\Utility\NotFoundJSONResponse;
22
use OCA\Passman\Utility\Utils;
23
use OCP\AppFramework\Db\DoesNotExistException;
24
use OCP\AppFramework\Http\NotFoundResponse;
25
use OCP\IConfig;
26
use OCP\IRequest;
27
use OCP\AppFramework\Http\JSONResponse;
28
use OCP\AppFramework\ApiController;
29
30
use OCP\IGroupManager;
31
use OCP\IUserManager;
32
33
use OCA\Passman\Service\VaultService;
34
use OCA\Passman\Service\ActivityService;
35
use OCA\Passman\Activity;
36
37
38
class ShareController extends ApiController {
39
	private $userId;
40
	private $activityService;
41
	private $groupManager;
42
	private $userManager;
43
	private $vaultService;
44
	private $shareService;
45
	private $credentialService;
46
	private $notificationService;
47
	private $fileService;
48
	private $settings;
49
50
	private $limit = 50;
51
	private $offset = 0;
52
53
	public function __construct($AppName,
54
								IRequest $request,
55
								$UserId,
56
								IGroupManager $groupManager,
57
								IUserManager $userManager,
58
								ActivityService $activityService,
59
								VaultService $vaultService,
60
								ShareService $shareService,
61
								CredentialService $credentialService,
62
								NotificationService $notificationService,
63
								FileService $fileService,
64
								SettingsService $config
65
	) {
66
		parent::__construct($AppName, $request);
67
68
		$this->userId = $UserId;
69
		$this->userManager = $userManager;
70
		$this->groupManager = $groupManager;
71
		$this->activityService = $activityService;
72
		$this->vaultService = $vaultService;
73
		$this->shareService = $shareService;
74
		$this->credentialService = $credentialService;
75
		$this->notificationService = $notificationService;
76
		$this->fileService = $fileService;
77
		$this->settings = $config;
78
	}
79
80
81
	/**
82
	 * @param $item_id
83
	 * @param $item_guid
84
	 * @param $permissions
85
	 * @param $expire_timestamp
86
	 * @NoAdminRequired
87
	 * @NoCSRFRequired
88
	 */
89
	public function createPublicShare($item_id, $item_guid, $permissions, $expire_timestamp, $expire_views) {
90
91
		if (!$this->settings->isEnabled('link_sharing_enabled')) {
92
			return new JSONResponse(array());
93
		}
94
95
		try {
96
			$credential = $this->credentialService->getCredentialByGUID($item_guid);
97
		} catch (\Exception $exception) {
98
			return new NotFoundResponse();
99
		}
100
101
		try {
102
			$acl = $this->shareService->getACL(null, $item_guid);
103
		} catch (\Exception $exception) {
104
			$acl = new SharingACL();
105
		}
106
107
108
		$acl->setItemId($item_id);
109
		$acl->setItemGuid($item_guid);
110
		$acl->setPermissions($permissions);
111
		$acl->setExpire($expire_timestamp);
112
		$acl->setExpireViews($expire_views);
113
		if (!$acl->getId()) {
114
			$this->shareService->createACLEntry($acl);
115
116
			$this->activityService->add(
117
				'item_shared_publicly', [$credential->getLabel()],
118
				'', array(),
119
				'', $this->userId->getUID(), Activity::TYPE_ITEM_SHARED);
120
		} else {
121
			$this->shareService->updateCredentialACL($acl);
122
		}
123
124
	}
125
126
	/**
127
	 * @NoAdminRequired
128
	 * @NoCSRFRequired
129
	 */
130
	public function applyIntermediateShare($item_id, $item_guid, $vaults, $permissions) {
131
		if (!$this->settings->isEnabled('user_sharing_enabled')) {
132
			return new JSONResponse(array());
133
		}
134
		/**
135
		 * Assemble notification
136
		 */
137
		//@TODO add expire_time
138
		//@TODO add expire_views
139
		$credential = $this->credentialService->getCredentialById($item_id, $this->userId->getUID());
140
		$credential_owner = $credential->getUserId();
141
142
		$first_vault = $vaults[0];
143
		try {
144
			$shareRequests = $this->shareService->getPendingShareRequestsForCredential($item_guid, $first_vault['user_id']);
145
			if (count($shareRequests) > 0) {
146
				return new JSONResponse(array('error' => 'User got already pending requests'));
147
			}
148
		} catch (\Exception $exception) {
149
			// no need to catch this
150
		}
151
152
		$acl = null;
153
		try {
154
			$acl = $this->shareService->getCredentialAclForUser($first_vault['user_id'], $item_guid);
155
		} catch (\Exception $exception) {
156
			// no need to catch this
157
		}
158
159
		if ($acl) {
160
			return new JSONResponse(array('error' => 'User got already this credential'));
161
		}
162
163
		$result = $this->shareService->createBulkRequests($item_id, $item_guid, $vaults, $permissions, $credential_owner);
164
		if ($credential) {
165
			$processed_users = array();
166
			foreach ($result as $vault) {
167
				if (!in_array($vault->getTargetUserId(), $processed_users)) {
168
					$target_user = $vault->getTargetUserId();
169
					$notification = array(
170
						'from_user' => ucfirst($this->userId->getDisplayName()),
171
						'credential_label' => $credential->getLabel(),
172
						'credential_id' => $credential->getId(),
173
						'item_id' => $credential->getId(),
174
						'target_user' => $target_user,
175
						'req_id' => $vault->getId()
176
					);
177
					$this->notificationService->credentialSharedNotification(
178
						$notification
179
					);
180
					array_push($processed_users, $target_user);
181
182
					$this->activityService->add(
183
						'item_shared', [$credential->getLabel(), $target_user],
184
						'', array(),
185
						'', $this->userId->getUID(), Activity::TYPE_ITEM_SHARED);
186
187
188
					$this->activityService->add(
189
						'item_share_received', [$credential->getLabel(), $this->userId->getUID()],
190
						'', array(),
191
						'', $target_user, Activity::TYPE_ITEM_SHARED);
192
				}
193
			}
194
		}
195
196
197
		return new JSONResponse($result);
198
	}
199
200
	/**
201
	 * @NoAdminRequired
202
	 * @NoCSRFRequired
203
	 */
204
	public function searchUsers($search) {
205
		$users = array();
206
		$usersTmp = $this->userManager->searchDisplayName($search, $this->limit, $this->offset);
207
208
		foreach ($usersTmp as $user) {
209
			if ($this->userId->getUID() !== $user->getUID() && count($this->vaultService->getByUser($user->getUID())) >= 1) {
210
				$users[] = array(
211
					'text' => $user->getDisplayName(),
212
					'uid' => $user->getUID(),
213
					'type' => 'user'
214
				);
215
			}
216
		}
217
		return $users;
218
	}
219
220
221
	/**
222
	 * @NoAdminRequired
223
	 * @NoCSRFRequired
224
	 */
225
	public function unshareCredential($item_guid) {
226
		if (!$this->settings->isEnabled('user_sharing_enabled')) {
227
			return new JSONResponse(array());
228
		}
229
		$acl_list = $this->shareService->getCredentialAclList($item_guid);
230
		$request_list = $this->shareService->getShareRequestsByGuid($item_guid);
231
		foreach ($acl_list as $ACL) {
232
			$this->shareService->deleteShareACL($ACL);
233
		}
234
		foreach ($request_list as $request) {
235
			$this->shareService->deleteShareRequest($request);
236
			$manager = \OC::$server->getNotificationManager();
237
			$notification = $manager->createNotification();
238
			$notification->setApp('passman')
239
				->setObject('passman_share_request', $request->getId())
240
				->setUser($request->getTargetUserId());
241
			$manager->markProcessed($notification);
242
		}
243
		return new JSONResponse(array('result' => true));
244
	}
245
246
247
	public function unshareCredentialFromUser($item_guid, $user_id) {
248
		$acl = null;
249
		$sr = null;
250
		try {
251
			$acl = $this->shareService->getCredentialAclForUser($user_id, $item_guid);
252
		} catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
253
254
		}
255
		try {
256
			$sr = array_pop($this->shareService->getPendingShareRequestsForCredential($item_guid, $user_id));
0 ignored issues
show
Bug introduced by
$this->shareService->get...l($item_guid, $user_id) cannot be passed to array_pop() as the parameter $array expects a reference.
Loading history...
257
		} catch (\Exception $e) {
258
			// no need to catch this
259
		}
260
261
		if ($sr) {
262
			$this->shareService->cleanItemRequestsForUser($sr);
263
			$manager = \OC::$server->getNotificationManager();
264
			$notification = $manager->createNotification();
265
			$notification->setApp('passman')
266
				->setObject('passman_share_request', $sr->getId())
267
				->setUser($user_id);
268
			$manager->markProcessed($notification);
269
		}
270
		if ($acl) {
271
			$this->shareService->deleteShareACL($acl);
272
		}
273
		return new JSONResponse(array('result' => true));
274
	}
275
276
	/**
277
	 * @NoAdminRequired
278
	 * @NoCSRFRequired
279
	 */
280
	public function search($search) {
281
		$user_search = $this->searchUsers($search);
282
		return new JSONResponse($user_search);
283
	}
284
285
286
	/**
287
	 * @NoAdminRequired
288
	 * @NoCSRFRequired
289
	 */
290
	public function getVaultsByUser($user_id) {
291
		$user_vaults = $this->vaultService->getByUser($user_id);
292
		$result = array();
293
		foreach ($user_vaults as $vault) {
294
			array_push($result,
295
				array(
296
					'vault_id' => $vault->getId(),
297
					'guid' => $vault->getGuid(),
298
					'public_sharing_key' => $vault->getPublicSharingKey(),
299
					'user_id' => $user_id,
300
				));
301
		}
302
		return new JSONResponse($result);
303
	}
304
305
	/**
306
	 * @NoAdminRequired
307
	 * @NoCSRFRequired
308
	 */
309
	public function savePendingRequest($item_guid, $target_vault_guid, $final_shared_key) {
310
		try {
311
			$sr = $this->shareService->getRequestByGuid($item_guid, $target_vault_guid);
312
		} catch (\Exception $ex) {
313
			return new NotFoundResponse();
314
		}
315
316
		$manager = \OC::$server->getNotificationManager();
317
		$notification = $manager->createNotification();
318
		$notification->setApp('passman')
319
			->setObject('passman_share_request', $sr->getId())
320
			->setUser($this->userId->getUID());
321
		$manager->markProcessed($notification);
322
323
		$notification = array(
324
			'from_user' => ucfirst($this->userId->getDisplayName()),
325
			'credential_label' => $this->credentialService->getCredentialLabelById($sr->getItemId())->getLabel(),
326
			'target_user' => $sr->getFromUserId(),
327
			'req_id' => $sr->getId()
328
		);
329
330
		$this->notificationService->credentialAcceptedSharedNotification(
331
			$notification
332
		);
333
334
335
		$this->shareService->applyShare($item_guid, $target_vault_guid, $final_shared_key);
336
	}
337
338
	/**
339
	 * @NoAdminRequired
340
	 * @NoCSRFRequired
341
	 */
342
	public function getPendingRequests() {
343
		if (!$this->settings->isEnabled('user_sharing_enabled')) {
344
			return new JSONResponse(array());
345
		}
346
		try {
347
			$requests = $this->shareService->getUserPendingRequests($this->userId->getUID());
348
			$results = array();
349
			foreach ($requests as $request) {
350
				$result = $request->jsonSerialize();
351
				$c = $this->credentialService->getCredentialLabelById($request->getItemId());
352
				$result['credential_label'] = $c->getLabel();
353
				array_push($results, $result);
354
			}
355
			return new JSONResponse($results);
356
		} catch (\Exception $ex) {
357
			return new NotFoundResponse();
358
		}
359
	}
360
361
	/**
362
	 * @param $item_guid
363
	 * @return JSONResponse
364
	 * @NoAdminRequired
365
	 * @NoCSRFRequired
366
	 */
367
	public function getRevisions($item_guid) {
368
		try {
369
			return new JSONResponse($this->shareService->getItemHistory($this->userId, $item_guid));
370
		} catch (\Exception $ex) {
371
			return new NotFoundJSONResponse();
372
		}
373
	}
374
375
	/**
376
	 * Obtains the list of credentials shared with this vault
377
	 *
378
	 * @NoAdminRequired
379
	 * @NoCSRFRequired
380
	 */
381
	public function getVaultItems($vault_guid) {
382
		if (!$this->settings->isEnabled('user_sharing_enabled')) {
383
			return new JSONResponse(array());
384
		}
385
386
		try {
387
			return new JSONResponse($this->shareService->getSharedItems($this->userId->getUID(), $vault_guid));
388
		} catch (\Exception $ex) {
389
			return new NotFoundResponse();
390
		}
391
	}
392
393
	/**
394
	 * @param $share_request_id
395
	 * @return JSONResponse
396
	 * @NoAdminRequired
397
	 * @NoCSRFRequired
398
	 */
399
	public function deleteShareRequest($share_request_id) {
400
		try {
401
402
			$sr = $this->shareService->getShareRequestById($share_request_id);
403
			$notification = array(
404
				'from_user' => ucfirst($this->userId->getDisplayName()),
405
				'credential_label' => $this->credentialService->getCredentialLabelById($sr->getItemId())->getLabel(),
406
				'target_user' => $sr->getFromUserId(),
407
				'req_id' => $sr->getId()
408
			);
409
			$this->notificationService->credentialDeclinedSharedNotification(
410
				$notification
411
			);
412
413
414
			$manager = \OC::$server->getNotificationManager();
415
			$notification = $manager->createNotification();
416
			$notification->setApp('passman')
417
				->setObject('passman_share_request', $share_request_id)
418
				->setUser($this->userId->getUID());
419
			$manager->markProcessed($notification);
420
421
			$this->shareService->cleanItemRequestsForUser($sr);
422
			return new JSONResponse(array('result' => true));
423
		} catch (\Exception $ex) {
424
			return new NotFoundJSONResponse();
425
		}
426
	}
427
428
	/**
429
	 * @param $credential_guid
430
	 * @return JSONResponse
431
	 * @NoAdminRequired
432
	 * @NoCSRFRequired
433
	 * @PublicPage
434
	 */
435
	public function getPublicCredentialData($credential_guid) {
436
		if (!$this->settings->isEnabled('user_sharing_enabled')) {
437
			return new JSONResponse(array());
438
		}
439
		//@TODO Check expire date
440
		$acl = $this->shareService->getACL(null, $credential_guid);
441
442
		if ($acl->getExpire() > 0 && Utils::getTime() > $acl->getExpire()) {
443
			return new NotFoundJSONResponse();
444
		}
445
446
		$views = $acl->getExpireViews();
447
		if ($views === 0) {
448
			return new NotFoundJSONResponse();
449
		} else if ($views !== -1) {
450
			$views--;
451
			$acl->setExpireViews($views);
452
			$this->shareService->updateCredentialACL($acl);
453
		}
454
455
456
		try {
457
			$credential = $this->shareService->getSharedItem(null, $credential_guid);
458
			return new JSONResponse($credential);
459
		} catch (\Exception $ex) {
460
			return new NotFoundJSONResponse();
461
		}
462
	}
463
464
	/**
465
	 * @param $item_guid
466
	 * @return JSONResponse
467
	 * @NoAdminRequired
468
	 * @NoCSRFRequired
469
	 */
470
	public function getItemAcl($item_guid) {
471
		$acl = $this->shareService->getCredentialAclList($item_guid);
472
		$pending = $this->shareService->getCredentialPendingAclList($item_guid);
473
		try {
474
			$credential = $this->credentialService->getCredentialByGUID($item_guid);
475
			if ($credential->getUserId() === $this->userId->getUID()) {
476
				foreach ($pending as &$item) {
477
					$item = $item->asACLJson();
478
				}
479
				$acl = array_merge($acl, $pending);
480
				return new JSONResponse($acl);
481
			} else {
482
				return new NotFoundResponse();
483
			}
484
		} catch (\Exception $ex) {
485
			return new JSONResponse(array());
486
		}
487
	}
488
489
	/**
490
	 * @param $credential_guid
491
	 * @param $file_guid
492
	 * @NoAdminRequired
493
	 * @PublicPage
494
	 * @return JSONResponse
495
	 * @return NotFoundResponse
496
	 */
497
	public function getFile($item_guid, $file_guid) {
498
		try {
499
			$credential = $this->credentialService->getCredentialByGUID($item_guid);
500
		} catch (\Exception $e) {
501
			return new NotFoundJSONResponse();
502
		}
503
		$userId = ($this->userId) ? $this->userId->getUID() : null;
504
		$acl = $this->shareService->getACL($userId, $credential->getGuid());
505
		if (!$acl->hasPermission(SharingACL::FILES)) {
506
			return new NotFoundJSONResponse();
507
		} else {
508
			return $this->fileService->getFileByGuid($file_guid);
509
		}
510
	}
511
512
	/**
513
	 * @param $item_guid
514
	 * @param  $user_id
515
	 * @param $permission
516
	 * @return JSONResponse
517
	 * @NoAdminRequired
518
	 * @NoCSRFRequired
519
	 */
520
	public function updateSharedCredentialACL($item_guid, $user_id, $permission) {
521
		try {
522
			$credential = $this->credentialService->getCredentialByGUID($item_guid);
523
		} catch (\Exception $exception) {
524
			return new NotFoundJSONResponse();
525
		}
526
		if ($this->userId->getUID() === $credential->getUserId()) {
527
			$acl = null;
528
			try {
529
				$acl = $this->shareService->getACL($user_id, $item_guid);
530
				$acl->setPermissions($permission);
531
				return $this->shareService->updateCredentialACL($acl);
532
			} catch (\Exception $exception) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
533
534
			}
535
536
			if ($acl === null) {
537
				$this->shareService->updatePendingShareRequestsForCredential($item_guid, $user_id, $permission);
538
			}
539
540
		}
541
	}
542
}