Passed
Push — master ( 591d77...ff0d74 )
by Marcel
04:58
created

ShareService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 9
nc 1
nop 9
dl 0
loc 20
rs 9.9666
c 2
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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
		switch ($item_type) {
86
			case ShareService::SHARE_ITEM_TYPE_REPORT:
87
				$this->ActivityManager->triggerEvent($item_source, ActivityManager::OBJECT_REPORT, ActivityManager::SUBJECT_REPORT_SHARE);
88
				break;
89
			case ShareService::SHARE_ITEM_TYPE_DATASET:
90
				$this->ActivityManager->triggerEvent($item_source, ActivityManager::OBJECT_DATASET, ActivityManager::SUBJECT_DATASET_SHARE);
91
				break;
92
			case ShareService::SHARE_ITEM_TYPE_PANORAMA:
93
				$this->ActivityManager->triggerEvent($item_source, ActivityManager::OBJECT_PANORAMA, ActivityManager::SUBJECT_PANORAMA_SHARE);
94
				break;
95
		}
96
		return true;
97
	}
98
99
	/**
100
	 * get all shares for a report or panorama
101
	 *
102
	 * @param $item_source
103
	 * @param $item_type
104
	 * @return array
105
	 * @throws Exception
106
	 */
107
	public function read($item_type, $item_source) {
108
109
		$shares = $this->ShareMapper->getShares($item_type, $item_source);
110
		foreach ($shares as $key => $share) {
111
			if ((int)$share['type'] === self::SHARE_TYPE_USER) {
112
				if (!$this->userManager->userExists($share['uid_owner'])) {
113
					$this->ShareMapper->deleteShare($share['id']);
114
					unset($shares[$key]);
115
					continue;
116
				}
117
				$shares[$key]['displayName'] = $this->userManager->get($share['uid_owner'])->getDisplayName();
118
			}
119
			$shares[$key]['pass'] = $share['pass'] !== null;
120
		}
121
		return $shares;
122
	}
123
124
	/**
125
	 * get all report by token
126
	 *
127
	 * @param $token
128
	 * @return array
129
	 */
130
	public function getReportByToken($token) {
131
		$reportId = $this->ShareMapper->getReportByToken($token);
132
		return $this->VariableService->replaceTextVariables($reportId);
133
	}
134
135
	/**
136
	 * verify password hahes
137
	 *
138
	 * @param $password
139
	 * @param $sharePassword
140
	 * @return bool
141
	 */
142
	public function verifyPassword($password, $sharePassword) {
143
		return password_verify($password, $sharePassword);
144
	}
145
146
	/**
147
	 * get all shares for an item (report or panorama)
148
	 *
149
	 * @param $item_type
150
	 * @return array|false
151
	 * @throws Exception
152
	 */
153
	public function getSharedItems($item_type) {
154
		if ($item_type === self::SHARE_ITEM_TYPE_PANORAMA) {
155
			$sharedReports = $this->ShareMapper->getAllSharedPanoramas();
156
		} else {
157
			$sharedReports = $this->ShareMapper->getAllSharedReports();
158
		}
159
		$groupsOfUser = $this->groupManager->getUserGroups($this->userSession->getUser());
160
		$reports = array();
161
162
		foreach ($sharedReports as $sharedReport) {
163
			// shared with a group?
164
			if ((int)$sharedReport['shareType'] === self::SHARE_TYPE_GROUP) {
165
				// is the current user part of this group?
166
				$this->logger->debug('Shareservice: is group share');
167
				if (array_key_exists($sharedReport['shareUid_owner'], $groupsOfUser)) {
168
					// was the report not yet added to the result?
169
					if (!in_array($sharedReport["id"], array_column($reports, "id"))) {
170
						unset($sharedReport['shareType']);
171
						unset($sharedReport['shareUid_owner']);
172
						$sharedReport['isShare'] = self::SHARE_TYPE_GROUP;
173
						$reports[] = $sharedReport;
174
					}
175
				}
176
				// shared with a user directly?
177
			} elseif ((int)$sharedReport['shareType'] === self::SHARE_TYPE_USER) {
178
				// current user matching?
179
				$this->logger->debug('Shareservice: is user share; check against current user: ' . $this->userSession->getUser()
180
																													 ->getUID());
181
				if ($this->userSession->getUser()->getUID() === $sharedReport['shareUid_owner']) {
182
					// was the report not yet added to the result?
183
					$this->logger->debug('Shareservice: Share belongs to current user');
184
					if (!in_array($sharedReport["id"], array_column($reports, "id"))) {
185
						$this->logger->debug('Shareservice: Share added to output');
186
						unset($sharedReport['shareType']);
187
						unset($sharedReport['shareUid_owner']);
188
						$sharedReport['isShare'] = self::SHARE_TYPE_USER;
189
						$reports[] = $sharedReport;
190
					}
191
				}
192
			}
193
		}
194
195
		// no groupings of shares exist for panoramas
196
		if ($item_type !== self::SHARE_ITEM_TYPE_PANORAMA) {
197
			foreach ($reports as $report) {
198
				// if it is a shared group, get all reports below
199
				if ((int)$report['type'] === ReportService::REPORT_TYPE_GROUP) {
200
					$subreport = $this->ReportMapper->getReportsByGroup($report['id']);
201
					$subreport = array_map(function ($report) {
202
						$report['isShare'] = self::SHARE_TYPE_GROUP;
203
						return $report;
204
					}, $subreport);
205
206
					$reports = array_merge($reports, $subreport);
207
				}
208
			}
209
		}
210
		return $reports;
211
	}
