Failed Conditions
Push — master ( e8410d...a45585 )
by Marcos
09:36 queued 11s
created

ShareService   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 305
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
dl 0
loc 305
rs 9.76
c 0
b 0
f 0
wmc 33
lcom 1
cbo 8
1
<?php
2
/**
3
 * Nextcloud - passman
4
 *
5
 * @copyright Copyright (c) 2016, Sander Brand ([email protected])
6
 * @copyright Copyright (c) 2016, Marcos Zuriaga Miguel ([email protected])
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License as
11
 * published by the Free Software Foundation, either version 3 of the
12
 * License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
namespace OCA\Passman\Service;
25
26
27
use OCA\Passman\Db\CredentialMapper;
28
use OCA\Passman\Db\ShareRequest;
29
use OCA\Passman\Db\ShareRequestMapper;
30
use OCA\Passman\Db\SharingACL;
31
use OCA\Passman\Db\SharingACLMapper;
32
use OCA\Passman\Utility\Utils;
33
use OCP\AppFramework\Db\DoesNotExistException;
34
use OCP\AppFramework\Db\Entity;
35
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
36
use OCP\DB\Exception;
37
use OCP\DB\IResult;
38
use OCP\Notification\IManager;
39
40
class ShareService {
41
	private SharingACLMapper $sharingACL;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting T_FUNCTION or T_CONST
Loading history...
42
	private ShareRequestMapper $shareRequest;
43
	private CredentialMapper $credential;
44
	private CredentialRevisionService $revisions;
45
	private EncryptService $encryptService;
46
	private IManager $IManager;
47
48
49
	public function __construct(
50
		SharingACLMapper $sharingACL,
51
		ShareRequestMapper $shareRequest,
52
		CredentialMapper $credentials,
53
		CredentialRevisionService $revisions,
54
		EncryptService $encryptService,
55
		IManager $IManager
56
	) {
57
		$this->sharingACL = $sharingACL;
58
		$this->shareRequest = $shareRequest;
59
		$this->credential = $credentials;
60
		$this->revisions = $revisions;
61
		$this->encryptService = $encryptService;
62
		$this->IManager = $IManager;
63
	}
64
65
	/**
66
	 * Creates requests for all the items on the request array of objects.
67
	 * This array must follow this spec:
68
	 *      user_id:    The target user id
69
	 *      vault_id:   The id of the target vault
70
	 *      guid:       The guid of the target vault
71
	 *      key:        The shared key cyphered with the target vault RSA public key
72
	 *
73
	 * @param $target_item_id   string      The shared item ID
74
	 * @param $target_item_guid string      The shared item GUID
75
	 * @param $request_array    array
76
	 * @param $permissions      integer     Must be created with a bitmask from options on the ShareRequest class
77
	 * @return array                        Array of sharing requests
78
	 */
79
	public function createBulkRequests($target_item_id, $target_item_guid, $request_array, $permissions, $credential_owner) {
80
		$created = Utils::getTime();
81
		$requests = array();
82
		foreach ($request_array as $req) {
83
			$t = new ShareRequest();
84
			$t->setItemId($target_item_id);
85
			$t->setItemGuid($target_item_guid);
86
			$t->setTargetUserId($req['user_id']);
87
			$t->setTargetVaultId($req['vault_id']);
88
			$t->setTargetVaultGuid($req['guid']);
89
			$t->setSharedKey($req['key']);
90
			$t->setPermissions($permissions);
91
			$t->setCreated($created);
92
			$t->setFromUserId($credential_owner);
93
			array_push($requests, $this->shareRequest->createRequest($t));
94
		}
95
		return $requests;
96
	}
97
98
	/**
99
	 * @param SharingACL $acl
100
	 * @return Entity
101
	 */
102
	public function createACLEntry(SharingACL $acl) {
103
		if ($acl->getCreated() === null) $acl->setCreated((new \DateTime())->getTimestamp());
104
		return $this->sharingACL->createACLEntry($acl);
105
	}
106
107
	/**
108
	 * Applies the given share, defaults to no expire
109
	 *
110
	 * @param string $item_guid
111
	 * @param string $target_vault_guid
112
	 * @param string $final_shared_key
113
	 * @throws DoesNotExistException
114
	 * @throws Exception
115
	 * @throws MultipleObjectsReturnedException
116
	 */
117
	public function applyShare(string $item_guid, string $target_vault_guid, string $final_shared_key) {
118
		$request = $this->shareRequest->getRequestByItemAndVaultGuid($item_guid, $target_vault_guid);
119
		$permissions = $request->getPermissions();
120
121
		$acl = new SharingACL();
122
		$acl->setItemId($request->getItemId());
123
		$acl->setItemGuid($request->getItemGuid());
124
		$acl->setUserId($request->getTargetUserId());
125
		$acl->setCreated($request->getCreated());
126
		$acl->setExpire(0);
127
		$acl->setPermissions($permissions);
128
		$acl->setVaultId($request->getTargetVaultId());
129
		$acl->setVaultGuid($request->getTargetVaultGuid());
130
		$acl->setSharedKey($final_shared_key);
131
132
		$this->sharingACL->createACLEntry($acl);
133
		$this->shareRequest->cleanItemRequestsForUser($request->getItemId(), $request->getTargetUserId());
134
	}
