Catalyst-Manual
view release on metacpan or search on metacpan
lib/Catalyst/Manual/Cookbook.pod view on Meta::CPAN
administrator
=item *
moderator
=back
each with a distinct task (system administration versus content
administration).
=head3 Access Control Lists
Checking for roles all the time can be tedious and error prone.
The Authorization::ACL plugin lets us declare where we'd like checks
to be done automatically for us.
For example, we may want to completely block out anyone who isn't a
C<moose_feeder> from the entire C<MooseCage> controller:
Zoo->deny_access_unless( "/moose_cage", [qw/moose_feeder/] );
The role list behaves in the same way as C<check_roles>. However, the
ACL plugin isn't limited to just interacting with the Roles plugin. We
can use a code reference instead. For example, to allow either moose
trainers or moose feeders into the moose cage, we can create a more
complex check:
Zoo->deny_access_unless( "/moose_cage", sub {
my $c = shift;
$c->check_roles( "moose_trainer" ) || $c->check_roles( "moose_feeder" );
});
The more specific a role, the earlier it will be checked. Let's say
moose feeders are now restricted to only the C<feed_moose> action,
while moose trainers get access everywhere:
Zoo->deny_access_unless( "/moose_cage", [qw/moose_trainer/] );
Zoo->allow_access_if( "/moose_cage/feed_moose", [qw/moose_feeder/]);
When the C<feed_moose> action is accessed the second check will be
made. If the user is a C<moose_feeder>, then access will be
immediately granted. Otherwise, the next rule in line will be tested -
the one checking for a C<moose_trainer>. If this rule is not
satisfied, access will be immediately denied.
Rules applied to the same path will be checked in the order they were
added.
Lastly, handling access denial events is done by creating an
C<access_denied> private action:
sub access_denied : Private {
my ( $self, $c, $action ) = @_;
}
This action works much like auto, in that it is inherited across
namespaces (not like object oriented code). This means that the
C<access_denied> action which is B<nearest> to the action which was
blocked will be triggered.
If this action does not exist, an error will be thrown, which you can
clean up in your C<end> private action instead.
Also, it's important to note that if you restrict access to "/" then
C<end>, C<default>, etc. will also be restricted.
MyApp->acl_allow_root_internals;
will create rules that permit access to C<end>, C<begin>, and C<auto> in the
root of your app (but not in any other controller).
=head1 Models
Models are where application data belongs. Catalyst is extremely
flexible with the kind of models that it can use. The recipes here
are just the start.
=head2 Using existing DBIC (etc.) classes with Catalyst
Many people have existing Model classes that they would like to use
with Catalyst (or, conversely, they want to write Catalyst models that
can be used outside of Catalyst, e.g. in a cron job). It's trivial to
write a simple component in Catalyst that slurps in an outside Model:
package MyApp::Model::DB;
use base qw/Catalyst::Model::DBIC::Schema/;
__PACKAGE__->config(
schema_class => 'Some::DBIC::Schema',
connect_info => ['dbi:SQLite:foo.db', '', '', {AutoCommit=>1}],
);
1;
and that's it! Now C<Some::DBIC::Schema> is part of your
Cat app as C<MyApp::Model::DB>.
=head2 DBIx::Class as a Catalyst Model
See L<Catalyst::Model::DBIC::Schema>.
=head2 Create accessors to preload static data once per server instance
When you have data that you want to load just once from the model at
startup, instead of for each request, use mk_group_accessors to
create accessors and tie them to resultsets in your package that
inherits from DBIx::Class::Schema:
package My::Schema;
use base qw/DBIx::Class::Schema/;
__PACKAGE__->register_class('RESULTSOURCEMONIKER',
'My::Schema::RESULTSOURCE');
__PACKAGE__->mk_group_accessors('simple' =>
qw(ACCESSORNAME1 ACCESSORNAME2 ACCESSORNAMEn));
sub connection {
my ($self, @rest) = @_;
$self->next::method(@rest);
( run in 2.319 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )