[Rt-commit] r2153 - in rt/branches/PLATANO-EXPERIMENTAL: . html/Elements lib/RT

jesse at bestpractical.com jesse at bestpractical.com
Wed Feb 2 10:57:20 EST 2005


Author: jesse
Date: Wed Feb  2 10:57:19 2005
New Revision: 2153

Modified:
   rt/branches/PLATANO-EXPERIMENTAL/   (props changed)
   rt/branches/PLATANO-EXPERIMENTAL/html/Elements/SelectOwner
   rt/branches/PLATANO-EXPERIMENTAL/lib/RT/Users_Overlay.pm
Log:
 r4010 at hualien:  jesse | 2005-02-02T15:40:31.594185Z
  r3885 at hualien:  jesse | 2005-01-18T15:02:02.574134Z
  Reimplemented RT::Users->WhoHaveRights to remove O(n^2) SQL calls. (That means it's faster now)
  Reimplemented SelectOwner widget to take advantage of the new WhoHaveRights
  
  
 


Modified: rt/branches/PLATANO-EXPERIMENTAL/html/Elements/SelectOwner
==============================================================================
--- rt/branches/PLATANO-EXPERIMENTAL/html/Elements/SelectOwner	(original)
+++ rt/branches/PLATANO-EXPERIMENTAL/html/Elements/SelectOwner	Wed Feb  2 10:57:19 2005
@@ -67,25 +67,20 @@
 	@objects = keys %{$cfqueues};
 }
 else {
-        my $Queues = RT::Queues->new($session{CurrentUser});
-	$Queues->UnLimit();
-	while (my $Queue = $Queues->Next()) {
-	      push( @objects, $Queue );
-        }
+    # Let's check rights on an empty queue object. that will do a search for any queue.
+    my $queue = RT::Queue->new($session{'CurrentUser'});
+	      push( @objects, $queue );
 }
 
 my %user_uniq_hash;
 foreach my $object (@objects) {
 	my $Users = RT::Users->new($session{CurrentUser});
-        $Users->WhoHaveRight(Right => 'OwnTicket',
-                     Object => $object,
-                     IncludeSystemRights => 1,
-                     IncludeSuperusers => 0);
+        $Users->WhoHaveRight(Right => 'OwnTicket', Object => $object, IncludeSystemRights => 1, IncludeSuperusers => 0); 
         while (my $User = $Users->Next()) {
 	      $user_uniq_hash{$User->Id()} = $User;
         }
 }
- at users = sort { uc($a->Name) cmp uc($b->Name) } values %user_uniq_hash;
+ at users = sort { uc($a->Name) cmp uc($b->Name) } values %user_uniq_hash; 
 </%INIT>
 
 <%ARGS>

Modified: rt/branches/PLATANO-EXPERIMENTAL/lib/RT/Users_Overlay.pm
==============================================================================
--- rt/branches/PLATANO-EXPERIMENTAL/lib/RT/Users_Overlay.pm	(original)
+++ rt/branches/PLATANO-EXPERIMENTAL/lib/RT/Users_Overlay.pm	Wed Feb  2 10:57:19 2005
@@ -239,6 +239,7 @@
 or as members of groups
 
 
+If passed a queue object, with no id, it will find users who have that right for _any_ queue
 
 
 
