PageRenderTime 44ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/landing/lib/rights.php

https://gitlab.com/alexprowars/bitrix
PHP | 1113 lines | 800 code | 106 blank | 207 comment | 92 complexity | db10f1b904379b6706073eaec7f8b5a4 MD5 | raw file
  1. <?php
  2. namespace Bitrix\Landing;
  3. use \Bitrix\Landing\Internals\RightsTable;
  4. use \Bitrix\Main\Localization\Loc;
  5. use \Bitrix\Main\UserAccessTable;
  6. Loc::loadMessages(__FILE__);
  7. class Rights
  8. {
  9. /**
  10. * Option for debug, set full access for admin.
  11. */
  12. const MODE_ADMIN_FULL_ACCESS = true;
  13. /**
  14. * Site entity type.
  15. */
  16. const ENTITY_TYPE_SITE = 'S';
  17. /**
  18. * Access types for different levels.
  19. */
  20. const ACCESS_TYPES = [
  21. 'denied' => 'denied',
  22. 'read' => 'read',
  23. 'edit' => 'edit',
  24. 'sett' => 'sett',
  25. 'public' => 'public',
  26. 'delete' => 'delete'
  27. ];
  28. /**
  29. * Additional rights for some functionality.
  30. */
  31. const ADDITIONAL_RIGHTS = [
  32. 'menu24' => 'menu24',//show in main menu of Bitrix24
  33. 'create' => 'create',//can create new sites
  34. 'knowledge_menu24' => 'knowledge_menu24',// show Knowledge in main menu of Bitrix24
  35. 'knowledge_create' => 'knowledge_create',//can create new Knowledge base
  36. 'group_create' => 'group_create',//can create new social network group base
  37. 'group_menu24' => 'group_menu24',// show group in main menu of Bitrix24
  38. ];
  39. /**
  40. * Allowed site ids with full access.
  41. * @var int[]
  42. */
  43. protected static $allowedSites = [];
  44. /**
  45. * If true, rights is not checking.
  46. * @var bool
  47. */
  48. protected static $available = true;
  49. /**
  50. * If true, rights is not checking (global mode).
  51. * @var bool
  52. */
  53. protected static $globalAvailable = true;
  54. /**
  55. * Context user id.
  56. * @var int
  57. */
  58. protected static $userId = null;
  59. /**
  60. * Set rights checking to 'no'.
  61. * @return void
  62. */
  63. public static function setOff()
  64. {
  65. self::$available = false;
  66. }
  67. /**
  68. * Set rights checking to 'yes'.
  69. * @return void
  70. */
  71. public static function setOn()
  72. {
  73. self::$available = true;
  74. }
  75. /**
  76. * Set rights checking to 'no' (global mode).
  77. * @return void
  78. */
  79. public static function setGlobalOff()
  80. {
  81. self::$globalAvailable = false;
  82. }
  83. /**
  84. * Set rights checking to 'yes' (global mode).
  85. * @return void
  86. */
  87. public static function setGlobalOn()
  88. {
  89. self::$globalAvailable = true;
  90. }
  91. /**
  92. * Check current status for checking rights.
  93. * @return bool
  94. */
  95. public static function isOn()
  96. {
  97. if (
  98. defined('LANDING_DISABLE_RIGHTS') &&
  99. LANDING_DISABLE_RIGHTS === true
  100. )
  101. {
  102. return false;
  103. }
  104. if (!self::$globalAvailable)
  105. {
  106. return false;
  107. }
  108. return self::$available;
  109. }
  110. /**
  111. * Current user is admin or not.
  112. * @return bool
  113. */
  114. public static function isAdmin()
  115. {
  116. if (self::MODE_ADMIN_FULL_ACCESS)
  117. {
  118. return Manager::isAdmin();
  119. }
  120. return false;
  121. }
  122. /**
  123. * Returns allowed sites with full access.
  124. * @return int[]
  125. */
  126. public static function getAllowedSites(): array
  127. {
  128. return self::$allowedSites;
  129. }
  130. /**
  131. * Sets context user id.
  132. * @param int $uid
  133. * @return void
  134. */
  135. public static function setContextUserId(int $uid): void
  136. {
  137. self::$userId = $uid;
  138. }
  139. /**
  140. * Clears context user id.
  141. * @return void
  142. */
  143. public static function clearContextUserId(): void
  144. {
  145. self::$userId = null;
  146. }
  147. /**
  148. * Returns context user id (current by default).
  149. * @return int
  150. */
  151. public static function getContextUserId(): int
  152. {
  153. if (!self::$userId)
  154. {
  155. self::$userId = Manager::getUserId();
  156. }
  157. return self::$userId;
  158. }
  159. /**
  160. * Available or not permission feature by current plan.
  161. * @return bool
  162. */
  163. protected static function isFeatureOn()
  164. {
  165. return Manager::checkFeature(
  166. Manager::FEATURE_PERMISSIONS_AVAILABLE
  167. );
  168. }
  169. /**
  170. * Gets tasks for access.
  171. * @return array
  172. */
  173. public static function getAccessTasks()
  174. {
  175. static $tasks = [];
  176. if (empty($tasks))
  177. {
  178. $res = \CTask::getList(
  179. ['LETTER' => 'ASC'],
  180. ['MODULE_ID' => 'landing']
  181. );
  182. while ($row = $res->fetch())
  183. {
  184. $row['NAME'] = mb_substr($row['NAME'], 14);
  185. $tasks[$row['ID']] = $row;
  186. }
  187. }
  188. return $tasks;
  189. }
  190. /**
  191. * Gets tasks for access.
  192. * @return array
  193. */
  194. public static function getAccessTasksReferences()
  195. {
  196. static $tasks = [];
  197. if (empty($tasks))
  198. {
  199. foreach (self::getAccessTasks() as $accessTask)
  200. {
  201. $tasks[$accessTask['NAME']] = $accessTask['ID'];
  202. }
  203. }
  204. return $tasks;
  205. }
  206. /**
  207. * Remove all rows for entity.
  208. * @param int|array $entityId Entity id (id or array of id).
  209. * @param string $entityType Entity type.
  210. * @return void
  211. */
  212. protected static function removeData($entityId, $entityType)
  213. {
  214. if (self::isFeatureOn())
  215. {
  216. $res = RightsTable::getList([
  217. 'select' => [
  218. 'ID'
  219. ],
  220. 'filter' => [
  221. 'ENTITY_ID' => $entityId,
  222. '=ENTITY_TYPE' => $entityType
  223. ]
  224. ]);
  225. while ($row = $res->fetch())
  226. {
  227. RightsTable::delete($row['ID']);
  228. }
  229. }
  230. }
  231. /**
  232. * Remove all rows for site.
  233. * @param int|array $siteId Site id (id or array of id).
  234. * @return void
  235. */
  236. public static function removeDataForSite($siteId)
  237. {
  238. self::removeData(
  239. $siteId,
  240. self::ENTITY_TYPE_SITE
  241. );
  242. }
  243. /**
  244. * Get all rows for entity.
  245. * @param int|array $entityId Entity id (id or array of id).
  246. * @param string $entityType Entity type.
  247. * @param array $preDefined Predefined array of rights.
  248. * @return array
  249. */
  250. protected static function getData($entityId, $entityType, array $preDefined = [])
  251. {
  252. static $access = null;
  253. $items = [];
  254. $codes = [];
  255. if ($access === null)
  256. {
  257. $access = new \CAccess;
  258. }
  259. // filter (with predefined_
  260. $filter = [
  261. 'ENTITY_ID' => $entityId,
  262. '=ENTITY_TYPE' => $entityType
  263. ];
  264. if ($preDefined)
  265. {
  266. $filter['=ACCESS_CODE'] = array_keys($preDefined);
  267. }
  268. // main query
  269. $res = RightsTable::getList([
  270. 'select' => [
  271. 'TASK_ID',
  272. 'ACCESS_CODE'
  273. ],
  274. 'filter' => $filter
  275. ]);
  276. while ($row = $res->fetch())
  277. {
  278. $codes[] = $row['ACCESS_CODE'];
  279. if (!isset($items[$row['ACCESS_CODE']]))
  280. {
  281. $row['TASK_ID'] = [$row['TASK_ID']];
  282. $items[$row['ACCESS_CODE']] = $row;
  283. }
  284. else
  285. {
  286. $items[$row['ACCESS_CODE']]['TASK_ID'][] = $row['TASK_ID'];
  287. }
  288. if (isset($preDefined[$row['ACCESS_CODE']]))
  289. {
  290. unset($preDefined[$row['ACCESS_CODE']]);
  291. }
  292. }
  293. $items = array_values($items);
  294. // fill with predefined
  295. foreach ($preDefined as $accessCode => $rightCode)
  296. {
  297. $items[] = [
  298. 'TASK_ID' => $rightCode,
  299. 'ACCESS_CODE' => $accessCode
  300. ];
  301. $codes[] = $accessCode;
  302. }
  303. // get titles
  304. if ($items)
  305. {
  306. $codesNames = $access->getNames($codes);
  307. foreach ($items as &$item)
  308. {
  309. if (isset($codesNames[$item['ACCESS_CODE']]))
  310. {
  311. $item['ACCESS_PROVIDER'] = (
  312. isset($codesNames[$item['ACCESS_CODE']]['provider']) &&
  313. $codesNames[$item['ACCESS_CODE']]['provider']
  314. )
  315. ? $codesNames[$item['ACCESS_CODE']]['provider']
  316. : '';
  317. $item['ACCESS_NAME'] = isset($codesNames[$item['ACCESS_CODE']]['name'])
  318. ? $codesNames[$item['ACCESS_CODE']]['name']
  319. : $item['ACCESS_CODE'];
  320. }
  321. }
  322. unset($item);
  323. }
  324. return $items;
  325. }
  326. /**
  327. * Get all rows for site.
  328. * @param int|array $siteId Site id (id or array of id).
  329. * @param array $preDefined Predefined array of rights.
  330. * @return array
  331. */
  332. public static function getDataForSite($siteId, array $preDefined = [])
  333. {
  334. return self::getData(
  335. $siteId,
  336. self::ENTITY_TYPE_SITE,
  337. $preDefined
  338. );
  339. }
  340. /**
  341. * Get all available operations for entity (for current user).
  342. * @param int|array $entityId Entity id (id or array of id).
  343. * @param string $entityType Entity type.
  344. * @return array
  345. */
  346. protected static function getOperations($entityId, $entityType)
  347. {
  348. // full access for allowed sites
  349. if (
  350. $entityType == self::ENTITY_TYPE_SITE &&
  351. in_array($entityId, self::$allowedSites)
  352. )
  353. {
  354. $types = self::ACCESS_TYPES;
  355. unset($types[self::ACCESS_TYPES['delete']]);
  356. return array_values($types);
  357. }
  358. $operations = [];
  359. $operationsDefault = [];
  360. $wasChecked = false;
  361. $uid = self::getContextUserId();
  362. $extendedMode = self::isExtendedMode();
  363. // full access for admin
  364. if (
  365. $uid &&
  366. self::isOn() &&
  367. !self::isAdmin() &&
  368. self::isFeatureOn() &&
  369. self::exist()
  370. )
  371. {
  372. $wasChecked = true;
  373. $entityIdFilter = $entityId;
  374. if (is_array($entityIdFilter))
  375. {
  376. $entityIdFilter[] = 0;
  377. }
  378. else
  379. {
  380. $entityIdFilter = [
  381. $entityIdFilter, 0
  382. ];
  383. }
  384. $filter = [
  385. 'ENTITY_ID' => $entityIdFilter,
  386. '=ENTITY_TYPE' => $entityType,
  387. 'USER_ACCESS.USER_ID' => $uid,
  388. '!TASK_OPERATION.OPERATION.NAME' => false
  389. ];
  390. if ($extendedMode)
  391. {
  392. $filter['ROLE_ID'] = 0;
  393. }
  394. else
  395. {
  396. $filter['ROLE_ID'] = Role::getExpectedRoleIds();
  397. }
  398. $res = RightsTable::getList(
  399. [
  400. 'select' => [
  401. 'ENTITY_ID',
  402. 'OPERATION_NAME' => 'TASK_OPERATION.OPERATION.NAME'
  403. ],
  404. 'filter' => $filter
  405. ]
  406. );
  407. while ($row = $res->fetch())
  408. {
  409. if ($row['ENTITY_ID'] == 0)
  410. {
  411. $operationsDefault[] = mb_substr($row['OPERATION_NAME'], 8);
  412. continue;
  413. }
  414. if (!isset($operations[$row['ENTITY_ID']]))
  415. {
  416. $operations[$row['ENTITY_ID']] = array();
  417. }
  418. $operations[$row['ENTITY_ID']][] = mb_substr($row['OPERATION_NAME'], 8);
  419. $operations[$row['ENTITY_ID']] = array_unique($operations[$row['ENTITY_ID']]);
  420. }
  421. }
  422. // set full rights, if rights are empty
  423. foreach ((array) $entityId as $id)
  424. {
  425. if (!isset($operations[$id]))
  426. {
  427. if ($wasChecked && !$extendedMode)
  428. {
  429. $operations[$id] = !empty($operationsDefault)
  430. ? $operationsDefault
  431. : [self::ACCESS_TYPES['denied']];
  432. }
  433. else
  434. {
  435. $operations[$id] = array_values(self::ACCESS_TYPES);
  436. }
  437. }
  438. }
  439. return is_array($entityId)
  440. ? $operations
  441. : $operations[$entityId];
  442. }
  443. /**
  444. * Gets all available operations for site (for current user).
  445. * @param int|array $siteId Site id (id or array of id).
  446. * @return array
  447. */
  448. public static function getOperationsForSite($siteId)
  449. {
  450. if (
  451. is_array($siteId) ||
  452. $siteId == 0 ||
  453. Site::ping($siteId, true)
  454. )
  455. {
  456. return self::getOperations(
  457. $siteId,
  458. self::ENTITY_TYPE_SITE
  459. );
  460. }
  461. else
  462. {
  463. return [];
  464. }
  465. }
  466. /**
  467. * Can current user do something.
  468. * @param int $siteId Site id.
  469. * @param string $accessType Access type code.
  470. * @param bool $deleted And from recycle bin.
  471. * @return boolean
  472. */
  473. public static function hasAccessForSite($siteId, $accessType, $deleted = false)
  474. {
  475. static $operations = [];
  476. $siteId = intval($siteId);
  477. if (!is_string($accessType))
  478. {
  479. return false;
  480. }
  481. if (!isset($operations[$siteId]))
  482. {
  483. if ($siteId === 0 || !self::isOn() || Site::ping($siteId, $deleted))
  484. {
  485. $operations[$siteId] = self::getOperations(
  486. $siteId,
  487. self::ENTITY_TYPE_SITE
  488. );
  489. }
  490. else
  491. {
  492. $operations[$siteId] = [];
  493. }
  494. }
  495. return in_array($accessType, $operations[$siteId]);
  496. }
  497. /**
  498. * Can current user do something.
  499. * @param int $landingId Landing id.
  500. * @param string $accessType Access type code.
  501. * @return boolean
  502. */
  503. public static function hasAccessForLanding($landingId, $accessType)
  504. {
  505. static $operations = [];
  506. $landingId = intval($landingId);
  507. if (!is_string($accessType))
  508. {
  509. return false;
  510. }
  511. if (!isset($operations[$landingId]))
  512. {
  513. $site = Landing::getList([
  514. 'select' => [
  515. 'SITE_ID'
  516. ],
  517. 'filter' => [
  518. 'ID' => $landingId,
  519. '=SITE.DELETED' => ['Y', 'N'],
  520. '=DELETED' => ['Y', 'N']
  521. ]
  522. ])->fetch();
  523. if ($site)
  524. {
  525. $operations[$landingId] = self::getOperations(
  526. $site['SITE_ID'],
  527. self::ENTITY_TYPE_SITE
  528. );
  529. }
  530. else
  531. {
  532. $operations[$landingId] = [];
  533. }
  534. }
  535. return in_array($accessType, $operations[$landingId]);
  536. }
  537. /**
  538. * Set operations for entity.
  539. * @param int $entityId Entity id.
  540. * @param string $entityType Entity type.
  541. * @param array $rights Rights array (set empty for clear rights).
  542. * @return boolean
  543. */
  544. protected static function setOperations($entityId, $entityType, array $rights = [])
  545. {
  546. if (!self::isFeatureOn())
  547. {
  548. return false;
  549. }
  550. $tasks = self::getAccessTasksReferences();
  551. $entityId = intval($entityId);
  552. self::removeData(
  553. $entityId,
  554. $entityType
  555. );
  556. // add new rights
  557. foreach ($rights as $accessCode => $rightCodes)
  558. {
  559. $rightCodes = (array) $rightCodes;
  560. if (in_array(self::ACCESS_TYPES['denied'], $rightCodes))
  561. {
  562. $rightCodes = [self::ACCESS_TYPES['denied']];
  563. }
  564. else if (!in_array(self::ACCESS_TYPES['read'], $rightCodes))
  565. {
  566. $rightCodes[] = self::ACCESS_TYPES['read'];
  567. }
  568. foreach ($rightCodes as $rightCode)
  569. {
  570. if (isset($tasks[$rightCode]))
  571. {
  572. RightsTable::add([
  573. 'ENTITY_ID' => $entityId,
  574. 'ENTITY_TYPE' => $entityType,
  575. 'TASK_ID' => $tasks[$rightCode],
  576. 'ACCESS_CODE' => $accessCode
  577. ]);
  578. }
  579. }
  580. }
  581. return true;
  582. }
  583. /**
  584. * Set operations for site.
  585. * @param int $siteId Site id.
  586. * @param array $rights Rights array (set empty for clear rights).
  587. * @return bool
  588. */
  589. public static function setOperationsForSite($siteId, array $rights = [])
  590. {
  591. $siteId = intval($siteId);
  592. if ($siteId == 0 || Site::ping($siteId))
  593. {
  594. return self::setOperations(
  595. $siteId,
  596. self::ENTITY_TYPE_SITE,
  597. $rights
  598. );
  599. }
  600. else
  601. {
  602. return false;
  603. }
  604. }
  605. /**
  606. * If any records of rights exists.
  607. * @return bool
  608. */
  609. protected static function exist()
  610. {
  611. static $exist = null;
  612. if ($exist === null)
  613. {
  614. $type = Site\Type::getCurrentScopeId();
  615. $res = RightsTable::getList([
  616. 'select' => [
  617. 'ID'
  618. ],
  619. 'filter' => $type
  620. ? ['=ROLE.TYPE' => $type]
  621. : [],
  622. 'limit' => 1
  623. ]);
  624. $exist = (bool) $res->fetch();
  625. }
  626. return $exist;
  627. }
  628. /**
  629. * Gets access filter for current user.
  630. * @param array $additionalFilterOr Additional filter for OR section.
  631. * @return array
  632. */
  633. public static function getAccessFilter(array $additionalFilterOr = [])
  634. {
  635. $filter = [];
  636. if (
  637. self::isOn() &&
  638. !self::isAdmin() &&
  639. self::isFeatureOn() &&
  640. self::exist()
  641. )
  642. {
  643. $tasks = self::getAccessTasksReferences();
  644. $extendedRights = self::isExtendedMode();
  645. $uid = self::getContextUserId();
  646. if ($extendedRights)
  647. {
  648. $filter[] = [
  649. 'LOGIC' => 'OR',
  650. [
  651. '!RIGHTS.TASK_ID' => $tasks[Rights::ACCESS_TYPES['denied']],
  652. 'RIGHTS.USER_ACCESS.USER_ID' => $uid
  653. ],
  654. [
  655. '=RIGHTS.TASK_ID' => null
  656. ],
  657. $additionalFilterOr
  658. ];
  659. }
  660. else
  661. {
  662. if ($additionalFilterOr)
  663. {
  664. $filter[] = [
  665. 'LOGIC' => 'OR',
  666. [
  667. '!RIGHTS.TASK_ID' => $tasks[Rights::ACCESS_TYPES['denied']],
  668. 'RIGHTS.USER_ACCESS.USER_ID' => $uid
  669. ],
  670. $additionalFilterOr
  671. ];
  672. }
  673. else
  674. {
  675. $filter['RIGHTS.USER_ACCESS.USER_ID'] = $uid;
  676. $filter['!RIGHTS.TASK_ID'] = $tasks[Rights::ACCESS_TYPES['denied']];
  677. }
  678. }
  679. }
  680. return $filter;
  681. }
  682. /**
  683. * Extended mode available.
  684. * @return bool
  685. */
  686. public static function isExtendedMode()
  687. {
  688. if (Manager::isB24())
  689. {
  690. return Manager::getOption('rights_extended_mode', 'N') == 'Y';
  691. }
  692. else
  693. {
  694. return true;
  695. }
  696. }
  697. /**
  698. * Switch extended mode.
  699. * @return void
  700. */
  701. public static function switchMode()
  702. {
  703. if (self::isFeatureOn())
  704. {
  705. $current = Manager::getOption('rights_extended_mode', 'N');
  706. $current = ($current == 'Y') ? 'N' : 'Y';
  707. Manager::setOption('rights_extended_mode', $current);
  708. }
  709. }
  710. /**
  711. * Refresh additional rights for all roles.
  712. * @param array $additionalRights Array for set additional.
  713. * @return void
  714. */
  715. public static function refreshAdditionalRights(array $additionalRights = [])
  716. {
  717. if (!self::isFeatureOn())
  718. {
  719. return;
  720. }
  721. $rights = [];
  722. foreach (self::ADDITIONAL_RIGHTS as $right)
  723. {
  724. $rights[$right] = [];
  725. }
  726. // get additional from all roles
  727. $res = Role::getList([
  728. 'select' => [
  729. 'ID', 'ACCESS_CODES', 'ADDITIONAL_RIGHTS'
  730. ]
  731. ]);
  732. while ($row = $res->fetch())
  733. {
  734. $row['ACCESS_CODES'] = (array) $row['ACCESS_CODES'];
  735. $row['ADDITIONAL_RIGHTS'] = (array) $row['ADDITIONAL_RIGHTS'];
  736. foreach ($row['ADDITIONAL_RIGHTS'] as $right)
  737. {
  738. if (isset($rights[$right]))
  739. {
  740. $rights[$right][$row['ID']] = $row['ACCESS_CODES'];
  741. }
  742. }
  743. }
  744. // refresh options
  745. foreach ($rights as $code => $right)
  746. {
  747. // gets current from option
  748. $option = Manager::getOption('access_codes_' . $code, '');
  749. $option = unserialize($option, ['allowed_classes' => false]);
  750. if (isset($option[0]))
  751. {
  752. $right[0] = $option[0];
  753. }
  754. // rewrite some rights, if need
  755. if (
  756. isset($additionalRights[$code]) &&
  757. is_array($additionalRights[$code])
  758. )
  759. {
  760. foreach ($additionalRights[$code] as $i => $accCodes)
  761. {
  762. $right[$i] = (array) $accCodes;
  763. }
  764. }
  765. // set new rights in option
  766. Manager::setOption('access_codes_' . $code, $right ? serialize($right) : '');
  767. // clear menu cache
  768. if (Manager::isB24())
  769. {
  770. Manager::getCacheManager()->clearByTag(
  771. 'bitrix24_left_menu'
  772. );
  773. Manager::getCacheManager()->cleanDir(
  774. 'menu'
  775. );
  776. \CBitrixComponent::clearComponentCache(
  777. 'bitrix:menu'
  778. );
  779. }
  780. }
  781. }
  782. /**
  783. * Set additional right.
  784. * @param string $code Code from ADDITIONAL_RIGHTS.
  785. * @param array $accessCodes Additional rights array.
  786. * @return void
  787. */
  788. public static function setAdditionalRightExtended($code, array $accessCodes = [])
  789. {
  790. if (!is_string($code))
  791. {
  792. return;
  793. }
  794. self::refreshAdditionalRights([
  795. $code => [
  796. 0 => $accessCodes
  797. ]
  798. ]);
  799. }
  800. /**
  801. * Gets additional right.
  802. * @param string $code Code from ADDITIONAL_RIGHTS.
  803. * @return array
  804. */
  805. public static function getAdditionalRightExtended($code)
  806. {
  807. static $access = null;
  808. $return = [];
  809. if (!is_string($code))
  810. {
  811. return $return;
  812. }
  813. if ($access === null)
  814. {
  815. $access = new \CAccess;
  816. }
  817. $option = Manager::getOption('access_codes_' . $code, '');
  818. $option = unserialize($option, ['allowed_classes' => false]);
  819. $accessCodes = isset($option[0]) ? (array)$option[0] : [];
  820. $codesNames = $access->getNames($accessCodes);
  821. foreach ($accessCodes as $code)
  822. {
  823. if (isset($codesNames[$code]))
  824. {
  825. $provider = (
  826. isset($codesNames[$code]['provider']) &&
  827. $codesNames[$code]['provider']
  828. )
  829. ? $codesNames[$code]['provider']
  830. : '';
  831. $name = isset($codesNames[$code]['name'])
  832. ? $codesNames[$code]['name']
  833. : $code;
  834. $return[$code] = [
  835. 'CODE' => $code,
  836. 'PROVIDER' => $provider,
  837. 'NAME' => $name
  838. ];
  839. }
  840. }
  841. return $return;
  842. }
  843. /**
  844. * Gets additional rights with labels.
  845. * @return array
  846. */
  847. public static function getAdditionalRightsLabels()
  848. {
  849. $rights = [];
  850. $type = Site\Type::getCurrentScopeId();
  851. foreach (self::ADDITIONAL_RIGHTS as $right)
  852. {
  853. if (mb_strpos($right, '_') > 0)
  854. {
  855. [$prefix, ] = explode('_', $right);
  856. $prefix = mb_strtoupper($prefix);
  857. if ($prefix != $type)
  858. {
  859. continue;
  860. }
  861. }
  862. else if ($type !== null)
  863. {
  864. continue;
  865. }
  866. $rights[$right] = Loc::getMessage('LANDING_RIGHTS_R_'.mb_strtoupper($right));
  867. }
  868. return $rights;
  869. }
  870. /**
  871. * Has user some extra access?
  872. * @return bool
  873. */
  874. protected static function hasExtraRights(): bool
  875. {
  876. // has context user access to crm forms
  877. if (\Bitrix\Main\Loader::includeModule('crm'))
  878. {
  879. $access = new \CCrmPerms(self::getContextUserId());
  880. if (!$access->havePerm('WEBFORM', BX_CRM_PERM_NONE, 'WRITE'))
  881. {
  882. // grant access to crm forms sites
  883. $res = Site::getList([
  884. 'select' => [
  885. 'ID'
  886. ],
  887. 'filter' => [
  888. 'CODE' => '/' . Site\Type::PSEUDO_SCOPE_CODE_FORMS . '%',
  889. '=SPECIAL' => 'Y',
  890. 'CHECK_PERMISSIONS' => 'N'
  891. ]
  892. ]);
  893. while ($row = $res->fetch())
  894. {
  895. self::$allowedSites[] = $row['ID'];
  896. }
  897. return true;
  898. }
  899. }
  900. return false;
  901. }
  902. /**
  903. * Has current user additional right or not.
  904. * @param string $code Code from ADDITIONAL_RIGHTS.
  905. * @param string $type Scope type.
  906. * @param bool $checkExtraRights Check extra rights.
  907. * @return bool
  908. */
  909. public static function hasAdditionalRight($code, $type = null, bool $checkExtraRights = false)
  910. {
  911. static $options = [];
  912. if ($checkExtraRights && self::hasExtraRights())
  913. {
  914. return true;
  915. }
  916. if (!is_string($code))
  917. {
  918. return false;
  919. }
  920. if ($type === null)
  921. {
  922. $type = Site\Type::getCurrentScopeId();
  923. }
  924. if ($type !== null)
  925. {
  926. $type = mb_strtolower($type);
  927. //@todo: hotfix for group right
  928. if ($type == Site\Type::SCOPE_CODE_GROUP)
  929. {
  930. return true;
  931. }
  932. $code = $type . '_' . $code;
  933. }
  934. if (array_key_exists($code, self::ADDITIONAL_RIGHTS))
  935. {
  936. if (!self::isFeatureOn())
  937. {
  938. return true;
  939. }
  940. if (!self::getContextUserId())
  941. {
  942. return false;
  943. }
  944. if (self::isAdmin())
  945. {
  946. return true;
  947. }
  948. $accessCodes = [];
  949. if (!isset($options[$code]))
  950. {
  951. $options[$code] = Manager::getOption('access_codes_' . $code, '');
  952. $options[$code] = unserialize($options[$code], ['allowed_classes' => false]);
  953. }
  954. $option = $options[$code];
  955. if (!is_array($option))
  956. {
  957. return true;
  958. }
  959. if (empty($option))
  960. {
  961. return false;
  962. }
  963. if (self::isExtendedMode())
  964. {
  965. if (isset($option[0]) && is_array($option[0]))
  966. {
  967. $accessCodes = $option[0];
  968. }
  969. }
  970. else
  971. {
  972. if (isset($option[0]))
  973. {
  974. unset($option[0]);
  975. }
  976. foreach ($option as $roleAccess)
  977. {
  978. $accessCodes = array_merge($accessCodes, (array)$roleAccess);
  979. }
  980. $accessCodes = array_unique($accessCodes);
  981. }
  982. if ($accessCodes)
  983. {
  984. static $accessCodesStatic = [];
  985. sort($accessCodes);
  986. $accessCodesStr = implode('|', $accessCodes);
  987. if (array_key_exists($accessCodesStr, $accessCodesStatic))
  988. {
  989. return $accessCodesStatic[$accessCodesStr];
  990. }
  991. $res = UserAccessTable::getList([
  992. 'select' => [
  993. 'USER_ID'
  994. ],
  995. 'filter' => [
  996. '=ACCESS_CODE' => $accessCodes,
  997. 'USER_ID' => self::getContextUserId()
  998. ]
  999. ]);
  1000. $accessCodesStatic[$accessCodesStr] = (boolean)$res->fetch();
  1001. return $accessCodesStatic[$accessCodesStr];
  1002. }
  1003. return false;
  1004. }
  1005. return false;
  1006. }
  1007. }