# BEGIN BPS TAGGED BLOCK {{{
-#
+#
# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC
-# <jesse@bestpractical.com>
-#
+#
+# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
+# <sales@bestpractical.com>
+#
# (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
# been provided with this software, but in any event can be snarfed
# from www.gnu.org.
-#
+#
# This work is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
-#
+#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 or visit their web page on the internet at
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
-#
-#
+#
+#
# 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
# 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 }}}
+
=head1 NAME
RT::Scrips - a collection of RT Scrip objects
=head1 METHODS
-=begin testing
-
-ok (require RT::Scrips);
-
-=end testing
=cut
sub Commit {
my $self = shift;
+ # RT::Scrips->_SetupSourceObjects will clobber
+ # the CurrentUser, but we need to keep this ticket
+ # so that the _TransactionBatch cache is maintained
+ # and doesn't run twice. sigh.
+ $self->_StashCurrentUser( TicketObj => $self->{TicketObj} ) if $self->{TicketObj};
+
+ #We're really going to need a non-acled ticket for the scrips to work
+ $self->_SetupSourceObjects( TicketObj => $self->{'TicketObj'},
+ TransactionObj => $self->{'TransactionObj'} );
foreach my $scrip (@{$self->Prepared}) {
+ $RT::Logger->debug(
+ "Committing scrip #". $scrip->id
+ ." on txn #". $self->{'TransactionObj'}->id
+ ." of ticket #". $self->{'TicketObj'}->id
+ );
$scrip->Commit( TicketObj => $self->{'TicketObj'},
TransactionObj => $self->{'TransactionObj'} );
}
+
+ # Apply the bandaid.
+ $self->_RestoreCurrentUser( TicketObj => $self->{TicketObj} ) if $self->{TicketObj};
}
Type => undef,
@_ );
+ # RT::Scrips->_SetupSourceObjects will clobber
+ # the CurrentUser, but we need to keep this ticket
+ # so that the _TransactionBatch cache is maintained
+ # and doesn't run twice. sigh.
+ $self->_StashCurrentUser( TicketObj => $args{TicketObj} ) if $args{TicketObj};
+
#We're really going to need a non-acled ticket for the scrips to work
$self->_SetupSourceObjects( TicketObj => $args{'TicketObj'},
Ticket => $args{'Ticket'},
#Iterate through each script and check it's applicability.
while ( my $scrip = $self->Next() ) {
- next
unless ( $scrip->IsApplicable(
TicketObj => $self->{'TicketObj'},
TransactionObj => $self->{'TransactionObj'}
- ) );
+ ) ) {
+ $RT::Logger->debug("Skipping Scrip #".$scrip->Id." because it isn't applicable");
+ next;
+ }
#If it's applicable, prepare and commit it
- next
unless ( $scrip->Prepare( TicketObj => $self->{'TicketObj'},
TransactionObj => $self->{'TransactionObj'}
- ) );
+ ) ) {
+ $RT::Logger->debug("Skipping Scrip #".$scrip->Id." because it didn't Prepare");
+ next;
+ }
push @{$self->{'prepared_scrips'}}, $scrip;
}
+ # Apply the bandaid.
+ $self->_RestoreCurrentUser( TicketObj => $args{TicketObj} ) if $args{TicketObj};
+
+
return (@{$self->Prepared});
};
return ($self->{'prepared_scrips'} || []);
}
+=head2 _StashCurrentUser TicketObj => RT::Ticket
+
+Saves aside the current user of the original ticket that was passed to these scrips.
+This is used to make sure that we don't accidentally leak the RT_System current user
+back to the calling code.
+
+=cut
+
+sub _StashCurrentUser {
+ my $self = shift;
+ my %args = @_;
+
+ $self->{_TicketCurrentUser} = $args{TicketObj}->CurrentUser;
+}
+
+=head2 _RestoreCurrentUser TicketObj => RT::Ticket
+
+Uses the current user saved by _StashCurrentUser to reset a Ticket object
+back to the caller's current user and avoid leaking an RT_System ticket to
+calling code.
+
+=cut
+
+sub _RestoreCurrentUser {
+ my $self = shift;
+ my %args = @_;
+ unless ( $self->{_TicketCurrentUser} ) {
+ RT->Logger->debug("Called _RestoreCurrentUser without a stashed current user object");
+ return;
+ }
+ $args{TicketObj}->CurrentUser($self->{_TicketCurrentUser});
+
+}
# {{{ sup _SetupSourceObjects
TransactionObj => undef,
@_ );
- if ( ( $self->{'TicketObj'} = $args{'TicketObj'} ) ) {
+
+ if ( $self->{'TicketObj'} = $args{'TicketObj'} ) {
+ # This clobbers the passed in TicketObj by turning it into one
+ # whose current user is RT_System. Anywhere in the Web UI
+ # currently calling into this is thus susceptable to a privilege
+ # leak; the only current call site is ->Apply, which bandaids
+ # over the top of this by re-asserting the CurrentUser
+ # afterwards.
$self->{'TicketObj'}->CurrentUser( $self->CurrentUser );
}
else {
$self->{'TicketObj'} = RT::Ticket->new( $self->CurrentUser );
$self->{'TicketObj'}->Load( $args{'Ticket'} )
- || $RT::Logger->err("$self couldn't load ticket $args{'Ticket'}\n");
+ || $RT::Logger->err("$self couldn't load ticket $args{'Ticket'}");
}
if ( ( $self->{'TransactionObj'} = $args{'TransactionObj'} ) ) {
else {
$self->{'TransactionObj'} = RT::Transaction->new( $self->CurrentUser );
$self->{'TransactionObj'}->Load( $args{'Transaction'} )
- || $RT::Logger->err( "$self couldn't load transaction $args{'Transaction'}\n");
+ || $RT::Logger->err( "$self couldn't load transaction $args{'Transaction'}");
}
}
);
# Promise some kind of ordering
- $self->OrderBy( FIELD => 'description' );
+ $self->OrderBy( FIELD => 'Description' );
+
+ # we call Count below, but later we always do search
+ # so just do search and get count from results
+ $self->_DoSearch if $self->{'must_redo_search'};
- $RT::Logger->debug("Found ".$self->Count. " scrips");
+ $RT::Logger->debug(
+ "Found ". $self->Count ." scrips for $args{'Stage'} stage"
+ ." with applicable type(s) $args{'Type'}"
+ ." for txn #".$self->{TransactionObj}->Id
+ ." on ticket #".$self->{TicketObj}->Id
+ );
}
# }}}