Browse Source

Fixes #4216 - Allow placeholders in trigger perform actions for ticket/custom attributes.

Rolf Schmidt 2 years ago
parent
commit
220aa4dc23

+ 11 - 4
app/models/ticket.rb

@@ -935,9 +935,10 @@ perform changes on ticket
       end
     end
 
+    objects              = build_notification_template_objects(article)
     perform_notification = {}
-    perform_article = {}
-    changed = false
+    perform_article      = {}
+    changed              = false
     perform.each do |key, value|
       (object_name, attribute) = key.split('.', 2)
       raise "Unable to update object #{object_name}.#{attribute}, only can update tickets, send notifications and create articles!" if object_name != 'ticket' && object_name != 'article' && object_name != 'notification'
@@ -1014,6 +1015,14 @@ perform changes on ticket
 
       changed = true
 
+      if value['value'].is_a?(String)
+        value['value'] = NotificationFactory::Mailer.template(
+          templateInline: value['value'],
+          objects:        objects,
+          quote:          true,
+        )
+      end
+
       self[attribute] = value['value']
       logger.debug { "set #{object_name}.#{attribute} = #{value['value'].inspect} for ticket_id #{id}" }
     end
@@ -1022,8 +1031,6 @@ perform changes on ticket
       save!
     end
 
-    objects = build_notification_template_objects(article)
-
     perform_article.each do |key, value|
       raise __("Article could not be created. An unsupported key other than 'article.note' was provided.") if key != 'article.note'
 

+ 2 - 1
lib/notification_factory/template.rb

@@ -23,7 +23,7 @@ examples how to use
   def to_s
     result = @template
     result.gsub!(%r{<%(?!%)}, '<%%') if !@trusted
-    result.gsub(%r{\#{\s*(.*?)\s*}}m) do
+    result = result.gsub(%r{(?<!\\)\#{\s*(.*?)\s*}}m) do
       # some browsers start adding HTML tags
       # fixes https://github.com/zammad/zammad/issues/385
       input_template = $1.gsub(%r{\A<.+?>\s*|\s*<.+?>\z}, '')
@@ -39,6 +39,7 @@ examples how to use
         %(<%= d "#{sanitize_object_name(input_template)}", #{@escape} %>)
       end
     end
+    result.gsub(%r{\\\#{\s*(.*?)\s*}}m, '#{\1}') # rubocop:disable Lint/InterpolationCheck
   end
 
   def sanitize_text(string)

+ 21 - 1
spec/lib/notification_factory/template_spec.rb

@@ -30,6 +30,26 @@ RSpec.describe NotificationFactory::Template do
       end
     end
 
+    context 'for escaped input template' do
+      let(:template_string) { "\\\#{ticket.customer.name}" }
+
+      context 'with escape = true' do
+        let(:escape) { true }
+
+        it 'returns the original template string' do
+          expect(template.to_s).to eq('#{ticket.customer.name}') # rubocop:disable Lint/InterpolationCheck
+        end
+      end
+
+      context 'with escape = false' do
+        let(:escape) { false }
+
+        it 'returns the original template string' do
+          expect(template.to_s).to eq('#{ticket.customer.name}') # rubocop:disable Lint/InterpolationCheck
+        end
+      end
+    end
+
     context 'for sanitizing the template string' do
       let(:escape) { false }
 
@@ -54,7 +74,7 @@ RSpec.describe NotificationFactory::Template do
 
     context 'for input template using #t helper' do
       let(:template_string) { "\#{t('some text')}" }
-      let(:escape) { false }
+      let(:escape)          { false }
 
       it 'returns an ERB template with the #t helper, and passes escape arg as string' do
         expect(template.to_s).to eq('<%= t "some text", false %>')

+ 18 - 0
spec/models/ticket_spec.rb

@@ -847,6 +847,24 @@ RSpec.describe Ticket, type: :model do
           expect { ticket.perform_changes(trigger, 'trigger', {}, 1) }.to have_enqueued_job(TriggerWebhookJob).with(trigger, ticket, nil)
         end
       end
+
+      context 'Allow placeholders in trigger perform actions for ticket/custom attributes #4216' do
+        let(:customer) { create(:customer, mobile: '+491907655431') }
+        let(:ticket) { create(:ticket, customer: customer) }
+
+        let(:perform) do
+          {
+            'ticket.title' => {
+              'value' => ticket.customer.mobile.to_s,
+            }
+          }
+        end
+
+        it 'does replace custom fields in trigger' do
+          ticket.perform_changes(performable, 'trigger', ticket, User.first)
+          expect(ticket.reload.title).to eq(customer.mobile)
+        end
+      end
     end
 
     describe '#trigger_based_notification?' do