ACL.pm 6.49 KB
Newer Older
1
# BEGIN BPS TAGGED BLOCK {{{
Jesse Vincent's avatar
Jesse Vincent committed
2
#
3
# COPYRIGHT:
Jesse Vincent's avatar
Jesse Vincent committed
4
#
5
# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
Kevin Falcone's avatar
Kevin Falcone committed
6
#                                          <sales@bestpractical.com>
Jesse Vincent's avatar
Jesse Vincent committed
7
#
8
# (Except where explicitly superseded by other copyright notices)
Jesse Vincent's avatar
Jesse Vincent committed
9
10
#
#
11
# LICENSE:
Jesse Vincent's avatar
Jesse Vincent committed
12
#
13
14
15
# This work is made available to you under the terms of Version 2 of
# the GNU General Public License. A copy of that license should have
# been provided with this software, but in any event can be snarfed
16
# from www.gnu.org.
Jesse Vincent's avatar
Jesse Vincent committed
17
#
18
19
20
21
# This work is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
Jesse Vincent's avatar
Jesse Vincent committed
22
#
23
24
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
Jesse Vincent's avatar
Jesse Vincent committed
25
26
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 or visit their web page on the internet at
Ruslan Zakirov's avatar
Ruslan Zakirov committed
27
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
Jesse Vincent's avatar
Jesse Vincent committed
28
29
#
#
30
# CONTRIBUTION SUBMISSION POLICY:
Jesse Vincent's avatar
Jesse Vincent committed
31
#
32
33
34
35
36
# (The following paragraph is not intended to limit the rights granted
# to you to modify and distribute this software under the terms of
# the GNU General Public License and is only of importance to you if
# you choose to contribute your changes and enhancements to the
# community by submitting them to Best Practical Solutions, LLC.)
Jesse Vincent's avatar
Jesse Vincent committed
37
#
38
39
40
41
42
43
44
45
# By intentionally submitting any modifications, corrections or
# derivatives to this work, or any other work intended for use with
# Request Tracker, to Best Practical Solutions, LLC, you confirm that
# you are the copyright holder for those contributions and you grant
# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
# royalty-free, perpetual, license to use, copy, create derivative
# works based on those contributions, and sublicense and distribute
# those contributions and any derivatives thereof.
Jesse Vincent's avatar
Jesse Vincent committed
46
#
47
# END BPS TAGGED BLOCK }}}
48

Jesse Vincent's avatar
rt.2.1  
Jesse Vincent committed
49
50
51
52
53
54
55
=head1 NAME

  RT::ACL - collection of RT ACE objects

=head1 SYNOPSIS

  use RT::ACL;
56
my $ACL = RT::ACL->new($CurrentUser);
Jesse Vincent's avatar
rt.2.1  
Jesse Vincent committed
57
58
59
60
61
62
63
64
65

=head1 DESCRIPTION


=head1 METHODS


=cut

66
67

package RT::ACL;
68
69
use base 'RT::SearchBuilder';

70
71
use RT::ACE;

72
sub Table { 'ACL'}
73

74
use strict;
75
76
use warnings;

Jesse Vincent's avatar
rt.2.1  
Jesse Vincent committed
77
78


79
80
81
82
83
84
85
86
=head2 Next

Hand out the next ACE that was found

=cut



87
=head2 LimitToObject $object
88

89
Limit the ACL to rights for the object $object. It needs to be an RT::Record class.
90
91
92
93
94

=cut

sub LimitToObject {
    my $self = shift;
95
    my $obj  = shift;
96
97
98
99
100
101

    my $obj_type = ref($obj)||$obj;
    my $obj_id = eval { $obj->id};

    my $object_clause = 'possible_objects';
    $self->_OpenParen($object_clause);
102
    $self->Limit(
103
        SUBCLAUSE       => $object_clause,
104
105
        FIELD           => 'ObjectType',
        OPERATOR        => '=',
106
107
        VALUE           => (ref($obj)||$obj),
        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
113
        FIELD           => 'ObjectId',
        OPERATOR        => '=',
114
115
        VALUE           => $obj_id,
        ENTRYAGGREGATOR => 'AND',
116
117
        QUOTEVALUE      => 0
    );
118
119
    }
    $self->_CloseParen($object_clause);
120

Jesse Vincent's avatar
rt.2.1  
Jesse Vincent committed
121
}
122

Jesse Vincent's avatar
rt.2.1  
Jesse Vincent committed
123

Jesse Vincent's avatar
Jesse Vincent committed
124

Jesse Vincent's avatar
Jesse Vincent committed
125
=head2 LimitToPrincipal { Type => undef, Id => undef, IncludeGroupMembership => undef }
126
127

Limit the ACL to the principal with PrincipalId Id and PrincipalType Type
Jesse Vincent's avatar
rt.2.1  
Jesse Vincent committed
128

129
130
131
Id is not optional.
Type is.

