diff options
Diffstat (limited to 'rt/lib/RT/Groups_Overlay.pm')
-rw-r--r-- | rt/lib/RT/Groups_Overlay.pm | 273 |
1 files changed, 244 insertions, 29 deletions
diff --git a/rt/lib/RT/Groups_Overlay.pm b/rt/lib/RT/Groups_Overlay.pm index 3d2c660fe..cf29114dc 100644 --- a/rt/lib/RT/Groups_Overlay.pm +++ b/rt/lib/RT/Groups_Overlay.pm @@ -1,8 +1,14 @@ -# BEGIN LICENSE BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # -# Copyright (c) 1996-2003 Jesse Vincent <jesse@bestpractical.com> +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC +# <jesse@bestpractical.com> # -# (Except where explictly superceded by other copyright notices) +# (Except where explicitly superseded by other copyright notices) +# +# +# LICENSE: # # 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 @@ -14,13 +20,30 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# Unless otherwise specified, all modifications, corrections or -# extensions to this work which alter its source code become the -# property of Best Practical Solutions, LLC when submitted for -# inclusion in the work. +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# +# +# CONTRIBUTION SUBMISSION POLICY: +# +# (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.) # +# 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. # -# END LICENSE BLOCK +# END BPS TAGGED BLOCK }}} + =head1 NAME RT::Groups - a collection of RT::Group objects @@ -29,7 +52,7 @@ use RT::Groups; my $groups = $RT::Groups->new($CurrentUser); - $groups->LimitToReal(); + $groups->UnLimit(); while (my $group = $groups->Next()) { print $group->Id ." is a group id\n"; } @@ -48,6 +71,9 @@ ok (require RT::Groups); =cut + +package RT::Groups; + use strict; no warnings qw(redefine); @@ -80,7 +106,8 @@ Return only SystemInternal Groups, such as "privileged" "unprivileged" and "ever sub LimitToSystemInternalGroups { my $self = shift; $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'SystemInternal'); - $self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => ''); + # All system internal groups have the same instance. No reason to limit down further + #$self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => '0'); } @@ -98,7 +125,8 @@ Return only UserDefined Groups sub LimitToUserDefinedGroups { my $self = shift; $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'UserDefined'); - $self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => ''); + # All user-defined groups have the same instance. No reason to limit down further + #$self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => ''); } @@ -121,8 +149,7 @@ sub LimitToPersonalGroupsFor { $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'Personal'); $self->Limit( FIELD => 'Instance', OPERATOR => '=', - VALUE => $princ, - ENTRY_AGGREGATOR => 'OR'); + VALUE => $princ); } @@ -130,7 +157,7 @@ sub LimitToPersonalGroupsFor { # {{{ LimitToRolesForQueue -=item LimitToRolesForQueue QUEUE_ID +=head2 LimitToRolesForQueue QUEUE_ID Limits the set of groups found to role groups for queue QUEUE_ID @@ -147,7 +174,7 @@ sub LimitToRolesForQueue { # {{{ LimitToRolesForTicket -=item LimitToRolesForTicket Ticket_ID +=head2 LimitToRolesForTicket Ticket_ID Limits the set of groups found to role groups for Ticket Ticket_ID @@ -164,7 +191,7 @@ sub LimitToRolesForTicket { # {{{ LimitToRolesForSystem -=item LimitToRolesForSystem System_ID +=head2 LimitToRolesForSystem System_ID Limits the set of groups found to role groups for System System_ID @@ -227,25 +254,115 @@ sub WithMember { } +=head2 WithRight { Right => RIGHTNAME, Object => RT::Record, IncludeSystemRights => 1, IncludeSuperusers => 0, EquivObjects => [ ] } + + +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. + +=begin testing + +my $q = RT::Queue->new($RT::SystemUser); +my ($id, $msg) =$q->Create( Name => 'GlobalACLTest'); +ok ($id, $msg); + +my $testuser = RT::User->new($RT::SystemUser); +($id,$msg) = $testuser->Create(Name => 'JustAnAdminCc'); +ok ($id,$msg); + +my $global_admin_cc = RT::Group->new($RT::SystemUser); +$global_admin_cc->LoadSystemRoleGroup('AdminCc'); +ok($global_admin_cc->id, "Found the global admincc group"); +my $groups = RT::Groups->new($RT::SystemUser); +$groups->WithRight(Right => 'OwnTicket', Object => $q); +is($groups->Count, 1); +($id, $msg) = $global_admin_cc->PrincipalObj->GrantRight(Right =>'OwnTicket', Object=> $RT::System); +ok ($id,$msg); +ok (!$testuser->HasRight(Object => $q, Right => 'OwnTicket') , "The test user does not have the right to own tickets in the test queue"); +($id, $msg) = $q->AddWatcher(Type => 'AdminCc', PrincipalId => $testuser->id); +ok($id,$msg); +ok ($testuser->HasRight(Object => $q, Right => 'OwnTicket') , "The test user does have the right to own tickets now. thank god."); + +$groups = RT::Groups->new($RT::SystemUser); +$groups->WithRight(Right => 'OwnTicket', Object => $q); +ok ($id,$msg); +is($groups->Count, 2); + +my $RTxGroup = RT::Group->new($RT::SystemUser); +($id, $msg) = $RTxGroup->CreateUserDefinedGroup( Name => 'RTxGroup', Description => "RTx extension group"); +ok ($id,$msg); + +my $RTxSysObj = {}; +bless $RTxSysObj, 'RTx::System'; +*RTx::System::Id = sub { 1; }; +*RTx::System::id = *RTx::System::Id; +my $ace = RT::Record->new($RT::SystemUser); +$ace->Table('ACL'); +$ace->_BuildTableAttributes unless ($_TABLE_ATTR->{ref($self)}); +($id, $msg) = $ace->Create( PrincipalId => $RTxGroup->id, PrincipalType => 'Group', RightName => 'RTxGroupRight', ObjectType => 'RTx::System', ObjectId => 1); +ok ($id, "ACL for RTxSysObj created"); + +my $RTxObj = {}; +bless $RTxObj, 'RTx::System::Record'; +*RTx::System::Record::Id = sub { 4; }; +*RTx::System::Record::id = *RTx::System::Record::Id; + +$groups = RT::Groups->new($RT::SystemUser); +$groups->WithRight(Right => 'RTxGroupRight', Object => $RTxSysObj); +is($groups->Count, 1, "RTxGroupRight found for RTxSysObj"); + +$groups = RT::Groups->new($RT::SystemUser); +$groups->WithRight(Right => 'RTxGroupRight', Object => $RTxObj); +is($groups->Count, 0, "RTxGroupRight not found for RTxObj"); + +$groups = RT::Groups->new($RT::SystemUser); +$groups->WithRight(Right => 'RTxGroupRight', Object => $RTxObj, EquivObjects => [ $RTxSysObj ]); +is($groups->Count, 1, "RTxGroupRight found for RTxObj using EquivObjects"); + +$ace = RT::Record->new($RT::SystemUser); +$ace->Table('ACL'); +$ace->_BuildTableAttributes unless ($_TABLE_ATTR->{ref($self)}); +($id, $msg) = $ace->Create( PrincipalId => $RTxGroup->id, PrincipalType => 'Group', RightName => 'RTxGroupRight', ObjectType => 'RTx::System::Record', ObjectId => 5 ); +ok ($id, "ACL for RTxObj created"); + +my $RTxObj2 = {}; +bless $RTxObj2, 'RTx::System::Record'; +*RTx::System::Record::Id = sub { 5; }; + +$groups = RT::Groups->new($RT::SystemUser); +$groups->WithRight(Right => 'RTxGroupRight', Object => $RTxObj2); +is($groups->Count, 1, "RTxGroupRight found for RTxObj2"); + +$groups = RT::Groups->new($RT::SystemUser); +$groups->WithRight(Right => 'RTxGroupRight', Object => $RTxObj2, EquivObjects => [ $RTxSysObj ]); +is($groups->Count, 1, "RTxGroupRight found for RTxObj2"); + + + +=end testing + + +=cut + + sub WithRight { my $self = shift; my %args = ( Right => undef, Object => => undef, - IncludeSystemRights => undef, + IncludeSystemRights => 1, IncludeSuperusers => undef, + EquivObjects => [ ], @_ ); - my $groupprinc = $self->NewAlias('Principals'); my $acl = $self->NewAlias('ACL'); # {{{ Find only rows where the right granted is the one we're looking up or _possibly_ superuser $self->Limit( ALIAS => $acl, FIELD => 'RightName', - OPERATOR => '=', - VALUE => $args{Right}, + OPERATOR => ($args{Right} ? '=' : 'IS NOT'), + VALUE => $args{Right} || 'NULL', ENTRYAGGREGATOR => 'OR' ); - if ( $args{'IncludeSuperusers'} ) { + if ( $args{'IncludeSuperusers'} and $args{'Right'} ) { $self->Limit( ALIAS => $acl, FIELD => 'RightName', OPERATOR => '=', @@ -254,7 +371,8 @@ sub WithRight { } # }}} - my ($or_check_ticket_roles, $or_check_roles, $or_look_at_object); + my ($or_check_ticket_roles, $or_check_roles); + my $which_object = "$acl.ObjectType = 'RT::System'"; if ( defined $args{'Object'} ) { if ( ref($args{'Object'}) eq 'RT::Ticket' ) { @@ -271,28 +389,125 @@ sub WithRight { $or_check_roles = " OR ( ( (main.Domain = 'RT::Queue-Role' AND main.Instance = " . $args{'Object'}->Id . ") $or_check_ticket_roles ) " . - " AND main.Type = $acl.PrincipalType AND main.id = $groupprinc.id) "; + " AND main.Type = $acl.PrincipalType) "; } - $or_look_at_object = - " OR ($acl.ObjectType = '" . ref($args{'Object'}) . "'" . + if ( $args{'IncludeSystemRights'} ) { + $which_object .= ' OR '; + } + else { + $which_object = ''; + } + foreach my $obj ( @{ $args{'EquivObjects'} } ) { + next unless ( UNIVERSAL::can( $obj, 'id' ) ); + $which_object .= "($acl.ObjectType = '" . ref( $obj ) . "' AND $acl.ObjectId = " . $obj->id . ") OR "; + } + $which_object .= + " ($acl.ObjectType = '" . ref($args{'Object'}) . "'" . " AND $acl.ObjectId = " . $args{'Object'}->Id . ") "; } - $self->_AddSubClause( "WhichObject", "($acl.ObjectType = 'RT::System' $or_look_at_object)" ); + $self->_AddSubClause( "WhichObject", "($which_object)" ); $self->_AddSubClause( "WhichGroup", qq{ - ( ( $acl.PrincipalId = $groupprinc.id + ( ( $acl.PrincipalId = main.id AND $acl.PrincipalType = 'Group' AND ( main.Domain = 'SystemInternal' OR main.Domain = 'UserDefined' - OR main.Domain = 'ACLEquivalence') - AND main.id = $groupprinc.id) + OR main.Domain = 'ACLEquivalence')) $or_check_roles) } ); } +# {{{ sub LimitToEnabled + +=head2 LimitToEnabled + +Only find items that haven\'t been disabled + +=cut + +sub LimitToEnabled { + my $self = shift; + + my $alias = $self->Join( + TYPE => 'left', + ALIAS1 => 'main', + FIELD1 => 'id', + TABLE2 => 'Principals', + FIELD2 => 'id' + ); + + $self->Limit( ALIAS => $alias, + FIELD => 'Disabled', + VALUE => '0', + OPERATOR => '=' ); +} +# }}} + +# {{{ sub LimitToDisabled + +=head2 LimitToDeleted + +Only find items that have been deleted. + +=cut + +sub LimitToDeleted { + my $self = shift; + + my $alias = $self->Join( + TYPE => 'left', + ALIAS1 => 'main', + FIELD1 => 'id', + TABLE2 => 'Principals', + FIELD2 => 'id' + ); + + $self->{'find_disabled_rows'} = 1; + $self->Limit( ALIAS => $alias, + FIELD => 'Disabled', + OPERATOR => '=', + VALUE => '1' + ); +} +# }}} + +# {{{ sub Next + +sub Next { + my $self = shift; + + # Don't show groups which the user isn't allowed to see. + + my $Group = $self->SUPER::Next(); + if ((defined($Group)) and (ref($Group))) { + unless ($Group->CurrentUserHasRight('SeeGroup')) { + return $self->Next(); + } + + return $Group; + } + else { + return undef; + } +} + + + +sub _DoSearch { + my $self = shift; + + #unless we really want to find disabled rows, make sure we\'re only finding enabled ones. + unless($self->{'find_disabled_rows'}) { + $self->LimitToEnabled(); + } + + return($self->SUPER::_DoSearch(@_)); + +} + 1; |