Completed
Pull Request — master (#155)
by Sander
02:24
created

ShareController::getPublicCredentialData()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

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