X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=rt%2Flib%2FRT%2FGroup_Overlay.pm;h=41cf49732444b6977397bfb343a67e42d0600924;hb=673b9a458d9138523026963df6fa3b4683e09bae;hp=f71fe7f7e268f3085a4fcee162004730f35b821c;hpb=eb9668a6f3181ee02cb335272c5ee4616e61fd09;p=freeside.git diff --git a/rt/lib/RT/Group_Overlay.pm b/rt/lib/RT/Group_Overlay.pm index f71fe7f7e..41cf49732 100644 --- a/rt/lib/RT/Group_Overlay.pm +++ b/rt/lib/RT/Group_Overlay.pm @@ -1,9 +1,15 @@ -# BEGIN LICENSE BLOCK +# BEGIN BPS TAGGED BLOCK {{{ # -# Copyright (c) 1996-2003 Jesse Vincent +# COPYRIGHT: +# +# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC +# # -# (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 @@ -15,13 +21,29 @@ # 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.) # -# END LICENSE BLOCK +# 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 BPS TAGGED BLOCK }}} # Released under the terms of version 2 of the GNU Public License =head1 NAME @@ -30,21 +52,13 @@ =head1 SYNOPSIS - use RT::Group; +use RT::Group; my $group = new RT::Group($CurrentUser); =head1 DESCRIPTION An RT group object. -=head1 AUTHOR - -Jesse Vincent, jesse@bestpractical.com - -=head1 SEE ALSO - -RT - =head1 METHODS @@ -132,6 +146,9 @@ ok($group_3->HasMemberRecursively($principal_2) == undef, "group 3 has member 2 =cut + +package RT::Group; + use strict; no warnings qw(redefine); @@ -146,7 +163,10 @@ $RIGHTS = { AdminGroup => 'Modify group metadata or delete group', # loc_pair AdminGroupMembership => 'Modify membership roster for this group', # loc_pair - ModifyOwnMembership => 'Join or leave this group' # loc_pair + ModifyOwnMembership => 'Join or leave this group', # loc_pair + EditSavedSearches => 'Edit saved searches for this group', # loc_pair + ShowSavedSearches => 'Display saved searches for this group', # loc_pair + SeeGroup => 'Make this group visible to user', # loc_pair }; # Tell RT::ACE that this sort of object can get acls granted @@ -411,6 +431,7 @@ sub LoadSystemRoleGroup { # }}} # {{{ sub Create + =head2 Create You need to specify what sort of group you're creating by calling one of the other @@ -445,6 +466,7 @@ sub _Create { Type => undef, Instance => '0', InsideTransaction => undef, + _RecordTransaction => 1, @_ ); @@ -490,8 +512,12 @@ sub _Create { $cgm->Create(Group =>$self->PrincipalObj, Member => $self->PrincipalObj, ImmediateParent => $self->PrincipalObj); + if ( $args{'_RecordTransaction'} ) { + $self->_NewTransaction( Type => "Create" ); + } $RT::Handle->Commit() unless ($args{'InsideTransaction'}); + return ( $id, $self->loc("Group created") ); } @@ -686,6 +712,7 @@ If passed a positive value, this group will be disabled. No rights it commutes o It will not appear in most group listings. This routine finds all the cached group members that are members of this group (recursively) and disables them. + =cut # }}} @@ -730,7 +757,7 @@ This routine finds all the cached group members that are members of this group #Clear the key cache. TODO someday we may want to just clear a little bit of the keycache space. # TODO what about the groups key cache? - RT::Principal->_InvalidateACLCache(); + RT::Principal->InvalidateACLCache(); @@ -762,7 +789,8 @@ sub Disabled { =head2 DeepMembersObj -Returns an RT::CachedGroupMembers object of this group's members. +Returns an RT::CachedGroupMembers object of this group's members, +including all members of subgroups. =cut @@ -815,7 +843,7 @@ sub UserMembersObj { =head2 MembersObj -Returns an RT::CachedGroupMembers object of this group's members. +Returns an RT::GroupMembers object of this group's direct members. =cut @@ -1141,11 +1169,70 @@ sub _DeleteMember { # }}} +# {{{ sub _CleanupInvalidDelegations + +=head2 _CleanupInvalidDelegations { InsideTransaction => undef } + +Revokes all ACE entries delegated by members of this group which are +inconsistent with their current delegation rights. Does not perform +permission checks. Should only ever be called from inside the RT +library. + +If called from inside a transaction, specify a true value for the +InsideTransaction parameter. + +Returns a true value if the deletion succeeded; returns a false value +and logs an internal error if the deletion fails (should not happen). + +=cut + +# XXX Currently there is a _CleanupInvalidDelegations method in both +# RT::User and RT::Group. If the recursive cleanup call for groups is +# ever unrolled and merged, this code will probably want to be +# factored out into RT::Principal. + +sub _CleanupInvalidDelegations { + my $self = shift; + my %args = ( InsideTransaction => undef, + @_ ); + + unless ( $self->Id ) { + $RT::Logger->warning("Group not loaded."); + return (undef); + } + + my $in_trans = $args{InsideTransaction}; + + # TODO: Can this be unrolled such that the number of DB queries is constant rather than linear in exploded group size? + my $members = $self->DeepMembersObj(); + $members->LimitToUsers(); + $RT::Handle->BeginTransaction() unless $in_trans; + while ( my $member = $members->Next()) { + my $ret = $member->MemberObj->_CleanupInvalidDelegations(InsideTransaction => 1, + Object => $args{Object}); + unless ($ret) { + $RT::Handle->Rollback() unless $in_trans; + return (undef); + } + } + $RT::Handle->Commit() unless $in_trans; + return(1); +} + +# }}} + # {{{ ACL Related routines # {{{ sub _Set sub _Set { my $self = shift; + my %args = ( + Field => undef, + Value => undef, + TransactionType => 'Set', + RecordTransaction => 1, + @_ + ); if ($self->Domain eq 'Personal') { if ($self->CurrentUser->PrincipalId == $self->Instance) { @@ -1163,7 +1250,30 @@ sub _Set { return ( 0, $self->loc('Permission Denied') ); } } - return ( $self->SUPER::_Set(@_) ); + + my $Old = $self->SUPER::_Value("$args{'Field'}"); + + my ($ret, $msg) = $self->SUPER::_Set( Field => $args{'Field'}, + Value => $args{'Value'} ); + + #If we can't actually set the field to the value, don't record + # a transaction. instead, get out of here. + if ( $ret == 0 ) { return ( 0, $msg ); } + + if ( $args{'RecordTransaction'} == 1 ) { + + my ( $Trans, $Msg, $TransObj ) = $self->_NewTransaction( + Type => $args{'TransactionType'}, + Field => $args{'Field'}, + NewValue => $args{'Value'}, + OldValue => $Old, + TimeTaken => $args{'TimeTaken'}, + ); + return ( $Trans, scalar $TransObj->Description ); + } + else { + return ( $ret, $msg ); + } } # }}} @@ -1171,7 +1281,7 @@ sub _Set { -=item CurrentUserHasRight RIGHTNAME +=head2 CurrentUserHasRight RIGHTNAME Returns true if the current user has the specified right for this group. @@ -1251,5 +1361,21 @@ sub PrincipalId { } # }}} + +sub BasicColumns { + ( + [ Name => 'Name' ], + [ Description => 'Description' ], + ); +} + 1; +=head1 AUTHOR + +Jesse Vincent, jesse@bestpractical.com + +=head1 SEE ALSO + +RT +