I've been kicking some ideas around for a few days and not coming up with a
solution I like.  So, I'm now asking for help here from the Moose
community, specifically for fresh ideas for adding a permissions
architecture on top of my Moose classes.


Some time back we started replacing one big, ugly monolithic web app with
Catalyst.  We used DBIC as the "Model" layer as is commonly done and pushed
much business logic into Result and ResultSet classes.

But with a dozen or so developers, some with old habits, I see our
Controllers growing fat with business logic.  But, we need to be able to
use the "app" in more than just Catalyst (and in more than one Catalyst
app, as well), so I'm working on adding a Moose-based Model layer that sits
on top of our DBIC layer where that business logic can be located (and thus
used by many consumers).

One handy thing about Catalyst is we are able to hook into the request and
see what "action" is going to run before it runs.  That makes it pretty
easy to
do things like centralized data validation (which is why I asked about
"automatically" wrapping methods) and access control before an action runs.

The other thing Catalyst does is abstract out the model methods by URL. So
"GET /widget/123" can read a row from the widget table if the user has
access, an "PUT /widget/123/owner" might set a column on the same widget
row but makes it easy to add additional access/permission checking (you
have access AND be an admin or current "owner" of the widget).

I don't want to reinvent Catalyst, but I now have a set of Moose classes
that sit on top of DBIC (and other data sources) that mostly provides an
abstraction layer to hold that code that was sitting in the fat Catalyst
controllers.  But, I'd like to separate out the access/permission checking
from the work of fetching and updating -- a large number of methods in this
new model need to test the same permissions.

Access/permission control is very important -- and in our app tends to be
complex and expensive to test.  So, I'd like to have this live as it's own
set of classes (with its own tests, and caching, etc.).  Something that
enforces a clean separation of concerns and is easier to maintain.   And
that is the architecture I'm struggling with.


Anyone have suggestions how to use Moose to structure this?

It's not a terribly hard problem, but again looking for something a bit
more clever than just:

package App::Model::Widget;
use Moose;

sub set_widget_owner {
     my ( $self, $new_owner, $current_user ) = @_;

     die unless $self->access_layer->widget->can_set_owner( $self,
$current_user );

     # update owner
     ...
}




-- 
Bill Moseley
mose...@hank.org

Reply via email to