Jesse Vincent's avatar
Jesse Vincent committed
132
133
134
if IncludeGroupMembership => 1 is specified, ACEs which apply to the principal due to group membership will be included in the resultset.


Jesse Vincent's avatar
rt.2.1  
Jesse Vincent committed
135
136
=cut

137
138
sub LimitToPrincipal {
    my $self = shift;
Jesse Vincent's avatar
Jesse Vincent committed
139
140
    my %args = ( Type                   => undef,
                 Id                     => undef,
Jesse Vincent's avatar
Jesse Vincent committed
141
                 IncludeGroupMembership => undef,
Jesse Vincent's avatar
Jesse Vincent committed
142
143
                 @_
               );
Jesse Vincent's avatar
Jesse Vincent committed
144
145
146
147
148
    if ( $args{'IncludeGroupMembership'} ) {
        my $cgm = $self->NewAlias('CachedGroupMembers');
        $self->Join( ALIAS1 => 'main',
                     FIELD1 => 'PrincipalId',
                     ALIAS2 => $cgm,
Jesse Vincent's avatar
Jesse Vincent committed
149
150
                     FIELD2 => 'GroupId'
                   );
151
152
153
        $self->Limit( ALIAS => $cgm,
                      FIELD => 'Disabled',
                      VALUE => 0 );
Jesse Vincent's avatar
Jesse Vincent committed
154
155
156
157
        $self->Limit( ALIAS           => $cgm,
                      FIELD           => 'MemberId',
                      OPERATOR        => '=',
                      VALUE           => $args{'Id'},
Jesse Vincent's avatar
Jesse Vincent committed
158
159
160
                      ENTRYAGGREGATOR => 'OR'
                    );
    } else {
Jesse Vincent's avatar
Jesse Vincent committed
161
162
163
164
        if ( defined $args{'Type'} ) {
            $self->Limit( FIELD           => 'PrincipalType',
                          OPERATOR        => '=',
                          VALUE           => $args{'Type'},
Jesse Vincent's avatar
Jesse Vincent committed
165
166
167
168
169
170
171
172
173
174
175
176
177
178
                          ENTRYAGGREGATOR => 'OR'
                        );
        }

        # if the principal id points to a user, we really want to point
        # to their ACL equivalence group. The machinations we're going through
        # lead me to start to suspect that we really want users and groups
        # to just be the same table. or _maybe_ that we want an object db.
        my $princ = RT::Principal->new( RT->SystemUser );
        $princ->Load( $args{'Id'} );
        if ( $princ->PrincipalType eq 'User' ) {
            my $group = RT::Group->new( RT->SystemUser );
            $group->LoadACLEquivalenceGroup($princ);
            $args{'Id'} = $group->PrincipalId;
Jesse Vincent's avatar
Jesse Vincent committed
179
180
181
182
        }
        $self->Limit( FIELD           => 'PrincipalId',
                      OPERATOR        => '=',
                      VALUE           => $args{'Id'},
Jesse Vincent's avatar
Jesse Vincent committed
183
184
                      ENTRYAGGREGATOR => 'OR'
                    );
185
    }
186
187
188
}


Jesse Vincent's avatar
Jesse Vincent committed
189
190


Jesse Vincent's avatar
rt.2.1  
Jesse Vincent committed
191
192
sub Next {
    my $self = shift;
193

Jesse Vincent's avatar
rt.2.1  
Jesse Vincent committed
194
    my $ACE = $self->SUPER::Next();
195
196
197
    # Short-circuit having to load up the ->Object
    return $ACE
        if $self->CurrentUser->PrincipalObj->Id == RT->SystemUser->Id;
198
199
200
201
202
203
204
205
206
207
208
209
210
211
    if ( ( defined($ACE) ) and ( ref($ACE) ) ) {

        if ( $self->CurrentUser->HasRight( Right  => 'ShowACL',
                                           Object => $ACE->Object )
             or $self->CurrentUser->HasRight( Right  => 'ModifyACL',
                                              Object => $ACE->Object )
          ) {
            return ($ACE);
        }

        #If the user doesn't have the right to show this ACE
        else {
            return ( $self->Next() );
        }
Jesse Vincent's avatar
rt.2.1  
Jesse Vincent committed
212
    }
213

Jesse Vincent's avatar
rt.2.1  
Jesse Vincent committed
214
215
    #if there never was any ACE
    else {
216
217
218
        return (undef);
    }

Jesse Vincent's avatar
rt.2.1  
Jesse Vincent committed
219
220
}

221
222
223
224
225
226
227
228
229
230
231
232
=head2 NewItem

Returns an empty new RT::ACE item

=cut

sub NewItem {
    my $self = shift;
    return(RT::ACE->new($self->CurrentUser));
}
RT::Base->_ImportOverlays();

Jesse Vincent's avatar
rt.2.1  
Jesse Vincent committed
233
1;