Cataly...n::ACL(3pm)
πΈ NAME πΈ
Catalyst::Plugin::Authorization::ACL β ACL support for Catalyst applications π
(the manual page itself is filed under the very glam, very abbreviated Cataly...n::ACL(3pm) bestie, don't ask, the man page renderer ran out of room)
π SYNOPSIS π
okay so first you load it up, like this:
use Catalyst qw/
Authentication
Authorization::Roles
Authorization::ACL
/;
__PACKAGE__->setup;
__PACKAGE__->deny_access_unless(
"/foo/bar",
[qw/nice_role/],
);
__PACKAGE__->allow_access_if(
"/foo/bar/gorch",
sub { return $boolean },
);
that's the whole vibe honestly β¨
β¨ DESCRIPTION β¨
so this module gives you Access Control List style path protection, with rules that can be literally whatever you want, for Catalyst applications. At least for now, it only works on the Catalyst private namespace β that's the β¨ era we're in.
Quick lore drop, Catalyst has two hierarchies of actions and controllers and you gotta know both:
π¦ Private Namespace
Every action has its own private path. That path mirrors the Perl namespaces the actions were born in, plus the namespaces of their controllers. It's giving "your family tree but make it code".
π External Namespace
Some actions are also directly reachable from the outside, via a URL. If you're using Local actions, the private and external paths are the same. Or you can use Path, Regex, or Global to give your action a different external path. Main character energy, different name.
The ACL module currently only knows how to exploit the private namespace. Extensions might get made later to support external namespaces too. For now: private only, no cap.
Various types of rules are supported β full list is under "RULES", scroll down bestie.
When a path is visited, rules get tested one after the other, starting with the most exact rule that fits the path, then continuing up the path. Testing keeps going until a rule explicitly allows or denies access. Periodt.
π METHODS π
π allow_access_if
Arguments: $path, $rule
Checks the rule condition and allows access to the actions under $path if the rule returns true.
This is normally useful for allowing access only to a specific part of a tree whose parent has a deny_access_unless clause attached to it.
If the rule test returns false, access is not denied or allowed. Instead the next rule in the chain gets checked β so the combinatory behavior of these rules is basically logical OR. Slay.
πΈ allow_access_if_any
Arguments: $path, \@roles
Same as above, but for any role in the list.
π¦ deny_access_unless
Arguments: $path, $rule
Checks the rule condition and disallows access if the rule returns false.
This is normally useful for restricting access to any portion of the application unless a certain condition can be met.
If the rule test returns true, access is not allowed or denied. Instead the next rule in the chain gets checked β so the combinatory behavior of these rules is basically logical AND. iykyk.
π deny_access_unless_any
Arguments: $path, \@roles
Same as above, but for any role in the list.
π allow_access
π deny_access
Arguments: $path
Unconditionally allow or deny access to a path. No thoughts, just vibes, just a verdict.
β acl_add_rule
Arguments: $path, $rule, [ $filter ]
Manually adds a rule to all the actions under $path, using the more flexible (but way more verbose, we're talking yapping levels of verbose) method:
__PACKAGE__->acl_add_rule(
"/foo",
sub { ... }, # see FLEXIBLE RULES below
sub {
my $action = shift;
# return a true value if you want to apply the rule to this action
# called for all the actions under "/foo"
}
);
In this case the rule must be a sub reference (or method name) to be invoked on $c.
The default filter skips all actions starting with an underscore β so _DISPATCH, _AUTO, etc β but not auto, begin, et al. Those are safe bestie, don't worry.
π acl_access_denied
Arguments: $c, $class, $action, $err
π acl_access_allowed
Arguments: $c, $class, $action
These are the default event handlers for access denied or allowed conditions. Scroll down for handling access violations π
π«Ά acl_allow_root_internals
Adds rules that permit access to the root controller (YourApp.pm) auto, begin and end unconditionally. Free pass, no questions asked.
π₯ EXTENDED METHODS π₯
π execute
The hook for rule evaluation. This is where the magic happens fr fr.
π setup_actions
(that's it, that's the description π )
π§ RULE EVALUATION π§
When a rule is attached to an action, the "distance" from the path it was specified in gets recorded. The closer the path is to the rule, the earlier it gets checked. It's giving "closest friends get checked first".
Any rule can either explicitly deny or explicitly allow access to a particular action. If a rule does not explicitly allow or permit access, the next rule gets checked, until the whole list of rules is finished. And if no rule has determined a policy? Access to the path will be permitted. Default = yes babes π
π PATHS π
To apply a rule to an action or a group of actions you gotta supply a path.
This path is what you should see dumped at the beginning of the Catalyst server's debug output. So if you're confused, check the debug output, it's literally right there.
For example, for the foo action defined at the root level of your application, specify "/foo". Under the Moose controller (e.g. MyApp::C::Moose), the action bar will be "/moose/bar". See the pattern? β¨
The "distance" a path has from an action that's contained in it is the difference in the number of slashes between the path of the action, and the path to which the rule was applied. Count those slashes bestie π«Ά
β RULES β
π Easy Rules
There are several kinds of rules you can create without using the complex interface described in "FLEXIBLE RULES". Easy mode, we love her.
The easy rules are all predicate-list oriented. allow_access_if will explicitly allow access if the predicate is true, and deny_access_unless will explicitly disallow if the predicate is false. Simple as.
π Role Lists
__PACAKGE__->deny_access_unless_any( "/foo/bar", [qw/admin moose_trainer/] );
When the role is evaluated, the Catalyst::Plugin::Authorization::Roles will be used to check whether the currently logged in user has the specified roles.
If allow_access_if_any is used, the presence of any of the roles in the list will immediately permit access. And if deny_access_unless_any is used, the lack of all of the roles will immediately deny access.
Similarly, if allow_access_if is used, the presence of all the roles will immediately permit access, and if deny_access_unless is used, the lack of any of the roles will immediately deny access.
When specifying a role list without the Catalyst::Plugin::Authorization::Roles plugin loaded, the ACL engine will throw an error. Like, it will literally error out. Load the plugin babes π
π¦ Predicate Code Reference / Method Name
The code reference or method is invoked with the context and the action objects. The boolean return value will determine the behavior of the rule.
__PACKAGE__->allow_access_if( "/gorch", sub { ... } );
__PACKAGE__->deny_access_unless( "/moose", "method_name" );
When specifying a method name, the rule engine ensures that it can be invoked using can in UNIVERSAL. Safety check, love that for us.
π Constant
You can use undef, 0 and '' to use as a constant false predicate, or 1 to use as a constant true predicate. Sometimes you just know the answer already β¨
π§ Flexible Rules
These rules are the most annoying to write, but they provide the most flexibility. High effort, high reward, that's the deal.
All access control is performed using exceptions β $Catalyst::Plugin::Authorization::ACL::Engine::DENIED, and $Catalyst::Plugin::Authorization::ACL::Engine::ALLOWED (these can be imported from the engine module).
If no rule decides to explicitly allow or deny access, access will be permitted. (yes, again, default is yes π )
Here is a rule that will always break out of rule processing by either explicitly allowing or denying access based on how much mojo the current user has:
__PACKAGE__->acl_add_rule(
"/foo",
sub {
my ( $c, $action ) = @_;
if ( $c->user->mojo > 50 ) {
die $ALLOWED;
} else {
die $DENIED;
}
}
);
mojo check, iconic π₯
π HANDLING DENIAL π
There are two plugin methods that can be called when a rule makes a decision about an action:
acl_access_allowedβ a no-op. Does nothing. Living its best peaceful life.acl_access_deniedβ looks for a private action namedaccess_deniedfrom the denied action's controller and outwards (much likeauto), and if none is found, throws an access denied exception. Dramatic exit πforcibly_allow_accessβ within anaccess_deniedaction this will immediately cause the blocked action to be executed anyway. "You shall not pass" except actually yes you shall.
This means you have several alternatives:
πΈ Provide an access_denied action
package MyApp::Controller::Foo;
sub access_denied : Private {
my ( $self, $c, $action ) = @_;
...
$c->forcibly_allow_access
if $you->mean_it eq "really";
}
If you call forcibly_allow_access then the blocked action will be immediately unblocked. Otherwise the execution of the action will cease, and return to its caller or end. Choose wisely bestie π«Ά
π¦ Cleanup in end
sub end : Private {
my ( $self, $c ) = @_;
if ( $c->error and $c->error->[-1] eq "access denied" ) {
$c->error(0); # clear the error
# access denied
} else {
# normal end
}
}
π Override the plugin event handler methods
package MyApp;
sub acl_access_allowed {
my ( $c, $class, $action ) = @_;
...
}
sub acl_access_denied {
my ( $c, $class, $action, $err ) = @_;
...
}
$class is the controller class the $action object was going to be executed in, and $err is the exception caught during rule evaluation, if any β note that access is denied if a rule raises an exception. So like, exceptions = denied, no takebacks π
π SEE ALSO π
Catalyst::Plugin::AuthenticationCatalyst::Plugin::Authorization::Roleshttp://catalyst.perl.org/calendar/2005/24
π AUTHOR π
Yuval Kogman <nothingmuch@woobling.org>
π«Ά CONTRIBUTORS π«Ά
- castaway: Jess Robinson
- caelum: Rafael Kitover
<rkitover@cpan.org>
π COPYRIGHT & LICENSE π
Copyright (c) 2005 - 2009 the Catalyst::Plugin::Authorization::ACL "AUTHOR" and "CONTRIBUTORS" as listed above.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
and that's the whole page bestie π
this lil gem was rendered by perl v5.34.0 on 2022-06-09, filed under Cataly...n::ACL(3pm) in the User Contributed Perl Documentation section β go forth and ACL responsibly, mwah πβ¨
π¦ where this page comes from
- debian bookworm: libcatalyst-plugin-authorization-acl-perl 0.16-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- debian trixie: libcatalyst-plugin-authorization-acl-perl 0.16-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu noble: libcatalyst-plugin-authorization-acl-perl 0.16-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libcatalyst-plugin-authorization-acl-perl 0.16-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libcatalyst-plugin-authorization-acl-perl 0.16-2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms