Issues (3882)

Security Analysis    39 potential vulnerabilities

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting (9)
Response Splitting can be used to send arbitrary responses.
  File Manipulation (2)
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure (7)
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection (13)
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting (8)
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

app/PrivilegeUtil.php (15 issues)

1
<?php
2
/**
3
 * Privilege Util basic class.
4
 *
5
 * @package App
6
 *
7
 * @copyright YetiForce S.A.
8
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
9
 * @author    Mariusz Krzaczkowski <[email protected]>
10
 * @author    RadosÅ‚aw Skrzypczak <[email protected]>
11
 */
12
13
namespace App;
14
15
class PrivilegeUtil
16
{
17
	/** @var int Allowed group nests */
18
	public const GROUP_LOOP_LIMIT = 5;
19
20
	/** Function to get parent record owner.
21
	 * @param $tabid    -- tabid :: Type integer
0 ignored issues
show
Documentation Bug introduced by
The doc comment -- at position 0 could not be parsed: Unknown type name '--' at position 0 in --.
Loading history...
22
	 * @param $parModId -- parent module id :: Type integer
23
	 * @param $recordId -- record id :: Type integer
24
	 * @returns $parentRecOwner -- parentRecOwner:: Type integer
25
	 */
26
	public static function getParentRecordOwner($tabid, $parModId, $recordId)
27
	{
28
		Log::trace("Entering getParentRecordOwner($tabid,$parModId,$recordId) method ...");
29
		$parentRecOwner = [];
30
		$parentTabName = Module::getModuleName($parModId);
31
		$relTabName = Module::getModuleName($tabid);
32
		$fnName = 'get' . $relTabName . 'Related' . $parentTabName;
33
		$entId = static::$fnName($recordId);
34
		if ('' !== $entId) {
35
			$recordMetaData = \vtlib\Functions::getCRMRecordMetadata($entId);
36
			if ($recordMetaData) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $recordMetaData of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
37
				$ownerId = $recordMetaData['smownerid'];
38
				$type = \App\Fields\Owner::getType($ownerId);
39
				$parentRecOwner[$type] = $ownerId;
40
			}
41
		}
42
		Log::trace('Exiting getParentRecordOwner method ...');
43
		return $parentRecOwner;
44
	}
45
46
	/**
47 1
	 * Function return related account with ticket.
48
	 *
49 1
	 * @param int $recordId
50 1
	 *
51 1
	 * @return int
52
	 */
53
	private static function getHelpDeskRelatedAccounts($recordId)
54
	{
55
		return (new Db\Query())->select(['parent_id'])->from('vtiger_troubletickets')
0 ignored issues
show
Bug Best Practice introduced by
The expression return new App\Db\Query(... 'Accounts'))->scalar() also could return the type false|string which is incompatible with the documented return type integer.
Loading history...
56
			->innerJoin('vtiger_crmentity', 'vtiger_troubletickets.parent_id = vtiger_crmentity.crmid')
57
			->where(['ticketid' => $recordId, 'vtiger_crmentity.setype' => 'Accounts'])->scalar();
58
	}
59
60
	protected static $datashareRelatedCache = false;
61 2
62
	/**
63 2
	 * Function to get data share related modules.
64 1
	 *
65 1
	 * @return array
66 1
	 */
67 1
	public static function getDatashareRelatedModules()
68 1
	{
69
		if (false === static::$datashareRelatedCache) {
70
			$relModSharArr = [];
71
			$dataReader = (new \App\Db\Query())->from('vtiger_datashare_relatedmodules')->createCommand()->query();
72 1
			while ($row = $dataReader->read()) {
73 1
				$relTabId = $row['relatedto_tabid'];
74
				if (isset($relModSharArr[$relTabId]) && \is_array($relModSharArr[$relTabId])) {
75 1
					$temArr = $relModSharArr[$relTabId];
76
					$temArr[] = $row['tabid'];
77 1
				} else {
78
					$temArr = [];
79 2
					$temArr[] = $row['tabid'];
80
				}
81
				$relModSharArr[$relTabId] = $temArr;
82
			}
83
			static::$datashareRelatedCache = $relModSharArr;
84
		}
85
		return static::$datashareRelatedCache;
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::datashareRelatedCache also could return the type true which is incompatible with the documented return type array.
Loading history...
86
	}
87
88
	protected static $defaultSharingActionCache = false;
89 2
90
	/**
91 2
	 * This Function returns the Default Organisation Sharing Action Array for all modules.
92 1
	 *
93 1
	 * @return array
94
	 */
95 2
	public static function getAllDefaultSharingAction()
96
	{
97
		if (false === static::$defaultSharingActionCache) {
98
			Log::trace('getAllDefaultSharingAction');
99
			static::$defaultSharingActionCache = array_map('intval', (new \App\Db\Query())->select(['tabid', 'permission'])->from('vtiger_def_org_share')->createCommand()->queryAllByGroup(0));
100
		}
101
		return static::$defaultSharingActionCache;
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::defaultSharingActionCache also could return the type true which is incompatible with the documented return type array.
Loading history...
102
	}
103
104
	/**
105 3
	 * Function to get the vtiger_role related user ids.
106
	 *
107 3
	 * @param string $roleId Role ID
108
	 *
109
	 * @return array $users Role related user array
110 3
	 */
111 3
	public static function getUsersByRole($roleId): array
112 3
	{
113 3
		if (Cache::has('getUsersByRole', $roleId)) {
114
			return Cache::get('getUsersByRole', $roleId);
115
		}
116
		$users = static::getQueryToUsersByRole($roleId)->column();
117
		$users = array_map('intval', $users);
118
		Cache::save('getUsersByRole', $roleId, $users);
119
		return $users;
120
	}
121
122
	/**
123 2
	 * Function to get the users names by role.
124
	 *
125 2
	 * @param int $roleId
126
	 *
127
	 * @return array $users
128 2
	 */
129 2
	public static function getUsersNameByRole($roleId)
130 2
	{
131 1
		if (Cache::has('getUsersNameByRole', $roleId)) {
132 1
			return Cache::get('getUsersNameByRole', $roleId);
133
		}
134
		$users = static::getUsersByRole($roleId);
135 2
		$roleRelatedUsers = [];
136 2
		if ($users) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $users of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
137
			foreach ($users as $userId) {
138
				$roleRelatedUsers[$userId] = Fields\Owner::getUserLabel($userId);
139
			}
140
		}
141
		Cache::save('getUsersNameByRole', $roleId, $roleRelatedUsers);
142
		return $roleRelatedUsers;
143
	}
144 14
145
	/**
146 14
	 * Function to get the role related user ids.
147 2
	 *
148
	 * @param int $userId RoleId :: Type varchar
149 14
	 */
150 14
	public static function getRoleByUsers($userId)
151 14
	{
152 14
		if (Cache::has('getRoleByUsers', $userId)) {
153 14
			return Cache::get('getRoleByUsers', $userId);
154
		}
155
		$roleId = (new \App\Db\Query())->select(['roleid'])
156
			->from('vtiger_user2role')->where(['userid' => $userId])
157
			->scalar();
158
		Cache::save('getRoleByUsers', $userId, $roleId);
159
		return $roleId;
160
	}
161
162
	/**
163 14
	 * Function to get user groups.
164
	 *
165 14
	 * @param int $userId
166
	 *
167
	 * @return array - groupId's
168 14
	 */
169 14
	public static function getUserGroups($userId)
170 14
	{
171 14
		if (Cache::has('UserGroups', $userId)) {
172
			return Cache::get('UserGroups', $userId);
173
		}
174
		$groupIds = (new \App\Db\Query())->select(['groupid'])->from('vtiger_users2group')->where(['userid' => $userId])->column();
175
		$groupIds = array_map('intval', $groupIds);
176
		Cache::save('UserGroups', $userId, $groupIds);
177
		return $groupIds;
178
	}
179
180
	/**
181 5778
	 * This function is to retreive the vtiger_profiles associated with the  the specified role.
182
	 *
183 5778
	 * @param string $roleId
184 5778
	 *
185 5771
	 * @return array
186
	 */
187 14
	public static function getProfilesByRole($roleId)
188 14
	{
189 14
		$profiles = Cache::staticGet('getProfilesByRole', $roleId);
190 14
		if ($profiles) {
191 14
			return $profiles;
192 14
		}
193 14
		$profiles = (new \App\Db\Query())
194 14
			->select(['profileid'])
195
			->from('vtiger_role2profile')
196
			->where(['roleid' => $roleId])
197
			->column();
198
		$profiles = array_map('intval', $profiles);
199
		Cache::staticSave('getProfilesByRole', $roleId, $profiles);
200
		return $profiles;
201
	}
202
203
	/**
204 2
	 *  This function is to retreive the vtiger_profiles associated with the  the specified user.
205
	 *
206 2
	 * @param int $userId
207
	 *
208 2
	 * @return array
209
	 */
210
	public static function getProfilesByUser($userId)
211
	{
212
		$roleId = static::getRoleByUsers($userId);
213
214
		return static::getProfilesByRole($roleId);
215
	}
216
217
	const MEMBER_TYPE_USERS = 'Users';
218
	const MEMBER_TYPE_GROUPS = 'Groups';
219
	const MEMBER_TYPE_ROLES = 'Roles';
220
	const MEMBER_TYPE_ROLE_AND_SUBORDINATES = 'RoleAndSubordinates';
221
222
	protected static $membersCache = false;
223
224
	/**
225
	 * Function to get all members.
226
	 *
227
	 * @return array
228
	 */
229
	public static function getMembers()
230
	{
231
		if (false === static::$membersCache) {
232
			$members = [];
233
			$owner = new \App\Fields\Owner();
234
			foreach ($owner->initUsers() as $id => $user) {
235
				$members[static::MEMBER_TYPE_USERS][static::MEMBER_TYPE_USERS . ':' . $id] = ['name' => $user['fullName'], 'id' => $id, 'type' => static::MEMBER_TYPE_USERS];
236
			}
237
			foreach ($owner->getGroups(false) as $id => $groupName) {
238
				$members[static::MEMBER_TYPE_GROUPS][static::MEMBER_TYPE_GROUPS . ':' . $id] = ['name' => $groupName, 'id' => $id, 'type' => static::MEMBER_TYPE_GROUPS];
239
			}
240
			foreach (\Settings_Roles_Record_Model::getAll() as $id => $roleModel) {
241
				$members[static::MEMBER_TYPE_ROLES][static::MEMBER_TYPE_ROLES . ':' . $id] = ['name' => $roleModel->getName(), 'id' => $id, 'type' => static::MEMBER_TYPE_ROLES];
242
				$members[static::MEMBER_TYPE_ROLE_AND_SUBORDINATES][static::MEMBER_TYPE_ROLE_AND_SUBORDINATES . ':' . $id] = ['name' => $roleModel->getName(), 'id' => $id, 'type' => static::MEMBER_TYPE_ROLE_AND_SUBORDINATES];
243
			}
244
			static::$membersCache = $members;
245
		}
246
		return static::$membersCache;
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::membersCache also could return the type true which is incompatible with the documented return type array.
Loading history...
247
	}
248
249
	/**
250 1
	 * Get list of users based on members, eg. Users:2, Roles:H2.
251
	 *
252 1
	 * @param string $member
253
	 *
254
	 * @return array
255 1
	 */
256 1
	public static function getUserByMember($member)
257 1
	{
258 1
		if (Cache::has('getUserByMember', $member)) {
259 1
			return Cache::get('getUserByMember', $member);
260 1
		}
261 1
		[$type, $id] = explode(':', $member);
262 1
		$users = [];
263 1
		switch ($type) {
264 1
			case 'Users':
265 1
				$users[] = (int) $id;
266 1
				break;
267 1
			case 'Groups':
268 1
				$users = array_merge($users, static::getUsersByGroup($id));
0 ignored issues
show
$id of type string is incompatible with the type integer expected by parameter $groupId of App\PrivilegeUtil::getUsersByGroup(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

268
				$users = array_merge($users, static::getUsersByGroup(/** @scrutinizer ignore-type */ $id));
Loading history...
269 1
				break;
270
			case 'Roles':
271
				$users = array_merge($users, static::getUsersByRole($id));
272
				break;
273 1
			case 'RoleAndSubordinates':
274 1
				$users = array_merge($users, static::getUsersByRoleAndSubordinate($id));
275 1
				break;
276
			default:
277
				break;
278
		}
279
		$users = array_unique($users);
280
		Cache::save('getUserByMember', $member, $users, Cache::LONG);
281
		return $users;
282
	}
283
284
	/**
285
	 * Get list of users based on group id.
286
	 *
287 1
	 * @param int        $groupId
288
	 * @param array|bool $subGroups
289 1
	 * @param int        $i
290 1
	 *
291
	 * @return array
292
	 */
293
	public static function getUsersByGroup($groupId, $subGroups = false, $i = 0)
294 1
	{
295
		$cacheKey = $groupId . (false === $subGroups ? '' : '#');
296 1
		if (Cache::has('getUsersByGroup', $cacheKey)) {
297 1
			return Cache::get('getUsersByGroup', $cacheKey);
298 1
		}
299 1
		if (false === $subGroups) {
300
			$users = static::getQueryToUsersByGroup($groupId)->column();
301
		} else {
302 1
			$users = static::getQueryToUsersByGroup($groupId, false)->column();
303 1
			if ($i < self::GROUP_LOOP_LIMIT) {
304 1
				++$i;
305 1
				if (true === $subGroups) {
306
					$subGroups = [];
307 1
				}
308 1
				$dataReader = (new \App\Db\Query())->select(['containsgroupid'])->from('vtiger_group2grouprel')->where(['groupid' => $groupId])->createCommand()->query();
309
				$containsGroups = [];
310
				while ($containsGroupId = $dataReader->readColumn(0)) {
311
					$roleUsers = static::getUsersByGroup($containsGroupId, $subGroups, $i);
312 1
					$containsGroups = array_merge($containsGroups, $roleUsers['users']);
313 1
					if (!isset($subGroups[$containsGroupId])) {
314 1
						$subGroups[$containsGroupId] = $containsGroups;
315
					}
316
					foreach ($roleUsers['subGroups'] as $key => $value) {
317
						if (!isset($subGroups[$key])) {
318
							$subGroups[$key] = $containsGroups;
319
						}
320
					}
321
				}
322
				if ($containsGroups) {
323
					$users = array_merge($users, $containsGroups);
324
				}
325
			} else {
326
				Log::error('Exceeded the recursive limit, a loop might have been created. Group ID:' . $groupId);
327
			}
328
		}
329
		$users = array_unique($users);
330 1
		$return = (false === $subGroups ? $users : ['users' => $users, 'subGroups' => $subGroups]);
331
		Cache::save('getUsersByGroup', $cacheKey, $return, Cache::LONG);
332
		return $return;
333
	}
334
335
	/**
336 1
	 * Gets query to users by members.
337 1
	 *
338 1
	 * @param array $members
339 1
	 *
340
	 * @return Db\Query
341
	 */
342
	public static function getQueryToUsersByMembers(array $members): Db\Query
343
	{
344
		$queryGenerator = (new \App\QueryGenerator('Users'))->setFields(['id']);
345
		$columName = $queryGenerator->getColumnName('id');
346
		$conditions = ['or'];
347
		foreach ($members as $member) {
348
			[$type, $id] = explode(':', $member);
349 1
			switch ($type) {
350
					case self::MEMBER_TYPE_USERS:
351 1
						if (!isset($conditions[$type])) {
352
							$conditions[$type][$columName] = [(int) $id];
353
						} else {
354 1
							$conditions[$type][$columName][] = (int) $id;
355 1
						}
356 1
						break;
357 1
					case self::MEMBER_TYPE_GROUPS:
358 1
						$conditions[] = [$columName => (new \App\Db\Query())->select(['userid'])->from(["condition_{$type}_{$id}_" . \App\Layout::getUniqueId() => self::getQueryToUsersByGroup((int) $id)])];
359 1
						break;
360
					case self::MEMBER_TYPE_ROLES:
361 1
						$conditions[] = [$columName => self::getQueryToUsersByRole($id)];
362
						break;
363
					case self::MEMBER_TYPE_ROLE_AND_SUBORDINATES:
364
						$conditions[] = [$columName => self::getQueryToUsersByRoleAndSubordinate($id)];
365
						break;
366
					default:
367
						break;
368
				}
369
		}
370
		if (\count($conditions) <= 1) {
371 5788
			$conditions[] = [$columName => -1];
372
		}
373 5788
374 5782
		return $queryGenerator->setFields(['id'])->addNativeCondition(array_values($conditions))->createQuery();
375
	}
376 20
377 20
	/**
378 20
	 * Gets query to users by group.
379 20
	 *
380 20
	 * @param int  $groupId
381 20
	 * @param bool $recursive
382 20
	 * @param int  $depth
383
	 *
384 20
	 * @return Db\Query
385 20
	 */
386
	public static function getQueryToUsersByGroup(int $groupId, bool $recursive = true, int $depth = 0): Db\Query
387
	{
388
		++$depth;
389
		$query = (new \App\Db\Query())->select(['userid'])->from('vtiger_users2group')->where(['groupid' => $groupId])
390
			->union(
391
			(new \App\Db\Query())->select(['vtiger_user2role.userid'])
392
				->from('vtiger_group2role')
393
				->innerJoin('vtiger_user2role', 'vtiger_group2role.roleid=vtiger_user2role.roleid')->where(['groupid' => $groupId])
394
			)
395 4
			->union(
396
			(new \App\Db\Query())->select(['vtiger_user2role.userid'])->from('vtiger_group2rs')
397 4
				->innerJoin('vtiger_role', "vtiger_group2rs.roleandsubid=vtiger_role.roleid OR vtiger_role.parentrole like CONCAT('%', vtiger_group2rs.roleandsubid, '::%')")
398 4
				->innerJoin('vtiger_user2role', 'vtiger_role.roleid=vtiger_user2role.roleid')
399
				->where(['vtiger_group2rs.groupid' => $groupId])
400
			);
401
		if ($recursive) {
402
			if ($depth < self::GROUP_LOOP_LIMIT) {
403
				$dataReader = (new \App\Db\Query())->select(['containsgroupid'])->from('vtiger_group2grouprel')->where(['groupid' => $groupId])->createCommand()->query();
404
				while ($containsGroupId = $dataReader->readColumn(0)) {
405
					$query->union((new \App\Db\Query())->select(['userid'])->from(["query_{$groupId}_{$containsGroupId}_{$depth}" => static::getQueryToUsersByGroup($containsGroupId, $recursive, $depth)]));
406
				}
407
				$dataReader->close();
408
			} else {
409 14
				Log::error('Exceeded the recursive limit, a loop might have been created. Group ID:' . $groupId);
410
			}
411 14
		}
412 14
		return $query;
413
	}
414
415
	/**
416
	 * Gets query to users by role.
417
	 *
418
	 * @param string $roleId
419
	 *
420
	 * @return Db\Query
421
	 */
422 2
	public static function getQueryToUsersByRole(string $roleId): Db\Query
423
	{
424 2
		return (new \App\Db\Query())->select(['userid'])->from('vtiger_user2role')->where(['roleid' => $roleId]);
425
	}
426
427 2
	/**
428 2
	 * Gets query to users by role and subordinate.
429 2
	 *
430 2
	 * @param string $roleId
431 2
	 *
432 2
	 * @return Db\Query
433 2
	 */
434 2
	public static function getQueryToUsersByRoleAndSubordinate(string $roleId): Db\Query
435
	{
436
		$parentRole = static::getRoleDetail($roleId)['parentrole'] ?? '-';
437
		return (new \App\Db\Query())->select(['vtiger_user2role.userid'])->from('vtiger_user2role')
438
			->innerJoin('vtiger_role', 'vtiger_user2role.roleid = vtiger_role.roleid')
439
			->where(['or', ['vtiger_role.parentrole' => $parentRole], ['like', 'vtiger_role.parentrole', "{$parentRole}::%", false]]);
440
	}
441
442
	/**
443
	 * Function to get the roles and subordinate users.
444 1
	 *
445
	 * @param string $roleId
446 1
	 *
447 1
	 * @return array
448
	 */
449
	public static function getUsersByRoleAndSubordinate($roleId)
450 1
	{
451 1
		if (Cache::has('getUsersByRoleAndSubordinate', $roleId)) {
452 1
			return Cache::get('getUsersByRoleAndSubordinate', $roleId);
453 1
		}
454 1
		$users = static::getQueryToUsersByRoleAndSubordinate($roleId)->column();
455
		$users = array_map('intval', $users);
456
		Cache::save('getUsersByRoleAndSubordinate', $roleId, $users, Cache::LONG);
457
458
		return $users;
459
	}
460
461
	/**
462
	 * Function to get the vtiger_role information of the specified vtiger_role.
463
	 *
464 1
	 * @param $roleId
465
	 *
466 1
	 * @return array|bool|string
467
	 */
468
	public static function getRoleDetail($roleId)
469 1
	{
470 1
		if (Cache::has('RoleDetail', $roleId)) {
471 1
			return Cache::get('RoleDetail', $roleId);
472 1
		}
473 1
		$row = (new Db\Query())->from('vtiger_role')->where(['roleid' => $roleId])->one();
474
		if ($row) {
475
			$parentRoleArr = explode('::', $row['parentrole']);
476
			array_pop($parentRoleArr);
477
			$row['parentRoles'] = $parentRoleArr;
478
			$immediateParent = array_pop($parentRoleArr);
479
			$row['immediateParent'] = $immediateParent;
480
		}
481
		Cache::save('RoleDetail', $roleId, $row);
482
		return $row;
483 2
	}
484
485 2
	/**
486
	 * Function to get the role name.
487
	 *
488 2
	 * @param int $roleId
489 2
	 *
490 2
	 * @return string
491 2
	 */
492 1
	public static function getRoleName($roleId)
493 1
	{
494
		$roleInfo = static::getRoleDetail($roleId);
495
		return $roleInfo['rolename'];
496
	}
497
498
	/**
499
	 * To retreive the parent vtiger_role of the specified vtiger_role.
500
	 *
501
	 * @param $roleid -- The Role Id:: Type varchar
0 ignored issues
show
Documentation Bug introduced by
The doc comment -- at position 0 could not be parsed: Unknown type name '--' at position 0 in --.
Loading history...
502
	 * @param mixed $roleId
503
	 *
504
	 * @return parent vtiger_role array in the following format:
505 2
	 */
506 2
	public static function getParentRole($roleId)
507
	{
508
		$roleInfo = static::getRoleDetail($roleId);
509
		return $roleInfo['parentRoles'];
510
	}
511
512
	/**
513
	 * To retreive the subordinate vtiger_roles of the specified parent vtiger_role.
514
	 *
515
	 * @param int $roleId
516 2
	 *
517
	 * @return array
518 2
	 */
519
	public static function getRoleSubordinates($roleId)
520
	{
521 2
		if (Cache::has('getRoleSubordinates', $roleId)) {
522 2
			return Cache::get('getRoleSubordinates', $roleId);
523 2
		}
524 1
		$roleDetails = static::getRoleDetail($roleId);
525 1
		$roleSubordinates = (new \App\Db\Query())
526
			->select(['roleid'])
527
			->from('vtiger_role')
528
			->where(['like', 'parentrole', $roleDetails['parentrole'] . '::%', false])
529
			->column();
530
		Cache::save('getRoleSubordinates', $roleId, $roleSubordinates, Cache::LONG);
531
		return $roleSubordinates;
532
	}
533
534
	/**
535
	 * Function to get the Profile Tab Permissions for the specified vtiger_profileid.
536
	 *
537 2
	 * @param int $profileid
538 2
	 *
539 2
	 * @return int[]
540
	 */
541 2
	public static function getProfileTabsPermission($profileid)
542 2
	{
543
		Log::trace('Entering getProfileTabsPermission(' . $profileid . ') method ...');
544
		if (Cache::has('getProfileTabsPermission', $profileid)) {
545
			return Cache::get('getProfileTabsPermission', $profileid);
546
		}
547
		$profileData = (new Db\Query())->select(['tabid', 'permissions'])->from('vtiger_profile2tab')->where(['profileid' => $profileid])->createCommand()->queryAllByGroup(0);
548
		$profileData = array_map('intval', $profileData);
549
		Cache::save('getProfileTabsPermission', $profileid, $profileData);
550
		Log::trace('Exiting getProfileTabsPermission method ...');
551
		return $profileData;
552 1
	}
553
554 1
	/**
555 1
	 * Function to get the Profile Global Information for the specified vtiger_profileid.
556 1
	 *
557 1
	 * @param int $profileid
558 1
	 *
559
	 * @return int[]
560 1
	 */
561
	public static function getProfileGlobalPermission($profileid)
562
	{
563
		if (Cache::has('getProfileGlobalPermission', $profileid)) {
564
			return Cache::get('getProfileGlobalPermission', $profileid);
565
		}
566
		$profileData = (new Db\Query())->select(['globalactionid', 'globalactionpermission'])->from('vtiger_profile2globalpermissions')
567
			->where(['profileid' => $profileid])->createCommand()->queryAllByGroup(0);
568
		$profileData = array_map('intval', $profileData);
569
		Cache::save('getProfileGlobalPermission', $profileid, $profileData);
570 1
		return $profileData;
571
	}
572 1
573 1
	/**
574 1
	 * To retreive the global permission of the specifed user from the various vtiger_profiles associated with the user.
575 1
	 *
576 1
	 * @param int $userId
577
	 *
578 1
	 * @return int[]
579
	 */
580
	public static function getCombinedUserGlobalPermissions($userId)
581
	{
582
		if (Cache::staticHas('getCombinedUserGlobalPermissions', $userId)) {
583
			return Cache::staticGet('getCombinedUserGlobalPermissions', $userId);
584
		}
585
		$userGlobalPerrArr = [];
586
		$profArr = static::getProfilesByUser($userId);
587
		$profileId = array_shift($profArr);
588 1
		if ($profileId) {
589
			$userGlobalPerrArr = static::getProfileGlobalPermission($profileId);
590 1
			foreach ($profArr as $profileId) {
591
				$tempUserGlobalPerrArr = static::getProfileGlobalPermission($profileId);
592
				foreach ($userGlobalPerrArr as $globalActionId => $globalActionPermission) {
593 1
					if (1 === $globalActionPermission) {
594 1
						$permission = $tempUserGlobalPerrArr[$globalActionId];
595 1
						if (0 === $permission) {
596 1
							$userGlobalPerrArr[$globalActionId] = $permission;
597 1
						}
598 1
					}
599
				}
600 1
			}
601
		}
602 1
		Cache::staticSave('getCombinedUserGlobalPermissions', $userId, $userGlobalPerrArr);
603 1
		return $userGlobalPerrArr;
604
	}
605
606
	/**
607
	 * To retreive the vtiger_tab permissions of the specifed user from the various vtiger_profiles associated with the user.
608
	 *
609
	 * @param int $userId
610
	 *
611
	 * @return array
612
	 */
613 2
	public static function getCombinedUserModulesPermissions($userId)
614
	{
615 2
		if (Cache::staticHas('getCombinedUserModulesPermissions', $userId)) {
616 2
			return Cache::staticGet('getCombinedUserModulesPermissions', $userId);
617 2
		}
618 1
		$profArr = static::getProfilesByUser($userId);
619 1
		$profileId = array_shift($profArr);
620
		if ($profileId) {
621 2
			$userTabPerrArr = static::getProfileTabsPermission($profileId);
622 2
			foreach ($profArr as $profileId) {
623
				$tempUserTabPerrArr = static::getProfileTabsPermission($profileId);
624
				foreach ($userTabPerrArr as $tabId => $tabPermission) {
625
					if (1 === $tabPermission) {
626
						$permission = $tempUserTabPerrArr[$tabId];
627
						if (0 === $permission) {
628
							$userTabPerrArr[$tabId] = $permission;
629
						}
630
					}
631
				}
632
			}
633
		}
634
		$homeId = Module::getModuleId('Home');
635
		if (!isset($userTabPerrArr[$homeId])) {
636 2
			$dashBoardId = Module::getModuleId('Dashboard');
637
			$userTabPerrArr[$homeId] = $userTabPerrArr[$dashBoardId] ?? 1;
638
		}
639
		Cache::staticSave('getCombinedUserModulesPermissions', $userId, $userTabPerrArr);
640
		return $userTabPerrArr;
641
	}
642
643
	/**
644
	 * Function to get all the vtiger_tab utility action permission for the specified vtiger_profile.
645
	 *
646
	 * @param int $profileid
647
	 *
648
	 * @return array
649
	 */
650
	public static function getUtilityPermissions($profileid)
651
	{
652
		$permissions = [];
653
		$dataReader = (new Db\Query())->from('vtiger_profile2utility')
654
			->where(['profileid' => $profileid])->createCommand()->query();
655
		while ($row = $dataReader->read()) {
656
			$permissions[$row['tabid']][$row['activityid']] = (int) $row['permission'];
657
		}
658
		return $permissions;
659
	}
660
661
	/**
662
	 * Function to get the Profile Action Permissions for the specified vtiger_profileid.
663
	 *
664
	 * @param int $profileid
665
	 *
666
	 * @return array
667
	 */
668 2
	public static function getStandardPermissions($profileid)
669
	{
670 2
		$permissions = [];
671 2
		$dataReader = (new Db\Query())->from('vtiger_profile2standardpermissions')
672
			->where(['profileid' => $profileid])->createCommand()->query();
673
		while ($row = $dataReader->read()) {
674 2
			$permissions[$row['tabid']][$row['operation']] = (int) $row['permissions'];
675 2
		}
676 2
		return $permissions;
677 2
	}
678 2
679 2
	/**
680
	 * Function to get the Standard and Utility Profile Action Permissions for the specified vtiger_profileid.
681 2
	 *
682 2
	 * @param int $profileid
683 2
	 *
684
	 * @return array
685
	 */
686
	public static function getAllProfilePermissions($profileid)
687
	{
688
		if (Cache::staticHas(__METHOD__, $profileid)) {
689
			return Cache::staticGet(__METHOD__, $profileid);
690
		}
691
		$allActions = static::getStandardPermissions($profileid);
692
		$utilityActions = static::getUtilityPermissions($profileid);
693
		foreach ($utilityActions as $tabid => $utilityAction) {
694
			$actionTabs = $allActions[$tabid] ?? [];
695
			foreach ($utilityAction as $utilityId => $utilityPermission) {
696
				$actionTabs[$utilityId] = (int) $utilityPermission;
697
			}
698 2
			$allActions[$tabid] = $actionTabs;
699
		}
700 2
		Cache::staticSave(__METHOD__, $profileid, $allActions);
701 2
		return $allActions;
702 2
	}
703 2
704 2
	/**
705
	 * To retreive the vtiger_tab acion permissions of the specifed user from the various vtiger_profiles associated with the user.
706 2
	 *
707
	 * @param int $userId
708 2
	 *
709 2
	 * @return array
710
	 */
711 2
	public static function getCombinedUserActionsPermissions($userId)
712
	{
713
		$profiles = static::getProfilesByUser($userId);
714
		$actionPermissions = [];
715
		if (isset($profiles[0])) {
716
			$actionPermissions = static::getAllProfilePermissions($profiles[0]);
717
			unset($profiles[0]);
718
		}
719
		if (\is_array($profiles)) {
0 ignored issues
show
The condition is_array($profiles) is always true.
Loading history...
720
			foreach ($profiles as $profileId) {
721
				$tempActionPerrArr = static::getAllProfilePermissions($profileId);
722
				foreach ($actionPermissions as $tabId => $permissionsInModule) {
723
					foreach ($permissionsInModule as $actionId => $permission) {
724
						if (1 == $permission) {
725
							$nowPermission = $tempActionPerrArr[$tabId][$actionId];
726
							if (0 == $nowPermission && '' != $nowPermission) {
727
								$actionPermissions[$tabId][$actionId] = $nowPermission;
728
							}
729
						}
730 2
					}
731 2
				}
732 2
			}
733 1
		}
734
		return $actionPermissions;
735
	}
736 2
737 2
	protected static $dataShareStructure = [
738
		'role2role' => ['vtiger_datashare_role2role', 'to_roleid'],
739
		'role2rs' => ['vtiger_datashare_role2rs', 'to_roleandsubid'],
740
		'role2group' => ['vtiger_datashare_role2group', 'to_groupid'],
741
		'role2user' => ['vtiger_datashare_role2us', 'to_userid'],
742
		'rs2role' => ['vtiger_datashare_rs2role', 'to_roleid'],
743
		'rs2rs' => ['vtiger_datashare_rs2rs', 'to_roleandsubid'],
744
		'rs2group' => ['vtiger_datashare_rs2grp', 'to_groupid'],
745
		'rs2user' => ['vtiger_datashare_rs2us', 'to_userid'],
746
		'group2role' => ['vtiger_datashare_grp2role', 'to_roleid'],
747
		'group2rs' => ['vtiger_datashare_grp2rs', 'to_roleandsubid'],
748
		'group2user' => ['vtiger_datashare_grp2us', 'to_userid'],
749
		'group2group' => ['vtiger_datashare_grp2grp', 'to_groupid'],
750
		'user2user' => ['vtiger_datashare_us2us', 'to_userid'],
751
		'user2group' => ['vtiger_datashare_us2grp', 'to_groupid'],
752
		'user2role' => ['vtiger_datashare_us2role', 'to_roleid'],
753
		'user2rs' => ['vtiger_datashare_us2rs', 'to_roleandsubid'],
754
	];
755
756 2
	/**
757 2
	 * Get data share.
758 1
	 *
759
	 * @param int   $tabId
760 2
	 * @param int   $roleId
761 2
	 * @param mixed $type
762
	 * @param mixed $data
763
	 *
764
	 * @return array
765
	 */
766
	public static function getDatashare($type, $tabId, $data)
767
	{
768
		$cacheKey = "$type|$tabId|" . (\is_array($data) ? implode(',', $data) : $data);
769
		if (Cache::staticHas('getDatashare', $cacheKey)) {
770
			return Cache::staticGet('getDatashare', $cacheKey);
771
		}
772
		$structure = static::$dataShareStructure[$type];
773
		$query = (new \App\Db\Query())->select([$structure[0] . '.*'])->from($structure[0])
774
			->innerJoin('vtiger_datashare_module_rel', "$structure[0].shareid = vtiger_datashare_module_rel.shareid")
775
			->where(['vtiger_datashare_module_rel.tabid' => $tabId]);
776
		if ($data) {
777
			$query->andWhere([$structure[1] => $data]);
778
		}
779
		$rows = $query->all();
780
		Cache::staticSave('getDatashare', $cacheKey, $rows);
781 2
		return $rows;
782 2
	}
783
784
	/**
785
	 * Gives an array which contains the information for what all roles, groups and user data is to be shared with the spcified user for the specified module.
786
	 *
787
	 * @param string $module            module name
788
	 * @param int    $userid            user id
789
	 * @param array  $defOrgShare       default organization sharing permission array
790
	 * @param string $currentUserRoles  roleid
791
	 * @param string $parentRoles       parent roles
792
	 * @param int    $currentUserGroups user id
793
	 *
794
	 * @return array array which contains the id of roles,group and users data shared with specifed user for the specified module
795
	 */
796
	public static function getUserModuleSharingObjects($module, $userid, $defOrgShare, $currentUserRoles, $parentRoles, $currentUserGroups)
797
	{
798
		$modTabId = Module::getModuleId($module);
799
		$modShareWritePermission = $modShareReadPermission = ['ROLE' => [], 'GROUP' => []];
800 2
		$modDefOrgShare = null;
801
		if (isset($defOrgShare[$modTabId])) {
802
			$modDefOrgShare = $defOrgShare[$modTabId];
803
		}
804
		$shareIdMembers = [];
805
		//If Sharing of leads is Private
806
		if (3 === $modDefOrgShare || 0 === $modDefOrgShare) {
807
			$roleWritePer = $roleWritePer = $grpReadPer = $grpWritePer = $roleReadPer = [];
0 ignored issues
show
The assignment to $roleWritePer is dead and can be removed.
Loading history...
808
			//Retreiving from vtiger_role to vtiger_role
809
			foreach (static::getDatashare('role2role', $modTabId, $currentUserRoles) as $row) {
810
				$shareRoleId = $row['share_roleid'];
811
				$shareIdRoles = [];
812
				$shareIdRoles[] = $shareRoleId;
813
				$shareIdMembers[$row['shareid']] = ['ROLE' => $shareIdRoles];
814
				if (1 === (int) $row['permission']) {
815
					if (3 === $modDefOrgShare && !isset($roleReadPer[$shareRoleId])) {
816
						$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
817
					}
818
					if (!isset($roleWritePer[$shareRoleId])) {
819
						$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
820 2
					}
821
				} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
822
					if (!isset($roleReadPer[$shareRoleId])) {
823
						$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
824
					}
825
				}
826
			}
827
			//Retreiving from role to rs
828
			$parRoleList = [];
829
			if (\is_array($parentRoles)) {
0 ignored issues
show
The condition is_array($parentRoles) is always false.
Loading history...
830
				foreach ($parentRoles as $par_role_id) {
831
					$parRoleList[] = $par_role_id;
832
				}
833
			}
834
			$parRoleList[] = $currentUserRoles;
835
			foreach (static::getDatashare('role2rs', $modTabId, $parRoleList) as $row) {
836
				$shareRoleId = $row['share_roleid'];
837
				$shareIdRoles = [];
838
				$shareIdRoles[] = $shareRoleId;
839
				$shareIdMembers[$row['shareid']] = ['ROLE' => $shareIdRoles];
840 2
				if (1 === (int) $row['permission']) {
841
					if (3 === $modDefOrgShare && !isset($roleReadPer[$shareRoleId])) {
842
						$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
843
					}
844
					if (!isset($roleWritePer[$shareRoleId])) {
845
						$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
846
					}
847
				} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
848
					if (!isset($roleReadPer[$shareRoleId])) {
849
						$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
850
					}
851
				}
852
			}
853
			//Get roles from Role2Grp
854
			$groupList = $currentUserGroups;
855
			if (empty($groupList)) {
856
				$groupList = [0];
857
			}
858
			if ($groupList) {
859
				foreach (static::getDatashare('role2group', $modTabId, $groupList) as $row) {
860 2
					$shareRoleId = $row['share_roleid'];
861
					$shareIdRoles = [];
862
					$shareIdRoles[] = $shareRoleId;
863
					$shareIdMembers[$row['shareid']] = ['ROLE' => $shareIdRoles];
864
					if (1 === (int) $row['permission']) {
865
						if (3 === $modDefOrgShare && !isset($roleReadPer[$shareRoleId])) {
866
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
867
						}
868
						if (!isset($roleWritePer[$shareRoleId])) {
869
							$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
870
						}
871
					} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
872
						if (!isset($roleReadPer[$shareRoleId])) {
873
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
874
						}
875
					}
876
				}
877
			}
