[Rt-devel] [PATCH]: Check Select* CF fields for valid values in ticket REST interface

Philip Kime pkime at Shopzilla.com
Sun Dec 24 13:16:22 EST 2006


This patch to <rt path>/share/html/REST/1.0/Forms/ticket/default checks
Select* fields for valid values and won't set them if the value isn't
valid. Works for multiple fields too. This has to be enforced in the
REST code - it's enforced in the GUI simply by the semantics of select
boxes.
Patch should be valid against 3.6.x

--- /tmp/rt-3.6.3/html/REST/1.0/Forms/ticket/default	2006-09-26
08:06:31.000000000 -0700
+++ /usr/local/rt/share/html/REST/1.0/Forms/ticket/default
2006-12-24 09:58:22.553405248 -0800
@@ -128,18 +128,6 @@
             if (exists $create{lc $k}) {
                 $v{$create{lc $k}} = delete $data{$k};
             }
-            # Set custom field
-            elsif ($k =~ /^CF-/i) {
-                my $cf = RT::CustomField->new( $RT::SystemUser );
-                my $cfk = $k;
-                $cfk =~ s/^CF-//i;
-                unless($cf->LoadByName( Name => $cfk )) {
-                    push @comments, "# Invalid custom field name
($cfk)";
-                    delete $data{$k};
-                    next;
-                }
-                $v{"CustomField-".$cf->Id()} = delete $data{$k};
-            }
             elsif (lc $k eq 'text') {
                 $text = delete $data{$k};
             }
@@ -157,6 +145,8 @@
                 );
         }
 