212
213
	/**
214
	 * get metadata of a report, shared with current user
215
	 * used to check if user is allowed to execute current report
216
	 *
217
	 * @param $reportId
218
	 * @return array
219
	 * @throws Exception
220
	 */
221
	public function getSharedReport($reportId) {
222
		$sharedReport = $this->getSharedItems(self::SHARE_ITEM_TYPE_REPORT);
223
		if (in_array($reportId, array_column($sharedReport, "id"))) {
224
			$key = array_search($reportId, array_column($sharedReport, 'id'));
225
			return $sharedReport[$key];
226
		} else {
227
			return [];
228
		}
229
	}
230
231
	/**
232
	 * get metadata of a report, shared with current user as part of a panorama
233
	 * used to check if user is allowed to execute current report
234
	 *
235
	 * @param $reportId
236
	 * @return array
237
	 * @throws Exception
238
	 */
239
	public function getSharedPanoramaReport($reportId) {
240
		$foundReportId = 0;
241
		$panoramaOwner = null;
242
		$sharedPanoramas = $this->getSharedItems(self::SHARE_ITEM_TYPE_PANORAMA);
243
		foreach ($sharedPanoramas as $sharedPanorama) {
244
			$panoramaOwner = $sharedPanorama['user_id'];
245
			$pages = json_decode($sharedPanorama['pages'], true);
246
			foreach ($pages as $page) {
247
				$reports = $page['reports'];
248
				foreach ($reports as $report) {
249
					// only use report type 0 = report; not text or image
250
					if ($report['type'] === 0 && $report['value'] === $reportId) {
251
						$foundReportId = $reportId;
252
						break 3;
253
					}
254
				}
255
			}
256
		}
257
258
		if ($foundReportId !== 0) {
0 ignored issues
show
introduced by
The condition $foundReportId !== 0 is always false.
Loading history...
259
			$report = $this->ReportMapper->read($foundReportId);
260
			// check against the original owner of the panorama
261
			// This is needed to prevent getting other reports by modifying the panorama properties
262
			if ($report['user_id'] === $panoramaOwner) {
263
				return $report;
264
			} else {
265
				return [];
266
			}
267
		} else {
268
			return [];
269
		}
270
	}
271
272
	/**
273
	 * Delete an own share (sharee or receiver)
274
	 *
275
	 * @param $shareId
276
	 * @return bool
277
	 * @throws Exception
278
	 */
279
	public function delete($shareId) {
280
		$this->ShareMapper->deleteShare($shareId);
281
		return true;
282
	}
283
284
	/**
285
	 * delete all shares for a report or panorama
286
	 *
287
	 * @param $item_type
288
	 * @param $item_source
289
	 * @return bool
290
	 * @throws Exception
291
	 */
292
	public function deleteSharesByItem($item_type, $item_source) {
293
		return $this->ShareMapper->deleteSharesByItem($item_type, $item_source);
294
	}
295
296
	/**
297
	 * delete all shares when a share-receiving-user is deleted
298
	 *
299
	 * @param $userId
300
	 * @return bool
301
	 */
302
	public function deleteByUser($userId) {
303
		return $this->ShareMapper->deleteByUser($userId);
304
	}
305
306
	/**
307
	 * update/set share password
308
	 *
309
	 * @param $shareId
310
	 * @param string|null $password
311
	 * @param string|null $canEdit
312
	 * @param string|null $domain
313
	 * @return bool
314
	 */
315
	public function update($shareId, $password = null, $canEdit = null, $domain = null) {
316
		if ($password !== null) {
317
			$password = password_hash($password, PASSWORD_DEFAULT);
318
			return $this->ShareMapper->updateSharePassword($shareId, $password);
319
		}
320
		if ($domain !== null) {
321
			return $this->ShareMapper->updateShareDomain($shareId, $domain);
322
		}
323
		if ($canEdit !== null) {
324
			$canEdit === true ? $canEdit = \OCP\Constants::PERMISSION_UPDATE : $canEdit = \OCP\Constants::PERMISSION_READ;
0 ignored issues
show
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...
introduced by
The condition $canEdit === true is always false.
Loading history...
325
			return $this->ShareMapper->updateSharePermissions($shareId, $canEdit);
326
		}
327
	}
328
329
	/**
330
	 * generate to token used to authenticate federated shares
331
	 *
332
	 * @return string
333
	 */
334
	private function generateToken() {
335
		$token = $this->secureRandom->generate(15, ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS);
336
		return $token;
337
	}
338
}