878
			//Get roles from Role2Us
879 2
			if (!empty($userid)) {
880 2
				foreach (static::getDatashare('role2user', $modTabId, $userid) as $row) {
881
					$shareRoleId = $row['share_roleid'];
882
					$shareIdRoles = [];
883 2
					$shareIdRoles[] = $shareRoleId;
884
					$shareIdMembers[$row['shareid']] = ['ROLE' => $shareIdRoles];
885
					if (1 === (int) $row['permission']) {
886
						if (3 === $modDefOrgShare && !isset($roleReadPer[$shareRoleId])) {
887
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
888
						}
889
						if (!isset($roleWritePer[$shareRoleId])) {
890
							$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
891
						}
892
					} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare && !isset($roleReadPer[$shareRoleId])) {
893
						$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
894
					}
895
				}
896
			}
897
			//Retreiving from rs to vtiger_role
898
			foreach (static::getDatashare('rs2role', $modTabId, $currentUserRoles) as $row) {
899
				$shareRoleIds = static::getRoleSubordinates($row['share_roleandsubid']);
900
				$shareRoleIds[] = $row['share_roleandsubid'];
901
				foreach ($shareRoleIds as $shareRoleId) {
902
					if (1 === (int) $row['permission']) {
903
						if (3 === $modDefOrgShare && !isset($roleReadPer[$shareRoleId])) {
904
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
905
						}
906
						if (!isset($roleWritePer[$shareRoleId])) {
907
							$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
908
						}
909
					} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
910
						if (!isset($roleReadPer[$shareRoleId])) {
911
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
912
						}
913
					}
914
				}