135
136
	/**
137
	 * Obtains pending requests for the given user ID
138
	 *
139
	 * @param string $user_id
140
	 * @return Entity[]
141
	 */
142
	public function getUserPendingRequests(string $user_id) {
143
		return $this->shareRequest->getUserPendingRequests($user_id);
144
	}
145
146
	/**
147
	 * Get shared credentials from a user
148
	 *
149
	 * @param string $user_id
150
	 * @param string $vault_guid
151
	 * @return array
152
	 * @throws DoesNotExistException
153
	 * @throws MultipleObjectsReturnedException
154
	 */
155
	public function getSharedItems(string $user_id, string $vault_guid) {
156
		$entries = $this->sharingACL->getVaultEntries($user_id, $vault_guid);
157
158
		$return = [];
159
		foreach ($entries as $entry) {
160
			// Check if the user can read the credential, probably unnecesary, but just to be sure
161
			if (!$entry->hasPermission(SharingACL::READ)) continue;
162
			$tmp = $entry->jsonSerialize();
163
			$credential = $this->credential->getCredentialById($entry->getItemId());
164
			$credential = $this->encryptService->decryptCredential($credential);
165
			$tmp['credential_data'] = $credential->jsonSerialize();
166
167
			if (!$entry->hasPermission(SharingACL::FILES)) unset($tmp['credential_data']['files']);
168
			unset($tmp['credential_data']['shared_key']);
169
			$return[] = $tmp;
170
		}
171
		return $return;
172
	}
173
174
	/**
175
	 * Gets the acl for a given item guid
176
	 *
177
	 * @param string $user_id
178
	 * @param string $item_guid
179
	 * @return Entity
180
	 * @throws DoesNotExistException
181
	 * @throws MultipleObjectsReturnedException
182
	 */
183
	public function getACL(string $user_id, string $item_guid) {
184
		return $this->sharingACL->getItemACL($user_id, $item_guid);
185
	}
186
187
	/**
188
	 * @param string $user_id
189
	 * @param string $item_guid
190
	 * @return array|mixed
191
	 * @throws DoesNotExistException
192
	 * @throws MultipleObjectsReturnedException
193
	 */
194
	public function getSharedItem(string $user_id, string $item_guid) {
195
		$acl = $this->sharingACL->getItemACL($user_id, $item_guid);
196
197
		// Check if the user can read the credential, probably unnecesary, but just to be sure
198
		if (!$acl->hasPermission(SharingACL::READ)) throw new DoesNotExistException("Item not found or wrong access level");
199
200
		$tmp = $acl->jsonSerialize();
201
		$credential = $this->credential->getCredentialById($acl->getItemId());
202
		$credential = $this->encryptService->decryptCredential($credential);
203
204
		$tmp['credential_data'] = $credential->jsonSerialize();
205
206
		if (!$acl->hasPermission(SharingACL::FILES)) unset($tmp['credential_data']['files']);
207
		unset($tmp['credential_data']['shared_key']);
208
209
		return $tmp;
210
	}
211
212
	/**
213
	 * Gets history from the given item checking the user's permissions to access it
214
	 *
215
	 * @param string $user_id
216
	 * @param string $item_guid
217
	 * @return array|Entity[]
218
	 * @throws DoesNotExistException
219
	 * @throws MultipleObjectsReturnedException
220
	 * @throws \Exception
221
	 */
222
	public function getItemHistory(string $user_id, string $item_guid) {
223
		$acl = $this->sharingACL->getItemACL($user_id, $item_guid);
224
		if (!$acl->hasPermission(SharingACL::READ | SharingACL::HISTORY)) return [];
225
226
		return $this->revisions->getRevisions($acl->getItemId());
227
	}
228
229
230
	/**
231
	 * Deletes a share request by the item ID
232
	 *
233
	 * @param ShareRequest $request
234
	 * @return int|IResult
235
	 * @throws Exception
236
	 */
237
	public function cleanItemRequestsForUser(ShareRequest $request) {
238
		return $this->shareRequest->cleanItemRequestsForUser($request->getItemId(), $request->getTargetUserId());
239
	}
240
241
	/**
242
	 * Get an share request by id
243
	 *
244
	 * @param int $id
245
	 * @return Entity
246
	 * @throws DoesNotExistException
247
	 * @throws MultipleObjectsReturnedException
248
	 */
249
	public function getShareRequestById(int $id) {
250
		return $this->shareRequest->getShareRequestById($id);
251
	}
