Passed
Push — master ( 1330f4...591d77 )
by Marcel
05:54 queued 15s
created

ShareService::deleteSharesByItem()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Analytics
4
 *
5
 * SPDX-FileCopyrightText: 2019-2022 Marcel Scherello
6
 * SPDX-License-Identifier: AGPL-3.0-or-later
7
 */
8
9
namespace OCA\Analytics\Service;
10
11
use OCA\Analytics\Activity\ActivityManager;
12
use OCA\Analytics\Db\ShareMapper;
13
use OCA\Analytics\Db\ReportMapper;
14
use OCP\DB\Exception;
0 ignored issues
show
Bug introduced by
The type OCP\DB\Exception was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use OCP\IGroupManager;
0 ignored issues
show
Bug introduced by
The type OCP\IGroupManager was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
use OCP\IUserManager;
0 ignored issues
show
Bug introduced by
The type OCP\IUserManager was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use OCP\IUserSession;
0 ignored issues
show
Bug introduced by
The type OCP\IUserSession was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
use OCP\Security\ISecureRandom;
0 ignored issues
show
Bug introduced by
The type OCP\Security\ISecureRandom was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
use Psr\Log\LoggerInterface;
0 ignored issues
show
Bug introduced by
The type Psr\Log\LoggerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
20
21
class ShareService {
22
	const SHARE_TYPE_USER = 0;
23
	const SHARE_TYPE_GROUP = 1;
24
	const SHARE_TYPE_USERGROUP = 2; // obsolete
25
	const SHARE_TYPE_LINK = 3;
26
	const SHARE_TYPE_ROOM = 10;
27
	const SHARE_ITEM_TYPE_REPORT = 'report';
28
	const SHARE_ITEM_TYPE_PANORAMA = 'panorama';
29
	const SHARE_ITEM_TYPE_DATASET = 'dataset';
30
31
	/** @var IUserSession */
32
	private $userSession;
33
	/** @var LoggerInterface */
34
	private $logger;
35
	/** @var ShareMapper */
36
	private $ShareMapper;
37
	private $ReportMapper;
38
	private $secureRandom;
39
	private $ActivityManager;
40
	/** @var IGroupManager */
41
	private $groupManager;
42
	/** @var IUserManager */
43
	private $userManager;
44
	private $VariableService;
45
46
	public function __construct(
47
		IUserSession    $userSession,
48
		LoggerInterface $logger,
49
		ShareMapper     $ShareMapper,
50
		ReportMapper    $ReportMapper,
51
		ActivityManager $ActivityManager,
52
		IGroupManager   $groupManager,
53
		ISecureRandom   $secureRandom,
54
		IUserManager    $userManager,
55
		VariableService $VariableService
56
	) {
57
		$this->userSession = $userSession;
58
		$this->logger = $logger;
59
		$this->ShareMapper = $ShareMapper;
60
		$this->ReportMapper = $ReportMapper;
61
		$this->secureRandom = $secureRandom;
62
		$this->groupManager = $groupManager;
63
		$this->ActivityManager = $ActivityManager;
64
		$this->userManager = $userManager;
65
		$this->VariableService = $VariableService;
66
	}
67
68
	/**
69
	 * create a new share
70
	 *
71
	 * @param $item_type
72
	 * @param $item_source
73
	 * @param $type
74
	 * @param $user
75
	 * @return bool
76
	 * @throws Exception
77
	 */
78
	public function create($item_type, $item_source, $type, $user) {
79
		$token = null;
80
		if ((int)$type === self::SHARE_TYPE_LINK) {
81
			$token = $this->generateToken();
82
		}
83
		$this->ShareMapper->createShare($item_type, $item_source, $type, $user, $token);
84
85
		//TODO
86
		//$this->ActivityManager->triggerEvent($item_source, ActivityManager::OBJECT_REPORT, ActivityManager::SUBJECT_REPORT_SHARE);
87
		return true;
88
	}
89
90
	/**
91
	 * get all shares for a report or panorama
92
	 *
93
	 * @param $item_source
94
	 * @param $item_type
95
	 * @return array
96
	 * @throws Exception
97
	 */
98
	public function read($item_type, $item_source) {
99
100
		$shares = $this->ShareMapper->getShares($item_type , $item_source);
101
		foreach ($shares as $key => $share) {
102
			if ((int)$share['type'] === self::SHARE_TYPE_USER) {
103
				if (!$this->userManager->userExists($share['uid_owner'])) {
104
					$this->ShareMapper->deleteShare($share['id']);
105
					unset($shares[$key]);
106
					continue;
107
				}
108
				$shares[$key]['displayName'] = $this->userManager->get($share['uid_owner'])->getDisplayName();
109
			}
110
			$shares[$key]['pass'] = $share['pass'] !== null;
111
		}
112
		return $shares;
113
	}
114
115
	/**
116
	 * get all report by token
117
	 *
118
	 * @param $token
119
	 * @return array
120
	 */
121
	public function getReportByToken($token) {
122
		$reportId = $this->ShareMapper->getReportByToken($token);
123
		return $this->VariableService->replaceTextVariables($reportId);
124
	}
125
126
	/**
127
	 * verify password hahes
128
	 *
129
	 * @param $password
130
	 * @param $sharePassword
131
	 * @return bool
132
	 */
133
	public function verifyPassword($password, $sharePassword) {
134
		return password_verify($password, $sharePassword);
135
	}
136
137
	/**
138
	 * get all shares for an item (report or panorama)
139
	 *
140
	 * @param $item_type
141
	 * @return array|false
142
	 * @throws Exception
143
	 */
144
	public function getSharedItems($item_type) {
145
		if ($item_type === self::SHARE_ITEM_TYPE_PANORAMA) {
146
			$sharedReports = $this->ShareMapper->getAllSharedPanoramas();
147
		} else {
148
			$sharedReports = $this->ShareMapper->getAllSharedReports();
149
		}
150
		$groupsOfUser = $this->groupManager->getUserGroups($this->userSession->getUser());
151
		$reports = array();
152
153
		foreach ($sharedReports as $sharedReport) {
154
			// shared with a group?
155
			if ((int)$sharedReport['shareType'] === self::SHARE_TYPE_GROUP) {
156
				// is the current user part of this group?
157
				$this->logger->debug('Shareservice: is group share');
158
				if (array_key_exists($sharedReport['shareUid_owner'], $groupsOfUser)) {
159
					// was the report not yet added to the result?
160
					if (!in_array($sharedReport["id"], array_column($reports, "id"))) {
161
						unset($sharedReport['shareType']);
162
						unset($sharedReport['shareUid_owner']);
163
						$sharedReport['isShare'] = self::SHARE_TYPE_GROUP;
164
						$reports[] = $sharedReport;
165
					}
166
				}
167
				// shared with a user directly?
168
			} elseif ((int)$sharedReport['shareType'] === self::SHARE_TYPE_USER) {
169
				// current user matching?
170
				$this->logger->debug('Shareservice: is user share; check against current user: ' . $this->userSession->getUser()
171
																													 ->getUID());
172
				if ($this->userSession->getUser()->getUID() === $sharedReport['shareUid_owner']) {
173
					// was the report not yet added to the result?
174
					$this->logger->debug('Shareservice: Share belongs to current user');
175
					if (!in_array($sharedReport["id"], array_column($reports, "id"))) {
176
						$this->logger->debug('Shareservice: Share added to output');
177
						unset($sharedReport['shareType']);
178
						unset($sharedReport['shareUid_owner']);
179
						$sharedReport['isShare'] = self::SHARE_TYPE_USER;
180
						$reports[] = $sharedReport;
181
					}
182
				}
183
			}
184
		}
185
186
		// no groupings of shares exist for panoramas
187
		if ($item_type !== self::SHARE_ITEM_TYPE_PANORAMA) {
188
			foreach ($reports as $report) {
189
				// if it is a shared group, get all reports below
190
				if ((int)$report['type'] === ReportService::REPORT_TYPE_GROUP) {
191
					$subreport = $this->ReportMapper->getReportsByGroup($report['id']);
192
					$subreport = array_map(function ($report) {
193
						$report['isShare'] = self::SHARE_TYPE_GROUP;
194
						return $report;
195
					}, $subreport);
196
197
					$reports = array_merge($reports, $subreport);
198
				}
199
			}
200
		}
201
		return $reports;
202
	}
203
204
	/**
205
	 * get metadata of a report, shared with current user
206
	 * used to check if user is allowed to execute current report
207
	 *
208
	 * @param $reportId
209
	 * @return array
210
	 * @throws Exception
211
	 */
212
	public function getSharedReport($reportId) {
213
		$sharedReport = $this->getSharedItems(self::SHARE_ITEM_TYPE_REPORT);
214
		if (in_array($reportId, array_column($sharedReport, "id"))) {
215
			$key = array_search($reportId, array_column($sharedReport, 'id'));
216
			return $sharedReport[$key];
217
		} else {
218
			return [];
219
		}
220
	}
221
222
	/**
223
	 * get metadata of a report, shared with current user as part of a panorama
224
	 * used to check if user is allowed to execute current report
225
	 *
226
	 * @param $reportId
227
	 * @return array
228
	 * @throws Exception
229
	 */
230
	public function getSharedPanoramaReport($reportId) {
231
		$foundReportId = 0;
232
		$panoramaOwner = null;
233
		$sharedPanoramas = $this->getSharedItems(self::SHARE_ITEM_TYPE_PANORAMA);
234
		foreach ($sharedPanoramas as $sharedPanorama) {
235
			$panoramaOwner = $sharedPanorama['user_id'];
236
			$pages = json_decode($sharedPanorama['pages'], true);
237
			foreach ($pages as $page) {
238
				$reports = $page['reports'];
239
				foreach ($reports as $report) {
240
					// only use report type 0 = report; not text or image
241
					if ($report['type'] === 0 && $report['value'] === $reportId) {
242
						$foundReportId = $reportId;
243
						break 3;
244
					}
245
				}
246
			}
247
		}
248
249
		if ($foundReportId !== 0) {
0 ignored issues
show
introduced by
The condition $foundReportId !== 0 is always false.
Loading history...
250
			$report = $this->ReportMapper->read($foundReportId);
251
			// check against the original owner of the panorama
252
			// This is needed to prevent getting other reports by modifying the panorama properties
253
			if ($report['user_id'] === $panoramaOwner) {
254
				return $report;
255
			} else {
256
				return [];
257
			}
258
		} else {
259
			return [];
260
		}
261
	}
262
263
	/**
264
	 * Delete an own share (sharee or receiver)
265
	 *
266
	 * @param $shareId
267
	 * @return bool
268
	 * @throws Exception
269
	 */
270
	public function delete($shareId) {
271
		$this->ShareMapper->deleteShare($shareId);
272
		return true;
273
	}
274
275
	/**
276
	 * delete all shares for a report or panorama
277
	 *
278
	 * @param $item_type
279
	 * @param $item_source
280
	 * @return bool
281
	 * @throws Exception
282
	 */
283
	public function deleteSharesByItem($item_type, $item_source) {
284
		return $this->ShareMapper->deleteSharesByItem($item_type, $item_source);
285
	}
286
287
	/**
288
	 * delete all shares when a share-receiving-user is deleted
289
	 *
290
	 * @param $userId
291
	 * @return bool
292
	 */
293
	public function deleteByUser($userId) {
294
		return $this->ShareMapper->deleteByUser($userId);
295
	}
296
297
	/**
298
	 * update/set share password
299
	 *
300
	 * @param $shareId
301
	 * @param string|null $password
302
	 * @param string|null $canEdit
303
	 * @param string|null $domain
304
	 * @return bool
305
	 */
306
	public function update($shareId, $password = null, $canEdit = null, $domain = null) {
307
		if ($password !== null) {
308
			$password = password_hash($password, PASSWORD_DEFAULT);
309
			return $this->ShareMapper->updateSharePassword($shareId, $password);
310
		}
311
		if ($domain !== null) {
312
			return $this->ShareMapper->updateShareDomain($shareId, $domain);
313
		}
314
		if ($canEdit !== null) {
315
			$canEdit === true ? $canEdit = \OCP\Constants::PERMISSION_UPDATE : $canEdit = \OCP\Constants::PERMISSION_READ;
0 ignored issues
show
introduced by
The condition $canEdit === true is always false.
Loading history...
Bug introduced by
The type OCP\Constants was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
316
			return $this->ShareMapper->updateSharePermissions($shareId, $canEdit);
317
		}
318
	}
319
320
	/**
321
	 * generate to token used to authenticate federated shares
322
	 *
323
	 * @return string
324
	 */
325
	private function generateToken() {
326
		$token = $this->secureRandom->generate(15, ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS);
327
		return $token;
328
	}
329
}