915
				$shareIdMembers[$row['shareid']] = ['ROLE' => $shareRoleIds];
916
			}
917
			//Retreiving from rs to rs
918
			foreach (static::getDatashare('rs2rs', $modTabId, $parRoleList) as $row) {
919
				$shareRoleIds = static::getRoleSubordinates($row['share_roleandsubid']);
920
				$shareRoleIds[] = $row['share_roleandsubid'];
921
				foreach ($shareRoleIds as $shareRoleId) {
922
					if (1 === (int) $row['permission']) {
923
						if (3 === $modDefOrgShare && !isset($roleReadPer[$shareRoleId])) {
924
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
925
						}
926
						if (!isset($roleWritePer[$shareRoleId])) {
927
							$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
928
						}
929 2
					} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
930
						if (!isset($roleReadPer[$shareRoleId])) {
931
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
932
						}
933
					}
934
				}
935
				$shareIdMembers[$row['shareid']] = ['ROLE' => $shareRoleIds];
936
			}
937
			//Get roles from Rs2Grp
938
			foreach (static::getDatashare('rs2group', $modTabId, $groupList) as $row) {
939
				$shareRoleIds = static::getRoleSubordinates($row['share_roleandsubid']);
940
				$shareRoleIds[] = $row['share_roleandsubid'];
941
				foreach ($shareRoleIds as $shareRoleId) {
942
					if (1 === (int) $row['permission']) {
943
						if (3 === $modDefOrgShare && !isset($roleReadPer[$shareRoleId])) {
944
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
945
						}
946
						if (!isset($roleWritePer[$shareRoleId])) {
947
							$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
948
						}
949
					} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
950
						if (!isset($roleReadPer[$shareRoleId])) {
951
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
952
						}
953
					}
954
				}
955
				$shareIdMembers[$row['shareid']] = ['ROLE' => $shareRoleIds];
956
			}
957
			//Get roles from Rs2Us
958
			foreach (static::getDatashare('rs2user', $modTabId, $userid) as $row) {
959
				$shareRoleIds = static::getRoleSubordinates($row['share_roleandsubid']);
960
				$shareRoleIds[] = $row['share_roleandsubid'];
961
				foreach ($shareRoleIds as $shareRoleId) {
962
					if (1 === (int) $row['permission']) {
963
						if (3 === $modDefOrgShare && !isset($roleReadPer[$shareRoleId])) {
964
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
965
						}
966
						if (!isset($roleWritePer[$shareRoleId])) {
967
							$roleWritePer[$shareRoleId] = static::getUsersByRole($shareRoleId);
968
						}
969
					} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
970
						if (!isset($roleReadPer[$shareRoleId])) {
971
							$roleReadPer[$shareRoleId] = static::getUsersByRole($shareRoleId);
972
						}
973
					}
974
				}
975 2
				$shareIdMembers[$row['shareid']] = ['ROLE' => $shareRoleIds];
976
			}
977
			$modShareReadPermission['ROLE'] = $roleReadPer;
978
			$modShareWritePermission['ROLE'] = $roleWritePer;
979
980
			//Retreiving from the grp2role sharing
981
			foreach (static::getDatashare('group2role', $modTabId, $currentUserRoles) as $row) {
982
				$shareGrpId = (int) $row['share_groupid'];
983
				$shareIdGrps = [];
984
				$shareIdGrps[] = $shareGrpId;
985
				if (1 === (int) $row['permission']) {
986
					if (3 === $modDefOrgShare && !isset($grpReadPer[$shareGrpId])) {
987
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
988
						$grpReadPer[$shareGrpId] = $usersByGroup['users'];
989
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
990
							if (!isset($grpReadPer[$subgrpid])) {
991
								$grpReadPer[$subgrpid] = $subgrpusers;
992
							}
993
							if (!\in_array($subgrpid, $shareIdGrps)) {
994
								$shareIdGrps[] = $subgrpid;
995
							}
996
						}
997
					}
998
					if (!isset($grpWritePer[$shareGrpId])) {
999
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1000
						$grpWritePer[$shareGrpId] = $usersByGroup['users'];
1001
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1002
							if (!isset($grpWritePer[$subgrpid])) {
1003
								$grpWritePer[$subgrpid] = $subgrpusers;
1004
							}
1005
							if (!\in_array($subgrpid, $shareIdGrps)) {
1006
								$shareIdGrps[] = $subgrpid;
1007
							}
1008
						}
1009
					}
1010
				} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
