line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Tree::Authz::Role;
|
2
|
1
|
|
|
1
|
|
13972
|
use strict;
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
67
|
|
3
|
1
|
|
|
1
|
|
7
|
use warnings;
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
39
|
|
4
|
1
|
|
|
1
|
|
7
|
use Carp;
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
94
|
|
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
6
|
use overload '""' => 'name';
|
|
1
|
|
|
|
|
9
|
|
|
1
|
|
|
|
|
11
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
# NOTE: if this class ever holds any more data than just its name, it
|
9
|
|
|
|
|
|
|
# should probably be a singleton
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=over
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=item new( $role, $authz_class )
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
Represents a role.
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=cut
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# called by Tree::Authz::role
|
20
|
|
|
|
|
|
|
sub new {
|
21
|
0
|
|
|
0
|
1
|
|
my ($proto, $role, $authz_class) = @_;
|
22
|
|
|
|
|
|
|
|
23
|
0
|
|
|
|
|
|
my $self = [ $role, $authz_class ];
|
24
|
|
|
|
|
|
|
|
25
|
0
|
|
0
|
|
|
|
bless $self, ref( $proto ) || $proto;
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# $self->_init;
|
28
|
|
|
|
|
|
|
|
29
|
0
|
|
|
|
|
|
return $self;
|
30
|
|
|
|
|
|
|
}
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=item name()
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
Returns the name of this role.
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
=item group_name()
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
DEPRECATED.
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
Use C instead.
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=cut
|
43
|
|
|
|
|
|
|
|
44
|
0
|
|
|
0
|
1
|
|
sub name { $_[0]->[0] }
|
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=item authz
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
Returns the L subclass used to instantiate this role.
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=cut
|
51
|
|
|
|
|
|
|
|
52
|
0
|
|
|
0
|
1
|
|
sub authz { $_[0]->[1] }
|
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub group_name {
|
55
|
0
|
|
|
0
|
1
|
|
carp "'group_name' is deprecated - use 'name' instead";
|
56
|
0
|
|
|
|
|
|
goto &name;
|
57
|
|
|
|
|
|
|
}
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=item list_roles
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
Returns a list of roles inherited by this role, including this role.
|
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=cut
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub list_roles {
|
66
|
0
|
|
|
0
|
1
|
|
my ($self) = @_;
|
67
|
|
|
|
|
|
|
|
68
|
0
|
|
|
|
|
|
my @my_roles = grep { $self->can( $_ ) } $self->authz->list_roles;
|
|
0
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
70
|
0
|
0
|
|
|
|
|
wantarray ? @my_roles : [ @my_roles ];
|
71
|
|
|
|
|
|
|
}
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
=item setup_permissions( $cando )
|
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
Instance method.
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
Adds methods to the class representing the role. I<$cando> is a single method
|
79
|
|
|
|
|
|
|
name, or arrayref of method names. No-op methods are added to the class
|
80
|
|
|
|
|
|
|
representing the group:
|
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
my $spies = $authz->role( 'spies' );
|
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
my $cando = [ qw( read_secret wear_disguise ) ];
|
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
$spies->setup_permissions( $cando );
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
if ( $spies->can( 'read_secret' ) ) {
|
89
|
|
|
|
|
|
|
warn 'Compromised!';
|
90
|
|
|
|
|
|
|
}
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
warn 'Trust no-one' if $spies->can( 'wear_disguise' );
|
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
=cut
|
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub setup_permissions {
|
97
|
0
|
|
|
0
|
1
|
|
my ($self, $cando) = @_;
|
98
|
|
|
|
|
|
|
|
99
|
0
|
0
|
|
|
|
|
croak( 'Nothing to permit' ) unless $cando;
|
100
|
0
|
|
0
|
|
|
|
my $class = ref( $self ) || croak( 'object method called on class name' );
|
101
|
|
|
|
|
|
|
|
102
|
0
|
|
|
|
|
|
$class->_setup_perms( $cando );
|
103
|
|
|
|
|
|
|
}
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub _setup_perms {
|
106
|
0
|
|
|
0
|
|
|
my ($class, $cando) = @_;
|
107
|
|
|
|
|
|
|
|
108
|
0
|
0
|
|
|
|
|
my @permits = ref( $cando ) ? @$cando : ( $cando );
|
109
|
|
|
|
|
|
|
|
110
|
1
|
|
|
1
|
|
447
|
no strict 'refs';
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
217
|
|
111
|
0
|
|
|
|
|
|
foreach my $permit ( @permits ) {
|
112
|
0
|
|
|
0
|
|
|
*{"${class}::$permit"} = sub {};
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
}
|
114
|
|
|
|
|
|
|
}
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=item setup_abilities( $name => $coderef, [ $name2 => $coderef2 ], ... )
|
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
Instance method.
|
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
Adds methods to the class representing the group. Keys give method names and
|
121
|
|
|
|
|
|
|
values are coderefs that will be installed as methods on the group class:
|
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
my $spies = $authz->get_group( 'spies' );
|
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
my %able = ( read_secret => sub {
|
126
|
|
|
|
|
|
|
my ($self, $file) = @_;
|
127
|
|
|
|
|
|
|
open( SECRET, $file );
|
128
|
|
|
|
|
|
|
local $/;
|
129
|
|
|
|
|
|
|
;
|
130
|
|
|
|
|
|
|
},
|
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
find_moles => sub { ... },
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
);
|
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
$spies->setup_abilities( %able );
|
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
if ( $spies->can( 'read_secret' ) ) {
|
139
|
|
|
|
|
|
|
print $spies->read_secret( '/path/to/secret/file' );
|
140
|
|
|
|
|
|
|
}
|
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
# or
|
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
if ( my $read = $spies->can( 'read_secret' ) ) {
|
145
|
|
|
|
|
|
|
print $spies->$read( '/path/to/secret/file' );
|
146
|
|
|
|
|
|
|
}
|
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# with an unknown $group
|
149
|
|
|
|
|
|
|
my $get_secret = $group->can( 'read_secret' ) || # spy
|
150
|
|
|
|
|
|
|
$group->can( 'steal_document' ) || # mole
|
151
|
|
|
|
|
|
|
$group->can( 'create_secret' ) || # spymaster
|
152
|
|
|
|
|
|
|
$group->can( 'do_illicit_thing' ) || # politician
|
153
|
|
|
|
|
|
|
sub {}; # boring life
|
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
my $secret = $group->$get_secret;
|
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=cut
|
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
sub setup_abilities {
|
160
|
0
|
|
|
0
|
1
|
|
my ($self, %code) = @_;
|
161
|
|
|
|
|
|
|
|
162
|
0
|
0
|
|
|
|
|
croak( 'Nothing to set up' ) unless %code;
|
163
|
|
|
|
|
|
|
|
164
|
0
|
|
0
|
|
|
|
my $class = ref( $self ) || croak( 'object method called on class name' );
|
165
|
|
|
|
|
|
|
|
166
|
0
|
|
|
|
|
|
$class->_setup_abil( %code );
|
167
|
|
|
|
|
|
|
}
|
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub _setup_abil {
|
170
|
0
|
|
|
0
|
|
|
my ($class, %code) = @_;
|
171
|
|
|
|
|
|
|
|
172
|
1
|
|
|
1
|
|
6
|
no strict 'refs';
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
208
|
|
173
|
0
|
|
|
|
|
|
foreach my $method ( keys %code ) {
|
174
|
0
|
|
|
|
|
|
*{"${class}::$method"} = $code{ $method };
|
|
0
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
}
|
176
|
|
|
|
|
|
|
}
|
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
=item setup_plugins( $plugins )
|
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
Instance method.
|
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
Instead of adding a set of coderefs to a group's class, this method adds
|
183
|
|
|
|
|
|
|
a class to the C<@ISA> array of the group's class.
|
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
package My::Spies;
|
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
sub wear_disguise {}
|
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
sub read_secret {
|
190
|
|
|
|
|
|
|
my ($self, $file) = @_;
|
191
|
|
|
|
|
|
|
open( SECRET, $file );
|
192
|
|
|
|
|
|
|
local $/;
|
193
|
|
|
|
|
|
|
;
|
194
|
|
|
|
|
|
|
}
|
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
package main;
|
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
my $spies = $authz->get_group( 'spies' );
|
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
$spies->setup_plugins( 'My::Spies' );
|
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
if ( $spies->can( 'read_secret' ) ) {
|
203
|
|
|
|
|
|
|
warn 'Compromised!';
|
204
|
|
|
|
|
|
|
print $spies->read_secret( '/path/to/secret/file' );
|
205
|
|
|
|
|
|
|
}
|
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
warn 'Trust no-one' if $spies->can( 'wear_disguise' );
|
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=back
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=cut
|
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
sub setup_plugins {
|
215
|
0
|
|
|
0
|
1
|
|
my ($self, $plugins) = @_;
|
216
|
|
|
|
|
|
|
|
217
|
0
|
0
|
|
|
|
|
croak( 'Nothing to plug in' ) unless $plugins;
|
218
|
|
|
|
|
|
|
|
219
|
0
|
|
0
|
|
|
|
my $class = ref( $self ) || croak( 'object method called on class name' );
|
220
|
|
|
|
|
|
|
|
221
|
0
|
|
|
|
|
|
$class->_setup_plugins( $plugins );
|
222
|
|
|
|
|
|
|
}
|
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
sub _setup_plugins {
|
225
|
0
|
|
|
0
|
|
|
my ($class, $plugins) = @_;
|
226
|
|
|
|
|
|
|
|
227
|
0
|
0
|
|
|
|
|
my @plugins = ref( $plugins ) ? @$plugins : ( $plugins );
|
228
|
|
|
|
|
|
|
|
229
|
1
|
|
|
1
|
|
5
|
no strict 'refs';
|
|
1
|
|
|
|
|
11
|
|
|
1
|
|
|
|
|
147
|
|
230
|
|
|
|
|
|
|
|
231
|
0
|
|
|
|
|
|
push( @{"${class}::ISA"}, $_ ) for @plugins;
|
|
0
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
}
|
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
1;
|
235
|
|
|
|
|
|
|
|