]> git.uio.no Git - usit-rt.git/blame - lib/RT/ACL.pm
Removed LDAP-lookup loop for new external users.
[usit-rt.git] / lib / RT / ACL.pm
CommitLineData
84fb5b46
MKG
1# BEGIN BPS TAGGED BLOCK {{{
2#
3# COPYRIGHT:
4#
5# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
6# <sales@bestpractical.com>
7#
8# (Except where explicitly superseded by other copyright notices)
9#
10#
11# LICENSE:
12#
13# This work is made available to you under the terms of Version 2 of
14# the GNU General Public License. A copy of that license should have
15# been provided with this software, but in any event can be snarfed
16# from www.gnu.org.
17#
18# This work is distributed in the hope that it will be useful, but
19# WITHOUT ANY WARRANTY; without even the implied warranty of
20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21# General Public License for more details.
22#
23# You should have received a copy of the GNU General Public License
24# along with this program; if not, write to the Free Software
25# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26# 02110-1301 or visit their web page on the internet at
27# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
28#
29#
30# CONTRIBUTION SUBMISSION POLICY:
31#
32# (The following paragraph is not intended to limit the rights granted
33# to you to modify and distribute this software under the terms of
34# the GNU General Public License and is only of importance to you if
35# you choose to contribute your changes and enhancements to the
36# community by submitting them to Best Practical Solutions, LLC.)
37#
38# By intentionally submitting any modifications, corrections or
39# derivatives to this work, or any other work intended for use with
40# Request Tracker, to Best Practical Solutions, LLC, you confirm that
41# you are the copyright holder for those contributions and you grant
42# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
43# royalty-free, perpetual, license to use, copy, create derivative
44# works based on those contributions, and sublicense and distribute
45# those contributions and any derivatives thereof.
46#
47# END BPS TAGGED BLOCK }}}
48
49=head1 NAME
50
51 RT::ACL - collection of RT ACE objects
52
53=head1 SYNOPSIS
54
55 use RT::ACL;
56my $ACL = RT::ACL->new($CurrentUser);
57
58=head1 DESCRIPTION
59
60
61=head1 METHODS
62
63
64=cut
65
66
67package RT::ACL;
68use RT::ACE;
69
70use base 'RT::SearchBuilder';
71
72sub Table { 'ACL'}
73
74use strict;
75use warnings;
76
77
78
79=head2 Next
80
81Hand out the next ACE that was found
82
83=cut
84
85
86
87=head2 LimitToObject $object
88
89Limit the ACL to rights for the object $object. It needs to be an RT::Record class.
90
91=cut
92
93sub LimitToObject {
94 my $self = shift;
95 my $obj = shift;
96
97 my $obj_type = ref($obj)||$obj;
98 my $obj_id = eval { $obj->id};
99
100 my $object_clause = 'possible_objects';
101 $self->_OpenParen($object_clause);
102 $self->Limit(
103 SUBCLAUSE => $object_clause,
104 FIELD => 'ObjectType',
105 OPERATOR => '=',
106 VALUE => (ref($obj)||$obj),
107 ENTRYAGGREGATOR => 'OR' # That "OR" applies to the separate objects we're searching on, not "Type Or ID"
108 );
109 if ($obj_id) {
110 $self->Limit(
111 SUBCLAUSE => $object_clause,
112 FIELD => 'ObjectId',
113 OPERATOR => '=',
114 VALUE => $obj_id,
115 ENTRYAGGREGATOR => 'AND',
116 QUOTEVALUE => 0
117 );
118 }
119 $self->_CloseParen($object_clause);
120
121}
122
123
124
125=head2 LimitNotObject $object
126
127Limit the ACL to rights NOT on the object $object. $object needs to be
128an RT::Record class.
129
130=cut
131
132sub LimitNotObject {
133 my $self = shift;
134 my $obj = shift;
135 unless ( defined($obj)
136 && ref($obj)
137 && UNIVERSAL::can( $obj, 'id' )
138 && $obj->id )
139 {
140 return undef;
141 }
142 $self->Limit( FIELD => 'ObjectType',
143 OPERATOR => '!=',
144 VALUE => ref($obj),
145 ENTRYAGGREGATOR => 'OR',
146 SUBCLAUSE => $obj->id
147 );
148 $self->Limit( FIELD => 'ObjectId',
149 OPERATOR => '!=',
150 VALUE => $obj->id,
151 ENTRYAGGREGATOR => 'OR',
152 QUOTEVALUE => 0,
153 SUBCLAUSE => $obj->id
154 );
155}
156
157
158
159=head2 LimitToPrincipal { Type => undef, Id => undef, IncludeGroupMembership => undef }
160
161Limit the ACL to the principal with PrincipalId Id and PrincipalType Type
162
163Id is not optional.
164Type is.
165
166if IncludeGroupMembership => 1 is specified, ACEs which apply to the principal due to group membership will be included in the resultset.
167
168
169=cut
170
171sub LimitToPrincipal {
172 my $self = shift;
173 my %args = ( Type => undef,
174 Id => undef,
175 IncludeGroupMembership => undef,
176 @_
177 );
178 if ( $args{'IncludeGroupMembership'} ) {
179 my $cgm = $self->NewAlias('CachedGroupMembers');
180 $self->Join( ALIAS1 => 'main',
181 FIELD1 => 'PrincipalId',
182 ALIAS2 => $cgm,
183 FIELD2 => 'GroupId'
184 );
185 $self->Limit( ALIAS => $cgm,
186 FIELD => 'Disabled',
187 VALUE => 0 );
188 $self->Limit( ALIAS => $cgm,
189 FIELD => 'MemberId',
190 OPERATOR => '=',
191 VALUE => $args{'Id'},
192 ENTRYAGGREGATOR => 'OR'
193 );
194 } else {
195 if ( defined $args{'Type'} ) {
196 $self->Limit( FIELD => 'PrincipalType',
197 OPERATOR => '=',
198 VALUE => $args{'Type'},
199 ENTRYAGGREGATOR => 'OR'
200 );
201 }
202
203 # if the principal id points to a user, we really want to point
204 # to their ACL equivalence group. The machinations we're going through
205 # lead me to start to suspect that we really want users and groups
206 # to just be the same table. or _maybe_ that we want an object db.
207 my $princ = RT::Principal->new( RT->SystemUser );
208 $princ->Load( $args{'Id'} );
209 if ( $princ->PrincipalType eq 'User' ) {
210 my $group = RT::Group->new( RT->SystemUser );
211 $group->LoadACLEquivalenceGroup($princ);
212 $args{'Id'} = $group->PrincipalId;
213 }
214 $self->Limit( FIELD => 'PrincipalId',
215 OPERATOR => '=',
216 VALUE => $args{'Id'},
217 ENTRYAGGREGATOR => 'OR'
218 );
219 }
220}
221
222
223
224
225sub Next {
226 my $self = shift;
227
228 my $ACE = $self->SUPER::Next();
229 # Short-circuit having to load up the ->Object
230 return $ACE
231 if $self->CurrentUser->PrincipalObj->Id == RT->SystemUser->Id;
232 if ( ( defined($ACE) ) and ( ref($ACE) ) ) {
233
234 if ( $self->CurrentUser->HasRight( Right => 'ShowACL',
235 Object => $ACE->Object )
236 or $self->CurrentUser->HasRight( Right => 'ModifyACL',
237 Object => $ACE->Object )
238 ) {
239 return ($ACE);
240 }
241
242 #If the user doesn't have the right to show this ACE
243 else {
244 return ( $self->Next() );
245 }
246 }
247
248 #if there never was any ACE
249 else {
250 return (undef);
251 }
252
253}
254
255
256
257
258#wrap around _DoSearch so that we can build the hash of returned
259#values
260sub _DoSearch {
261 my $self = shift;
262 # $RT::Logger->debug("Now in ".$self."->_DoSearch");
263 my $return = $self->SUPER::_DoSearch(@_);
264 # $RT::Logger->debug("In $self ->_DoSearch. return from SUPER::_DoSearch was $return");
265 if ( $self->{'must_redo_search'} ) {
266 $RT::Logger->crit(
267"_DoSearch is not so successful as it still needs redo search, won't call _BuildHash"
268 );
269 }
270 else {
271 $self->_BuildHash();
272 }
273 return ($return);
274}
275
276
277#Build a hash of this ACL's entries.
278sub _BuildHash {
279 my $self = shift;
280
281 while (my $entry = $self->Next) {
282 my $hashkey = join '-', map $entry->__Value( $_ ),
283 qw(ObjectType ObjectId RightName PrincipalId PrincipalType);
284
285 $self->{'as_hash'}->{"$hashkey"} =1;
286
287 }
288}
289
290
291
292=head2 HasEntry
293
294=cut
295
296sub HasEntry {
297
298 my $self = shift;
299 my %args = ( RightScope => undef,
300 RightAppliesTo => undef,
301 RightName => undef,
302 PrincipalId => undef,
303 PrincipalType => undef,
304 @_ );
305
306 #if we haven't done the search yet, do it now.
307 $self->_DoSearch();
308
309 if ($self->{'as_hash'}->{ $args{'RightScope'} . "-" .
310 $args{'RightAppliesTo'} . "-" .
311 $args{'RightName'} . "-" .
312 $args{'PrincipalId'} . "-" .
313 $args{'PrincipalType'}
314 } == 1) {
315 return(1);
316 }
317 else {
318 return(undef);
319 }
320}
321
322# }}}
323
324
325=head2 NewItem
326
327Returns an empty new RT::ACE item
328
329=cut
330
331sub NewItem {
332 my $self = shift;
333 return(RT::ACE->new($self->CurrentUser));
334}
335RT::Base->_ImportOverlays();
336
3371;