[Rt-commit] rt branch, 4.2/add-reassignticket-right, created. rt-4.1.6-415-g43f0e87

Jim Brandt jbrandt at bestpractical.com
Thu Apr 18 15:55:12 EDT 2013


The branch, 4.2/add-reassignticket-right has been created
        at  43f0e872019ca3abd20168730905477dac98785d (commit)

- Log -----------------------------------------------------------------
commit 12c1c7ac81db7a3236a4b0ddb06dd711a66c5c0a
Author: Jim Brandt <jbrandt at bestpractical.com>
Date:   Fri Apr 5 13:38:23 2013 -0400

    Add a ReassignTicket right to allow owner changes on owned tickets
    
    Users have frequently requested the ability to change the owner on
    a ticket that already has an owner. Previously RT required you to own
    a ticket to change the owner, so you had to steal a ticket owned by
    someone else, then set the owner. The new ReassignTicket right allows
    users to change owner directly (reassign tickets).

diff --git a/lib/RT/Queue.pm b/lib/RT/Queue.pm
index 86d05c9..e89e015 100644
--- a/lib/RT/Queue.pm
+++ b/lib/RT/Queue.pm
@@ -135,6 +135,7 @@ our $RIGHTS = {
     DeleteTicket        => 'Delete tickets',                                            # loc_pair
     TakeTicket          => 'Take tickets',                                              # loc_pair
     StealTicket         => 'Steal tickets',                                             # loc_pair
+    ReassignTicket      => 'Modify ticket owner on owned tickets',                      # loc_pair
 
     ForwardMessage      => 'Forward messages outside of RT',                            # loc_pair
 };
@@ -165,6 +166,7 @@ our $RIGHT_CATEGORIES = {
     DeleteTicket        => 'Staff',
     TakeTicket          => 'Staff',
     StealTicket         => 'Staff',
+    ReassignTicket      => 'Staff',
     ForwardMessage      => 'Staff',
 };
 
diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index b5eff48..586acd4 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -2097,6 +2097,10 @@ sub SetOwner {
 
 sub _CurrentUserHasRightToSetOwner {
     my $self = shift;
+
+    # ReassignTicket unconditionally allows you to SetOwner
+    return 1 if $self->CurrentUserHasRight('ReassignTicket');
+
     # must have ModifyTicket rights
     # or TakeTicket/StealTicket and $NewOwner is self
     # see if it's a take
@@ -2133,10 +2137,11 @@ sub _IsProposedOwnerChangeValid {
     my $OldOwnerObj = $self->OwnerObj;
 
     # If we're not stealing and the ticket has an owner and it's not
-    # the current user
+    # the current user, and the current user can't reassign tickets
     if (     $Type ne 'Steal' and $Type ne 'Force'
          and $OldOwnerObj->Id != RT->Nobody->Id
-         and $OldOwnerObj->Id != $self->CurrentUser->Id ) {
+         and $OldOwnerObj->Id != $self->CurrentUser->Id
+         and not $self->CurrentUserHasRight('ReassignTicket') ) {
         if ( $NewOwnerObj->id == $self->CurrentUser->id) {
             return ( 0, $self->loc("You can only take tickets that are unowned") )
         }
diff --git a/t/api/ticket.t b/t/api/ticket.t
index 57e6183..4db8d7e 100644
--- a/t/api/ticket.t
+++ b/t/api/ticket.t
@@ -205,20 +205,23 @@ is ($t1->Requestors->MembersObj->Count, 2);
 
 }
 
+diag "Test owner changes";
 {
 
 my $root = RT::User->new(RT->SystemUser);
 $root->Load('root');
 ok ($root->Id, "Loaded the root user");
 my $t = RT::Ticket->new(RT->SystemUser);
-$t->Load(1);
+my ($val, $msg) = $t->Create( Subject => 'Owner test 1', Queue => 'General');
+ok( $t->Id, "Created a new ticket with id $val: $msg");
+
 $t->SetOwner('root');
 is ($t->OwnerObj->Name, 'root' , "Root owns the ticket");
 $t->Steal();
 is ($t->OwnerObj->id, RT->SystemUser->id , "SystemUser owns the ticket");
 my $txns = RT::Transactions->new(RT->SystemUser);
 $txns->OrderBy(FIELD => 'id', ORDER => 'DESC');
-$txns->Limit(FIELD => 'ObjectId', VALUE => '1');
+$txns->Limit(FIELD => 'ObjectId', VALUE => $t->Id);
 $txns->Limit(FIELD => 'ObjectType', VALUE => 'RT::Ticket');
 $txns->Limit(FIELD => 'Type', OPERATOR => '!=',  VALUE => 'EmailRecord');
 
@@ -226,6 +229,37 @@ my $steal  = $txns->First;
 is($steal->OldValue , $root->Id , "Stolen from root");
 is($steal->NewValue , RT->SystemUser->Id , "Stolen by the systemuser");
 
+ok(my $user1 = RT::User->new(RT->SystemUser), "Creating a user1 rt::user");
+($val, $msg) = $user1->Create(Name => 'User1', EmailAddress => 'user1 at example.com');
+ok( $val, "Created new user with id: $val");
+ok( $user1->Id,  "Found the user1 rt user");
+
+my $t1 = RT::Ticket->new($user1);
+($val, $msg) = $t1->Load($t->Id);
+ok( $t1->Id, "Loaded ticket with id $val");
+
+($val, $msg) = $t1->SetOwner('root');
+ok( !$val, "user1 can't set owner to root: $msg");
+is ($t->OwnerObj->id, RT->SystemUser->id , "SystemUser still owns ticket " . $t1->Id);
+
+my $queue = RT::Queue->new(RT->SystemUser);
+$queue->Load("General");
+
+($val, $msg) = $user1->PrincipalObj->GrantRight(
+         Object => $queue, Right => 'ModifyTicket'
+     );
+
+($val, $msg) = $t1->SetOwner('root');
+ok( !$val, "With ModifyTicket user1 can't set owner to root: $msg");
+is ($t->OwnerObj->id, RT->SystemUser->id , "SystemUser still owns ticket " . $t1->Id);
+
+($val, $msg) = $user1->PrincipalObj->GrantRight(
+         Object => $queue, Right => 'ReassignTicket'
+     );
+
+($val, $msg) = $t1->SetOwner('root');
+ok( $val, "With ReassignTicket user1 reassigned ticket " . $t1->Id . " to root: $msg");
+is ($t1->OwnerObj->Name, 'root' , "Root owns ticket " . $t1->Id);
 
 }
 

commit ace3dda2141a7825eec29941629bdf9379792d73
Author: Jim Brandt <jbrandt at bestpractical.com>
Date:   Fri Apr 12 11:32:58 2013 -0400

    Change _CurrentUserHasRightToSetOwner to public CurrentUserCanSetOwner
    
    Make public and rename to CurrentUserCanSetOwner to make it
    consistent with other CurrentUserCan method names.
    
    Meld _IsProposedOwnerChangeValid into CurrentUserCanSetOwner to
    handle all of the logic in one place and provide a single
    response from CurrentUserCanSetOwner. This simplifies SetOwner
    and makes CurrentUserCanSetOwner suitable for calling to test
    for owner change permissions in the context of the current
    ticket.

diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index 586acd4..4553260 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -2061,17 +2061,11 @@ sub SetOwner {
 
     my $NewOwnerObj = RT::User->new( $self->CurrentUser );
     $NewOwnerObj->Load( $NewOwner );
-    unless ( $NewOwnerObj->Id ) {
-        $RT::Handle->Rollback();
-        return ( 0, $self->loc("That user does not exist") );
-    }
 
-    if ( !$self->_CurrentUserHasRightToSetOwner ) {
-        $RT::Handle->Rollback();
-        return ( 0, $self->loc("Permission Denied") );
-    }
+    my ( $val, $msg ) = $self->CurrentUserCanSetOwner(
+                            NewOwnerObj => $NewOwnerObj,
+                            Type        => $Type );
 
-    my ( $val, $msg ) = $self->_IsProposedOwnerChangeValid( $NewOwnerObj, $Type );
     unless ($val) {
         $RT::Handle->Rollback();
         return ( $val, $msg );
@@ -2095,72 +2089,179 @@ sub SetOwner {
     return ( $val, $msg );
 }
 
-sub _CurrentUserHasRightToSetOwner {
+=head2 CurrentUserCanSetOwner
+
+Confirm the current user can set the owner of the current ticket.
+
+There are several different rights to manage owner changes and
+this method evaluates these rights, guided by parameters provided.
+
+This method evaluates these rights in the context of the state of
+the current ticket. For example, it evaluates Take for tickets that
+are owned by Nobody because that is the context appropriate for the
+TakeTicket right. If you need to strictly test a user for a right,
+use HasRight to check for the right directly.
+
+=head3 Rights to Set Owner
+
+The current user can set or change the Owner field in the following
+cases:
+
+=over
+
+=item *
+
+ReassignTicket unconditionally grants the right to set the owner
+to any user who has OwnTicket. This can be used to break an
+Owner lock held by another user (see below) and can be a convenient
+right for managers or administrators who need to assign tickets
+without necessarily owning them.
+
+=item *
+
+ModifyTicket grants the right to set the owner to any user who
+has OwnTicket, provided the ticket is currently owned by the current
+user or is not owned (owned by Nobody). (See the details on the Force
+parameter below for exceptions to this.)
+
+=item *
+
+If the ticket is currently not owned (owned by Nobody),
+TakeTicket is sufficient to set the owner to yourself (but not
+an arbitrary person), but only if you have OwnTicket. It is
+thus a subset of the possible changes provided by ModifyTicket.
+This exists to allow granting TakeTicket freely, and
+the broader ModifyTicket only to Owners.
+
+=item *
+
+If the ticket is currently owned by someone who is not you or
+Nobody, StealTicket is sufficient to set the owner to yourself,
+but only if you have OwnTicket. This is hence non-overlapping
+with the changes provided by ModifyTicket, and is used to break
+a lock held by another user.
+
+=back
+
+=head3 Parameters
+
+This method returns ($result, $message) with $result containing
+true or false indicating if the current user can set owner and $message
+containing a message, typically in the case of a false response.
+
+If called with no parameters, this method determines if the current
+user could set the owner of the current ticket given any
+permutation of the rights described above. This can be useful
+when determining whether to make owner-setting options available
+in the GUI.
+
+This method accepts the following parameters as a paramshash:
+
+NewOwnerObj: Optional. A user object representing the proposed
+new owner of the ticket.
+
+Type: Optional. The type of set owner operation. Valid values are Take,
+Steal, or Force.
+
+As noted above, there are exceptions to the standard ticket-based rights
+described here. The Force option allows for these and is used
+when moving tickets between queues, for reminders (because the full
+owner rights system is too complex for them), and optionally during
+bulk update.
+
+=cut
+
+sub CurrentUserCanSetOwner {
     my $self = shift;
+    my %args = ( Type => '',
+                 @_);
+    my $OldOwnerObj = $self->OwnerObj;
+
+    # Confirm rights for new owner if we got one
+    if ( $args{'NewOwnerObj'} ){
+        my ($ok, $message) = $self->_NewOwnerCanOwnTicket($args{'NewOwnerObj'}, $OldOwnerObj);
+        return ($ok, $message) if not $ok;
+    }
 
     # ReassignTicket unconditionally allows you to SetOwner
-    return 1 if $self->CurrentUserHasRight('ReassignTicket');
+    return (1, undef) if $self->CurrentUserHasRight('ReassignTicket');
 
-    # must have ModifyTicket rights
-    # or TakeTicket/StealTicket and $NewOwner is self
-    # see if it's a take
-    my $OldOwnerObj = $self->OwnerObj;
+    # Ticket is unowned
+    # Can set owner to yourself withn ModifyTicket or TakeTicket
+    # and OwnTicket.
     if ( $OldOwnerObj->Id == RT->Nobody->Id ) {
-        unless (    $self->CurrentUserHasRight('ModifyTicket')
-                 || $self->CurrentUserHasRight('TakeTicket') ) {
-            return 0;
+
+        # Steal is not applicable for unowned tickets.
+        if ( $args{'Type'} eq 'Steal' ){
+            return ( 0, $self->loc("You can only steal a ticket owned by someone else") )
+        }
+
+        unless ( (  $self->CurrentUserHasRight('ModifyTicket')
+                 or $self->CurrentUserHasRight('TakeTicket') )
+                 and $self->CurrentUserHasRight('OwnTicket') ) {
+            return ( 0, $self->loc("Permission Denied") );
         }
     }
 
-    # see if it's a steal
+    # Ticket is owned by someone else
+    # Can set owner to yourself with ModifyTicket or StealTicket
+    # and OwnTicket.
     elsif (    $OldOwnerObj->Id != RT->Nobody->Id
             && $OldOwnerObj->Id != $self->CurrentUser->id ) {
 
         unless (    $self->CurrentUserHasRight('ModifyTicket')
                  || $self->CurrentUserHasRight('StealTicket') ) {
-            return 0;
+            return ( 0, $self->loc("Permission Denied") )
+        }
+
+        if ( $args{'Type'} eq 'Steal' || $args{'Type'} eq 'Force' ){
+            return ( 1, undef ) if $self->CurrentUserHasRight('OwnTicket');
+            return ( 0, $self->loc("Permission Denied") );
+        }
+
+        # Not a steal or force
+        if ( $args{'Type'} eq 'Take'
+             or ( $args{'NewOwnerObj'}
+                  and $args{'NewOwnerObj'}->id == $self->CurrentUser->id )) {
+            return ( 0, $self->loc("You can only take tickets that are unowned") );
+        }
+        else {
+            return ( 0, $self->loc( "You can only reassign tickets that you own or that are unowned"));
         }
+
     }
+    # You own the ticket
+    # Untake falls through to here, so we don't need to explicitly handle that Type
     else {
         unless ( $self->CurrentUserHasRight('ModifyTicket') ) {
-            return 0;
+            return ( 0, $self->loc("Permission Denied") );
         }
     }
-    return 1;
+
+    return ( 1, undef );
 }
 
-sub _IsProposedOwnerChangeValid {
-    my $self        = shift;
-    my $NewOwnerObj = shift;
-    my $Type        = shift;
+# Verify the proposed new owner can own the ticket.
 
-    my $OldOwnerObj = $self->OwnerObj;
+sub _NewOwnerCanOwnTicket {
+    my $self = shift;
+    my $NewOwnerObj = shift;
+    my $OldOwnerObj = shift;
 
-    # If we're not stealing and the ticket has an owner and it's not
-    # the current user, and the current user can't reassign tickets
-    if (     $Type ne 'Steal' and $Type ne 'Force'
-         and $OldOwnerObj->Id != RT->Nobody->Id
-         and $OldOwnerObj->Id != $self->CurrentUser->Id
-         and not $self->CurrentUserHasRight('ReassignTicket') ) {
-        if ( $NewOwnerObj->id == $self->CurrentUser->id) {
-            return ( 0, $self->loc("You can only take tickets that are unowned") )
-        }
-        else {
-            return ( 0, $self->loc( "You can only reassign tickets that you own or that are unowned"));
-        }
+    unless ( $NewOwnerObj->Id ) {
+        return ( 0, $self->loc("That user does not exist") );
     }
 
-    #If we've specified a new owner and that user can't modify the ticket
-    elsif ( !$NewOwnerObj->HasRight( Right => 'OwnTicket', Object => $self ) )
-    {
+    # The proposed new owner can't own the ticket
+    if ( !$NewOwnerObj->HasRight( Right => 'OwnTicket', Object => $self ) ){
         return ( 0, $self->loc("That user may not own tickets in that queue") );
     }
 
-    # If the ticket has an owner and it's the new owner, we don't need
-    # To do anything
+    # Ticket's current owner is the same as the new owner, nothing to do
     elsif ( $NewOwnerObj->Id == $OldOwnerObj->Id ) {
         return ( 0, $self->loc("That user already owns that ticket") );
     }
+
     return (1, undef);
 }
 
diff --git a/t/api/ticket.t b/t/api/ticket.t
index 4db8d7e..b30dda5 100644
--- a/t/api/ticket.t
+++ b/t/api/ticket.t
@@ -215,8 +215,17 @@ my $t = RT::Ticket->new(RT->SystemUser);
 my ($val, $msg) = $t->Create( Subject => 'Owner test 1', Queue => 'General');
 ok( $t->Id, "Created a new ticket with id $val: $msg");
 
-$t->SetOwner('root');
+($val, $msg) = $t->SetOwner('bogususer');
+ok( !$val, "Can't set owner to bogus user");
+is( $msg, "That user does not exist", "Got message: $msg");
+
+($val, $msg) = $t->SetOwner('root');
 is ($t->OwnerObj->Name, 'root' , "Root owns the ticket");
+
+($val, $msg) = $t->SetOwner('root');
+ok( !$val, "User already owns ticket");
+is( $msg, "That user already owns that ticket", "Got message: $msg");
+
 $t->Steal();
 is ($t->OwnerObj->id, RT->SystemUser->id , "SystemUser owns the ticket");
 my $txns = RT::Transactions->new(RT->SystemUser);
diff --git a/t/mail/gateway.t b/t/mail/gateway.t
index eb0283d..785b8e7 100644
--- a/t/mail/gateway.t
+++ b/t/mail/gateway.t
@@ -739,7 +739,7 @@ ok( $status, "successfuly granted right: $msg" );
 my $ace_id = $status;
 ok( $user->HasRight( Right => 'ReplyToTicket', Object => $tick ), "User can reply to ticket" );
 
-$m->next_warning_like(qr/Permission Denied/);
+$m->next_warning_like(qr/That user may not own tickets in that queue/);
 $m->next_warning_like(qr/Could not record email: Ticket not taken/);
 $m->no_leftover_warnings_ok;
 
@@ -758,7 +758,7 @@ DBIx::SearchBuilder::Record::Cachable->FlushCache;
 cmp_ok( $tick->Owner, '!=', $user->id, "we didn't change owner" );
 is( $tick->Transactions->Count, 3, "one transactions added" );
 
-$m->next_warning_like(qr/Permission Denied/);
+$m->next_warning_like(qr/That user may not own tickets in that queue/);
 $m->next_warning_like(qr/Could not record email: Ticket not taken/);
 $m->no_leftover_warnings_ok;
 
@@ -777,7 +777,7 @@ DBIx::SearchBuilder::Record::Cachable->FlushCache;
 cmp_ok( $tick->Owner, '!=', $user->id, "we didn't change owner" );
 is( $tick->Transactions->Count, 3, "no transactions added, user can't take ticket first" );
 
-$m->next_warning_like(qr/Permission Denied/);
+$m->next_warning_like(qr/That user may not own tickets in that queue/);
 $m->next_warning_like(qr/Could not record email: Ticket not taken/);
 $m->no_leftover_warnings_ok;
 

commit 43f0e872019ca3abd20168730905477dac98785d
Author: Jim Brandt <jbrandt at bestpractical.com>
Date:   Fri Apr 12 13:15:47 2013 -0400

    Replace individual rights checks with CurrentUserCanSetOwner
    
    CurrentUserCanSetOwner in RT::Ticket handles the various cases
    for changing owner based on Stealing and Taking tickets.
    With the new ReassignTicket right, it's no longer the case that
    OwnTicket is needed to have the rights to assign tickets to
    others.

diff --git a/share/html/Elements/Tabs b/share/html/Elements/Tabs
index a2f7743..c2d4674 100644
--- a/share/html/Elements/Tabs
+++ b/share/html/Elements/Tabs
@@ -604,7 +604,7 @@ my $build_main_nav = sub {
                 $tabs->child( history => title => loc('History'), path => "/Ticket/History.html?id=" . $id );
 
                 my %can = %{ $obj->CurrentUser->PrincipalObj->HasRights( Object => $obj ) };
-                $can{'_ModifyOwner'} = $can{'OwnTicket'} || $can{'TakeTicket'} || $can{'StealTicket'};
+                $can{'_ModifyOwner'} = $obj->CurrentUserCanSetOwner();
                 my $can = sub {
                     unless ($_[0] eq 'ExecuteCode') {
                         return $can{$_[0]} || $can{'SuperUser'};
@@ -686,17 +686,13 @@ my $build_main_nav = sub {
                     $actions->child( $key => title => loc( $key ), path => $url);
                 }
 
-                if ( $can->('OwnTicket') ) {
-                    if ( $obj->OwnerObj->Id == RT->Nobody->id
-                         && ( $can->('ModifyTicket') or $can->('TakeTicket') ) ) {
-                        $actions->child( take => title => loc('Take'), path => "/Ticket/Display.html?Action=Take;id=" . $id );
-                    }
-
-                    elsif (    $obj->OwnerObj->id != RT->Nobody->id
-                            && $obj->OwnerObj->id != $session{CurrentUser}->id
-                            && ( $can->('ModifyTicket') or $can->('StealTicket') ) ) {
-                        $actions->child( steal => title => loc('Steal'), path => "/Ticket/Display.html?Action=Steal;id=" . $id );
-                    }
+                my ($can_take, $tmsg) = $obj->CurrentUserCanSetOwner( Type => 'Take' );
+                my ($can_steal, $smsg) = $obj->CurrentUserCanSetOwner( Type => 'Steal' );
+                if ( $can_take ){
+                    $actions->child( take => title => loc('Take'), path => "/Ticket/Display.html?Action=Take;id=" . $id );
+                }
+                elsif ( $can_steal ){
+                    $actions->child( steal => title => loc('Steal'), path => "/Ticket/Display.html?Action=Steal;id=" . $id );
                 }
 
                 # TODO needs a "Can extract article into a class applied to this queue" check
diff --git a/share/html/Ticket/Elements/ShowSummary b/share/html/Ticket/Elements/ShowSummary
index 98dde90..b7981e3 100644
--- a/share/html/Ticket/Elements/ShowSummary
+++ b/share/html/Ticket/Elements/ShowSummary
@@ -104,7 +104,5 @@ $Attachments => undef
 <%INIT>
 my $can_modify = $Ticket->CurrentUserHasRight('ModifyTicket');
 my $can_modify_cf = $Ticket->CurrentUserHasRight('ModifyCustomField');
-my $can_modify_owner = $Ticket->CurrentUserHasRight('OwnTicket')
-                    || $Ticket->CurrentUserHasRight('TakeTicket')
-                    || $Ticket->CurrentUserHasRight('StealTicket');
+my $can_modify_owner = $Ticket->CurrentUserCanSetOwner();
 </%INIT>
diff --git a/t/web/ticket_owner.t b/t/web/ticket_owner.t
index 4704935..5d30e15 100644
--- a/t/web/ticket_owner.t
+++ b/t/web/ticket_owner.t
@@ -2,7 +2,7 @@
 use strict;
 use warnings;
 
-use RT::Test nodata => 1, tests => 105;
+use RT::Test nodata => 1, tests => undef;
 
 my $queue = RT::Test->load_or_create_queue( Name => 'Regression' );
 ok $queue && $queue->id, 'loaded or created queue';
@@ -10,12 +10,18 @@ ok $queue && $queue->id, 'loaded or created queue';
 my $user_a = RT::Test->load_or_create_user(
     Name => 'user_a', Password => 'password',
 );
-ok $user_a && $user_a->id, 'loaded or created user';
+ok $user_a && $user_a->id, 'loaded or created user: ' . $user_a->Name;
 
 my $user_b = RT::Test->load_or_create_user(
     Name => 'user_b', Password => 'password',
 );
-ok $user_b && $user_b->id, 'loaded or created user';
+ok $user_b && $user_b->id, 'loaded or created user: ' . $user_b->Name;
+
+# To give ReassignTicket
+my $user_c = RT::Test->load_or_create_user(
+    Name => 'user_c', Password => 'password',
+);
+ok $user_c && $user_c->id, 'loaded or created user: ' . $user_c->Name;
 
 my ($baseurl, $agent_a) = RT::Test->started_ok;
 
@@ -360,6 +366,7 @@ ok(
             ]
         },
         { Principal => $user_b, Right => [qw(SeeQueue ShowTicket OwnTicket)] },
+        { Principal => $user_c, Right => [qw(SeeQueue ShowTicket ReassignTicket)] },
     ),
     'set rights'
 );
@@ -416,3 +423,49 @@ diag
     $agent_b->content_like( qr{<a\b[^>]+>user_a</a>\s+-\s+Taken}, 'got user_a Taken message for user b ' );
 }
 
+my $agent_c = RT::Test::Web->new;
+ok $agent_c->login('user_c', 'password'), 'logged in as user C';
+
+diag "user can assign ticket to new owner with ReassignTicket right";
+{
+    my $ticket = RT::Ticket->new($user_a);
+    my ( $id, $txn, $msg ) = $ticket->Create(
+        Queue   => $queue->id,
+        Subject => 'test',
+    );
+    ok $id, 'created a ticket #' . $id or diag "error: $msg";
+    is $ticket->Owner, RT->Nobody->id, 'correct owner';
+
+    $agent_a->goto_ticket($id);
+    $agent_a->content_lacks('Taken', 'no Taken');
+    $agent_a->follow_link_ok( { text => 'Basics' }, 'Ticket -> Basics' );
+    $agent_a->submit_form(
+        form_name => 'TicketModify',
+        fields    => { Owner => $user_a->id },
+    );
+    $agent_a->content_contains( 'Owner changed from Nobody to user_a',
+        'got set message in Basics' );
+    $agent_a->goto_ticket($id);
+    $agent_a->content_like( qr{<a\b[^>]+>user_a</a>\s+-\s+Taken}, 'got user_a Taken message' );
+
+    $agent_c->goto_ticket($id);
+    $agent_c->follow_link_ok( { text => 'Basics' }, 'Ticket -> Basics' );
+    my $form = $agent_c->form_name('TicketModify');
+    is $form->value('Owner'), $user_a->id, 'correct owner selected';
+
+    ok grep($_ == $user_b->id,  $form->find_input('Owner')->possible_values),
+        'user B is listed as potential owner';
+    $agent_c->select('Owner', $user_b->id);
+    $agent_c->submit;
+    $agent_c->content_contains( 'Owner changed from user_a to user_b',
+        'got set message in Basics' );
+    $agent_c->goto_ticket($id);
+    $agent_c->content_like( qr{Owner forcibly changed}, 'got owner forcibly changed message' );
+
+}
+
+
+undef $agent_a;
+undef $agent_b;
+undef $agent_c;
+done_testing;

-----------------------------------------------------------------------


More information about the Rt-commit mailing list