Making Catalyst calls from a model?

I'm using the Catalyst from Catalyst::Plugin::Authentication and Catalyst::Plugin::Authorization::Roles , and I wonder whether there is an approach to adding an attribute to a model that I can not see.

Each user is allowed access to one or more companies, but there is always one primary (current) company at a time. A valid list is stored in the database, and access to the database is done primarily through DBIC .

My first inclination is to say that this is a user who has the current company, and thus put it as part of the user model: give the user the package " sub company { … } " to get / set the current company of the user. checking the database is pretty simple; just use " $self->search_related " (DBIC method inherited by the user model).

The problems that I encountered are as follows:

  • The current company should persist between requests, but I would prefer not to store it in the database (it should be saved only for this session). A natural place is a session ...
  • There is a role similar to Unix root , which allows you to act like any company, ignoring the list in the database. Verification of this role can be done through the database, but wherever the application $c->assert_user_role and friends is used.

I heard that it is best to keep the models as independent of Catalyst as possible. It also seems strange to have a $c->session manipulation model.

Of course, I could transfer these checks to the controllers and the model accepts everything that the controller sends, but it violates DRY quite hard, and just begging for a security problem if I forget one of the checks somewhere.

Any suggestions? Or am I just shrugging my shoulders and doing it in the model?

Thank you, and an apology for the title, I could not come up with a good one.

+4
source share
1 answer

The key is to create an instance of the model class for each request, and then pass parts of the requested request. In this case, you probably want to switch to the basic result set. Your model will make all database calls through $self->resultset->... , and it will "just work" for the current user. (If the current user is root, then you just go to $schema->resultset("Foo") . If the current user is someone else, go to $schema->resultset("Foo")->stuff_that_can_be_seen_by($c->user) . Your model does not care anymore).

I have some slides about this, but they are very outdated:

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

(See material immediately before and after, too.)

Note that limited result and network ACLs are orthogonal. You want to make the model as dense as possible (so that your application cannot accidentally do what you do not want, even if the code says), but various data only on the Internet should still be encoded into access control lists. (“You cannot view this page.” It is different from “You can only delete your own objects, not all." The ACL handles the first case, the limited result set processes the second. Even if you write $rs->delete , because the result set is limited , you did not delete everything in the database. You only deleted what you have to delete. Convenient!)

+2
source

All Articles