1011
					if (!isset($grpReadPer[$shareGrpId])) {
1012
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1013
						$grpReadPer[$shareGrpId] = $usersByGroup['users'];
1014
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1015
							if (!isset($grpReadPer[$subgrpid])) {
1016
								$grpReadPer[$subgrpid] = $subgrpusers;
1017
							}
1018
							if (!\in_array($subgrpid, $shareIdGrps)) {
1019
								$shareIdGrps[] = $subgrpid;
1020
							}
1021 2
						}
1022
					}
1023
				}
1024
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdGrps];
1025
			}
1026
			//Retreiving from the grp2rs sharing
1027
			foreach (static::getDatashare('group2rs', $modTabId, $parRoleList) as $row) {
1028
				$shareGrpId = (int) $row['share_groupid'];
1029
				$shareIdGrps = [];
1030
				$shareIdGrps[] = $shareGrpId;
1031
				if (1 === (int) $row['permission']) {
1032
					if (3 === $modDefOrgShare && !isset($grpReadPer[$shareGrpId])) {
1033
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1034
						$grpReadPer[$shareGrpId] = $usersByGroup['users'];
1035
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1036
							if (!isset($grpReadPer[$subgrpid])) {
1037
								$grpReadPer[$subgrpid] = $subgrpusers;
1038
							}
1039
							if (!\in_array($subgrpid, $shareIdGrps)) {
1040
								$shareIdGrps[] = $subgrpid;
1041
							}
1042
						}
1043
					}
1044
					if (!isset($grpWritePer[$shareGrpId])) {
1045
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1046
						$grpWritePer[$shareGrpId] = $usersByGroup['users'];
1047
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1048
							if (!isset($grpWritePer[$subgrpid])) {
1049
								$grpWritePer[$subgrpid] = $subgrpusers;
1050
							}
1051
							if (!\in_array($subgrpid, $shareIdGrps)) {
1052
								$shareIdGrps[] = $subgrpid;
1053
							}
1054
						}
1055
					}
1056
				} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
1057
					if (!isset($grpReadPer[$shareGrpId])) {
1058
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1059
						$grpReadPer[$shareGrpId] = $usersByGroup['users'];
1060
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1061
							if (!isset($grpReadPer[$subgrpid])) {
1062
								$grpReadPer[$subgrpid] = $subgrpusers;
1063
							}
1064
							if (!\in_array($subgrpid, $shareIdGrps)) {
1065
								$shareIdGrps[] = $subgrpid;
1066
							}
1067 2
						}
1068
					}
1069
				}
1070
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdGrps];
1071
			}
1072
			//Retreiving from the grp2us sharing
1073
			foreach (static::getDatashare('group2user', $modTabId, $userid) as $row) {
1074
				$shareGrpId = (int) $row['share_groupid'];
1075
				$shareIdGrps = [];
1076
				$shareIdGrps[] = $shareGrpId;
1077
				if (1 === (int) $row['permission']) {
1078
					if (3 === $modDefOrgShare && !isset($grpReadPer[$shareGrpId])) {
1079
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1080
						$grpReadPer[$shareGrpId] = $usersByGroup['users'];
1081
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1082
							if (!isset($grpReadPer[$subgrpid])) {
1083
								$grpReadPer[$subgrpid] = $subgrpusers;
1084
							}
1085
							if (!\in_array($subgrpid, $shareIdGrps)) {
1086 2
								$shareIdGrps[] = $subgrpid;
1087
							}
1088
						}
1089
					}
1090
					if (!isset($grpWritePer[$shareGrpId])) {
1091
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1092
						$grpWritePer[$shareGrpId] = $usersByGroup['users'];
1093
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1094
							if (!isset($grpWritePer[$subgrpid])) {
1095
								$grpWritePer[$subgrpid] = $subgrpusers;
1096
							}
1097
							if (!\in_array($subgrpid, $shareIdGrps)) {
1098
								$shareIdGrps[] = $subgrpid;
1099
							}
1100
						}
1101
					}
1102
				} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
1103
					if (!isset($grpReadPer[$shareGrpId])) {
1104
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1105 2
						$grpReadPer[$shareGrpId] = $usersByGroup['users'];
1106
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1107
							if (!isset($grpReadPer[$subgrpid])) {
1108
								$grpReadPer[$subgrpid] = $subgrpusers;
1109
							}
1110
							if (!\in_array($subgrpid, $shareIdGrps)) {
1111
								$shareIdGrps[] = $subgrpid;
1112
							}
1113
						}
1114
					}
1115
				}
1116
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdGrps];
1117
			}
1118
			//Retreiving from the grp2grp sharing
1119
			foreach (static::getDatashare('group2group', $modTabId, $groupList) as $row) {
1120
				$shareGrpId = (int) $row['share_groupid'];
1121
				$shareIdGrps = [];
1122
				$shareIdGrps[] = $shareGrpId;
1123
				if (1 === (int) $row['permission']) {
1124
					if (3 === $modDefOrgShare && !isset($grpReadPer[$shareGrpId])) {
1125 2
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1126
						$grpReadPer[$shareGrpId] = $usersByGroup['users'];
1127
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1128
							if (!isset($grpReadPer[$subgrpid])) {
1129
								$grpReadPer[$subgrpid] = $subgrpusers;
1130
							}
1131
							if (!\in_array($subgrpid, $shareIdGrps)) {
1132
								$shareIdGrps[] = $subgrpid;
1133
							}
1134
						}
1135
					}
1136
					if (!isset($grpWritePer[$shareGrpId])) {
1137
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1138
						$grpWritePer[$shareGrpId] = $usersByGroup['users'];
1139
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1140
							if (!isset($grpWritePer[$subgrpid])) {
1141
								$grpWritePer[$subgrpid] = $subgrpusers;
1142
							}
1143 2
							if (!\in_array($subgrpid, $shareIdGrps)) {
1144 2
								$shareIdGrps[] = $subgrpid;
1145
							}
1146
						}
1147 2
					}
1148 2
				} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
1149 2
					if (!isset($grpReadPer[$shareGrpId])) {
1150
						$usersByGroup = static::getUsersByGroup($shareGrpId, true);
1151
						$grpReadPer[$shareGrpId] = $usersByGroup['users'];
1152
						foreach ($usersByGroup['subGroups'] as $subgrpid => $subgrpusers) {
1153
							if (!isset($grpReadPer[$subgrpid])) {
1154
								$grpReadPer[$subgrpid] = $subgrpusers;
1155
							}
1156
							if (!\in_array($subgrpid, $shareIdGrps)) {
1157
								$shareIdGrps[] = $subgrpid;
1158
							}
1159
						}
1160 5778
					}
1161
				}
1162 5778
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdGrps];
1163 5767
			}
1164
			//Get roles from Us2Us
1165 14
			foreach (static::getDatashare('user2user', $modTabId, $userid) as $row) {
1166 14
				$shareUserId = (int) $row['share_userid'];
1167 14
				$shareIdUsers = [];
1168 14
				$shareIdUsers[] = $shareUserId;
1169 14
				if (1 === (int) $row['permission']) {
1170 14
					if (3 === $modDefOrgShare && !isset($grpReadPer[$shareUserId])) {
1171 14
						$grpReadPer[$shareUserId] = [$shareUserId];
1172 14
					}
1173 14
					if (!isset($grpWritePer[$shareUserId])) {
1174 13
						$grpWritePer[$shareUserId] = [$shareUserId];
1175
					}
1176 14
				} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
1177
					if (!isset($grpReadPer[$shareUserId])) {
1178
						$grpReadPer[$shareUserId] = [$shareUserId];
1179 14
					}
1180
				}
1181 14
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdUsers];
1182
			}
1183
			//Get roles from Us2Grp
1184
			foreach (static::getDatashare('user2group', $modTabId, $groupList) as $row) {
1185
				$shareUserId = (int) $row['share_userid'];
1186
				$shareIdUsers = [];
1187
				$shareIdUsers[] = $shareUserId;
1188
				if (1 === (int) $row['permission']) {
1189
					if (3 === $modDefOrgShare && !isset($grpReadPer[$shareUserId])) {
1190
						$grpReadPer[$shareUserId] = [$shareUserId];
1191
					}
1192 13
					if (!isset($grpWritePer[$shareUserId])) {
1193
						$grpWritePer[$shareUserId] = [$shareUserId];
1194 13
					}
1195 13
				} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
1196 13
					if (!isset($grpReadPer[$shareUserId])) {
1197 13
						$grpReadPer[$shareUserId] = [$shareUserId];
1198
					}
1199
				}
1200
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdUsers];
1201
			}
1202
			//Get roles from Us2role
1203 13
			foreach (static::getDatashare('user2role', $modTabId, $currentUserRoles) as $row) {
1204
				$shareUserId = (int) $row['share_userid'];
1205
				$shareIdUsers = [];
1206
				$shareIdUsers[] = $shareUserId;
1207
				if (1 === (int) $row['permission']) {
1208
					if (3 === $modDefOrgShare && !isset($grpReadPer[$shareUserId])) {
1209
						$grpReadPer[$shareUserId] = [$shareUserId];
1210
					}
1211
					if (!isset($grpWritePer[$shareUserId])) {
1212
						$grpWritePer[$shareUserId] = [$shareUserId];
1213
					}
1214
				} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
1215
					if (!isset($grpReadPer[$shareUserId])) {
1216
						$grpReadPer[$shareUserId] = [$shareUserId];
1217
					}
1218
				}
