File Coverage

lib/Maypole/Plugin/Authorization.pm
Criterion Covered Total %
statement 57 57 100.0
branch 12 14 85.7
condition 40 54 74.0
subroutine 8 8 100.0
pod 3 3 100.0
total 120 136 88.2


line stmt bran cond sub pod time code
1             package Maypole::Plugin::Authorization;
2 2     2   56146 use strict;
  2         6  
  2         100  
3 2     2   13 use warnings;
  2         4  
  2         1978  
4              
5             # This module provides role-based authorization for Maypole
6              
7             our $VERSION = '0.10';
8              
9             # 2005-01-27 djh v0.03 Modified get_authorized_* to make them work and
10             # accept arguments, and improved docs
11             # 2005-01-28 djh v0.04 Added arg checking to get_authorized_* and an
12             # example for get_authorized_methods. Thanks to
13             # Josef Chladek.
14             # 2005-02-08 djh v0.05 Improved error checking in authorize.
15             # 2005-08-20 djh v0.06 Improved docs suggested by Kieren Diment.
16             # 2005-08-20 djh v0.07 Added config options from Peter Speltz.
17             # 2005-08-22 djh v0.08 Added user_class default from Kieren Diment
18             # 2005-08-22 djh v0.09 Default {} if no config->auth
19             # 2005-08-24 djh v0.10 Allow entity other than model_class as requested
20             # by Kieren Diment & Peter Speltz
21              
22              
23             #=======================================================================
24             #
25             # Initialization
26              
27             Maypole::Config->mk_accessors('auth') unless Maypole::Config->can('auth');
28              
29              
30             # Code references to database queries could be cached at load time,
31             # except that Maypole::Application doesn't call our import function!
32              
33             # Authorization checking query for use by authorize()
34             my $_cdbi_class;
35             my $_check_authorization;
36              
37             sub _init_authorization_query {
38 2     2   4 my $r = shift;
39              
40             # Build a SQL query that checks whether a given user_id is
41             # authorized to invoke a particular method in a model_class
42             # and add it to a class that can run SQL queries for us
43 2   50     10 my $conf = $r->config->auth || {};
44 2   100     64 my $p_table = $conf->{permission_table} || 'permissions';
45 2   100     11 my $ra_table = $conf->{role_assign_table} || 'role_assignments';
46 2   100     10 my $user_fk = $conf->{user_fk} || 'user_id';
47 2   66     11 $_cdbi_class = $conf->{user_class} || (ref $r).'::User';
48              
49 2         25 $_cdbi_class->set_sql(check_authorization =>
50             "SELECT p.id FROM $p_table AS p, $ra_table AS r
51             WHERE r.$user_fk = ?
52             AND p.model_class = ?
53             AND (p.method = ? OR p.method = '*')
54             AND p.auth_role_id = r.auth_role_id
55             LIMIT 1");
56              
57 2         31 $_check_authorization = $_cdbi_class->can('sql_check_authorization');
58             }
59              
60              
61             # Query to find lists of authorized methods for get_authorized_classes()
62             my $_get_authorized_classes;
63              
64             sub _init_get_authorized_classes {
65 2     2   5 my $r = shift;
66              
67 2   50     10 my $conf = $r->config->auth || {};
68 2   100     38 my $p_table = $conf->{permission_table} || 'permissions';
69 2   100     17 my $ra_table = $conf->{role_assign_table} || 'role_assignments';
70 2   100     10 my $user_fk = $conf->{user_fk} || 'user_id';
71 2   66     17 $_cdbi_class = $conf->{user_class} || (ref $r).'::User';
72              
73 2         17 $_cdbi_class->set_sql(get_authorized_classes =>
74             "SELECT DISTINCT p.model_class FROM $p_table AS p, $ra_table AS r
75             WHERE r.$user_fk = ?
76             AND p.auth_role_id = r.auth_role_id");
77              
78 2         22 $_get_authorized_classes =
79             $_cdbi_class->can('sql_get_authorized_classes');
80             }
81              
82              
83             # Query to find lists of authorized methods for get_authorized_methods()
84             my $_get_authorized_methods;
85              
86             sub _init_get_authorized_methods {
87 2     2   7 my $r = shift;
88              
89 2   50     10 my $conf = $r->config->auth || {};
90 2   100     33 my $p_table = $conf->{permission_table} || 'permissions';
91 2   100     9 my $ra_table = $conf->{role_assign_table} || 'role_assignments';
92 2   100     24 my $user_fk = $conf->{user_fk} || 'user_id';
93 2   66     13 $_cdbi_class = $conf->{user_class} || (ref $r).'::User';
94              
95 2         16 $_cdbi_class->set_sql(get_authorized_methods =>
96             "SELECT p.method FROM $p_table AS p, $ra_table AS r
97             WHERE r.$user_fk = ?
98             AND p.model_class = ?
99             AND p.auth_role_id = r.auth_role_id");
100              
101 2         26 $_get_authorized_methods =
102             $_cdbi_class->can('sql_get_authorized_methods');
103             }
104              
105              
106             #=======================================================================
107              
108             # Main permission-checking method
109              
110             sub authorize {
111 2     2 1 2313 my ($self, $r, $entity) = @_;
112              
113             # Validate and extract values for permission check
114 2   33     20 $entity ||= $r->model_class;
115 2 50 33     32 return undef unless $r->user and $entity;
116 2         37 my $userid = $r->user->id;
117 2         23 my $method = $r->action;
118              
119             # Make sure the SQL query has been prepared, then check the permissions
120 2 50       20 _init_authorization_query($r) unless $_check_authorization;
121 2         17 return $_cdbi_class->sql_check_authorization->
122             select_val($userid, $entity, $method);
123             }
124              
125              
126             # Auxiliary method for finding list of authorized classes
127              
128             sub get_authorized_classes {
129 5     5 1 3009 my ($r, $userid) = @_;
130              
131             # Validate and extract parameters
132 5 100 66     18 return unless $r->user or $userid;
133 4   66     42 $userid ||= $r->user->id;
134              
135             # Make sure the SQL query has been prepared, then run it
136 4 100       26 _init_get_authorized_classes($r) unless $_get_authorized_classes;
137 4         17 my $sth = $_cdbi_class->sql_get_authorized_classes;
138 4         54 $sth->execute($userid);
139 4         45 return map { $_->[0] } @{$sth->fetchall_arrayref};
  3         84  
  4         18  
140             }
141              
142              
143             # Auxiliary method for finding list of authorized methods
144              
145             sub get_authorized_methods {
146 11     11 1 5372 my ($r, $userid, $class) = @_;
147              
148             # Validate and extract parameters
149 11 100 66     32 return unless $r->user or $userid;
150 10   66     69 $userid ||= $r->user->id;
151 10   100     66 $class ||= $r->model_class;
152 10 100       41 return unless $class;
153              
154             # Make sure the SQL query has been prepared, then run it
155 9 100       862 _init_get_authorized_methods($r) unless $_get_authorized_methods;
156 9         28 my $sth = $_cdbi_class->sql_get_authorized_methods;
157 9         682 $sth->execute($userid, $class);
158 9         101 return map { $_->[0] } @{$sth->fetchall_arrayref};
  5         67  
  9         23  
159             }
160              
161             1;
162              
163             __END__