#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC
# <sales@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
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(
$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'},
}
+ # 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
@_ );
- if ( $args{'TicketObj'} ) {
- # clone the ticket here as we need to change CurrentUser
- $self->{'TicketObj'} = bless { %{$args{'TicketObj'} } }, 'RT::Ticket';
+ 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 {