Делать звонки Catalyst от модели? - PullRequest
4 голосов
/ 01 сентября 2009

Я использую Катализатор с Catalyst::Plugin::Authentication и Catalyst::Plugin::Authorization::Roles и мне интересно, есть ли лучшее подход к добавлению атрибута к модели, которого я не вижу.

Каждому пользователю разрешен доступ к одной или нескольким компаниям, но есть всегда одна основная (текущая) компания за раз. Разрешенный список хранится в базе данных, и доступ к базе данных в основном осуществляется через DBIC.

Мое первое желание - сказать, что у пользователя есть текущий компания, и, следовательно, положить его как часть модели пользователя: дать пользователю пакет "sub company { … }", чтобы получить / установить текущую компанию пользователя. проверка базы данных довольно проста; просто используйте "$self->search_related" (DBIC метод, унаследованный пользовательской моделью).

Проблемы, с которыми я сталкиваюсь:

  • Текущая компания должна сохраняться между запросами, но я бы предпочел не хранить его в базе данных (он должен сохраняться только для этого сессия). Естественное место - сессия…
  • Существует роль, похожая на root Unix, которая позволяет вам действовать как любая компания, игнорируя список в базе данных. Проверка этой роли может быть сделано через базу данных, но везде в приложении используется $c->assert_user_role и друзья.

Я слышал, что лучше всего сохранять модели как независимые от Catalyst, так как возможный. Также довольно странно иметь модель манипулирования $c->session.

Конечно, я мог бы перенести эти проверки на контроллеры и получить модель принимает все, что отправляет контроллер, но это нарушает СУХОЙ довольно сильно, и просто умоляю о проблеме безопасности, если я забуду один из чеки где-то.

Есть предложения? Или мне просто пожать плечами и пойти дальше и сделать это в модели?

Спасибо, и извиняюсь за название, я не смог придумать хороший.

1 Ответ

2 голосов
/ 01 сентября 2009

Ключом является создание экземпляра класса модели для каждого запроса, а затем передача необходимых вам частей запроса. В этом случае вы, вероятно, захотите передать базовый набор результатов. Ваша модель будет выполнять все вызовы базы данных через $self->resultset->..., и она будет «просто работать» для текущего пользователя. (Если текущий пользователь является пользователем root, то вы просто передаете $schema->resultset("Foo"). Если текущим пользователем является кто-то другой, тогда передайте $schema->resultset("Foo")->stuff_that_can_be_seen_by($c->user). Ваша модель больше не заботится.)

У меня есть несколько слайдов по этому поводу, но они очень устарели:

http://www.jrock.us/doqueue-grr/slide95c.html#end

(См. Также непосредственно до и после).

Обратите внимание, что ограниченные наборы результатов и веб-ACL являются ортогональными. Вы хотите сделать модель как можно более узкой (чтобы ваше приложение не могло случайно сделать то, чего вы не хотите, даже если в коде написано это), но различные подробности, связанные только с веб-интерфейсом, все равно должны быть закодированы в списки управления доступом. («Вам не разрешено просматривать эту страницу.» Отличается от «Вы можете удалять только свои собственные объекты, а не все». ACL обрабатывает первый случай, ограниченный набор результатов обрабатывает второй. Даже если вы пишете $rs->delete, так как набор результатов ограничен, вы не удалили все в базе данных. Вы удалили только то, что имеете право удалять. Удобно!)

...