1 # BEGIN BPS TAGGED BLOCK {{{
5 # This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
6 # <sales@bestpractical.com>
8 # (Except where explicitly superseded by other copyright notices)
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
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.
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.
30 # CONTRIBUTION SUBMISSION POLICY:
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.)
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.
47 # END BPS TAGGED BLOCK }}}
51 RT::Groups - a collection of RT::Group objects
56 my $groups = RT::Groups->new($CurrentUser);
58 while (my $group = $groups->Next()) {
59 print $group->Id ." is a group id\n";
77 use base 'RT::SearchBuilder';
84 # XXX: below some code is marked as subject to generalize in Groups, Users classes.
85 # RUZ suggest name Principals::Generic or Principals::Base as abstract class, but
86 # Jesse wants something that doesn't imply it's a Principals.pm subclass.
87 # See comments below for candidats.
93 $self->{'with_disabled_column'} = 1;
95 my @result = $self->SUPER::_Init(@_);
97 $self->OrderBy( ALIAS => 'main',
101 # XXX: this code should be generalized
102 $self->{'princalias'} = $self->Join(
105 TABLE2 => 'Principals',
109 # even if this condition is useless and ids in the Groups table
110 # only match principals with type 'Group' this could speed up
111 # searches in some DBs.
112 $self->Limit( ALIAS => $self->{'princalias'},
113 FIELD => 'PrincipalType',
120 =head2 PrincipalsAlias
122 Returns the string that represents this Users object's primary "Principals" alias.
126 # XXX: should be generalized, code duplication
127 sub PrincipalsAlias {
129 return($self->{'princalias'});
135 =head2 LimitToSystemInternalGroups
137 Return only SystemInternal Groups, such as "privileged" "unprivileged" and "everyone"
142 sub LimitToSystemInternalGroups {
144 $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'SystemInternal', CASESENSITIVE => 0 );
145 # All system internal groups have the same instance. No reason to limit down further
146 #$self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => '0');
152 =head2 LimitToUserDefinedGroups
154 Return only UserDefined Groups
159 sub LimitToUserDefinedGroups {
161 $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'UserDefined', CASESENSITIVE => 0 );
162 # All user-defined groups have the same instance. No reason to limit down further
163 #$self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => '');
166 =head2 LimitToRolesForObject OBJECT
168 Limits the set of groups to role groups specifically for the object in question
169 based on the object's class and ID. If the object has no ID, the roles are not
170 limited by group C<Instance>. That is, calling this method on an unloaded
171 object will find all role groups for that class of object.
173 Replaces L</LimitToRolesForQueue>, L</LimitToRolesForTicket>, and
174 L</LimitToRolesForSystem>.
178 sub LimitToRolesForObject {
181 $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => ref($object) . "-Role", CASESENSITIVE => 0 );
182 $self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => $object->id);
185 =head2 LimitToRolesForQueue QUEUE_ID
187 B<DEPRECATED>. Use L</LimitToRolesForObject> instead.
189 Limits the set of groups found to role groups for queue QUEUE_ID
193 sub LimitToRolesForQueue {
197 Instead => "LimitToRolesForObject",
200 $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'RT::Queue-Role', CASESENSITIVE => 0 );
201 $self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => $queue);
206 =head2 LimitToRolesForTicket Ticket_ID
208 B<DEPRECATED>. Use L</LimitToRolesForObject> instead.
210 Limits the set of groups found to role groups for Ticket Ticket_ID
214 sub LimitToRolesForTicket {
218 Instead => "LimitToRolesForObject",
221 $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'RT::Ticket-Role', CASESENSITIVE => 0 );
222 $self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => $Ticket);
227 =head2 LimitToRolesForSystem System_ID
229 B<DEPRECATED>. Use L</LimitToRolesForObject> instead.
231 Limits the set of groups found to role groups for System System_ID
235 sub LimitToRolesForSystem {
238 Instead => "LimitToRolesForObject",
241 $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'RT::System-Role', CASESENSITIVE => 0 );
242 $self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => RT::System->Id );
246 =head2 WithMember {PrincipalId => PRINCIPAL_ID, Recursively => undef}
248 Limits the set of groups returned to groups which have
249 Principal PRINCIPAL_ID as a member. Returns the alias used for the join.
255 my %args = ( PrincipalId => undef,
256 Recursively => undef,
258 my $members = $self->Join(
259 ALIAS1 => 'main', FIELD1 => 'id',
261 ? (TABLE2 => 'CachedGroupMembers')
262 # (GroupId, MemberId) is unique in GM table
263 : (TABLE2 => 'GroupMembers', DISTINCT => 1)
268 $self->Limit(ALIAS => $members, FIELD => 'MemberId', OPERATOR => '=', VALUE => $args{'PrincipalId'});
269 $self->Limit(ALIAS => $members, FIELD => 'Disabled', VALUE => 0)
270 if $args{'Recursively'};
278 PrincipalId => undef,
279 Recursively => undef,
283 my $members = $args{'Recursively'} ? 'CachedGroupMembers' : 'GroupMembers';
284 my $members_alias = $self->Join(
289 DISTINCT => $members eq 'GroupMembers',
292 LEFTJOIN => $members_alias,
293 ALIAS => $members_alias,
296 VALUE => $args{'PrincipalId'},
299 LEFTJOIN => $members_alias,
300 ALIAS => $members_alias,
303 ) if $args{'Recursively'};
305 ALIAS => $members_alias,
313 =head2 WithRight { Right => RIGHTNAME, Object => RT::Record, IncludeSystemRights => 1, IncludeSuperusers => 0, EquivObjects => [ ] }
316 Find all groups which have RIGHTNAME for RT::Record. Optionally include global rights and superusers. By default, include the global rights, but not the superusers.
322 #XXX: should be generilized
325 my %args = ( Right => undef,
327 IncludeSystemRights => 1,
328 IncludeSuperusers => undef,
329 IncludeSubgroupMembers => 0,
333 my $from_role = $self->Clone;
334 $from_role->WithRoleRight( %args );
336 my $from_group = $self->Clone;
337 $from_group->WithGroupRight( %args );
340 use DBIx::SearchBuilder::Union;
341 my $union = DBIx::SearchBuilder::Union->new();
342 $union->add($from_role);
343 $union->add($from_group);
345 bless $self, ref($union);
350 #XXX: methods are active aliases to Users class to prevent code duplication
351 # should be generalized
355 return 'main' unless $args{'IncludeSubgroupMembers'};
356 return $self->RT::Users::_JoinGroups( %args );
358 sub _JoinGroupMembers {
361 return 'main' unless $args{'IncludeSubgroupMembers'};
362 return $self->RT::Users::_JoinGroupMembers( %args );
364 sub _JoinGroupMembersForGroupRights {
367 my $group_members = $self->_JoinGroupMembers( %args );
368 unless( $group_members eq 'main' ) {
369 return $self->RT::Users::_JoinGroupMembersForGroupRights( %args );
371 $self->Limit( ALIAS => $args{'ACLAlias'},
372 FIELD => 'PrincipalId',
377 sub _JoinACL { return (shift)->RT::Users::_JoinACL( @_ ) }
378 sub _RoleClauses { return (shift)->RT::Users::_RoleClauses( @_ ) }
379 sub _WhoHaveRoleRightSplitted { return (shift)->RT::Users::_WhoHaveRoleRightSplitted( @_ ) }
380 sub _GetEquivObjects { return (shift)->RT::Users::_GetEquivObjects( @_ ) }
381 sub WithGroupRight { return (shift)->RT::Users::WhoHaveGroupRight( @_ ) }
382 sub WithRoleRight { return (shift)->RT::Users::WhoHaveRoleRight( @_ ) }
384 sub ForWhichCurrentUserHasRight {
388 IncludeSuperusers => undef,
392 # Non-disabled groups...
393 $self->LimitToEnabled;
395 # ...which are the target object of an ACL with that right, or
396 # where the target is the system object (a global right)
397 my $acl = $self->_JoinACL( %args );
398 $self->_AddSubClause(
399 ACLObjects => "( (main.id = $acl.ObjectId AND $acl.ObjectType = 'RT::Group')"
400 . " OR $acl.ObjectType = 'RT::System')");
402 # ...and where that right is granted to any group..
403 my $member = $self->Join(
405 FIELD1 => 'PrincipalId',
406 TABLE2 => 'CachedGroupMembers',
415 # ...with the current user in it
419 VALUE => $self->CurrentUser->Id,
425 =head2 LimitToEnabled
427 Only find items that haven't been disabled
434 $self->{'handled_disabled_column'} = 1;
436 ALIAS => $self->PrincipalsAlias,
443 =head2 LimitToDeleted
445 Only find items that have been deleted.
452 $self->{'handled_disabled_column'} = $self->{'find_disabled_rows'} = 1;
454 ALIAS => $self->PrincipalsAlias,
465 # Don't show groups which the user isn't allowed to see.
467 my $Group = $self->SUPER::Next();
468 if ((defined($Group)) and (ref($Group))) {
469 unless ($Group->CurrentUserHasRight('SeeGroup')) {
470 return $self->Next();
485 #unless we really want to find disabled rows, make sure we're only finding enabled ones.
486 unless($self->{'find_disabled_rows'}) {
487 $self->LimitToEnabled();
490 return($self->SUPER::_DoSearch(@_));
494 RT::Base->_ImportOverlays();