[Rt-commit] [rtir] 01/13: Wrap ACLEquivalenceObjects for tickets

Kevin Falcone falcone at bestpractical.com
Wed Apr 16 17:29:40 EDT 2014


This is an automated email from the git hooks/post-receive script.

falcone pushed a commit to branch master
in repository rtir.

commit cdf7e7d1e7a45f7716f4a6e82f5e18c8e52b11fa
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Wed Mar 26 13:58:22 2014 -0400

    Wrap ACLEquivalenceObjects for tickets
    
    Primary purpose of this method is to return two queues in the case that
    an Incident has a Constituency CF of EDUNET and the queue Incides - EDUNET
    exists.
    
    It has a lot of complexity to avoid running on non-IR queues
    and to try and cache whenever possible (although we no longer have a
    negative cache because of 1200cb16 which doesn't note the bug it fixes).
    
    While removing Hook::LexWrap and changing to return more traditionally,
    I also added a number of comments to document what I understand it to be
    doing and to note a few things that concern me and that can possibly be
    removed/cleaned up after tests pass.
---
 lib/RT/IR.pm | 77 +++++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 47 insertions(+), 30 deletions(-)

diff --git a/lib/RT/IR.pm b/lib/RT/IR.pm
index 061a88c..e7095ec 100644
--- a/lib/RT/IR.pm
+++ b/lib/RT/IR.pm
@@ -656,46 +656,63 @@ if ( RT::IR->HasConstituency ) {
         return $self->RT::Record::_AddCustomFieldValue(@_);
     };
 
-    require RT::Ticket;
-    wrap 'RT::Ticket::ACLEquivalenceObjects', pre => sub {
+    # Tickets with Constituencies CF values that point to a Constituency
+    # Queue such as Incidents - EDUNET should return multiple Queues as
+    # EquivalenceObjects for checking rights. Constituency DutyTeams
+    # have their rights granted on the relevant Constituency Queues, so
+    # RT needs to know to check in both places for the combination of
+    # their rights.
+    my $orig_ACLEquivaluenceObjects = RT::Ticket->can('ACLEquivalenceObjects');
+    *RT::Ticket::ACLEquivalenceObjects = sub {
         my $self = shift;
 
         my $queue = RT::Queue->new(RT->SystemUser);
         $queue->Load($self->__Value('Queue'));
 
-        # We do this, rather than fall through to the orignal sub, as that
-        # interacts poorly with our overloaded QueueObj below
-        # Don't try and load Constituencies outside of RTIR.  It results
-        # in a lot of useless checks.
+        # For historical reasons, the System just returned a System Queue on this Ticket
+        # rather than delve into the overridden QueueObj.  It's possible this is no longer needed.
+        # We punt early on non-IR queues because otherwise we try to look for constituency Queues
+        # and the negative cache (_none) is disabled, leading to perf problems.
+        # It's also somewhat concerning that we return a SystemUser queue outside IR queues.
         if ( ( $self->CurrentUser->id == RT->SystemUser->id ) ||
              ( $queue->Name !~ /^(Incidents|Incident Reports|Investigations|Blocks)$/i ) ) {
-            $_[-1] =  [$queue];
-            return;
+            return [$queue];
         }
-        if ( UNIVERSAL::isa( $self, 'RT::Ticket' ) ) {
-            my $const = $RT::IR::ConstituencyCache{ $self->id };
-            if (!$const || $const eq '_none' ) {
-                my $systicket = RT::Ticket->new(RT->SystemUser);
-                $systicket->Load( $self->id );
-                $const = $RT::IR::ConstituencyCache{ $self->id } =
-                    $systicket->FirstCustomFieldValue('Constituency')
-                    || '_none';
-            }
-            return if $const eq '_none';
-            return if $RT::IR::HasNoQueueCache{ $const };
-
-            my $new_queue = RT::Queue->new(RT->SystemUser);
-            $new_queue->LoadByCols(
-                Name => $queue->Name . " - " . $const
-            );
-            unless ( $new_queue->id ) {
-                $RT::IR::HasNoQueueCache{$const} = 1;
-                return;
-            }
-            $_[-1] =  [$queue, $new_queue];
-        } else {
+
+        # Old old bulletproofing, can probably delete.
+        unless ( UNIVERSAL::isa( $self, 'RT::Ticket' ) ) {
             RT->Logger->crit("$self is not a ticket object like I expected");
+            return;
+        }
+
+        # We check both uncached constituencies and those explicitly negatively cached
+        # The commit that introduced this doesn't say what bug it was fixing, but it's definitely
+        # a perf hit.
+        my $const = $RT::IR::ConstituencyCache{ $self->id };
+        if (!$const || $const eq '_none' ) {
+            my $systicket = RT::Ticket->new(RT->SystemUser);
+            $systicket->Load( $self->id );
+            $const = $RT::IR::ConstituencyCache{ $self->id } =
+                $systicket->FirstCustomFieldValue('Constituency') || '_none';
+        }
+
+        # If this ticket still has no constituency, or the constituency it is assigned
+        # doesn't have a corresponding Constituency queue, return the default Queue.
+        if ( $const eq '_none' || $RT::IR::HasNoQueueCache{ $const } ) {
+            return $orig_ACLEquivaluenceObjects->($self, at _);
+        }
+
+        # Track that there is no Constituency queue for the Constituency recorded in the CF on this ticket.
+        my $constituency_queue = RT::Queue->new(RT->SystemUser);
+        $constituency_queue->LoadByCols( Name => $queue->Name . " - " . $const );
+        unless ( $constituency_queue->id ) {
+            $RT::IR::HasNoQueueCache{$const} = 1;
+            return $orig_ACLEquivaluenceObjects->($self, at _);
         }
+
+        # If a constituency queue such as 'Incidents - EDUNET' exists, we want to check
+        # ACLs on both of them.
+        return $queue, $constituency_queue;
     };
 }
 

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the rt-commit mailing list