Содержание
Этап разработки системы прав
Введение
На этом этапе мы разработаем экраны списка ролей и пользователей системы, наладим работу контроллера прав, проставим права в описатели таблиц, главное меню системы.
Развертывание этапа на площадке
- Скачаем архив LSS проекта для текущего этапа.
- Обновим проект из архива. Надо быть осторожным с конфигурационным файлом площадки php/config/config-place.php, он содержит текущие параметры соединения с базой данных, его обновлять не надо.
- Выполним с помощью утилиты pgAdmin скрипт обновления содержимого системных таблиц, файл export-import/backup/backup.sql.
Описание
Экранная форма ролей formRole
Описание экранной формы ролей расположено в файле php/perm/formRole.xml. Это описание практически идентично описанию стандартной формы справочника.
Экранная форма пользователей formUser
Описание экранной формы ролей расположено в файле php/perm/formUser.xml. Это описание практически идентично описанию стандартной формы справочника.
Контроллер источника данных пользователей
Файл контроллера php/datasources/user.php:
class DataSource_User_Ext extends DataSource_User { protected function onRowAfter(&$row, $params=Array()) { if ($row['password']) $row['password']='***'; } protected function onBeforeSave(&$params) { if ($params['password']) $params['password']=cryptPassword($params['password']); } } return new DataSource_User_Ext();
- обработчик onRowAfter скрывает отображение паролей пользователей, заменяя их на звездочки.
- обработчик onBeforeSave шифрует пароль пользователя перед сохранением в базе данных. Функция cryptPassword обеспечивает простейшее шифрование по md5 с солью.
- в описатель поля password таблицы user добавлен атрибут save=1 (см экранную форму Разработка/Структура базы). В результате правка этого поля вызывает автоматическое сохранение изменений строки таблицы. А в ответе вместо значения поля пароля приходят звездочки.
Контроллер прав доступа
Контроллер прав доступа PermController размещен в файле php/perm.php:
<?php class PermControllerPrj extends PermController { public function getPerm($mode, $operation) { // Если пользователь не авторизован, то ничего нельзя if (!getPP('isconnected')) return false; if ($mode=='connected') return true; // Если у пользователя права isroot, то все можно. Тут разрешаем и дальше уже проверять не будем if (getPP('isroot')) return true; // Режим root доступен только пользователю с правами isroot if ($mode=='root') return false; // Права доступны только АДМ if ($mode=='perm') { if (getPP('role')=='АДМ') return true; return false; } // Справочники на чтение доступны всем, а на правку только АДМ if ($mode=='ref') { if ($operation=='read') return true; if ($operation=='write' && getPP('role')=='АДМ') return true; return false; } // Системные справочники на чтение доступны всем, а на правку только isroot if ($mode=='rootref') { if ($operation=='read') return true; return false; } // Оборудование на чтение всем, на правку АДМ и ПРВ if ($mode=='machine') { if ($operation=='read') return true; if ($operation=='write' && (getPP('role')=='АДМ' || getPP('role')=='ПРВ')) return true; return false; } // Отчеты доступны всем - АДМ, ПРВ, ОТЧ if ($mode=='report') { if (getPP('role')=='АДМ' || getPP('role')=='ПРВ' || getPP('role')=='ОТЧ') return true; return false; } return false; } public function execConnect($login, $password) { $this->execDisconnect(); session_start(); try { if ($login==getCfg('root.login','root') && cryptPassword($password)==getCfg('root.password')) { $_SESSION['connect_isconnected']=true; $_SESSION['connect_login']='root'; if (getCfg('root.enabled', true)) { $_SESSION['connect_isroot']=true; } else { $_SESSION['connect_role']='АДМ'; } return true; } $sql_login=$this->str2Sql($login); $sql_password=$this->str2Sql(cryptPassword($password)); $sql=<<<SQL select "user".*, "role".code as role_code from "user" left join "role" on "role".id="user".roleid where "user".login='{$sql_login}' and "user".password='{$sql_password}' SQL; $rec=$this->pdoFetch($sql); if ($rec['id']) { $_SESSION['connect_isconnected']=true; $_SESSION['connect_login']=$rec['fio']; $_SESSION['connect_role']=$rec['role_code']; return true; } } finally { // защита от CSRF уязвимости посредством токена if (getCfg('csrftoken.enabled')) $_SESSION['connect_csrftoken']=getGUID(); session_write_close(); } return false; } } return new PermControllerPrj();
- метод execConnect вызывается диалогом аутентификации посредством запроса connect. Отдельно проверяется пользователь root, его параметры берутся из конфигурационного файла. Отдельно проверяются все остальные пользователи - на основе содержимого таблицы user. Если логин и пароль указаны правильно, то параметры пользователя сохраняются в сессии.
- метод getPerm проверяет доступность по правам текущему пользователю режима работы системы. Используем следующие режимы:
- connected - доступно всем авторизованным пользователям. Если проверка не прошла, то пользователя автоматически перенаправляют на экран аутентификации, посредством отправки ответа disconnected.
- root - доступно только пользователю root, например пункт меню Разработка должен быть доступен только программисту.
- ref - справочники, на чтение доступны всем авторизованным пользователям, правка только администратору
- rootref - системные справочники, на чтение доступны всем авторизованным пользователям, правка только root
- machine - работа с оборудованием и ремонтами, на чтение доступно всем авторизованным пользователям, правка доступна администратору и роли ПРВ
- report - выполнение отчетов, доступно всем авторизированным пользователям
- perm - пользователи и права, доступно только администратору
Права в описателях структуры данных
Экранная форма Разработка/Структура базы позволяет назначить режим прав каждой таблице (поле Режим по правам). Затем можно вызвать Пересчет/Генерация классов DataSource и перенести эти права в контроллеры источников данных DataSource.
Помимо режима прав (параметр mode) DataSource делит запросы на операции (параметр operation) read и write. Соответственно, контроллер прав PermController определяет доступность соответствующей операции текущему пользователю.
Права в главном меню системы
Проставим права в описании главного меню системы, файл php/config/appmenu.xml:
<root> <node name="Паспорта оборудования и ремонты" icon="box" form="formMachine" permmode="machine" permoper="read"/> <node name="Типы оборудования и нормативы ремонтов" icon="ref" form="ref.formMachineType" permmode="machine" permoper="read"/> <node name="Отчеты" icon="print" permmode="report" permoper="read"> <node name="Отчет по плану ремонтов" icon="print" form="reports.formReportPlan" permmode="report" permoper="read"/> <node name="Отчет по выполненным ремонтам" icon="print" form="reports.formReportFact" permmode="report" permoper="read"/> </node> <node name="Справочники" icon="reffolder" permmode="ref" permoper="read"> <node name="Структура предприятия" icon="ref" form="ref.formDepartment" permmode="ref" permoper="read"/> <node name="Виды ремонта" icon="ref" form="ref.formRepair" permmode="ref" permoper="read"/> <node name="Состояния оборудования" icon="ref" form="ref.formMachineStatus" permmode="ref" permoper="read"/> </node> <node name="Доступ" icon="perm" permmode="perm" permoper="read"> <node name="Пользователи" icon="user" form="perm.formUser" permmode="perm" permoper="read"/> <node name="Роли" icon="usergroup" form="perm.formRole" permmode="rootref" permoper="read"/> </node> <node name="Разработка" icon="root" permmode="root" permoper="read"> <node name="Структура базы" icon="tree" form="formSysTreeDataModel"/> <node name="Иконки" icon="icon" form="formSysIcons"/> </node> </root>
Права в контроллерах отчетов
Добавим проверку прав в контроллеры отчетов plan и fact:
class ReportPlan extends ReportController { public function getParams() { if (!getPerm('report','read')) throw new Exception('У Вас нет прав на выполнение этого отчета'); ...
Демонстрационные примеры и ссылки
Демонстрационные примеры доступны в режиме «только чтение». Для входа используйте логин root, пароль 1.
- демонстрация работы тестового примера «Материальные активы» у нас на сайте: https://lss.m-cti.ru/storage/example/lss-exampl