Пример создания ролевых прав доступа D7 для модулей CMS Bitrix

Код модуля

1. Устанавливаем модуль awz.admin

  • поддерживаются только модули содержащие в названии директории точку, например, partner.module
  • дальнейшая инструкция описана для модуля с кодом partner.module
  • в инструкции меняем partnermodule-, \\Partner\\Module\\, partner.moduleна свой

2. Генерируем права доступа

2.1. Переходим в генератор прав доступа и выбираем директорию с нашим модулем

Настройки -> AWZ: Конструктор списков -> Генератор прав доступа

2.2. Добавляем разделы прав доступа

Можно пропустить данный пункт если у нас только глобальные права на просмотр и редактирование модуля

Например, Просмотр курсов код: VIEW

2.3. Добавляем правила прав доступа

Можно пропустить данный пункт если у нас только глобальные права на просмотр и редактирование модуля

Параметр Пример Описание
Константа VIEW_USD Большие латинские буквы
Значение 4 Цифры 4 или строки 4.1 (1,2,3 - зарезервированы)
Правило viewcurrency Название класса с логикой проверки
будет сгенерирован в \lib\access\custom\rules
Название настройки Просмотр USD Значение для языковой переменной

При использовании строк 4.1 должны быть уже заведены права со значением 4 и выше вложенных прав, значение на скрине ниже неверные (в таком варианте получите исключение при сохранении прав)

Верная настройка, ниже

3. Добавляем настройки ui.entity-selector

В ядре стандартно нет возможности искать по всем пользователям и группам, поэтому пишем свои селекторы выбора

Добавляем опции в файл /bitrix/modules/partner.module/.settings.php (создаем если файла нет)

<?php
return [
    'ui.entity-selector' => [
        'value' => [
            'entities' => [
                [
                    'entityId' => 'partnermodule-user',
                    'provider' => [
                        'moduleId' => 'partner.module',
                        'className' => '\\Partner\\Module\\Access\\EntitySelectors\\User'
                    ],
                ],
                [
                    'entityId' => 'partnermodule-group',
                    'provider' => [
                        'moduleId' => 'partner.module',
                        'className' => '\\Partner\\Module\\Access\\EntitySelectors\\Group'
                    ],
                ],
            ]
        ],
        'readonly' => true,
    ]
];

4. Добавляем таблицы для хранения прав в базу данных

$connection = \Bitrix\Main\Application::getConnection();
if($connection->getType()=='mysql'){
    $sql = "CREATE TABLE IF NOT EXISTS partner_module_role (
    ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    NAME VARCHAR(250) NOT NULL,
    PRIMARY KEY (ID)
    );";
    $connection->queryExecute($sql);
    $sql = "CREATE TABLE IF NOT EXISTS partner_module_role_relation (
    ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    ROLE_ID INT(10) UNSIGNED NOT NULL,
    RELATION VARCHAR(8) NOT NULL DEFAULT '',
    PRIMARY KEY (ID),
    INDEX ROLE_ID (ROLE_ID),
    INDEX RELATION (RELATION)
    );";
    $connection->queryExecute($sql);
    $sql = "CREATE TABLE IF NOT EXISTS partner_module_permission (
    ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    ROLE_ID INT(10) UNSIGNED NOT NULL,
    PERMISSION_ID VARCHAR(32) NOT NULL DEFAULT '0',
    VALUE TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
    PRIMARY KEY (ID),
    INDEX ROLE_ID (ROLE_ID),
    INDEX PERMISSION_ID (PERMISSION_ID)
    );";
    $connection->queryExecute($sql);
}
elseif($connection->getType()=='pgsql'){
    $sql = "CREATE TABLE partner_module_role (
    ID int GENERATED BY DEFAULT AS IDENTITY NOT NULL,
    NAME varchar(250) NOT NULL,
    PRIMARY KEY (ID)
    );";
    $connection->queryExecute($sql);
    $sql = "CREATE TABLE partner_module_role_relation (
    ID int GENERATED BY DEFAULT AS IDENTITY NOT NULL,
    ROLE_ID int NOT NULL DEFAULT 0,
    RELATION varchar(8) NOT NULL DEFAULT '',
    PRIMARY KEY (ID)
    );";
    $connection->queryExecute($sql);
    $sql = "CREATE TABLE partner_module_permission (
    ID int GENERATED BY DEFAULT AS IDENTITY NOT NULL,
    ROLE_ID int NOT NULL DEFAULT 0,
    PERMISSION_ID varchar(32) NOT NULL DEFAULT '0',
    VALUE int NOT NULL DEFAULT 0,
    PRIMARY KEY (ID)
    );";
    $connection->queryExecute($sql);
    $connection->queryExecute(
        'CREATE INDEX partner_module_role_relation_role_id ON partner_module_role_relation (role_id);'
    );
    $connection->queryExecute(
        'CREATE INDEX partner_module_role_relation_relation ON partner_module_role_relation (relation);'
    );
    $connection->queryExecute(
        'CREATE INDEX partner_module_permission_role_id ON partner_module_permission (role_id);'
    );
    $connection->queryExecute(
        'CREATE INDEX partner_module_permission_permission_id ON partner_module_permission (permission_id);'
    );
}