1219
1220
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdUsers];
1221
			}
1222
			//Get roles from Us2rs
1223
			foreach (static::getDatashare('user2rs', $modTabId, $parRoleList) as $row) {
1224
				$shareUserId = (int) $row['share_userid'];
1225
				$shareIdUsers = [];
1226
				$shareIdUsers[] = $shareUserId;
1227
				if (1 === (int) $row['permission']) {
1228
					if (3 === $modDefOrgShare && !isset($grpReadPer[$shareUserId])) {
1229
						$grpReadPer[$shareUserId] = [$shareUserId];
1230
					}
1231
					if (!isset($grpWritePer[$shareUserId])) {
1232
						$grpWritePer[$shareUserId] = [$shareUserId];
1233
					}
1234
				} elseif (0 === (int) $row['permission'] && 3 === $modDefOrgShare) {
1235
					if (!isset($grpReadPer[$shareUserId])) {
1236
						$grpReadPer[$shareUserId] = [$shareUserId];
1237
					}
1238
				}
1239
				$shareIdMembers[$row['shareid']] = ['GROUP' => $shareIdUsers];
1240
			}
1241
			$modShareReadPermission['GROUP'] = $grpReadPer;
1242
			$modShareWritePermission['GROUP'] = $grpWritePer;
1243
		}
1244
		return [
1245
			'read' => $modShareReadPermission,
1246
			'write' => $modShareWritePermission,
1247
			'sharingrules' => $shareIdMembers,
1248
		];
1249
	}
1250
1251
	/**
1252
	 * Get all groups by user id.
1253
	 *
1254
	 * @param int $userId
1255
	 *
1256
	 * @return int[]
1257
	 */
1258
	public static function getAllGroupsByUser($userId)
1259
	{
1260
		if (Cache::has('getAllGroupsByUser', $userId)) {
1261
			return Cache::get('getAllGroupsByUser', $userId);
1262
		}
1263
		$userGroups = static::getUserGroups($userId);
1264
		$userRole = static::getRoleByUsers($userId);
1265
		$roleGroups = (new \App\Db\Query())->select(['groupid'])->from('vtiger_group2role')->where(['roleid' => $userRole])->column();
1266
		$roles = static::getParentRole($userRole);
1267
		$roles[] = $userRole;
1268
		$rsGroups = (new \App\Db\Query())->select(['groupid'])->from('vtiger_group2rs')->where(['roleandsubid' => $roles])->column();
1269
		$allGroups = array_unique(array_merge($userGroups, $roleGroups, $rsGroups));
1270
		$parentGroups = [];
1271
		foreach ($allGroups as $groupId) {
1272
			$parentGroups = array_merge($parentGroups, static::getParentGroups($groupId));
1273
		}
1274
		if ($parentGroups) {
1275
			$allGroups = array_unique(array_merge($allGroups, $parentGroups));
1276
		}
1277
		Cache::save('getAllGroupsByUser', $userId, $allGroups, Cache::LONG);
1278
1279
		return $allGroups;
1280
	}
1281
1282
	/**
1283
	 * Get parent grioups by group id.
1284
	 *
1285
	 * @param int $groupId
1286
	 * @param int $i
1287
	 *
1288
	 * @return int[]
1289
	 */
1290
	public static function getParentGroups($groupId, $i = 0)
1291
	{
1292
		$groups = [];
1293 4
		if ($i < 10) {
1294
			$dataReader = (new \App\Db\Query())->select(['groupid'])->from('vtiger_group2grouprel')->where(['containsgroupid' => $groupId])->createCommand()->query();
1295 4
			while ($parentGroupId = $dataReader->readColumn(0)) {
1296 4
				$groups = array_merge($groups, [$parentGroupId], static::getParentGroups($parentGroupId, $i++));
1297 4
			}
1298 4
		} else {
1299 4
			Log::warning('Exceeded the recursive limit, a loop might have been created. Group ID:' . $groupId);
1300 4
		}
1301 4
		return $groups;
1302 4
	}
1303
1304 4
	/**
1305 4
	 * Creates a query to all groups where the user is a member..
1306
	 *
1307
	 * @param int $userId
1308 4
	 *
1309
	 * @return Db\Query
1310 4
	 */
1311 4
	public static function getQueryToGroupsByUserId(int $userId): Db\Query
1312
	{
1313
		return (new \App\Db\Query())->select(['groupid'])->from('vtiger_groups')->where(['groupid' => self::getAllGroupsByUser($userId)]);
1314
	}
1315
1316
	/**
1317
	 * Returns the leaders of the groups where the user is a member.
1318 1
	 *
1319
	 * @param int $userId
1320 1
	 *
1321 1
	 * @return array
1322
	 */
1323
	public static function getLeadersGroupByUserId(int $userId): array
1324
	{
1325
		$db = \App\Db::getInstance();
1326
		$query = self::getQueryToGroupsByUserId($userId)->andWhere(['<>', 'parentid', 0])->andWhere(['not', ['parentid' => null]]);
1327
		$member = new \yii\db\Expression('CASE WHEN vtiger_users.id IS NOT NULL THEN CONCAT(' . $db->quoteValue(self::MEMBER_TYPE_USERS) . ',\':\', parentid) ELSE CONCAT(' . $db->quoteValue(self::MEMBER_TYPE_GROUPS) . ',\':\', parentid) END');
1328
		$query->select(['groupid', 'member' => $member])->leftJoin('vtiger_users', 'vtiger_groups.parentid=vtiger_users.id');
1329 1
1330
		return $query->createCommand()->queryAllByGroup(0);
1331 1
	}
1332 1
1333 1
	/**
1334 1
	 * Returns groups whose leader is the user.
1335 1
	 *
1336 1
	 * @param int $userId
1337 1
	 *
1338
	 * @return array
1339
	 */
1340
	public static function getGroupsWhereUserIsLeader(int $userId): array
1341
	{
1342
		return (new \App\Db\Query())->select(['groupid'])->from('vtiger_groups')->where(['or', ['parentid' => $userId], ['parentid' => self::getQueryToGroupsByUserId($userId)]])->column();
1343
	}
1344 1
1345 1
	/**
1346 1
	 * Tables to sharing rules.
1347
	 *
1348
	 * @var array
1349
	 */
1350
	private static $shareRulesTables = [
1351
		'US::GRP' => 'vtiger_datashare_us2grp',
1352
		'US::ROLE' => 'vtiger_datashare_us2role',
1353 1
		'US::RS' => 'vtiger_datashare_us2rs',
1354 1
		'US::US' => 'vtiger_datashare_us2us',
1355 1
		'GRP::GRP' => 'vtiger_datashare_grp2grp',
1356 1
		'GRP::ROLE' => 'vtiger_datashare_grp2role',
1357
		'GRP::RS' => 'vtiger_datashare_grp2rs',
1358
		'GRP::US' => 'vtiger_datashare_grp2us',
1359
		'ROLE::GRP' => 'vtiger_datashare_role2group',
1360
		'ROLE::ROLE' => 'vtiger_datashare_role2role',
1361
		'ROLE::RS' => 'vtiger_datashare_role2rs',
1362
		'ROLE::US' => 'vtiger_datashare_role2us',
1363
		'RS::GRP' => 'vtiger_datashare_rs2grp',
1364 1
		'RS::ROLE' => 'vtiger_datashare_rs2role',
1365 1
		'RS::RS' => 'vtiger_datashare_rs2rs',
1366
		'RS::US' => 'vtiger_datashare_rs2us',
1367
	];
1368
1369
	/**
1370
	 * List tables where sharing rules are save for users, groups and roles.
1371
	 *
1372
	 * @var array
1373
	 */
1374
	private static $shareRulesTablesIndex = [
1375
		'Users' => [
1376
			'vtiger_datashare_us2us' => 'share_userid::to_userid',
1377
			'vtiger_datashare_us2grp' => 'share_userid',
1378
			'vtiger_datashare_us2role' => 'share_userid',
1379
			'vtiger_datashare_us2rs' => 'share_userid',
1380
			'vtiger_datashare_grp2us' => 'to_userid',
1381
			'vtiger_datashare_rs2us' => 'to_userid',
1382
			'vtiger_datashare_role2us' => 'to_userid',
1383
		],
1384
		'Roles' => [
1385
			'vtiger_datashare_us2role' => 'to_roleid',
1386
			'vtiger_datashare_us2rs' => 'to_roleandsubid',
1387
			'vtiger_datashare_grp2role' => 'to_roleid',
1388
			'vtiger_datashare_grp2rs' => 'to_roleandsubid',
1389 1
			'vtiger_datashare_role2group' => 'share_roleid',
1390
			'vtiger_datashare_role2us' => 'share_roleid',
1391
			'vtiger_datashare_role2role' => 'share_roleid::to_roleid',
1392 1
			'vtiger_datashare_role2rs' => 'share_roleid::to_roleandsubid',
1393
			'vtiger_datashare_rs2grp' => 'share_roleandsubid',
1394
			'vtiger_datashare_rs2us' => 'share_roleandsubid',
1395
			'vtiger_datashare_rs2role' => 'share_roleandsubid::to_roleid',
1396
			'vtiger_datashare_rs2rs' => 'share_roleandsubid::to_roleandsubid',
1397
		],
1398
		'Groups' => [
1399
			'vtiger_datashare_grp2grp' => 'share_groupid::to_groupid',
1400
			'vtiger_datashare_grp2role' => 'share_groupid',
1401
			'vtiger_datashare_grp2rs' => 'share_groupid',
1402
			'vtiger_datashare_grp2us' => 'share_groupid',
1403
			'vtiger_datashare_role2group' => 'to_groupid',
1404
			'vtiger_datashare_rs2grp' => 'to_groupid',
1405
			'vtiger_datashare_us2grp' => 'to_groupid',
1406
		],
1407
	];
