Как работать с разрешениями пользователей при работе с пользователями системы администрирования и пользователями интерфейсного сайта? - PullRequest
5 голосов
/ 21 сентября 2011

Может ли кто-нибудь порекомендовать источник информации или рабочий пример, показывающий, как обращаться с разрешениями на доступ при одновременной работе с пользователями системы администратора и пользователями веб-сайта?

Наш код на данный момент напоминает большую версию интернет-магазина, где несколько сотрудников управляют заказами с помощью системы администратора, а любое количество клиентов - с помощью веб-сайта. Система администрирования построена на основе списка контроля доступа (например, LiveUser), но существует довольно большой «бэнд-бэнд», в который входит один «фиктивный» пользователь, играющий роль всех пользователей сайта (всех клиентов).

В идеале код приложения будет использовать такие фразы, как can_place_order(), чтобы определить, может ли пользователь выполнить задачу. Заказчик может разместить заказ, если уровень запасов не меньше, чем количество заказа, и он произвел оплату на сумму заказа. Пользователь с правами администратора может разместить заказ, если у него есть роль customer_services.

В идеале мы хотели бы расширить систему, чтобы некоторые зарегистрированные клиенты могли размещать заказы без достаточных запасов или оплаты, просто создав вместо этого счет-фактуру и предварительный заказ. Это будет как минимум две «роли» клиентов в дополнение к «ролям» многих сотрудников ...

  • Как я могу использовать одну и ту же систему разрешений с двумя отдельными списками пользователей?
  • Или, как я могу объединить два очевидных набора пользователей в один список?

Мы используем php & MySQL для приложения, но приветствуются любые другие языковые шаблоны.

1 Ответ

4 голосов
/ 22 сентября 2011

Я перепробовал множество различных схем для разрешений, и я когда-либо нашел только один способ заставить их работать, который удовлетворяет программиста И клиентов почти во всех случаях. И это делает их частично управляемыми данными.

Моя последняя попытка работает так:

  1. Каждый пользователь имеет прикрепленный к нему объект прав доступа. В моем случае создается автоматически при запросе пользователя. (В моем случае разрешения могут быть разными для разных разделов. Поэтому пользователю может быть разрешено делать X для Y, но не для Z.)
  2. Каждая страница, блок кода или представление, которое должно быть разрешающим, заключено в оператор if, который проверяет объект разрешения. Если это разрешение должно беспокоить и раздел, то текущие соответствующие идентификаторы раздела передаются в виде массива, возвращая новый массив bools для сопоставления.
  3. Интерфейс тогда не раскрывает этот сложный беспорядок непосредственно пользователям, вместо этого интерфейс superadmin позволяет создавать новые типы пользователей. Эти типы несут наборы разрешений, которые будут включены для этого «типа» пользователя. Разрешения разных типов могут перекрываться, поэтому как администратор, так и редактор могут «редактировать копию» или что-либо подобное.
  4. Нормальный интерфейс администратора позволяет отдельным пользователям назначаться разными типами пользователей для разных разделов. Таким образом, один пользователь может быть администратором для раздела 2 и редактором для разделов 2, 3, 4 и 5. Они также могут быть установлены глобально, что перегружает неиспользуемый раздел (0).

Это имеет много преимуществ и один недостаток. Во-первых, недостаток. Поскольку эти ключи запекаются непосредственно в коде, только суперадмин (он же разработчик) должен иметь доступ к этой части интерфейса. Действительно, интерфейс может вообще не понадобиться, так как список разрешений должен меняться только с кодом. Настоящая проблема здесь в том, что вы не будете знать, что с заголовком что-то не так, пока не запустите код, так как синтаксис будет просто отличным. Теперь, если бы это было закодировано в чем-то вроде C #, это было бы очень серьезной проблемой. Но практически все в PHP не является типобезопасным, поэтому на самом деле это просто номинал для курса. Эти значения также могут быть загружены из файла конфигурации или даже запрограммированы в графическом интерфейсе, из которого вы строите пользовательские типы, хотя это кажется неправильным.

Что вы получаете от этого, так это возможность устанавливать новые типы разрешений на лету. Вы получаете возможность переименовывать эти разрешения с относительной легкостью. (Поскольку система просто использует номер, заголовок используется только для захвата номера, поэтому его можно легко изменить всего в нескольких местах.) И код очень прост в использовании. Это будет выглядеть примерно так:

if($current_user->permissions->can("View Sales Records"))
{
    //Code to view sales records
}

Или немного сложнее

$sections = array(1,2,3,4); //Probably really a list of all sections in the system
$section_permissions = $current_user->permissions->these($sections)->can("Edit Section");
foreach($sections as $s)
{
    if($section_permissions[$s])
    {
        // Code for maybe displaying a list of sections to edit or something
    }
}

Метод цепочки также довольно прост. ->these() устанавливает внутренний массив для этих значений и затем возвращает ссылку на сам объект. ->can() затем действует в этом списке, если он существует, и затем отменяет его. В моей собственной версии у меня также есть ->any(), который всегда возвращает полный список разделов, поэтому я могу проверить ->any()->can().

Наконец, объект прав доступа также содержит список типов пользователей. Что позволяет действительно легко показать список пользователей и какие разрешения у них активны. В моем случае мы просто используем ->types() для доступа к этому списку и массиву ids => names.

Отсутствующие заголовки разрешений просто игнорируются. Они также сопоставляются в нижнем регистре с удаленными пробелами и специальными символами, чтобы помочь уменьшить проблемы с ошибками ввода Я подумал даже сделать проверку расстояния Левенштейна и выбрать ближайший матч. Но, в конце концов, лучше не полагаться на что-то подобное. (возможно зарегистрируйте ошибку, но изящно выберите ближайшее совпадение.)

Вне кода и в интерфейсе пользователям необходимо только общаться друг с другом в «Со-в-так» - это «Администратор», «Редактор», «Издатель», «Автор» и «Генеральный директор» и так далее. Также было бы тривиально создавать разные наборы пользовательских типов для разных организаций.

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

Я только хотел бы поделиться с вами настоящим кодом. Я просто не владею им и поэтому не могу опубликовать это.

...