Пример добавления таблиц в /bitrix/modules/partner.module/install/index.php

function InstallDB()
{
    global $DB, $DBType, $APPLICATION;
    $connection = \Bitrix\Main\Application::getConnection();
    $this->errors = false;
    if(!$this->errors && !$DB->TableExists(implode('_', explode('.',$this->MODULE_ID)).'_permission')) {
        $this->errors = $DB->RunSQLBatch($_SERVER['DOCUMENT_ROOT'] . "/bitrix/modules/" . $this->MODULE_ID . "/install/db/".$connection->getType()."/access.sql");
    }
    if (!$this->errors) {
        return true;
    } else {
        $APPLICATION->ThrowException(implode("", $this->errors));
        return $this->errors;
    }
}

function UnInstallDB()
{
    global $DB, $DBType, $APPLICATION;
    $connection = \Bitrix\Main\Application::getConnection();
    $this->errors = false;
    if (!$this->errors) {
        $this->errors = $DB->RunSQLBatch($_SERVER['DOCUMENT_ROOT'] . "/bitrix/modules/" . $this->MODULE_ID . "/install/db/" . $connection->getType() . "/unaccess.sql");
    }
    if (!$this->errors) {
        return true;
    }
    else {
        $APPLICATION->ThrowException(implode("", $this->errors));
        return $this->errors;
    }
}

5. Добавляем обработчик для пересчета групп

$moduleId = 'partner.module';
$eventManager = \Bitrix\Main\EventManager::getInstance();
$eventManager->registerEventHandlerCompatible(
    'main', 'OnAfterUserUpdate',
    $moduleId, '\\Partner\\Module\\Access\\Handlers', 'OnAfterUserUpdate'
);
$eventManager->registerEventHandlerCompatible(
    'main', 'OnAfterUserAdd',
    $moduleId, '\\Partner\\Module\\Access\\Handlers', 'OnAfterUserUpdate'
);

Пример добавления обработчиков в /bitrix/modules/partner.module/install/index.php

use \Bitrix\Main\EventManager;

function InstallEvents()
{
    $eventManager = EventManager::getInstance();
    $eventManager->registerEventHandlerCompatible(
        'main', 'OnAfterUserUpdate',
        $this->MODULE_ID, '\\Partner\\Module\\Access\\Handlers', 'OnAfterUserUpdate'
    );
    $eventManager->registerEventHandlerCompatible(
        'main', 'OnAfterUserAdd',
        $this->MODULE_ID, '\\Partner\\Module\\Access\\Handlers', 'OnAfterUserUpdate'
    );
    return true;
}

function UnInstallEvents()
{
    $eventManager = EventManager::getInstance();
    $eventManager->unRegisterEventHandler(
        'sale', 'OnAfterUserUpdate',
        $this->MODULE_ID, '\\Partner\\Module\\Access\\Handlers', 'OnAfterUserUpdate'
    );
    $eventManager->unRegisterEventHandler(
        'sale', 'OnAfterUserAdd',
        $this->MODULE_ID, '\\Partner\\Module\\Access\\Handlers', 'OnAfterUserUpdate'
    );
    return true;
}

