Compatible::buildForEntity

  1. Bitrix24 API (v. 23.675.0)
  2. crm
  3. Compatible
  4. buildForEntity
  • Модуль: crm
  • Путь к файлу: ~/bitrix/modules/crm/lib/security/controller/querybuilder/compatible.php
  • Класс: Bitrix\Crm\Security\Controller\QueryBuilder\Compatible
  • Вызов: Compatible::buildForEntity
protected function buildForEntity(Collection $attributes, Options $options, string $permEntity): string
{
	$entityListAttributes = $attributes->getByEntityType($permEntity);
	$scopeRegex = $this->getScopeRegexForEntity($permEntity);

	$enableCumulativeMode = \COption::GetOptionString('crm', 'enable_permission_cumulative_mode', 'Y') === 'Y';
	$userAccessAttributes = \Bitrix\Crm\Service\Container::getInstance()
		->getUserPermissions($attributes->getUserId())
		->getAttributesProvider()
		->getUserAttributes()
	;

	$intranetAttrs = [];
	$allIntranetAttrs =
		isset($userAccessAttributes['INTRANET']) && is_array($userAccessAttributes['INTRANET'])
			? $userAccessAttributes['INTRANET']
			: [];

	if (!empty($allIntranetAttrs))
	{
		foreach ($allIntranetAttrs as $attr)
		{
			if (preg_match('/^D\d+$/', $attr))
			{
				$intranetAttrs[] = "'{$attr}'";
			}
		}
	}

	$subIntranetAttrs = [];
	$allSubIntranetAttrs =
		isset($userAccessAttributes['SUBINTRANET']) && is_array($userAccessAttributes['SUBINTRANET'])
			? $userAccessAttributes['SUBINTRANET']
			: [];

	if (!empty($allSubIntranetAttrs))
	{
		foreach ($allSubIntranetAttrs as $attr)
		{
			if (preg_match('/^D\d+$/', $attr))
			{
				$subIntranetAttrs[] = "'{$attr}'";
			}
		}
	}

	$permissionSets = [];
	foreach ($entityListAttributes as &$attrs)
	{
		if (empty($attrs))
		{
			continue;
		}

		$permissionSet = [
			'USER' => '',
			'CONCERNED_USER' => '',
			'DEPARTMENTS' => [],
			'OPENED_ONLY' => '',
			'SCOPES' => [],
		];

		$qty = count($attrs);
		for ($i = 0; $i < $qty; $i++)
		{
			$attr = $attrs[$i];

			if ($scopeRegex !== '' && preg_match($scopeRegex, $attr))
			{
				$permissionSet['SCOPES'][] = "'{$attr}'";
			}
			elseif ($attr === 'O')
			{
				$permissionSet['OPENED_ONLY'] = "'{$attr}'";
			}
			elseif (preg_match('/^U\d+$/', $attr))
			{
				$permissionSet['USER'] = "'{$attr}'";
				$permissionSet['CONCERNED_USER'] = "'C{$attr}'";
			}
			elseif (preg_match('/^D\d+$/', $attr))
			{
				$permissionSet['DEPARTMENTS'][] = "'{$attr}'";
			}
		}

		if (empty($permissionSet['SCOPES']))
		{
			if ($permissionSet['OPENED_ONLY'] !== '')
			{
				//HACK: for OPENED ONLY mode - allow user own entities too.
				$userAttr = isset($userAccessAttributes['USER']) && is_array($userAccessAttributes['USER']) && !empty($userAccessAttributes['USER']) ? $userAccessAttributes['USER'][0] : '';
				if ($userAttr !== '')
				{
					$permissionSets[] = [
						'USER' => "'{$userAttr}'",
						'CONCERNED_USER' => "'C{$userAttr}'",
						'DEPARTMENTS' => [],
						'OPENED_ONLY' => '',
						'SCOPES' => [],
					];
				}

				if ($enableCumulativeMode && !empty($intranetAttrs))
				{
					//OPENED ONLY mode - allow user department entities too.
					$permissionSets[] = [
						'USER' => '',
						'CONCERNED_USER' => '',
						'DEPARTMENTS' => array_unique(array_merge($intranetAttrs, $subIntranetAttrs)),
						'OPENED_ONLY' => '',
						'SCOPES' => [],
					];
				}
			}

			$permissionSets[] = &$permissionSet;
			unset($permissionSet);
		}
		else
		{
			$permissionSet = $this->registerPermissionSet($permissionSets, $permissionSet);
			if ($permissionSet['OPENED_ONLY'] !== '')
			{
				//HACK: for OPENED ONLY mode - allow user own entities too.
				$userAttr = isset($userAccessAttributes['USER']) && is_array($userAccessAttributes['USER']) && !empty($userAccessAttributes['USER']) ? $userAccessAttributes['USER'][0] : '';
				if ($userAttr !== '')
				{
					$this->registerPermissionSet(
						$permissionSets,
						[
							'USER' => "'{$userAttr}'",
							'CONCERNED_USER' => "'C{$userAttr}'",
							'DEPARTMENTS' => [],
							'OPENED_ONLY' => '',
							'SCOPES' => $permissionSet['SCOPES'],
						]
					);
				}
			}
		}
	}
	unset($attrs);

	$isRestricted = false;
	$subQueries = [];

	$effectiveEntityIDs = $options->getLimitByIds();
	$aliasPrefix = $options->getAliasPrefix();

	foreach ($permissionSets as &$permissionSet)
	{
		$scopes = $permissionSet['SCOPES'];
		$scopeQty = count($scopes);
		if ($scopeQty === 0)
		{
			$restrictions = [];
			if ($permissionSet['OPENED_ONLY'] !== '')
			{
				$attr = $permissionSet['OPENED_ONLY'];
				$restrictions[] = "{$aliasPrefix}P.ATTR = {$attr}";
			}
			elseif ($permissionSet['USER'] !== '')
			{
				$restrictions[] = $aliasPrefix . 'P.ATTR = ' . $permissionSet['USER'];
				if ($permissionSet['CONCERNED_USER'] !== '')
				{
					$restrictions[] = $aliasPrefix . 'P.ATTR = ' . $permissionSet['CONCERNED_USER'];
				}
			}
			elseif (!empty($permissionSet['DEPARTMENTS']))
			{
				$departments = $permissionSet['DEPARTMENTS'];
				$restrictions[] = count($departments) > 1
					? $aliasPrefix . 'P.ATTR IN(' . implode(', ', $departments) . ')'
					: $aliasPrefix . 'P.ATTR = ' . $departments[0];
			}

			if (!empty($restrictions))
			{
				foreach ($restrictions as $restriction)
				{
					$subQuery = "SELECT {$aliasPrefix}P.ENTITY_ID FROM b_crm_entity_perms {$aliasPrefix}P WHERE {$aliasPrefix}P.ENTITY = '{$permEntity}' AND {$restriction}";
					if (!empty($effectiveEntityIDs))
					{
						$subQuery .= " AND {$aliasPrefix}P.ENTITY_ID IN (" . implode(', ', $effectiveEntityIDs) . ")";
					}
					$subQueries[] = $subQuery;
				}

				if (!$isRestricted)
				{
					$isRestricted = true;
				}
			}
		}
		else
		{
			$scopeSql = $scopeQty > 1
				? $aliasPrefix . 'P2.ATTR IN (' . implode(', ', $scopes) . ')'
				: $aliasPrefix . 'P2.ATTR = ' . $scopes[0];

			$restrictions = [];
			if ($permissionSet['OPENED_ONLY'] !== '')
			{
				$attr = $permissionSet['OPENED_ONLY'];
				$restrictions[] = "{$aliasPrefix}P1.ATTR = {$attr}";
			}
			elseif ($permissionSet['USER'] !== '')
			{
				$restrictions[] = $aliasPrefix . 'P1.ATTR = ' . $permissionSet['USER'];
				if ($permissionSet['CONCERNED_USER'] !== '')
				{
					$restrictions[] = $aliasPrefix . 'P1.ATTR = ' . $permissionSet['CONCERNED_USER'];
				}
			}
			elseif (!empty($permissionSet['DEPARTMENTS']))
			{
				$departments = $permissionSet['DEPARTMENTS'];
				$restrictions[] = count($departments) > 1
					? $aliasPrefix . 'P1.ATTR IN(' . implode(', ', $departments) . ')'
					: $aliasPrefix . 'P1.ATTR = ' . $departments[0];
			}

			if (!empty($restrictions))
			{
				foreach ($restrictions as $restriction)
				{
					$subQuery = "SELECT {$aliasPrefix}P2.ENTITY_ID FROM b_crm_entity_perms {$aliasPrefix}P1 INNER JOIN b_crm_entity_perms {$aliasPrefix}P2 ON {$aliasPrefix}P1.ENTITY = '{$permEntity}' AND {$aliasPrefix}P2.ENTITY = '{$permEntity}' AND {$aliasPrefix}P1.ENTITY_ID = {$aliasPrefix}P2.ENTITY_ID AND {$restriction} AND {$scopeSql}";
					if (!empty($effectiveEntityIDs))
					{
						$subQuery .= " AND {$aliasPrefix}P2.ENTITY_ID IN (" . implode(',', $effectiveEntityIDs) . ")";
					}
					$subQueries[] = $subQuery;
				}
			}
			else
			{
				$subQuery = "SELECT {$aliasPrefix}P2.ENTITY_ID FROM b_crm_entity_perms {$aliasPrefix}P2 WHERE {$aliasPrefix}P2.ENTITY = '{$permEntity}' AND {$scopeSql}";
				if (!empty($effectiveEntityIDs))
				{
					$subQuery .= " AND {$aliasPrefix}P2.ENTITY_ID IN (" . implode(',', $effectiveEntityIDs) . ")";
				}
				$subQueries[] = $subQuery;
			}

			if (!$isRestricted)
			{
				$isRestricted = true;
			}
		}
	}
	unset($permissionSet);

	if (!$isRestricted)
	{
		return '';
	}

	if ($options->isReadAllAllowed())
	{
		//Add permission 'Read allowed to Everyone' permission
		$readAll = \CCrmPerms::ATTR_READ_ALL;
		$subQuery = "SELECT {$aliasPrefix}P.ENTITY_ID FROM b_crm_entity_perms {$aliasPrefix}P WHERE {$aliasPrefix}P.ENTITY = '{$permEntity}' AND {$aliasPrefix}P.ATTR = '{$readAll}'";
		if (!empty($effectiveEntityIDs))
		{
			$subQuery .= " AND {$aliasPrefix}P.ENTITY_ID IN (" . implode(',', $effectiveEntityIDs) . ")";
		}
		$subQueries[] = $subQuery;
	}

	$subQuerySql = implode($options->needUseDistinctUnion() ? ' UNION ' : ' UNION ALL ', $subQueries);

	if ($options->needReturnRawQuery())
	{
		if ($options->getRawQueryLimit() > 0)
		{
			$order = $options->getRawQueryOrder();

			$subQuerySql = \Bitrix\Main\Application::getConnection()->getSqlHelper()->getTopSql(
				"{$subQuerySql} ORDER BY ENTITY_ID {$order}",
				$options->getRawQueryLimit()
			)
			;
		}

		return $subQuerySql;
	}

	$identityCol = $options->getIdentityColumnName();

	if ($options->needUseJoin())
	{
		return "INNER JOIN ({$subQuerySql}) {$aliasPrefix}GP ON {$aliasPrefix}.{$identityCol} = {$aliasPrefix}GP.ENTITY_ID";
	}

	return "{$aliasPrefix}.{$identityCol} IN ({$subQuerySql})";
}

Добавить комментарий