import of rt 3.0.4
[freeside.git] / rt / lib / RT / Groups_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::Groups - a collection of RT::Group objects
27
28 =head1 SYNOPSIS
29
30   use RT::Groups;
31   my $groups = $RT::Groups->new($CurrentUser);
32   $groups->LimitToReal();
33   while (my $group = $groups->Next()) {
34      print $group->Id ." is a group id\n";
35   }
36
37 =head1 DESCRIPTION
38
39
40 =head1 METHODS
41
42
43 =begin testing
44
45 ok (require RT::Groups);
46
47 =end testing
48
49 =cut
50
51 use strict;
52 no warnings qw(redefine);
53
54
55 # {{{ sub _Init
56
57 sub _Init { 
58   my $self = shift;
59   $self->{'table'} = "Groups";
60   $self->{'primary_key'} = "id";
61
62   $self->OrderBy( ALIAS => 'main',
63                   FIELD => 'Name',
64                   ORDER => 'ASC');
65
66
67   return ( $self->SUPER::_Init(@_));
68 }
69 # }}}
70
71 # {{{ LimiToSystemInternalGroups
72
73 =head2 LimitToSystemInternalGroups
74
75 Return only SystemInternal Groups, such as "privileged" "unprivileged" and "everyone" 
76
77 =cut
78
79
80 sub LimitToSystemInternalGroups {
81     my $self = shift;
82     $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'SystemInternal');
83     $self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => '');
84 }
85
86
87 # }}}
88
89 # {{{ LimiToUserDefinedGroups
90
91 =head2 LimitToUserDefined Groups
92
93 Return only UserDefined Groups
94
95 =cut
96
97
98 sub LimitToUserDefinedGroups {
99     my $self = shift;
100     $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'UserDefined');
101     $self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => '');
102 }
103
104
105 # }}}
106
107 # {{{ LimiToPersonalGroups
108
109 =head2 LimitToPersonalGroupsFor PRINCIPAL_ID
110
111 Return only Personal Groups for the user whose principal id 
112 is PRINCIPAL_ID
113
114 =cut
115
116
117 sub LimitToPersonalGroupsFor {
118     my $self = shift;
119     my $princ = shift;
120
121     $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'Personal');
122     $self->Limit(   FIELD => 'Instance',   
123                     OPERATOR => '=', 
124                     VALUE => $princ,
125                     ENTRY_AGGREGATOR => 'OR');
126 }
127
128
129 # }}}
130
131 # {{{ LimitToRolesForQueue
132
133 =item LimitToRolesForQueue QUEUE_ID
134
135 Limits the set of groups found to role groups for queue QUEUE_ID
136
137 =cut
138
139 sub LimitToRolesForQueue {
140     my $self = shift;
141     my $queue = shift;
142     $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'RT::Queue-Role');
143     $self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => $queue);
144 }
145
146 # }}}
147
148 # {{{ LimitToRolesForTicket
149
150 =item LimitToRolesForTicket Ticket_ID
151
152 Limits the set of groups found to role groups for Ticket Ticket_ID
153
154 =cut
155
156 sub LimitToRolesForTicket {
157     my $self = shift;
158     my $Ticket = shift;
159     $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'RT::Ticket-Role');
160     $self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => '$Ticket');
161 }
162
163 # }}}
164
165 # {{{ LimitToRolesForSystem
166
167 =item LimitToRolesForSystem System_ID
168
169 Limits the set of groups found to role groups for System System_ID
170
171 =cut
172
173 sub LimitToRolesForSystem {
174     my $self = shift;
175     $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'RT::System-Role');
176 }
177
178 # }}}
179
180 =head2 WithMember {PrincipalId => PRINCIPAL_ID, Recursively => undef}
181
182 Limits the set of groups returned to groups which have
183 Principal PRINCIPAL_ID as a member
184    
185 =begin testing
186
187 my $u = RT::User->new($RT::SystemUser);
188 $u->Create(Name => 'Membertests');
189 my $g = RT::Group->new($RT::SystemUser);
190 my ($id, $msg) = $g->CreateUserDefinedGroup(Name => 'Membertests');
191 ok ($id,$msg);
192
193 my ($aid, $amsg) =$g->AddMember($u->id);
194 ok ($aid, $amsg);
195 ok($g->HasMember($u->PrincipalObj),"G has member u");
196
197 my $groups = RT::Groups->new($RT::SystemUser);
198 $groups->LimitToUserDefinedGroups();
199 $groups->WithMember(PrincipalId => $u->id);
200 ok ($groups->Count == 1,"found the 1 group - " . $groups->Count);
201 ok ($groups->First->Id == $g->Id, "it's the right one");
202
203
204
205
206 =end testing
207
208
209 =cut
210
211 sub WithMember {
212     my $self = shift;
213     my %args = ( PrincipalId => undef,
214                  Recursively => undef,
215                  @_);
216     my $members;
217
218     if ($args{'Recursively'}) {
219         $members = $self->NewAlias('CachedGroupMembers');
220     } else {
221         $members = $self->NewAlias('GroupMembers');
222     }
223     $self->Join(ALIAS1 => 'main', FIELD1 => 'id',
224                 ALIAS2 => $members, FIELD2 => 'GroupId');
225
226     $self->Limit(ALIAS => $members, FIELD => 'MemberId', OPERATOR => '=', VALUE => $args{'PrincipalId'});
227 }
228
229
230 sub WithRight {
231     my $self = shift;
232     my %args = ( Right                  => undef,
233                  Object =>              => undef,
234                  IncludeSystemRights    => undef,
235                  IncludeSuperusers      => undef,
236                  @_ );
237
238     my $groupprinc = $self->NewAlias('Principals');
239     my $acl        = $self->NewAlias('ACL');
240
241     # {{{ Find only rows where the right granted is the one we're looking up or _possibly_ superuser 
242     $self->Limit( ALIAS           => $acl,
243                   FIELD           => 'RightName',
244                   OPERATOR        => '=',
245                   VALUE           => $args{Right},
246                   ENTRYAGGREGATOR => 'OR' );
247
248     if ( $args{'IncludeSuperusers'} ) {
249         $self->Limit( ALIAS           => $acl,
250                       FIELD           => 'RightName',
251                       OPERATOR        => '=',
252                       VALUE           => 'SuperUser',
253                       ENTRYAGGREGATOR => 'OR' );
254     }
255     # }}}
256
257     my ($or_check_ticket_roles, $or_check_roles, $or_look_at_object);
258
259     if ( defined $args{'Object'} ) {
260         if ( ref($args{'Object'}) eq 'RT::Ticket' ) {
261             $or_check_ticket_roles =
262                 " OR ( main.Domain = 'RT::Ticket-Role' AND main.Instance = " . $args{'Object'}->Id . ") ";
263
264             # If we're looking at ticket rights, we also want to look at the associated queue rights.
265             # this is a little bit hacky, but basically, now that we've done the ticket roles magic,
266             # we load the queue object and ask all the rest of our questions about the queue.
267             $args{'Object'}   = $args{'Object'}->QueueObj;
268         }
269         # TODO XXX This really wants some refactoring
270         if ( ref($args{'Object'}) eq 'RT::Queue' ) {
271             $or_check_roles =
272                 " OR ( ( (main.Domain = 'RT::Queue-Role' AND main.Instance = " .
273                 $args{'Object'}->Id . ") $or_check_ticket_roles ) " .
274                 " AND main.Type = $acl.PrincipalType AND main.id = $groupprinc.id) ";
275         }
276
277         $or_look_at_object =
278             " OR ($acl.ObjectType = '" . ref($args{'Object'}) . "'" .
279             " AND $acl.ObjectId = " . $args{'Object'}->Id . ") ";
280     }
281
282     $self->_AddSubClause( "WhichObject", "($acl.ObjectType = 'RT::System' $or_look_at_object)" );
283
284     $self->_AddSubClause( "WhichGroup",
285         qq{
286           ( (    $acl.PrincipalId = $groupprinc.id
287              AND $acl.PrincipalType = 'Group'
288              AND (   main.Domain = 'SystemInternal'
289                   OR main.Domain = 'UserDefined'
290                   OR main.Domain = 'ACLEquivalence')
291              AND main.id = $groupprinc.id)
292            $or_check_roles)
293         }
294     );
295 }
296
297 1;
298