6. Добавляем компонент для установки прав

копируем /bitrix/modules/partner.module/install/components/module.config.permissions в /bitrix/components/partner/module.config.permissions

Пример копирования в /bitrix/modules/partner.module/install/index.php

function InstallFiles()
{
    CopyDirFiles(
        $_SERVER['DOCUMENT_ROOT']."/bitrix/modules/".$this->MODULE_ID."/install/components/module.config.permissions/", 
        $_SERVER['DOCUMENT_ROOT']."/bitrix/components/partner/module.config.permissions", 
        true, true
    );
    return true;
}

function UnInstallFiles()
{
    DeleteDirFilesEx("/bitrix/components/partner/module.config.permissions");
    return true;
}

7. Добавляем окно управления правами

в /bitrix/modules/partner.module/options.php

7.1. Выводим кнопку открытия управления прав доступа в слайдере

7.1.1 Подключаем ui.sidepanel-content

use Bitrix\Main\UI\Extension;
Extension::load('ui.sidepanel-content');

7.1.2 Код вывода кнопки

use Partner\Module\Access\AccessController;
$module_id = "partner.module";
?>
<?
//проверим или у текущего пользователя есть права на просмотр настроек прав доступа
if(AccessController::isViewRight()){?>
    <button class="adm-header-btn adm-security-btn" onclick="BX.SidePanel.Instance.open('<?echo $APPLICATION->GetCurPage()?>?mid=<?=htmlspecialcharsbx($module_id)?>&lang=<?=LANGUAGE_ID?>&mid_menu=1');return false;">
        права доступа
    </button>
<?}?>

7.2 Логика вывода окна прав в слайдер

use Bitrix\Main\Application;
$request = Application::getInstance()->getContext()->getRequest();

//после пролога
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php");

if($request->get('IFRAME_TYPE')==='SIDE_SLIDER'){
    require_once('lib/access/include/moduleright.php');
    CMain::finalActions();
    die();
}

7.3 Если все сделали правильно, то при нажатии на кнопку откроется слайдер с настройками прав

7.3.1 Создаем роль и сохраняем права

7.3.2 Добавим дополнительной логики в класс проверки

/bitrix/modules/partner.module/lib/access/custom/rules/viewcurrency.php

Стандартный класс, сгенерированный модулем уже проверяет по первому добавленному (пункт 2.3)

class Viewcurrency extends \Bitrix\Main\Access\Rule\AbstractRule
{
    public function execute(AccessibleItem $item = null, $params = null): bool
    {
        if ($this->user->isAdmin() && !Helper::ADMIN_DECLINE)
        {
            return true;
        }
        if ($this->user->getPermission(PermissionDictionary::VIEW_EUR))
        {
            return true;
        }
        return false;
    }
}

Добавим проверку по кодам валют

class Viewcurrency extends \Bitrix\Main\Access\Rule\AbstractRule
{
    public function execute(AccessibleItem $item = null, $params = null): bool
    {
        if ($this->user->isAdmin() && !Helper::ADMIN_DECLINE)
            return true;
        if ($this->user->getPermission(PermissionDictionary::VIEW_ALL))
            return true;
        if($params == 'USD' && $this->user->getPermission(PermissionDictionary::VIEW_USD))
            return true;
        if($params == 'EUR' && $this->user->getPermission(PermissionDictionary::VIEW_EUR))
            return true;
        return false;
    }
}

7.3.3 Проверка прав доступа в модулях

use Partner\Module\Access\AccessController;
use Partner\Module\Access\Custom\ActionDictionary;
if(\Bitrix\Main\Loader::includeModule('awz.currency')){

    $res = \Awz\Currency\CursTable::getCurs(date('d.m.Y'));
    echo 'count all: '.count($res)."\n";
    foreach($res as $code=>$value){
        if(AccessController::can(0,ActionDictionary::ACTION_VIEW_ALL, false, $code)){
            echo $code.' - '.$value['AMOUNT']."\n";
        }
    }

}
### Результат выполнения команды
### count all: 4
### USD - 99.4215
#Вместо (старый вариант)
use Bitrix\Main\Loader;
$module_id = "partner.module";
Loader::includeModule($module_id);
$MODULE_RIGHT = $APPLICATION->GetGroupRight($module_id);
if (! ($MODULE_RIGHT >= "R"))
    $APPLICATION->AuthForm(Loc::getMessage("ACCESS_DENIED"));