@@ -246,38 +247,121 @@
 
 sub WhoHaveRight {
     my $self = shift;
-    my %args = ( Right                  => undef,
-                 Object                 => undef,
-                 IncludeSystemRights    => undef,
-                 IncludeSuperusers      => undef,
-                 IncludeSubgroupMembers => 1,
-                 @_ );
+    my %args = (
+        Right                  => undef,
+        Object                 => undef,
+        IncludeSystemRights    => undef,
+        IncludeSuperusers      => undef,
+        IncludeSubgroupMembers => 1,
+        @_
+    );
+
+    if ( defined $args{'ObjectType'} || defined $args{'ObjectId'} ) {
+        $RT::Logger->crit( "$self WhoHaveRight called with the Obsolete ObjectId/ObjectType API");
+        return (undef);
+    }
+    
+
+    # Find only members of groups that have the right.
+
+    my $acl       = $self->NewAlias('ACL');
+    my $groups    = $self->NewAlias('Groups');
+    my $userprinc = $self->{'princalias'};
+
+# The cachedgroupmembers table is used for unrolling group memberships to allow fast lookups
+# if we bind to CachedGroupMembers, we'll find all members of groups recursively.
+# if we don't we'll find only 'direct' members of the group in question
+    my $cgm;
+
+    if ( $args{'IncludeSubgroupMembers'} ) {
+        $cgm = $self->NewAlias('CachedGroupMembers');
+    }
+    else {
+        $cgm = $self->NewAlias('GroupMembers');
+    }
 
-    if (defined $args{'ObjectType'} || defined $args{'ObjectId'}) {
-        $RT::Logger->crit("$self WhoHaveRight called with the Obsolete ObjectId/ObjectType API");
-        return(undef);
-    }
-        my @privgroups;
-        my $Groups = RT::Groups->new($RT::SystemUser);
-        $Groups->WithRight(Right=> $args{'Right'},
-                     Object => $args{'Object'},
-                     IncludeSystemRights => $args{'IncludeSystemRights'},
-                     IncludeSuperusers => $args{'IncludeSuperusers'});
-        while (my $Group = $Groups->Next()) {
-                push @privgroups, $Group->Id();
+#Tie the users we're returning ($userprinc) to the groups that have rights granted to them ($groupprinc)
+    $self->Join(
+        ALIAS1 => $cgm,
+        FIELD1 => 'MemberId',
+        ALIAS2 => $userprinc,
+        FIELD2 => 'id'
+    );
+
+    $self->Join(
+        ALIAS1 => $groups,
+        FIELD1 => 'id',
+        ALIAS2 => $cgm,
+        FIELD2 => 'GroupId'
+    );
+
+# {{{ Find only rows where the right granted is the one we're looking up or _possibly_ superuser
+    $self->Limit(
+        ALIAS    => $acl,
+        FIELD    => 'RightName',
+        OPERATOR => ( $args{Right} ? '=' : 'IS NOT' ),
+        VALUE => $args{Right} || 'NULL',
+        ENTRYAGGREGATOR => 'OR'
+    );
+
+    if ( $args{'IncludeSuperusers'} and $args{'Right'} ) {
+        $self->Limit(
+            ALIAS           => $acl,
+            FIELD           => 'RightName',
+            OPERATOR        => '=',
+            VALUE           => 'SuperUser',
+            ENTRYAGGREGATOR => 'OR'
+        );
+    }
+
+    # }}}
+
+    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' ) {
+            $or_check_ticket_roles = " OR ( $groups.Domain = 'RT::Ticket-Role' AND $groups.Instance = " . $args{'Object'}->Id . ") ";
+
+# If we're looking at ticket rights, we also want to look at the associated queue rights.
+# this is a little bit hacky, but basically, now that we've done the ticket roles magic,
+# we load the queue object and ask all the rest of our questions about the queue.
+            $args{'Object'} = $args{'Object'}->QueueObj;
         }
 
+        # TODO XXX This really wants some refactoring
+        if ( ref( $args{'Object'} ) eq 'RT::Queue' ) {
+            $or_check_roles = " OR ( ( ($groups.Domain = 'RT::Queue-Role' ";
+            $or_check_roles .= "AND $groups.Instance = " . $args{'Object'}->id if ( $args{'Object'}->id );
+            $or_check_roles .= ") $or_check_ticket_roles ) " . " AND $groups.Type = $acl.PrincipalType) ";
+        }
+        if ( $args{'IncludeSystemRights'} ) {
+            $which_object .= ' OR ';
+        }
+        else {
+            $which_object = '';
+        }
+        $which_object .= " ($acl.ObjectType = '" . ref( $args{'Object'} ) . "'";
+        if ( $args{'Object'}->id ) {
+            $which_object .= " AND $acl.ObjectId = " . $args{'Object'}->id;
+        }
 
-    if (@privgroups) {
-        $self->WhoBelongToGroups(Groups => \@privgroups,
-                                 IncludeSubgroupMembers => $args{'IncludeSubgroupMembers'});
-    }
-    else {
-	# We don't have any group that matches -- make it impossible.
-	$self->Limit( FIELD => 'Id', VALUE => 'IS', OPERATOR => 'NULL' );
+        $which_object .=  ") ";
     }
-}
+    $self->_AddSubClause( "WhichObject", "($which_object)" );
+    $self->_AddSubClause(
+        "WhichGroup",
+            qq{ ( (    $acl.PrincipalId = $groups.id AND $acl.PrincipalType = 'Group' 
+                AND (   $groups.Domain = 'SystemInternal' OR $groups.Domain = 'UserDefined' OR $groups.Domain = 'ACLEquivalence')) 
+                $or_check_roles) }
+    );
+    # only include regular RT users
+    $self->LimitToEnabled;
+
+    # no system user
+    $self->Limit( ALIAS => $userprinc, FIELD => 'id', OPERATOR => '!=', VALUE => $RT::SystemUser->id);
 
+}
 # }}}
 
 # {{{ WhoBelongToGroups 
@@ -310,20 +394,14 @@
         $cgm = $self->NewAlias('GroupMembers');
     }
 
-    # {{{ Tie the users we're returning ($userprinc) to the groups that have rights granted to them ($groupprinc)
+    #Tie the users we're returning ($userprinc) to the groups that have rights granted to them ($groupprinc)
     $self->Join( ALIAS1 => $cgm, FIELD1 => 'MemberId',
                  ALIAS2 => $userprinc, FIELD2 => 'id' );
-    # }}} 
 
- #   my $and_check_groups = "($cgm.GroupId = NULL";
     foreach my $groupid (@{$args{'Groups'}}) {
         $self->Limit(ALIAS => $cgm, FIELD => 'GroupId', VALUE => $groupid, QUOTEVALUE => 0, ENTRYAGGREGATOR=> 'OR')
 
-        #$and_check_groups .= " OR $cgm.GroupId = $groupid";
     }
-    #$and_check_groups .= ")";
-
-    #$self->_AddSubClause("WhichGroup", $and_check_groups);
 }
 # }}}
 


More information about the Rt-commit mailing list