Я работаю над веб-приложением Rails, и в настоящее время его используют около 20 пользователей.
Некоторые части приложения доступны только некоторым пользователям, поэтому у нас уже есть базовая структура авторизации, которую я реализовал с помощью плагинаcts_as_authenticated.
Права пользователей зависят от того, в каком отделе они работают, например, администрация имеет доступ ко всем частям приложения, в то время как бухгалтерский учет имеет доступ только к частям, связанным с бухгалтерским учетом, а отдел продаж имеет доступ только к частям, связанным с продажами и т. д.
С другой стороны, пользователи видят ссылки на действия, для которых у них недостаточно прав. Например, сотрудники отдела продаж видят ссылку на финансовые отчеты в главном меню, но когда они нажимают на нее, ничего не происходит. Это так, потому что AFAIK не существует эффективного способа запросить привилегии пользователя с помощью actions_as_authenticated.
Я хочу изменить это двумя способами:
Хочу ввести более детальную авторизацию. В настоящее время авторизация выполняется на уровне контроллера. Я хочу сделать это на уровне действия или модели. Например, я хочу, чтобы сотрудники отдела продаж могли создавать и обновлять платежи, но не удалять их.
Я хочу иметь возможность эффективно запрашивать права пользователей, чтобы удалить ненужные (и сбивающие с толку) ссылки из интерфейса.
Как вы думаете, какой способ реализовать это наиболее элегантно?
В ответах на Rails нет необходимости, я просто хочу знать, как это должно быть реализовано в приложении, управляемом данными.
Наконец, вот как это реализовано в настоящее время:
def authorized?
current_user.role.foo? or current_user.role.bar?
end
И вот моя первоначальная идея, которая, как мне кажется, не лучший способ решить эту проблему:
+------------+------------+---------+ | department | controller | action | +------------+------------+---------+ | accounting | payments | index | | accounting | payments | new | | accounting | payments | create | | accounting | payments | edit | | accounting | payments | update | | accounting | payments | destroy | | sales | payments | new | | sales | payments | create | | sales | payments | edit | | sales | payments | update | +------------+------------+---------+
или же
+------------+----------+-------+--------+------+--------+--------+ | department | model | list | create | read | update | delete | +------------+----------+-------+--------+------+--------+--------+ | accounting | payments | TRUE | TRUE | TRUE | TRUE | TRUE | | sales | payments | FALSE | TRUE | TRUE | TRUE | FALSE | +------------+----------+-------+--------+------+--------+--------+





вам может потребоваться ввести понятие «функциональных точек» или «функций» в вашу модель в качестве контрольных точек для доступа; «функция» может иметь необязательную «родительскую функцию» для формирования иерархии. Вы можете решить, что является функцией, а что нет, и программно проверить разрешения. Это также должно позволить вам проверить доступ на уровне функций перед рисованием меню, чтобы пользователи никогда не видели ссылки на страницы, к которым им не разрешен доступ.
аналогичная ситуация / решение описывается здесь
Из двух ваших предложений первый вариант выглядит немного лучше, поскольку он позволяет вам добавлять действия, которые могут не быть действиями на уровне модели. Я предполагаю, что вы столкнетесь с ситуацией, когда вторая модель не совсем подходит, и вам нужно будет либо изменить схему, либо начать разбрасывать логику разрешений по всему вашему приложению (например, «Пользователи без доступа для создания» также не может запустить метод xxx ")
Я думаю, что причина того, что решение не выглядит очень СУХИМ, в том, что есть повторение:
Что касается №1, имеет смысл создать таблицу отделов и присвоить каждому отделу идентификатор.
Что касается №2, я согласен с первым комментарием. Вы, вероятно, можете сгруппировать различные контроллеры и действия в функциональные группы, а затем установить отношения «многие ко многим» (таблица сопоставления) между пользователями и функциями. Тогда функции будут иметь отношение «один ко многим» с тем, какие действия / контроллеры они разрешают. Это позволит вам с минимальным повторением сказать такие вещи, как «бухгалтерия и продажи должны иметь возможность читать все финансовые таблицы».
Основное понятие авторизации, насколько я понимаю, - это роль. Роль может выражать разные вещи:
Действительно детализированная система авторизации должна позволять вам определять роль для пользователя на основе любого из вышеупомянутых критериев. Кроме того, это должно позволить вам установить более одной роли для пользователя. (Простейшие формы плагинов авторизации для Rails обычно позволяют вам определять только первый тип ролей и устанавливать только одну роль для пользователя.)
Другая часть авторизации - это механизм, который решает, какую часть кода запускать (или не запускать) в зависимости от того, подходит ли пользователь к той или иной роли (набору ролей) или нет. Чтобы применить этот механизм, мы должны найти точки, в которых должна происходить авторизация, и выбрать роли, для которых код должен или не должен запускаться.
Для меня в Rails работает способ определения ролей на уровне модели и выхода из механизма авторизации (установка разрешенных ролей для частей кода, которые я хочу авторизовать, и вопрос, есть ли у текущего пользователя роль, которой разрешено запускать эту часть. ) полностью для контроллеров / представлений.
Для этого я использую настроенный плагин rails-authorization-plugin, который имеет все встроенные возможности, о которых я только что упомянул (различные виды ролей, множество ролей для одного пользователя, авторизация на контроллере и уровне представления).
У меня уже есть таблица отделов и таблица users_departments. Я упростил примерную таблицу для краткости.