#oop #design-patterns #class-design
#ооп #шаблоны проектирования #дизайн класса
Вопрос:
Я работаю над внедрением класса для управления разрешениями пользователей на моем веб-сайте.
Например: сотрудники могут просматривать записи клиентов, но ничего больше, работодатели могут просматривать клиентов, а также управлять сотрудниками, а администраторы могут делать обе эти вещи, а также управлять работодателями.
Пока что у меня получилось вот что:
-
Я сохранил список разрешений, например
addCustomer
,delCustomer
и т.д. Каждое разрешение связано со списком ролей пользователей, которым разрешено выполнять это действие. -
Я создал простой класс разрешений. Я использую это примерно так:
если ($permissions->can(‘AddCustomer’)) echo «Добавить клиента»; иначе echo «Не разрешено добавлять клиентов»;
Однако сложность заключается в том, что в некоторых местах мне нужно быть более конкретным. Например: клиент получил разрешение: readMsgs
которое позволяет ему читать сообщения между ним и сотрудником. Однако, если у него есть такое разрешение, он может просто изменить URL с:
site.com/messages/read/100
Для
site.com/messages/read/101
И прочитайте также сообщение # 101, которое может быть между другим клиентом и сотрудником. Клиент не должен иметь возможности читать чьи-либо сообщения, кроме себя.
Аналогично, клиент получил editCustomer
разрешение, которое позволяет ему редактировать свой собственный профиль, перейдя на:
site.com/customers/99
(где 99 — это его идентификатор клиента)
Но если он перейдет к site.com/customers/100
Ему не следует разрешать доступ к этой странице.
Как я могу решить эту проблему? В идеале я хотел бы иметь возможность передавать идентификатор классу разрешений. Например:
if (! $permissions->can('readMsg', $msgId))
echo 'not allowed';
if (! $permissions->can('editCustomer', $requestedCustomerId))
echo 'not allowed';
Есть идеи, как мне нужно было бы реструктурировать структуру моего класса, чтобы разрешить вышеуказанные вещи?
Ответ №1:
Я бы был более детализирован в своей таксономии разрешений (например, «readOwnMsgs» против «readAnyMsg»). Это привело бы к доработке вашего кода проверки разрешений (например, site.com/messages/read /### звучит что-то вроде «продолжить, если canReadAnyMsg или если canReadOwnMsg и автором сообщения является текущий пользователь»), предполагая, что эта логика должна быть инкапсулирована в отдельные классы с разбивкой по типу ресурса или любым другим обстоятельствам, которые могут повлиять на контекстную информацию, необходимую для принятия таких решений.
Ответ №2:
У меня был бы класс сообщений с canRead(User)
функцией. Это проверит разрешения пользователя и скажет: «О, я сообщение от менеджера сотруднику. Если пользователь не является получателем сообщения, он не сможет его прочитать «. или так же просто «Я сообщение от менеджера сотруднику. Пользователь — менеджер, поэтому он может это прочитать.»
Я печатаю это на английском, потому что я не владею php (который, похоже, является языком выбора).
Комментарии:
1. Я знаю Java, так что не стесняйтесь вводить это, если так будет проще. Но проблема в том, как класс узнает, является ли это запросом на чтение сообщения от сотрудника X клиенту X или это запрос на редактирование профиля клиента X? В обоих случаях, как только класс узнает, какой это класс, он может затем проверить, является ли текущий пользователь клиентом Y, и в этом случае запрос будет отклонен.
2. Я не уверен, что понимаю природу вашего последующего вопроса. Как бы ваш запрос не знал?
messages/read/XYZ
довольно четко определяет поведение.