#Новый вариант
use Bitrix\Main\Loader;
use Partner\Module\Access\AccessController;
$module_id = "partner.module";
Loader::includeModule($module_id);
if(!AccessController::isViewSettings())
    $APPLICATION->AuthForm(Loc::getMessage("ACCESS_DENIED"));

Добавление ссылок на настройки в меню модуля admin/menu.php

use Partner\Module\Access\AccessController;
use Bitrix\Main\Loader;
$module_id = "partner.module";
if(!Loader::includeModule($module_id)) return;
if(AccessController::isViewSettings() || AccessController::isViewRight()){
    $level2 = [];
    if(AccessController::isViewSettings()){
        $level2[] = [
            "text" => "Общие настройки",
            "url" => "settings.php?lang=".LANGUAGE_ID.'&mid='.$module_id.'&mid_menu=1'
        ];
    }
    if(AccessController::isViewRight()){
        $level2[] = [
            "text" => "Права доступа",
            "url" => "javascript:BX.SidePanel.Instance.open('/bitrix/admin/settings.php?mid=".$module_id."&lang=".LANGUAGE_ID."&mid_menu=1');"
        ];
    }
    $items[] = [
        "text" => "Настройки модуля",
        "items_id" => str_replace('.','_',$module_id).'_sett',
        "items"=>$level2
    ];
}

8. Структура

8.1 Структура классов

Partner\Module\Access

Класс Описание
Handlers Содержит обработчии (например расчет кодов прав)
AccessController Контроллер для проверки прав доступа в своих модулях

Partner\Module\Access\Tables

Таблицы в базе данных

Класс Описание
PermissionTable
RoleTable
RoleRelationTable

Partner\Module\Access\Entity

Класс Описание
User

Partner\Module\Access\Component

Класс Описание
ConfigPermissions

Partner\Module\Access\EntitySelectors

Класс Описание
Group
User

Partner\Module\Access\Model

Класс Описание
BaseModel
UserModel

Partner\Module\Access\Permission

Класс Описание
ActionDictionary
PermissionDictionary
RoleDictionary
RoleUtil
RuleFactory

Partner\Module\Access\Permission\Rules

Класс Описание
RightEdit
RightView
SettEdit
SettView

8.2. Структура - Классы для кастомизации

Partner\Module\Access\Custom

Справочники констант и логика для компонента управления прав

Класс Описание
ActionDictionary
ComponentConfig
Helper
PermissionDictionary
RoleDictionary

Partner\Module\Access\Custom\Rules

Содержатся сгенерированные классы прав

Класс Описание
Example

8.3. Структура - компонент сохранения прав

/bitrix/modules/partner.module/install/components/module.config.permissions

8.4. Структура - таблицы базы данных

/bitrix/modules/partner.module/install/db/mysql/access.sql
/bitrix/modules/partner.module/install/db/pgsql/access.sql
/bitrix/modules/partner.module/install/db/mysql/unaccess.sql /bitrix/modules/partner.module/install/db/pgsql/unaccess.sql

9. Обновление модуля partner.module все файлы

9.1 Добавляем опции в файл /bitrix/modules/partner.module/.settings.php (создаем если файла нет)

<?php
return [
    'ui.entity-selector' => [
        'value' => [
            'entities' => [
                [
                    'entityId' => 'partnermodule-user',
                    'provider' => [
                        'moduleId' => 'partner.module',
                        'className' => '\\Partner\\Module\\Access\\EntitySelectors\\User'
                    ],
                ],
                [
                    'entityId' => 'partnermodule-group',
                    'provider' => [
                        'moduleId' => 'partner.module',
                        'className' => '\\Partner\\Module\\Access\\EntitySelectors\\Group'
                    ],
                ],
            ]
        ],
        'readonly' => true,
    ]
];

9.2 Добавляем логику в установщик /bitrix/modules/partner.module/install/index.php

<?
use Bitrix\Main\Localization\Loc,
    Bitrix\Main\EventManager,
    Bitrix\Main\ModuleManager,
    Bitrix\Main\Application;

Loc::loadMessages(__FILE__);

class partner_module extends CModule
{
    var $MODULE_ID = "partner.module";
    var $MODULE_VERSION;
    var $MODULE_VERSION_DATE;
    var $MODULE_NAME;
    var $MODULE_DESCRIPTION;
    var $PARTNER_NAME;
    var $PARTNER_URI;
    var $MODULE_GROUP_RIGHTS = "N";

    public function __construct()
    {
        $arModuleVersion = array();
        include(__DIR__.'/version.php');

        $this->MODULE_VERSION = $arModuleVersion["VERSION"];
        $this->MODULE_VERSION_DATE = $arModuleVersion["VERSION_DATE"];
        /*$this->MODULE_NAME = Loc::getMessage("AWZ_ADMIN_MODULE_NAME");
        $this->MODULE_DESCRIPTION = Loc::getMessage("AWZ_ADMIN_MODULE_DESCRIPTION");
        $this->PARTNER_NAME = Loc::getMessage("AWZ_PARTNER_NAME");
        $this->PARTNER_URI = Loc::getMessage("AWZ_PARTNER_URI");*/
        return true;
    }
    function DoInstall()
    {
        global $APPLICATION, $step;

        $this->InstallFiles();
        $this->InstallDB();
        $this->checkOldInstallTables();
        $this->InstallEvents();
        $this->createAgents();

        ModuleManager::RegisterModule($this->MODULE_ID);

        return true;
    }

    function DoUninstall()
    {
        global $APPLICATION, $step;

        $step = intval($step);
        if($step < 2) { //выводим предупреждение
            $APPLICATION->IncludeAdminFile(
            Loc::getMessage('AWZ_ADMIN_INSTALL_TITLE'), 
            $_SERVER['DOCUMENT_ROOT'].'/bitrix/modules/'. $this->MODULE_ID .'/install/unstep.php'
            );
        }
        elseif($step == 2) {
            //проверяем условие
            if($_REQUEST['save'] != 'Y' && !isset($_REQUEST['save'])) {
                $this->UnInstallDB();
            }
            $this->UnInstallFiles();
            $this->UnInstallEvents();
            $this->deleteAgents();

            ModuleManager::UnRegisterModule($this->MODULE_ID);

            return true;
        }
    }

    function InstallDB()
    {
        global $DB, $DBType, $APPLICATION;
        $connection = \Bitrix\Main\Application::getConnection();
        $this->errors = false;
        /*if(!$this->errors && !$DB->TableExists('b_'.implode('_', explode('.',$this->MODULE_ID)).'_goption')) {
            $this->errors = $DB->RunSQLBatch($_SERVER['DOCUMENT_ROOT'] . "/bitrix/modules/". $this->MODULE_ID ."/install/db/".$connection->getType()."/install.sql");
        }*/
        if(!$this->errors && !$DB->TableExists(implode('_', explode('.',$this->MODULE_ID)).'_permission')) {
            $this->errors = $DB->RunSQLBatch($_SERVER['DOCUMENT_ROOT'] . "/bitrix/modules/" . $this->MODULE_ID . "/install/db/".$connection->getType()."/access.sql");
        }
        if (!$this->errors) {
            return true;
        } else {
            $APPLICATION->ThrowException(implode("", $this->errors));
            return $this->errors;
        }
    }

    function UnInstallDB()
    {
        global $DB, $DBType, $APPLICATION;
        $connection = \Bitrix\Main\Application::getConnection();
        $this->errors = false;
        /*if (!$this->errors) {
            $this->errors = $DB->RunSQLBatch($_SERVER['DOCUMENT_ROOT'] . "/bitrix/modules/" . $this->MODULE_ID . "/install/db/" . $connection->getType() . "/uninstall.sql");
        }*/
        if (!$this->errors) {
            $this->errors = $DB->RunSQLBatch($_SERVER['DOCUMENT_ROOT'] . "/bitrix/modules/" . $this->MODULE_ID . "/install/db/" . $connection->getType() . "/unaccess.sql");
        }
        if (!$this->errors) {
            return true;
        }
        else {
            $APPLICATION->ThrowException(implode("", $this->errors));
            return $this->errors;
        }
    }

    function InstallEvents()
    {
        $eventManager = EventManager::getInstance();
        $eventManager->registerEventHandlerCompatible(
            'main', 'OnAfterUserUpdate',
            $this->MODULE_ID, '\\Partner\\Module\\Access\\Handlers', 'OnAfterUserUpdate'
        );
        $eventManager->registerEventHandlerCompatible(
            'main', 'OnAfterUserAdd',
            $this->MODULE_ID, '\\Partner\\Module\\Access\\Handlers', 'OnAfterUserUpdate'
        );
        return true;
    }

    function UnInstallEvents()
    {
        $eventManager = EventManager::getInstance();
        $eventManager->unRegisterEventHandler(
            'sale', 'OnAfterUserUpdate',
            $this->MODULE_ID, '\\Partner\\Module\\Access\\Handlers', 'OnAfterUserUpdate'
        );
        $eventManager->unRegisterEventHandler(
            'sale', 'OnAfterUserAdd',
            $this->MODULE_ID, '\\Partner\\Module\\Access\\Handlers', 'OnAfterUserUpdate'
        );
        return true;
    }

    function InstallFiles()
    {
        CopyDirFiles($_SERVER['DOCUMENT_ROOT']."/bitrix/modules/".$this->MODULE_ID."/install/admin/", $_SERVER['DOCUMENT_ROOT']."/bitrix/admin/", true);
        CopyDirFiles($_SERVER['DOCUMENT_ROOT']."/bitrix/modules/".$this->MODULE_ID."/install/components/module.config.permissions/", $_SERVER['DOCUMENT_ROOT']."/bitrix/components/partner/module.config.permissions", true, true);
        return true;
    }

    function UnInstallFiles()
    {
        DeleteDirFilesEx("/bitrix/components/partner/module.config.permissions");
        DeleteDirFiles(
            $_SERVER['DOCUMENT_ROOT']."/bitrix/modules/".$this->MODULE_ID."/install/admin",
            $_SERVER['DOCUMENT_ROOT']."/bitrix/admin"
        );
        return true;
    }

    function createAgents() {
        return true;
    }

    function deleteAgents() {
        return true;
    }

    function checkOldInstallTables()
    {
        return true;
    }

}

9.3 пример options.php

require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_before.php");

use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Config\Option;
use Bitrix\Main\Loader;
use Bitrix\Main\Application;
use Bitrix\Main\UI\Extension;
use Partner\Module\Access\AccessController;

Loc::loadMessages(__FILE__);
global $APPLICATION;
$module_id = "partner.module";
if(!Loader::includeModule($module_id)) return;
Extension::load('ui.sidepanel-content');
$request = Application::getInstance()->getContext()->getRequest();
$APPLICATION->SetTitle(Loc::getMessage('PARTNER_MODULE_OPT_TITLE'));

if($request->get('IFRAME_TYPE')==='SIDE_SLIDER'){
    require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php");
    require_once('lib/access/include/moduleright.php');
    CMain::finalActions();
    die();
}

if(!AccessController::isViewSettings())
    $APPLICATION->AuthForm(Loc::getMessage("ACCESS_DENIED"));
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_after.php");

if ($request->getRequestMethod()==='POST' && AccessController::isEditSettings() && $request->get('Update'))
{
    //Option::set($module_id, "test", $request->get("test")=='Y' ? 'Y' : 'N', "");
}

$aTabs = array();

$aTabs[] = array(
    "DIV" => "edit1",
    "TAB" => Loc::getMessage('PARTNER_MODULE_OPT_SECT1'),
    "ICON" => "vote_settings",
    "TITLE" => Loc::getMessage('PARTNER_MODULE_OPT_SECT1')
);

