<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://rt-wiki.bestpractical.com/index.php?action=history&amp;feed=atom&amp;title=TicketOwnershipPermissions</id>
	<title>TicketOwnershipPermissions - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://rt-wiki.bestpractical.com/index.php?action=history&amp;feed=atom&amp;title=TicketOwnershipPermissions"/>
	<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=TicketOwnershipPermissions&amp;action=history"/>
	<updated>2026-08-22T05:27:41Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.41.1</generator>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=TicketOwnershipPermissions&amp;diff=3838&amp;oldid=prev</id>
		<title>Admin: 2 revisions imported</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=TicketOwnershipPermissions&amp;diff=3838&amp;oldid=prev"/>
		<updated>2016-04-06T20:39:27Z</updated>

		<summary type="html">&lt;p&gt;2 revisions imported&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;I was reading this code in RT::User_Overlay.pm::[[SetOwner]]():&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;if ( $self-&amp;amp;gt;OwnerObj-&amp;amp;gt;Id == $RT::Nobody-&amp;amp;gt;Id ) {&lt;br /&gt;
     unless (    $self-&amp;amp;gt;CurrentUserHasRight(&amp;#039;ModifyTicket&amp;#039;)&lt;br /&gt;
              || $self-&amp;amp;gt;CurrentUserHasRight(&amp;#039;TakeTicket&amp;#039;) ) {&lt;br /&gt;
         return ( 0, $self-&amp;amp;gt;loc(&amp;quot;Permission Denied&amp;quot;) );&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # see if it&amp;#039;s a steal&lt;br /&gt;
 elsif (    $self-&amp;amp;gt;OwnerObj-&amp;amp;gt;Id != $RT::Nobody-&amp;amp;gt;Id&lt;br /&gt;
         &amp;amp;amp;&amp;amp;amp; $self-&amp;amp;gt;OwnerObj-&amp;amp;gt;Id != $self-&amp;amp;gt;CurrentUser-&amp;amp;gt;id ) {&lt;br /&gt;
 &lt;br /&gt;
     unless (    $self-&amp;amp;gt;CurrentUserHasRight(&amp;#039;ModifyTicket&amp;#039;)&lt;br /&gt;
              || $self-&amp;amp;gt;CurrentUserHasRight(&amp;#039;StealTicket&amp;#039;) ) {&lt;br /&gt;
         return ( 0, $self-&amp;amp;gt;loc(&amp;quot;Permission Denied&amp;quot;) );&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 else {&lt;br /&gt;
     unless ( $self-&amp;amp;gt;CurrentUserHasRight(&amp;#039;ModifyTicket&amp;#039;) ) {&lt;br /&gt;
         return ( 0, $self-&amp;amp;gt;loc(&amp;quot;Permission Denied&amp;quot;) );&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 my $NewOwnerObj = RT::User-&amp;amp;gt;new( $self-&amp;amp;gt;CurrentUser );&lt;br /&gt;
 my $OldOwnerObj = $self-&amp;amp;gt;OwnerObj;&lt;br /&gt;
 &lt;br /&gt;
 $NewOwnerObj-&amp;amp;gt;Load($NewOwner);&lt;br /&gt;
 if ( !$NewOwnerObj-&amp;amp;gt;Id ) {&lt;br /&gt;
     return ( 0, $self-&amp;amp;gt;loc(&amp;quot;That user does not exist&amp;quot;) );&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 # If this ticket has an owner and it&amp;#039;s not us, and we&amp;#039;re not&lt;br /&gt;
 # stealing it or forcing it, we&amp;#039;re trying to assign it to someone&lt;br /&gt;
 # that isn&amp;#039;t us.&lt;br /&gt;
 if ( ( $Type ne &amp;#039;Steal&amp;#039; ) and ( $Type ne &amp;#039;Force&amp;#039; ) and&lt;br /&gt;
      ( $self-&amp;amp;gt;OwnerObj-&amp;amp;gt;Id != $RT::Nobody-&amp;amp;gt;Id ) and&lt;br /&gt;
      ( $self-&amp;amp;gt;CurrentUser-&amp;amp;gt;Id ne $self-&amp;amp;gt;OwnerObj-&amp;amp;gt;Id() )&lt;br /&gt;
   ) {&lt;br /&gt;
     return ( 0,&lt;br /&gt;
              $self-&amp;amp;gt;loc(&amp;quot;You can only reassign tickets that you own or that are unowned&amp;quot; ) );&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 #If we&amp;#039;ve specified a new owner and that user can&amp;#039;t modify the ticket&lt;br /&gt;
 elsif ( ( $NewOwnerObj-&amp;amp;gt;Id )&lt;br /&gt;
         and ( !$NewOwnerObj-&amp;amp;gt;HasRight( Right  =&amp;amp;gt; &amp;#039;OwnTicket&amp;#039;,&lt;br /&gt;
                                        Object =&amp;amp;gt; $self ) )&lt;br /&gt;
   ) {&lt;br /&gt;
     return ( 0, $self-&amp;amp;gt;loc(&amp;quot;That user may not own tickets in that queue&amp;quot;) );&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 #If the ticket has an owner and it&amp;#039;s the new owner, we don&amp;#039;t need&lt;br /&gt;
 #To do anything&lt;br /&gt;
 elsif (     ( $self-&amp;amp;gt;OwnerObj )&lt;br /&gt;
         and ( $NewOwnerObj-&amp;amp;gt;Id eq $self-&amp;amp;gt;OwnerObj-&amp;amp;gt;Id ) ) {&lt;br /&gt;
     return ( 0, $self-&amp;amp;gt;loc(&amp;quot;That user already owns that ticket&amp;quot;) );&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... with an eye to understanding which permissions did what. Here&amp;#039;s the current logic in plain English, referring to [[CurrentUser]] as &amp;quot;you&amp;quot; and tickets owned by the Nobody user as &amp;quot;unowned&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 1. Check this logic; if you fail, no change takes place&lt;br /&gt;
 If it&amp;#039;s unowned:&lt;br /&gt;
   You must have TakeTicket or ModifyTicket to change the owner&lt;br /&gt;
 Otherwise, if it&amp;#039;s not unowned and not owned by you:&lt;br /&gt;
   You must have StealTicket or ModifyTicket to change the owner&lt;br /&gt;
 Otherwise:&lt;br /&gt;
   You must have ModifyTicket to change the owner&lt;br /&gt;
 &lt;br /&gt;
 2. The new owner must exist in RT&lt;br /&gt;
 &lt;br /&gt;
 3. Check this set of logic&lt;br /&gt;
 &lt;br /&gt;
 If you&amp;#039;re not stealing the ticket and you&amp;#039;re not forcing an ownership&lt;br /&gt;
 change and the ticket is not unowned and not owned by you:&lt;br /&gt;
   You can&amp;#039;t change the owner no matter what permissions you have&lt;br /&gt;
 Otherwise, if the new owner exists and doesn&amp;#039;t have the OwnTicket right:&lt;br /&gt;
   You can&amp;#039;t change the owner to them no matter what&lt;br /&gt;
 Otherwise, if you&amp;#039;re changing the owner to the person who already&lt;br /&gt;
 owns this ticket:&lt;br /&gt;
   You can&amp;#039;t change the owner because it&amp;#039;s unnecessary&lt;br /&gt;
 &lt;br /&gt;
 4. Change the owner to the new owner.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Reading the logic in section 1 I&amp;#039;ve inferred that [[ModifyTicket]] should allow you to change the ownership in any way you like as long as the new owner exists and has the [[OwnTicket]] right. The [[ModifyTicket]] wiki page seems to back this up. /&amp;#039;&amp;#039;&amp;#039;Please correct me if I&amp;#039;m mistaken.&amp;#039;&amp;#039;&amp;#039;/&lt;br /&gt;
&lt;br /&gt;
It seems like there are three things that should be addressed:&lt;br /&gt;
&lt;br /&gt;
# We should check the new owner&amp;#039;s existence and [[OwnTicket]] right first; if it fails, it renders the rest of the logic moot.&lt;br /&gt;
# /*We should have a [[GiveTicket]] right*/ -- this is the big change proposed here&lt;br /&gt;
# You should be able to assign an owned ticket to someone if you have [[StealTicket]]+[[GiveTicket]]&lt;br /&gt;
&lt;br /&gt;
Further, it seems like there are 7 possibly valid from/to ownership transitions:&lt;br /&gt;
&lt;br /&gt;
* Nobody -&amp;amp;gt; Self&lt;br /&gt;
** A &amp;#039;&amp;#039;&amp;#039;Take&amp;#039;&amp;#039;&amp;#039; transaction which should require [[TakeTicket]]&lt;br /&gt;
* Nobody -&amp;amp;gt; Other&lt;br /&gt;
** A &amp;#039;&amp;#039;&amp;#039;Give&amp;#039;&amp;#039;&amp;#039; transaction (really &amp;#039;&amp;#039;&amp;#039;Take+Give&amp;#039;&amp;#039;&amp;#039;) which should require [[TakeTicket]] and [[GiveTicket]]&lt;br /&gt;
* Self -&amp;amp;gt; Nobody&lt;br /&gt;
** An &amp;#039;&amp;#039;&amp;#039;Untake&amp;#039;&amp;#039;&amp;#039; transaction which should not require any right&lt;br /&gt;
* Other -&amp;amp;gt; Nobody&lt;br /&gt;
** An &amp;#039;&amp;#039;&amp;#039;Untake&amp;#039;&amp;#039;&amp;#039; transaction /(currently Give)/ (really Steal+Untake) which should require [[StealTicket]]&lt;br /&gt;
* Self -&amp;amp;gt; Other&lt;br /&gt;
** A &amp;#039;&amp;#039;&amp;#039;Give&amp;#039;&amp;#039;&amp;#039; transaction which should require [[GiveTicket]]&lt;br /&gt;
* Other -&amp;amp;gt; Self&lt;br /&gt;
** A &amp;#039;&amp;#039;&amp;#039;Steal&amp;#039;&amp;#039;&amp;#039; transaction which should require [[StealTicket]]&lt;br /&gt;
* Other A -&amp;amp;gt; Other B&lt;br /&gt;
** A &amp;#039;&amp;#039;&amp;#039;Give&amp;#039;&amp;#039;&amp;#039; transaction (really Steal+Give) which should require [[StealTicket]] and [[GiveTicket]]&lt;br /&gt;
&lt;br /&gt;
So we could choose to set the transaction type internally based on the order of&lt;br /&gt;
&lt;br /&gt;
Thus, it seems like the logic should go:&lt;br /&gt;
&lt;br /&gt;
 1. New owner must exist and have OwnTicket&lt;br /&gt;
 &lt;br /&gt;
 2. Check this logic; if you fail, no change takes place:&lt;br /&gt;
    If it&amp;#039;s currently unowned:&lt;br /&gt;
      You must have TakeTicket or ModifyTicket&lt;br /&gt;
    Otherwise, if the old owner isn&amp;#039;t you:&lt;br /&gt;
      You must have StealTicket or ModifyTicket&lt;br /&gt;
 &lt;br /&gt;
    If the new owner isn&amp;#039;t Nobody and isn&amp;#039;t you:&lt;br /&gt;
      You must have GiveTicket or ModifyTicket&lt;br /&gt;
 &lt;br /&gt;
 3. Change the owner to the new owner&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
In code, this might resemble (warning: this was written in the wiki ... trust it not):&lt;br /&gt;
&lt;br /&gt;
 my $NewOwnerObj = RT::User-&amp;amp;gt;new( $self-&amp;amp;gt;CurrentUser );&lt;br /&gt;
 my $OldOwnerObj = $self-&amp;amp;gt;OwnerObj;&lt;br /&gt;
 &lt;br /&gt;
 $NewOwnerObj-&amp;amp;gt;Load($NewOwner);&lt;br /&gt;
 if ( ! $NewOwnerObj-&amp;amp;gt;Id ) {&lt;br /&gt;
     return ( 0, $self-&amp;amp;gt;loc(&amp;quot;That user does not exist&amp;quot;) );&lt;br /&gt;
 } elsif ( ! $NewOwnerObj-&amp;amp;gt;HasRight(&amp;#039;OwnTicket&amp;#039;) ) {&lt;br /&gt;
     return ( 0, $self-&amp;amp;gt;loc(&amp;quot;That user may not own tickets in that queue&amp;quot;) );&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 if ( $OldOwnerObj-&amp;amp;gt;Id == $RT::Nobody-&amp;amp;gt;Id )&lt;br /&gt;
     unless ( $self-&amp;amp;gt;CurrentUserHasRight(&amp;#039;TakeTicket&amp;#039;) ||&lt;br /&gt;
              $self-&amp;amp;gt;CurrentUserHasRight(&amp;#039;ModifyTicket&amp;#039;) ) {&lt;br /&gt;
         return ( 0, $self-&amp;amp;gt;loc(&amp;quot;Permission Denied&amp;quot;) );&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     $Type = &amp;quot;Take&amp;quot;;&lt;br /&gt;
 } elsif ( $OldOwnerObj-&amp;amp;gt;Id != $self-&amp;amp;gt;CurrentUser-&amp;amp;gt;Id ) {&lt;br /&gt;
     unless ( $self-&amp;amp;gt;CurrentUserHasRight(&amp;#039;StealTicket&amp;#039;) ||&lt;br /&gt;
              $self-&amp;amp;gt;CurrentUserHasRight(&amp;#039;ModifyTicket&amp;#039;) ) {&lt;br /&gt;
         return ( 0, $self-&amp;amp;gt;loc(&amp;quot;Permission Denied&amp;quot;) );&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     $Type = &amp;quot;Steal&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 if ( $NewOwnerObj-&amp;amp;gt;Id == $RT::Nobody-&amp;amp;gt;Id ) {&lt;br /&gt;
     $Type = &amp;quot;Untake&amp;quot;;&lt;br /&gt;
 } elsif ( $NewOwnerObj-&amp;amp;gt;Id != $self-&amp;amp;gt;CurrentUser-&amp;amp;gt;Id ) {&lt;br /&gt;
     unless ( $self-&amp;amp;gt;CurrentUserHasRight(&amp;#039;GiveTicket&amp;#039;) ||&lt;br /&gt;
              $self-&amp;amp;gt;CurrentUserHasRight(&amp;#039;ModifyTicket&amp;#039;) ) {&lt;br /&gt;
         return ( 0, $self-&amp;amp;gt;loc(&amp;quot;Permission Denied&amp;quot;) );&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     $Type = &amp;quot;Give&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 ...&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
</feed>