import rt 3.0.12
[freeside.git] / rt / lib / RT / ACL_Overlay.pm
1 # BEGIN LICENSE BLOCK
2
3 # Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com>
4
5 # (Except where explictly superceded by other copyright notices)
6
7 # This work is made available to you under the terms of Version 2 of
8 # the GNU General Public License. A copy of that license should have
9 # been provided with this software, but in any event can be snarfed
10 # from www.gnu.org.
11
12 # This work is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 # General Public License for more details.
16
17 # Unless otherwise specified, all modifications, corrections or
18 # extensions to this work which alter its source code become the
19 # property of Best Practical Solutions, LLC when submitted for
20 # inclusion in the work.
21
22
23 # END LICENSE BLOCK
24 =head1 NAME
25
26   RT::ACL - collection of RT ACE objects
27
28 =head1 SYNOPSIS
29
30   use RT::ACL;
31 my $ACL = new RT::ACL($CurrentUser);
32
33 =head1 DESCRIPTION
34
35
36 =head1 METHODS
37
38 =begin testing
39
40 ok(require RT::ACL);
41
42 =end testing
43
44 =cut
45
46 use strict;
47 no warnings qw(redefine);
48
49
50 =head2 Next
51
52 Hand out the next ACE that was found
53
54 =cut
55
56
57 # {{{ LimitToObject 
58
59 =head2 LimitToObject $object
60
61 Limit the ACL to rights for the object $object. It needs to be an RT::Record class.
62
63 =cut
64
65 sub LimitToObject {
66     my $self = shift;
67     my $obj = shift;
68     unless (defined($obj) && ref($obj) && UNIVERSAL::can($obj, 'id')) {
69     return undef;
70     }
71     $self->Limit(FIELD => 'ObjectType', OPERATOR=> '=', VALUE => ref($obj), ENTRYAGGREGATOR => 'OR');
72     $self->Limit(FIELD => 'ObjectId', OPERATOR=> '=', VALUE => $obj->id, ENTRYAGGREGATOR => 'OR', QUOTEVALUE => 0);
73
74 }
75
76 # }}}
77
78 # {{{ LimitToPrincipal 
79
80 =head2 LimitToPrincipal { Type => undef, Id => undef, IncludeGroupMembership => undef }
81
82 Limit the ACL to the principal with PrincipalId Id and PrincipalType Type
83
84 Id is not optional.
85 Type is.
86
87 if IncludeGroupMembership => 1 is specified, ACEs which apply to the principal due to group membership will be included in the resultset.
88
89
90 =cut
91
92 sub LimitToPrincipal {
93     my $self = shift;
94     my %args = ( Type                               => undef,
95                  Id                                 => undef,
96                  IncludeGroupMembership => undef,
97                  @_ );
98     if ( $args{'IncludeGroupMembership'} ) {
99         my $cgm = $self->NewAlias('CachedGroupMembers');
100         $self->Join( ALIAS1 => 'main',
101                      FIELD1 => 'PrincipalId',
102                      ALIAS2 => $cgm,
103                      FIELD2 => 'GroupId' );
104         $self->Limit( ALIAS           => $cgm,
105                       FIELD           => 'MemberId',
106                       OPERATOR        => '=',
107                       VALUE           => $args{'Id'},
108                       ENTRYAGGREGATOR => 'OR' );
109     }
110     else {
111         if ( defined $args{'Type'} ) {
112             $self->Limit( FIELD           => 'PrincipalType',
113                           OPERATOR        => '=',
114                           VALUE           => $args{'Type'},
115                           ENTRYAGGREGATOR => 'OR' );
116         }
117     # if the principal id points to a user, we really want to point
118     # to their ACL equivalence group. The machinations we're going through
119     # lead me to start to suspect that we really want users and groups
120     # to just be the same table. or _maybe_ that we want an object db.
121     my $princ = RT::Principal->new($RT::SystemUser);
122     $princ->Load($args{'Id'});
123     if ($princ->PrincipalType eq 'User') {
124     my $group = RT::Group->new($RT::SystemUser);
125         $group->LoadACLEquivalenceGroup($princ);
126         $args{'Id'} = $group->PrincipalId;
127     }
128         $self->Limit( FIELD           => 'PrincipalId',
129                       OPERATOR        => '=',
130                       VALUE           => $args{'Id'},
131                       ENTRYAGGREGATOR => 'OR' );
132     }
133 }
134
135 # }}}
136
137
138
139 # {{{ ExcludeDelegatedRights
140
141 =head2 ExcludeDelegatedRights 
142
143 Don't list rights which have been delegated.
144
145 =cut
146
147 sub ExcludeDelegatedRights {
148     my $self = shift;
149     $self->DelegatedBy(Id => 0);
150     $self->DelegatedFrom(Id => 0);
151 }
152 # }}}
153
154 # {{{ DelegatedBy 
155
156 =head2 DelegatedBy { Id => undef }
157
158 Limit the ACL to rights delegated by the principal whose Principal Id is
159 B<Id>
160
161 Id is not optional.
162
163 =cut
164
165 sub DelegatedBy {
166     my $self = shift;
167     my %args = (
168         Id => undef,
169         @_
170     );
171     $self->Limit(
172         FIELD           => 'DelegatedBy',
173         OPERATOR        => '=',
174         VALUE           => $args{'Id'},
175         ENTRYAGGREGATOR => 'OR'
176     );
177
178 }
179
180 # }}}
181
182 # {{{ DelegatedFrom 
183
184 =head2 DelegatedFrom { Id => undef }
185
186 Limit the ACL to rights delegate from the ACE which has the Id specified 
187 by the Id parameter.
188
189 Id is not optional.
190
191 =cut
192
193 sub DelegatedFrom {
194     my $self = shift;
195     my %args = (
196                  Id => undef,
197                  @_);
198     $self->Limit(FIELD => 'DelegatedFrom', OPERATOR=> '=', VALUE => $args{'Id'}, ENTRYAGGREGATOR => 'OR');
199
200 }
201
202 # }}}
203
204
205 # {{{ sub Next 
206 sub Next {
207     my $self = shift;
208
209     my $ACE = $self->SUPER::Next();
210     if ( ( defined($ACE) ) and ( ref($ACE) ) ) {
211
212         if ( $self->CurrentUser->HasRight( Right  => 'ShowACL',
213                                            Object => $ACE->Object )
214              or $self->CurrentUser->HasRight( Right  => 'ModifyACL',
215                                               Object => $ACE->Object )
216           ) {
217             return ($ACE);
218         }
219
220         #If the user doesn't have the right to show this ACE
221         else {
222             return ( $self->Next() );
223         }
224     }
225
226     #if there never was any ACE
227     else {
228         return (undef);
229     }
230
231 }
232
233 # }}}
234
235
236
237 #wrap around _DoSearch  so that we can build the hash of returned
238 #values 
239 sub _DoSearch {
240     my $self = shift;
241    # $RT::Logger->debug("Now in ".$self."->_DoSearch");
242     my $return = $self->SUPER::_DoSearch(@_);
243   #  $RT::Logger->debug("In $self ->_DoSearch. return from SUPER::_DoSearch was $return\n");
244     $self->_BuildHash();
245     return ($return);
246 }
247
248
249 #Build a hash of this ACL's entries.
250 sub _BuildHash {
251     my $self = shift;
252
253     while (my $entry = $self->Next) {
254        my $hashkey = $entry->ObjectType . "-" .  $entry->ObjectId . "-" .  $entry->RightName . "-" .  $entry->PrincipalId . "-" .  $entry->PrincipalType;
255
256         $self->{'as_hash'}->{"$hashkey"} =1;
257
258     }
259 }
260
261
262 # {{{ HasEntry
263
264 =head2 HasEntry
265
266 =cut
267
268 sub HasEntry {
269
270     my $self = shift;
271     my %args = ( RightScope => undef,
272                  RightAppliesTo => undef,
273                  RightName => undef,
274                  PrincipalId => undef,
275                  PrincipalType => undef,
276                  @_ );
277
278     #if we haven't done the search yet, do it now.
279     $self->_DoSearch();
280
281     if ($self->{'as_hash'}->{ $args{'RightScope'} . "-" .
282                               $args{'RightAppliesTo'} . "-" . 
283                               $args{'RightName'} . "-" .
284                               $args{'PrincipalId'} . "-" .
285                               $args{'PrincipalType'}
286                             } == 1) {
287         return(1);
288     }
289     else {
290         return(undef);
291     }
292 }
293
294 # }}}
295 1;