Сложная проблема с дизайном класса

#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 довольно четко определяет поведение.