+        # Don't add custom fields here - let it fall through to check
them later
+        # This creates a seperate transaction but that's ok
         $ticket->Create(%v);
         unless ($ticket->Id) {
             return [ "# Could not create ticket.", [], {}, 1 ];
@@ -229,7 +219,7 @@
     foreach $key (keys %data) {
         $val = $data{$key};
         $key = lc $key;
-        $n = 1;
+       # $n = 1;
 
         if (ref $val eq 'ARRAY') {
             unless ($key =~ /^(?:Requestors|Cc|AdminCc)$/i) {
@@ -302,17 +292,131 @@
         }
         # Set custom field
         elsif ($key =~ /^CF-/i) {
-            my $cf = RT::CustomField->new( $RT::SystemUser );
+            my @msgs;
+            my $CustomFieldObj = RT::CustomField->new( $RT::SystemUser
);
             $key =~ s/^CF-//i;
-            if (not $cf->LoadByName( Name => $key )) {
-                $n = 0;
-                $s = "Unknown custom field.";
-            }
-            else {
-                ($n, $s) = $ticket->AddCustomFieldValue(
-                             Field => $cf, Value => $val );
-                $s =~ s/^# // if defined $s;
-            }
+
+        	my ($r, $rmsg) = (undef, undef);
+        	$CustomFieldObj->LoadByName( Name => $key );
+          unless ($CustomFieldObj->Id) {
+          	$s = 0;
+            $n = "Could not load Custom Field \"$key\" - does it
exist?";
+            push @msgs, [ $s, $n ];
+            goto CFEND;
+          }
+
+        	if
($CustomFieldObj->CurrentUserHasRight('ModifyCustomField')) {
+            
+            # Don't change any field that hasn't changed - otherwise
the Asset History shows
+            # that every field changes on changing any field.
+            my $CFvalues = $ticket->CustomFieldValues($key);
+
+            goto CFEND unless ($CFvalues->Count || length($val)); # If
new and old are both empty, do nothing
+  
+            # Single-Valued Field
+  		      if ($CustomFieldObj->SingleValue) {
+  		      	
+  		      	# First check for valid value for Select fields,
as long as value isn't null (this is just a delete)
+  		      	if (($CustomFieldObj->Type eq "Select") &&
length($val)) {
+    		      	my $ValidVals = $CustomFieldObj->Values;
+    		      	my $valok = 0;
+    		      	while (my $vv = $ValidVals->Next()) {
+    		      	  if ($vv->Name eq $val) {
+    		      	  	$valok = 1;
+    		      	  	last;
+    		      	  }
+    		      	}
+    		      	if (!$valok) { # Stop processing this Custom
field if it's not a valid value.
+    		      	  $s = 0;
+                  $n = "$val is not a valid Value for Ticket Custom
Field $key";
+                  push @msgs, [ $s, $n ];
+                  goto CFEND;
+                }
+              }
+		        	if ((my $CFvalue = $CFvalues->Next()) ||
length($val) ) {
+		        		# Skip delete unless we're going
from a value to nothing (changing a value doesn't need a delete first)
+		        		goto SVCFADD unless ((defined
$CFvalue) && (! length($val))); 
+		        		goto CFEND if ($CFvalue->Content
eq $val); # Skip delete and add if there is nothing to do
+            	  unless ($ticket->DeleteCustomFieldValue(Field =>
$CustomFieldObj, Value => $CFvalue->Content)) {
+                  $s = 0;
+                  $n = "Could not delete Ticket Custom Field Value
".$CFvalue->Content." for Field $key";
+                  push @msgs, [ $s, $n ];
+                }
+SVCFADD:
+                goto CFEND unless length($val);
+              	unless ($ticket->AddCustomFieldValue(Field =>
$CustomFieldObj, Value => $val)) {
+                      $s = 0;
+                      $n = "Could not add value $val to Ticket Custom
Field $key";
+                      push @msgs, [ $s, $n ];
+                    }
+              }
+		        }
+		        # Multi-Valued Field
+		        elsif (! $CustomFieldObj->SingleValue) {
+		        	my @val = @ { vsplit($val) };
+		        	
+		          # First check for valid value for Select
fields, as long as value isn't null (this is just a delete)
+  		      	if ($CustomFieldObj->Type eq "Select") {
+    		      	my @ValidVals =
@{$CustomFieldObj->Values->ItemsArrayRef};
+    		      	my $valok;
+    		      	foreach my $pv (@val) {
+    		      		$valok = 0;
+      		      	foreach my $vv (@ValidVals) {
+      		      	  if ($vv->Name eq $pv) {
+      		      	  	$valok = 1;
+      		      	  	last;
+      		      	  }
+      		      	}
+      		      	if (!$valok) { # Stop processing this Custom
field if it's not a valid value.
+    		      	    $s = 0;
+                    $n = "$pv is not a valid Value for Ticket Custom
Field $key";
+                    push @msgs, [ $s, $n ];
+                    goto CFEND;
+                  }
+      		      }     	
+              }
+		        	
+              my @CFVALS = map {$_->Content}
@{$CFvalues->ItemsArrayRef};
+		        	my $CFvalue;
+		        	my $mv;
+		        	# Process additions
+		        	foreach my $newval (@val) {
+		        	  if (! grep {$newval eq $_} @CFVALS ) {
+		        	    unless
($ticket->AddCustomFieldValue(Field => $CustomFieldObj, Value =>
$newval)) {
+                    $s = 0;
+                    $n = "Could not add Ticket Custom Field Value
$newval to Ticket Custom Field $key";
+                    push @msgs, [ $s, $n ];
+                  }
+		        	  }
+		        	}
+		        	# Process deletions
+		        	foreach my $oldval (@CFVALS) {
+		        	  if (! grep {$oldval eq $_} @val ) {
+		        	    unless
($ticket->DeleteCustomFieldValue(Field => $CustomFieldObj, Value =>
$oldval)) {
+                    $s = 0;
+                    $n = "Could not delete Ticket Custom Field Value
$oldval to Ticket Custom Field $key";
+                    push @msgs, [ $s, $n ];
+                  }
+		        	  }
+		        	}
+            }  
+        	}
+          else {
+        	  $n = 0;
+            $s = "You do not have permission to modify these custom
fields";
+          }
+            
+            
+CFEND:
+          # collate all error messages from the above transactions into
one string
+          $n = 1;
+          if (@msgs = grep {$_->[0] == 0} @msgs) {
+              $n = 0;
+              $s = join "\n", map {"# ".$_->[1]} @msgs;
+              $s =~ s/^# //;
+          }
+            
+            
         }
         elsif ($key ne 'id' && $key ne 'type' && $key ne 'creator') {
             $n = 0;


More information about the Rt-devel mailing list