1408
1409
	/**
1410
	 * This function is to delete the organisation level sharing rule
1411
	 * It takes the following input parameters:.
1412
	 *
1413
	 * @param int $shareid Id of the Sharing Rule to be updated
1414
	 */
1415
	private static function deleteSharingRule($shareid)
1416
	{
1417
		Log::trace('Entering deleteSharingRule(' . $shareid . ') method ...');
1418
		$dbCommand = Db::getInstance()->createCommand();
1419
		$typestr = (new Db\Query())->select(['relationtype'])->from('vtiger_datashare_module_rel')->where(['shareid' => $shareid])->scalar();
1420
		$dbCommand->delete(static::$shareRulesTables[$typestr], ['shareid' => $shareid])->execute();
0 ignored issues
show
Since $shareRulesTables is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $shareRulesTables to at least protected.
Loading history...
1421
		$dbCommand->delete('vtiger_datashare_module_rel', ['shareid' => $shareid])->execute();
1422
		$dbCommand->delete('vtiger_datashare_relatedmodule_permission', ['shareid' => $shareid])->execute();
1423
		Log::trace('Exiting deleteSharingRule method ...');
1424
	}
1425
1426
	/**
1427
	 * Function to remove sharing rules from tables.
1428
	 *
1429
	 * @param int|string $id
1430
	 * @param string     $type
1431
	 */
1432
	public static function deleteRelatedSharingRules($id, $type)
1433
	{
1434
		Log::trace('Entering deleteRelatedSharingRules(' . $id . ') method ...');
1435
		foreach (static::$shareRulesTablesIndex[$type] as $tablename => $colname) {
0 ignored issues
show
Since $shareRulesTablesIndex is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $shareRulesTablesIndex to at least protected.
Loading history...
1436
			$colNameArr = explode('::', $colname);
1437
			$query = (new Db\Query())->select(['shareid'])
1438
				->from($tablename)
1439
				->where([$colNameArr[0] => $id]);
1440
			if (isset($colNameArr[1])) {
1441
				$query->orWhere([$colNameArr[1] => $id]);
1442
			}
1443
			$dataReader = $query->createCommand()->query();
1444
			while ($shareid = $dataReader->readColumn(0)) {
1445
				static::deleteSharingRule($shareid);
1446
			}
1447
			$dataReader->close();
1448
		}
1449
		Log::trace('Exiting deleteRelatedSharingRules method ...');
1450
	}
1451
1452
	/**
1453
	 * Function for test to check privilege utils.
1454
	 *
1455
	 * @param int $recordId
1456
	 */
1457
	public static function testPrivileges($recordId)
1458
	{
1459
		static::getHelpDeskRelatedAccounts($recordId);
1460
		return true;
1461
	}
1462
1463
	/**
1464
	 * Recalculate sharing rules by user id.
1465
	 *
1466
	 * @param int $id
1467
	 */
1468
	public static function recalculateSharingRulesByUser($id)
1469
	{
1470
		$userModel = \App\User::getUserModel($id);
1471
		if (!$userModel->getId()) {
1472
			return null;
1473
		}
1474
		$roles = explode('::', $userModel->getParentRolesSeq());
1475
		$groups = $userModel->getGroups();
1476
		$sharing = [];
1477
		foreach (\Settings_SharingAccess_Rule_Model::$dataShareTableColArr['ROLE'] as $key => $item) {
1478
			$row = (new \App\Db\Query())->select([$item['target_id']])->from($item['table'])->where([$item['source_id'] => $roles])->column();
1479
			if ($row) {
1480
				if (!isset($sharing[$key])) {
1481
					$sharing[$key] = [];
1482
				}
1483
				$sharing[$key] = array_merge($sharing[$key], $row);
1484
			}
1485
		}
1486
		foreach (\Settings_SharingAccess_Rule_Model::$dataShareTableColArr['RS'] as $key => $item) {
1487
			$row = (new \App\Db\Query())->select([$item['target_id']])->from($item['table'])->where([$item['source_id'] => $roles])->column();
1488
			if ($row) {
1489
				if (!isset($sharing[$key])) {
1490
					$sharing[$key] = [];
1491
				}
1492
				$sharing[$key] = array_merge($sharing[$key], $row);
1493
			}
1494
		}
1495
		if ($groups) {
1496
			foreach (\Settings_SharingAccess_Rule_Model::$dataShareTableColArr['GRP'] as $key => $item) {
1497
				$row = (new \App\Db\Query())->select([$item['target_id']])->from($item['table'])->where([$item['source_id'] => $groups])->column();
1498
				if ($row) {
1499
					if (!isset($sharing[$key])) {
1500
						$sharing[$key] = [];
1501
					}
1502
					$sharing[$key] = array_merge($sharing[$key], $row);
1503
				}
1504
			}
1505
		}
1506
		$users = [[]];
1507
		foreach ($sharing as $type => $item) {
1508
			switch ($type) {
1509
				case 'US':
1510
					$users[] = array_unique($item);
1511
					break;
1512
				case 'GRP':
1513
					foreach ($item as $grpId) {
1514
						$users[] = static::getUsersByGroup($grpId);
1515
					}
1516
					break;
1517
				case 'ROLE':
1518
					foreach ($item as $roleId) {
1519
						$users[] = static::getUsersByRole($roleId);
1520
					}
1521
					break;
1522
				case 'RS':
1523
					foreach ($item as $roleId) {
1524
						$users[] = static::getUsersByRoleAndSubordinate($roleId);
1525
					}
1526
					break;
1527
				default:
1528
					break;
1529
			}
1530
		}
1531
		foreach (array_unique(array_merge(...$users)) as $userId) {
1532
			UserPrivilegesFile::createUserSharingPrivilegesfile($userId);
1533
		}
1534
	}
1535
1536
	/**
1537
	 * Modify permissions for actions and views.
1538
	 *
1539
	 * @param string $moduleName
1540
	 * @param array  $actions
1541
	 * @param bool   $mode       true: add, false: remove
1542
	 *
1543
	 * @return bool
1544
	 */
1545
	public static function modifyPermissions(string $moduleName, array $actions, bool $mode): bool
1546
	{
1547
		$dbCommand = \App\Db::getInstance()->createCommand();
1548
		$result = false;
1549
		$tabId = Module::getModuleId($moduleName);
1550
		$actions = array_diff($actions, array_merge(\Vtiger_Action_Model::$nonConfigurableActions, \Vtiger_Action_Model::$standardActions));
1551
		$actionIds = array_filter(array_map('\App\Module::getActionId', $actions));
1552
		if ($mode) {
1553
			$profilesByAction = (new Db\Query())->select(['profileid', 'activityid'])
1554
				->from('vtiger_profile2utility')
1555
				->where(['tabid' => $tabId, 'activityid' => $actionIds])->createCommand()->queryAllByGroup(2);
1556
			foreach (\vtlib\Profile::getAllIds() as $profileId) {
1557
				$add = !isset($profilesByAction[$profileId]) ? $actionIds : array_diff($actionIds, $profilesByAction[$profileId]);
1558
				foreach ($add as $actionId) {
1559
					$result = $dbCommand->insert('vtiger_profile2utility', ['profileid' => $profileId, 'tabid' => $tabId, 'activityid' => $actionId, 'permission' => 1])->execute() || $result;
1560
				}
1561
			}
1562
		} else {
1563
			$result = $dbCommand->delete('vtiger_profile2utility', ['tabid' => $tabId, 'activityid' => $actionIds])->execute();
1564
		}
1565
		return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result could return the type integer which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
1566
	}
1567
1568
	/**
1569
	 * Check if element exists in organization structure.
1570
	 *
1571
	 * @param int|string $member
1572
	 *
1573
	 * @return bool
1574
	 */
1575
	public static function isExists($member): bool
1576
	{
1577
		$type = is_numeric($member) ? \App\Fields\Owner::getType($member) : 'Roles';
1578
		switch ($type) {
1579
			case 'Users':
1580
				$exists = \App\User::isExists($member);
1581
				break;
1582
			case 'Groups':
1583
				$exists = (new \App\Db\Query())->from('vtiger_groups')->where(['groupid' => $member])->exists();
1584
				break;
1585
			case 'Roles':
1586
				$exists = !empty(self::getRoleDetail($member));
1587
				break;
1588
			default:
1589
				$exists = false;
1590
				break;
1591
		}
1592
1593
		return $exists;
1594
	}
1595
}
1596