| SweetPea-Application documentation | Contained in the SweetPea-Application distribution. |
SweetPea::Application::Rbac - Role-Based Access Control for SweetPea-Application.
# Based on a common example
permissions.yml
---
roles:
administrator:
permissions:
manage accounts:
operations:
create account
update account
delete account
manager:
permissions:
manager accounts:
operations:
create account
guests:
permissions:
... from inside SweetPea::Application or a Controller;
# verify user access
$s->rbac->authorize($login, $password);
# change user
$s->rbac->subject($user_id);
# verify target user has permission to perform "create account" operation
$s->rbac->subject($user_id)->can('/manage accounts/create account');
# change user to default set by authenticate method
$s->rbac->subject;
# verify has the following role
$s->rbac->role('administrator');
$s->rbac->role('guests');
$s->rbac->can('/manage accounts/delete account');
The new method instantiates a new SweetPea::Application::Rbac object
which uses Yaml (via SweetPea::Application::Config) to provide methods
for retrieving authenticating and verifying system access permissions.
$s->plug( 'rbac', sub { return SweetPea::Application::Rbac->new($s); });
The override method re-authenticates as another system user while retaining
the originally logged in user's credentials. Thie method is useful for
applications that need to provide a means to temporarily switch accounts.
$s->rbac->override($login, $password);
# change back to the original user
$s->rbac->override;
The subject method specifies the user account permissions will be validated
against using the user id pass to it, if called with no parameters the
authenticated user's account will be used.
$s->rbac->subject($user_id);
$s->rbac->subject;
The role method verifies whether the subject (target user) has the role
specified.
if $s->rbac->role('administrator');
The "can" method verifies whether the subject (target user) has a specific
permission or has permission to perform a specific action.
# check if subject (target user) has permission generally
if $s->rbac->can('/manage accounts');
# check if subject (target user) has permission to perform a specific operation
if $s->rbac->can('/manage accounts/create account');
Al Newkirk, <al.newkirk at awnstudio.com>
| SweetPea-Application documentation | Contained in the SweetPea-Application distribution. |
package SweetPea::Application::Rbac; use warnings; use strict;
our $VERSION = '0.001';
sub new { my ($class, $s) = @_; my $self = {}; bless $self, $class; $self->{base} = $s; $self->{subject}= '0'; return $self; }
sub authorize { my ($self, $login, $password) = @_; my $s = $self->{base}; if ($login && $password) { my $user = $s->data->select( 'users', ['id','login','password','status'], { login => $login, password => $password } )->hash; if ($user) { if ($user->{status}) { $s->session->param('authenticated', 'true'); $s->session->param('user_id', $user->{id}); $s->session->param('user_login', $user->{login}); $s->session->param('original_user_id', $user->{id}); $s->session->param('original_user_login', $user->{login}); $s->session->flush; $self->{subject} = $user->{id}; return $self; } else { $s->error->message($s->locale->text('account_disabled')); } } else { $s->error->message($s->locale->text('no_account')); } } return 0; }
sub authorized { my ($self, $login, $password) = @_; my $s = $self->{base}; return $s->session->param('authenticated'); }
sub unauthorize { my ($self, $login, $password) = @_; my $s = $self->{base}; $s->session->param('authenticated', ''); return $self; }
sub override { my ($self, $login, $password) = @_; my $s = $self->{base}; if ($login && $password) { my $user = $s->data->select( 'users', ['id','login','password','status'], { login => $login, password => $password } )->hash; if ($user) { if ($user->{status}) { $s->session->param('authenticated', 'true'); $s->session->param('user_id', $user->{id}); $s->session->param('user_login', $user->{login}); $s->session->flush; $self->{subject} = $user->{id}; return $self; } else { $s->error->message($s->locale->text('account_disabled')); } } else { $s->error->message($s->locale->text('no_account')); } } else { $s->session->param('authenticated', 'true'); $s->session->param('user_id', $s->session->param('original_user_id')); $s->session->param('user_login', $s->session->param('original_user_login')); $s->session->flush; $self->{subject} = $s->session->param('original_user_id'); return $self; } return 0; }
sub subject { my ($self, $id) = @_; my $s = $self->{base}; if ($id =~ /^\d+$/) { $self->{subject} = $id; return $self; } else { if ($s->session->param('user_id')) { $self->{subject} = $s->session->param('user_id'); return $self; } } return 0; }
sub role { my ($self, $role) = @_; my $s = $self->{base}; if ($role) { my $has_role = $s->data->select( 'permissions', ['id','user','role','permission','operation'], { user => $self->{subject}, role => $role } )->rows; return $has_role; } return 0; }
sub can { my ($self, $request) = @_; my $s = $self->{base}; if ($request) { $request =~ s/^\///; my ($permission, $operation) = split /\//, $request; return 0 if !$permission; my $where = {}; $where->{user} = $self->{subject}; $where->{permission} = $permission if $permission; $where->{operation} = $operation if $operation; # check that permission and operation is defined my $permissions = $s->config->get('/permissions'); my ($permission_check, $operation_check); foreach my $r (keys %{$permissions->{roles}}) { foreach my $p (keys %{$permissions->{roles}->{$r}->{permissions}}) { $permission_check++ if lc($permission) eq lc($p); if ($operation) { foreach my $o ( @{$permissions->{roles}->{$r}->{permissions} ->{$p}->{operations}} ) { $operation_check++ if lc($operation) eq lc($o); } } } } die "Permission ($permission) has not been defined." unless $permission_check; if ($operation) { die "Operation ($operation) has not been defined." unless $operation_check; } my $can = $s->data->select( 'permissions', ['id','user','role','permission','operation'], $where )->rows; return $can; } return 0; }
1; # End of SweetPea::Application::Rbac