$saveUrl = $APPLICATION->GetCurPage(false).'?mid='.htmlspecialcharsbx($module_id).'&lang='.LANGUAGE_ID.'&mid_menu=1';
$tabControl = new CAdminTabControl("tabControl", $aTabs);
$tabControl->Begin();
?>
    <style>.adm-workarea option:checked {background-color: rgb(206, 206, 206);}</style>
    <form method="POST" action="<?=$saveUrl?>" id="FORMACTION">
        <?
        $tabControl->BeginNextTab();
        ?>
        <?if(false){?>
        <tr>
            <td style="width:200px;"><?=Loc::getMessage('PARTNER_MODULE_OPT_TEST_TITLE')?></td>
            <td>
                <?$val = Option::get($module_id, "test", "N","");?>
                <input type="checkbox" value="Y" name="test" <?if ($val=="Y") echo "checked";?>></td>
            </td>
        </tr>
        <?}?>
        <?
        $tabControl->Buttons();
        ?>
        <input <?if (!AccessController::isEditSettings()) echo "disabled" ?> type="submit" class="adm-btn-green" name="Update" value="<?=Loc::getMessage('PARTNER_MODULE_OPT_L_BTN_SAVE')?>" />
        <input type="hidden" name="Update" value="Y" />
        <?if(AccessController::isViewRight()){?>
            <button class="adm-header-btn adm-security-btn" onclick="BX.SidePanel.Instance.open('<?=$saveUrl?>');return false;">
                <?=Loc::getMessage('PARTNER_MODULE_OPT_SECT2')?>
            </button>
        <?}?>
        <?$tabControl->End();?>
    </form>
<?
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_admin.php");

/lang/ru/options.php

<?
$MESS["PARTNER_MODULE_OPT_TITLE"] = "Модуль partner.module";
$MESS["PARTNER_MODULE_OPT_SECT1"] = "Настройки модуля";
$MESS["PARTNER_MODULE_OPT_SECT2"] = "Права доступа";
$MESS["PARTNER_MODULE_OPT_L_BTN_SAVE"] = "Сохранить";
$MESS["PARTNER_MODULE_OPT_TEST_TITLE"] = "Тестовый режим";

9.4 updater.php обновления модуля

<?
$moduleId = "partner.module";
if(IsModuleInstalled($moduleId)) {
    $updater->CopyFiles(
        "install/components/module.config.permissions",
        "components/partner/module.config.permissions",
        true,
        true
    );
    $connection = \Bitrix\Main\Application::getConnection();
    if($connection->getType()=='mysql'){
        $sql = "CREATE TABLE IF NOT EXISTS partner_module_role (
        ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
        NAME VARCHAR(250) NOT NULL,
        PRIMARY KEY (ID)
        );";
        $connection->queryExecute($sql);
        $sql = "CREATE TABLE IF NOT EXISTS partner_module_role_relation (
        ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
        ROLE_ID INT(10) UNSIGNED NOT NULL,
        RELATION VARCHAR(8) NOT NULL DEFAULT '',
        PRIMARY KEY (ID),
        INDEX ROLE_ID (ROLE_ID),
        INDEX RELATION (RELATION)
        );";
        $connection->queryExecute($sql);
        $sql = "CREATE TABLE IF NOT EXISTS partner_module_permission (
        ID INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
        ROLE_ID INT(10) UNSIGNED NOT NULL,
        PERMISSION_ID VARCHAR(32) NOT NULL DEFAULT '0',
        VALUE TINYINT(3) UNSIGNED NOT NULL DEFAULT '0',
        PRIMARY KEY (ID),
        INDEX ROLE_ID (ROLE_ID),
        INDEX PERMISSION_ID (PERMISSION_ID)
        );";
        $connection->queryExecute($sql);
    }
    elseif($connection->getType()=='pgsql' && !$updater->TableExists('partner_module_permission')){
        $sql = "CREATE TABLE partner_module_role (
        ID int GENERATED BY DEFAULT AS IDENTITY NOT NULL,
        NAME varchar(250) NOT NULL,
        PRIMARY KEY (ID)
        );";
        $connection->queryExecute($sql);
        $sql = "CREATE TABLE partner_module_role_relation (
        ID int GENERATED BY DEFAULT AS IDENTITY NOT NULL,
        ROLE_ID int NOT NULL DEFAULT 0,
        RELATION varchar(8) NOT NULL DEFAULT '',
        PRIMARY KEY (ID)
        );";
        $connection->queryExecute($sql);
        $sql = "CREATE TABLE partner_module_permission (
        ID int GENERATED BY DEFAULT AS IDENTITY NOT NULL,
        ROLE_ID int NOT NULL DEFAULT 0,
        PERMISSION_ID varchar(32) NOT NULL DEFAULT '0',
        VALUE int NOT NULL DEFAULT 0,
        PRIMARY KEY (ID)
        );";
        $connection->queryExecute($sql);
        $connection->queryExecute(
            'CREATE INDEX partner_module_role_relation_role_id ON partner_module_role_relation (role_id);'
        );
        $connection->queryExecute(
            'CREATE INDEX partner_module_role_relation_relation ON partner_module_role_relation (relation);'
        );
        $connection->queryExecute(
            'CREATE INDEX partner_module_permission_role_id ON partner_module_permission (role_id);'
        );
        $connection->queryExecute(
            'CREATE INDEX partner_module_permission_permission_id ON partner_module_permission (permission_id);'
        );
    }

    $eventManager = \Bitrix\Main\EventManager::getInstance();
    $eventManager->registerEventHandlerCompatible(
        'main', 'OnAfterUserUpdate',
        $moduleId, '\\Partner\\Module\\Access\\Handlers', 'OnAfterUserUpdate'
    );
    $eventManager->registerEventHandlerCompatible(
        'main', 'OnAfterUserAdd',
        $moduleId, '\\Partner\\Module\\Access\\Handlers', 'OnAfterUserUpdate'
    );
}

9.5 пример menu.php

/bitrix/modules/partner.module/lang/ru/admin/menu.php

$MESS["PARTNER_MODULE_MENU_NAME"] = "partner.module";
$MESS["PARTNER_MODULE_MENU_NAME_SETT"] = "Настройки модуля";
$MESS["PARTNER_MODULE_MENU_NAME_SETT_1"] = "Общие настройки";
$MESS["PARTNER_MODULE_MENU_NAME_SETT_2"] = "Права доступа";

/bitrix/modules/partner.module/admin/menu.php

use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Loader;
use Bitrix\Main\Config\Option;
use Partner\Module\Access\AccessController;
use Partner\Module\Access\Custom\ActionDictionary;
Loc::loadMessages(__FILE__);
$module_id = "partner.module";
if(!Loader::includeModule($module_id)) return;

$items = [];
if(AccessController::isViewSettings() || AccessController::isViewRight()){
    $level2 = [];
    if(AccessController::isViewSettings()){
        $level2[] = [
            "text" => Loc::getMessage('PARTNER_MODULE_MENU_NAME_SETT_1'),
            "url" => "settings.php?lang=".LANGUAGE_ID.'&mid='.$module_id.'&mid_menu=1'
        ];
    }
    if(AccessController::isViewRight()){
        $level2[] = [
            "text" => Loc::getMessage('PARTNER_MODULE_MENU_NAME_SETT_2'),
            "url" => "javascript:BX.SidePanel.Instance.open('/bitrix/admin/settings.php?mid=".$module_id."&lang=".LANGUAGE_ID."&mid_menu=1');"
        ];
    }
    $items[] = [
        "text" => Loc::getMessage('PARTNER_MODULE_MENU_NAME_SETT'),
        "items_id" => str_replace('.','_',$module_id).'_sett',
        "items"=>$level2
    ];
}
if(empty($items)) return;
$aMenu[] = array(
    "parent_menu" => "global_menu_settings",
    "section" => str_replace('.','_',$module_id),
    "sort" => 100,
    "module_id" => $module_id,
    "text" => Loc::getMessage('PARTNER_MODULE_MENU_NAME'),
    "title" => Loc::getMessage('PARTNER_MODULE_MENU_NAME'),
    "items_id" => str_replace('.','_',$module_id),
    "items" => $items,
);
return $aMenu;

Обсуждение в Telegram

Для улучшения работы сайта используются cookie.
Подробнее об этом в Политике cookie.
Принять Настроить