252
253
	/**
254
	 * Get an share request by $item_guid and $target_vault_guid
255
	 *
256
	 * @param string $item_guid
257
	 * @param string $target_vault_guid
258
	 * @return Entity
259
	 * @throws DoesNotExistException
260
	 * @throws MultipleObjectsReturnedException
261
	 */
262
	public function getRequestByGuid(string $item_guid, string $target_vault_guid) {
263
		return $this->shareRequest->getRequestByItemAndVaultGuid($item_guid, $target_vault_guid);
264
	}
265
266
	/**
267
	 * Get the access control list by item guid
268
	 *
269
	 * @param string $item_guid
270
	 * @return Entity[]
271
	 */
272
	public function getCredentialAclList(string $item_guid) {
273
		return $this->sharingACL->getCredentialAclList($item_guid);
274
	}
275
276
	/**
277
	 * @param string $item_guid
278
	 * @return Entity[]
279
	 * @throws Exception
280
	 */
281
	public function getCredentialPendingAclList(string $item_guid) {
282
		return $this->shareRequest->getRequestsByItemGuidGroupedByUser($item_guid);
283
	}
284
285
	/**
286
	 * Gets the ACL on the credential for the user
287
	 *
288
	 * @param string $user_id
289
	 * @param string $item_guid
290
	 * @return Entity
291
	 * @throws DoesNotExistException
292
	 * @throws MultipleObjectsReturnedException
293
	 */
294
	public function getCredentialAclForUser(string $user_id, string $item_guid) {
295
		return $this->sharingACL->getItemACL($user_id, $item_guid);
296
	}
297
298
	/**
299
	 * Get pending share requests by guid
300
	 *
301
	 * @param string $item_guid
302
	 * @return Entity[]
303
	 */
304
	public function getShareRequestsByGuid(string $item_guid) {
305
		return $this->shareRequest->getShareRequestsByItemGuid($item_guid);
306
	}
307
308
	/**
309
	 * Get pending share requests by guid
310
	 *
311
	 * @param ShareRequest $request
312
	 * @return ShareRequest
313
	 */
314
	public function deleteShareRequest(ShareRequest $request) {
315
		return $this->shareRequest->deleteShareRequest($request);
316
	}
317
318
	/**
319
	 * Delete ACL
320
	 *
321
	 * @param SharingACL|Entity $ACL
322
	 * @return SharingACL|Entity
323
	 */
324
	public function deleteShareACL(SharingACL $ACL) {
325
		return $this->sharingACL->deleteShareACL($ACL);
326
	}
327
328
	/**
329
	 * Updates the given ACL entry
330
	 *
331
	 * @param SharingACL $sharingACL
332
	 * @return SharingACL|Entity
333
	 */
334
	public function updateCredentialACL(SharingACL $sharingACL) {
335
		return $this->sharingACL->updateCredentialACL($sharingACL);
336
	}
337
338
	/**
339
	 * @param ShareRequest $shareRequest
340
	 * @return ShareRequest
341
	 */
342
	public function updateCredentialShareRequest(ShareRequest $shareRequest) {
343
		return $this->shareRequest->updateShareRequest($shareRequest);
344
	}
345
346
347
	/**
348
	 * Get pending share requests by guid and uid
349
	 *
350
	 * @param string $item_guid
351
	 * @param string $user_id
352
	 * @return Entity[]
353
	 */
354
	public function getPendingShareRequestsForCredential(string $item_guid, string $user_id) {
355
		return $this->shareRequest->getPendingShareRequests($item_guid, $user_id);
356
	}
357
358
	/**
359
	 * @param string $item_guid
360
	 * @param string $user_id
361
	 * @param int $permissions
362
	 * @return int|IResult
363
	 * @throws Exception
364
	 */
365
	public function updatePendingShareRequestsForCredential(string $item_guid, string $user_id, int $permissions) {
366
		return $this->shareRequest->updatePendingRequestPermissions($item_guid, $user_id, $permissions);
367
	}
368
369
	/**
370
	 * Clean up on credential destroyed.
371
	 * This will delete all ACL's and share requests.
372
	 * @param string $item_guid
373
	 */
374
	public function unshareCredential(string $item_guid) {
375
		$acl_list = $this->getCredentialAclList($item_guid);
376
		$request_list = $this->getShareRequestsByGuid($item_guid);
377
		foreach ($acl_list as $ACL) {
378
			$this->deleteShareACL($ACL);
379
		}
380
		foreach ($request_list as $request) {
381
			$this->deleteShareRequest($request);
382
			$notification = $this->IManager->createNotification();
383
			$notification->setApp('passman')
384
				->setObject('passman_share_request', $request->getId())
385
				->setUser($request->getTargetUserId());
386
			$this->IManager->markProcessed($notification);
387
		}
388
	}
389
}
390