notification_factory_renderer_test.rb 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. require 'test_helper'
  2. class NotificationFactoryRendererTest < ActiveSupport::TestCase
  3. # RSpec incoming!
  4. def described_class
  5. NotificationFactory::Renderer
  6. end
  7. group = Group.new(name: 'Users')
  8. owner = User.new(firstname: 'Owner<b>xxx</b>', lastname: 'Agent1<b>yyy</b>')
  9. current_user = User.new(firstname: 'CurrentUser<b>xxx</b>', lastname: 'Agent2<b>yyy</b>')
  10. recipient = User.new(firstname: 'Recipient<b>xxx</b>', lastname: 'Customer1<b>yyy</b>')
  11. state = Ticket::State.new(name: 'new')
  12. ticket = Ticket.new(
  13. id: 1,
  14. title: '<b>Welcome to Zammad!</b>',
  15. group: group,
  16. owner: owner,
  17. state: state,
  18. created_by: current_user,
  19. updated_by: current_user,
  20. created_at: Time.zone.parse('2016-11-12 12:00:00 UTC'),
  21. updated_at: Time.zone.parse('2016-11-12 14:00:00 UTC'),
  22. )
  23. article_html1 = Ticket::Article.new(
  24. body: 'test <b>hello</b><br>some new line',
  25. content_type: 'text/html',
  26. )
  27. article_plain1 = Ticket::Article.new(
  28. body: "test <b>hello</b>\nsome new line",
  29. content_type: 'text/plain',
  30. )
  31. article_plain2 = Ticket::Article.new(
  32. body: "test <b>hello</b>\nsome new line",
  33. )
  34. test 'replace object attribute' do
  35. template = "\#{ticket.title}"
  36. result = described_class.new(
  37. {
  38. ticket: ticket,
  39. },
  40. 'en-us',
  41. template,
  42. ).render
  43. assert_equal(CGI.escapeHTML(ticket.title), result)
  44. template = "\#{ticket.created_at}"
  45. result = described_class.new(
  46. {
  47. ticket: ticket,
  48. },
  49. 'en-us',
  50. template,
  51. ).render
  52. assert_equal(ticket.created_at.to_s, result)
  53. template = "\#{ticket.created_by.firstname}"
  54. result = described_class.new(
  55. {
  56. ticket: ticket,
  57. },
  58. 'en-us',
  59. template,
  60. ).render
  61. assert_equal('CurrentUser&lt;b&gt;xxx&lt;/b&gt;', result)
  62. template = "\#{ticket.updated_at}"
  63. result = described_class.new(
  64. {
  65. ticket: ticket,
  66. },
  67. 'en-us',
  68. template,
  69. ).render
  70. assert_equal(ticket.updated_at.to_s, result)
  71. template = "\#{ticket.updated_by.firstname}"
  72. result = described_class.new(
  73. {
  74. ticket: ticket,
  75. },
  76. 'en-us',
  77. template,
  78. ).render
  79. assert_equal('CurrentUser&lt;b&gt;xxx&lt;/b&gt;', result)
  80. template = "\#{ticket.owner.firstname}"
  81. result = described_class.new(
  82. {
  83. ticket: ticket,
  84. },
  85. 'en-us',
  86. template,
  87. ).render
  88. assert_equal('Owner&lt;b&gt;xxx&lt;/b&gt;', result)
  89. template = "\#{ticket. title}"
  90. result = described_class.new(
  91. {
  92. ticket: ticket,
  93. },
  94. 'en-us',
  95. template,
  96. ).render
  97. assert_equal(CGI.escapeHTML(ticket.title), result)
  98. template = "\#{ticket.\n title}"
  99. result = described_class.new(
  100. {
  101. ticket: ticket,
  102. },
  103. 'en-us',
  104. template,
  105. ).render
  106. assert_equal(CGI.escapeHTML(ticket.title), result)
  107. template = "\#{ticket.\t title}"
  108. result = described_class.new(
  109. {
  110. ticket: ticket,
  111. },
  112. 'en-us',
  113. template,
  114. ).render
  115. assert_equal(CGI.escapeHTML(ticket.title), result)
  116. template = "\#{ticket.\t\n title\t}"
  117. result = described_class.new(
  118. {
  119. ticket: ticket,
  120. },
  121. 'en-us',
  122. template,
  123. ).render
  124. assert_equal(CGI.escapeHTML(ticket.title), result)
  125. template = "\#{ticket.\" title\t}"
  126. result = described_class.new(
  127. {
  128. ticket: ticket,
  129. },
  130. 'en-us',
  131. template,
  132. ).render
  133. assert_equal(CGI.escapeHTML(ticket.title), result)
  134. template = "\#{<a href=\"/test123\">ticket.\" title</a>}"
  135. result = described_class.new(
  136. {
  137. ticket: ticket,
  138. },
  139. 'en-us',
  140. template,
  141. ).render
  142. assert_equal(CGI.escapeHTML(ticket.title), result)
  143. template = "some test<br>\#{article.body}"
  144. result = described_class.new(
  145. {
  146. article: article_html1,
  147. },
  148. 'en-us',
  149. template,
  150. ).render
  151. assert_equal('some test<br>&gt; test hello<br>&gt; some new line<br>', result)
  152. result = described_class.new(
  153. {
  154. article: article_plain1,
  155. },
  156. 'en-us',
  157. template,
  158. ).render
  159. assert_equal('some test<br>&gt; test &lt;b&gt;hello&lt;/b&gt;<br>&gt; some new line<br>', result)
  160. result = described_class.new(
  161. {
  162. article: article_plain2,
  163. },
  164. 'en-us',
  165. template,
  166. ).render
  167. assert_equal('some test<br>&gt; test &lt;b&gt;hello&lt;/b&gt;<br>&gt; some new line<br>', result)
  168. end
  169. test 'config' do
  170. setting = 'fqdn'
  171. template = "\#{config.#{setting}}"
  172. result = described_class.new(
  173. {
  174. ticket: ticket,
  175. },
  176. 'en-us',
  177. template,
  178. ).render
  179. assert_equal(Setting.get(setting), result)
  180. setting1 = 'fqdn'
  181. setting2 = 'product_name'
  182. template = "some \#{config.#{setting1}} and \#{config.#{setting2}}"
  183. result = described_class.new(
  184. {
  185. ticket: ticket,
  186. },
  187. 'en-us',
  188. template,
  189. ).render
  190. assert_equal("some #{Setting.get(setting1)} and #{Setting.get(setting2)}", result)
  191. setting1 = 'fqdn'
  192. setting2 = 'product_name'
  193. template = "some \#{ config.#{setting1}} and \#{\tconfig.#{setting2}}"
  194. result = described_class.new(
  195. {
  196. ticket: ticket,
  197. },
  198. 'en-us',
  199. template,
  200. ).render
  201. assert_equal("some #{Setting.get(setting1)} and #{Setting.get(setting2)}", result)
  202. end
  203. test 'translation' do
  204. #template = "<%= t 'new' %>"
  205. template = "\#{t('new')}"
  206. result = described_class.new(
  207. {
  208. ticket: ticket,
  209. },
  210. 'de-de',
  211. template,
  212. ).render
  213. assert_equal('neu', result)
  214. template = "some text \#{t('new')} and \#{t('open')}"
  215. result = described_class.new(
  216. {
  217. ticket: ticket,
  218. },
  219. 'de-de',
  220. template,
  221. ).render
  222. assert_equal('some text neu and offen', result)
  223. template = "some text \#{t('new') } and \#{ t('open')}"
  224. result = described_class.new(
  225. {
  226. ticket: ticket,
  227. },
  228. 'de-de',
  229. template,
  230. ).render
  231. assert_equal('some text neu and offen', result)
  232. template = "some text \#{\nt('new') } and \#{ t('open')\t}"
  233. result = described_class.new(
  234. {
  235. ticket: ticket,
  236. },
  237. 'de-de',
  238. template,
  239. ).render
  240. assert_equal('some text neu and offen', result)
  241. end
  242. test 'chained function calls' do
  243. template = "\#{t(ticket.state.name)}"
  244. result = described_class.new(
  245. {
  246. ticket: ticket,
  247. },
  248. 'de-de',
  249. template,
  250. ).render
  251. assert_equal('neu', result)
  252. end
  253. test 'not existing object and attribute' do
  254. template = "\#{}"
  255. result = described_class.new(
  256. {
  257. ticket: ticket,
  258. },
  259. 'en-us',
  260. template,
  261. ).render
  262. assert_equal(CGI.escapeHTML('#{no such object}'), result)
  263. template = "\#{notexsiting.notexsiting}"
  264. result = described_class.new(
  265. {
  266. ticket: ticket,
  267. },
  268. 'en-us',
  269. template,
  270. ).render
  271. assert_equal(CGI.escapeHTML('#{notexsiting / no such object}'), result)
  272. template = "\#{ticket.notexsiting}"
  273. result = described_class.new(
  274. {
  275. ticket: ticket,
  276. },
  277. 'en-us',
  278. template,
  279. ).render
  280. assert_equal(CGI.escapeHTML('#{ticket.notexsiting / no such method}'), result)
  281. template = "\#{ticket.}"
  282. result = described_class.new(
  283. {
  284. ticket: ticket,
  285. },
  286. 'en-us',
  287. template,
  288. ).render
  289. assert_equal(CGI.escapeHTML('#{ticket. / no such method}'), result)
  290. template = "\#{ticket.title.notexsiting}"
  291. result = described_class.new(
  292. {
  293. ticket: ticket,
  294. },
  295. 'en-us',
  296. template,
  297. ).render
  298. assert_equal(CGI.escapeHTML('#{ticket.title.notexsiting / no such method}'), result)
  299. template = "\#{ticket.notexsiting.notexsiting}"
  300. result = described_class.new(
  301. {
  302. ticket: ticket,
  303. },
  304. 'en-us',
  305. template,
  306. ).render
  307. assert_equal(CGI.escapeHTML('#{ticket.notexsiting / no such method}'), result)
  308. template = "\#{notexsiting}"
  309. result = described_class.new(
  310. {
  311. ticket: ticket,
  312. },
  313. 'en-us',
  314. template,
  315. ).render
  316. assert_equal(CGI.escapeHTML('#{notexsiting / no such object}'), result)
  317. template = "\#{notexsiting.}"
  318. result = described_class.new(
  319. {
  320. ticket: ticket,
  321. },
  322. 'en-us',
  323. template,
  324. ).render
  325. assert_equal(CGI.escapeHTML('#{notexsiting / no such object}'), result)
  326. template = "\#{string}"
  327. result = described_class.new(
  328. {
  329. string: 'some string',
  330. },
  331. 'en-us',
  332. template,
  333. ).render
  334. assert_equal(CGI.escapeHTML('some string'), result)
  335. template = "\#{fixum}"
  336. result = described_class.new(
  337. {
  338. fixum: 123,
  339. },
  340. 'en-us',
  341. template,
  342. ).render
  343. assert_equal(CGI.escapeHTML('123'), result)
  344. template = "\#{float}"
  345. result = described_class.new(
  346. {
  347. float: 123.99,
  348. },
  349. 'en-us',
  350. template,
  351. ).render
  352. assert_equal(CGI.escapeHTML('123.99'), result)
  353. end
  354. test 'data key validation' do
  355. template = "\#{ticket.title `echo 1`}"
  356. result = described_class.new(
  357. {
  358. ticket: ticket,
  359. },
  360. 'en-us',
  361. template,
  362. ).render
  363. assert_equal(CGI.escapeHTML('#{ticket.title`echo1` / not allowed}'), result)
  364. template = "\#{ticket.destroy}"
  365. result = described_class.new(
  366. {
  367. ticket: ticket,
  368. },
  369. 'en-us',
  370. template,
  371. ).render
  372. assert_equal(CGI.escapeHTML('#{ticket.destroy / not allowed}'), result)
  373. template = "\#{ticket.save}"
  374. result = described_class.new(
  375. {
  376. ticket: ticket,
  377. },
  378. 'en-us',
  379. template,
  380. ).render
  381. assert_equal(CGI.escapeHTML('#{ticket.save / not allowed}'), result)
  382. template = "\#{ticket.update}"
  383. result = described_class.new(
  384. {
  385. ticket: ticket,
  386. },
  387. 'en-us',
  388. template,
  389. ).render
  390. assert_equal(CGI.escapeHTML('#{ticket.update / not allowed}'), result)
  391. template = "\#{ticket.create}"
  392. result = described_class.new(
  393. {
  394. ticket: ticket,
  395. },
  396. 'en-us',
  397. template,
  398. ).render
  399. assert_equal(CGI.escapeHTML('#{ticket.create / not allowed}'), result)
  400. template = "\#{ticket.delete}"
  401. result = described_class.new(
  402. {
  403. ticket: ticket,
  404. },
  405. 'en-us',
  406. template,
  407. ).render
  408. assert_equal(CGI.escapeHTML('#{ticket.delete / not allowed}'), result)
  409. template = "\#{ticket.remove}"
  410. result = described_class.new(
  411. {
  412. ticket: ticket,
  413. },
  414. 'en-us',
  415. template,
  416. ).render
  417. assert_equal(CGI.escapeHTML('#{ticket.remove / not allowed}'), result)
  418. template = "\#{ticket.drop}"
  419. result = described_class.new(
  420. {
  421. ticket: ticket,
  422. },
  423. 'en-us',
  424. template,
  425. ).render
  426. assert_equal(CGI.escapeHTML('#{ticket.drop / not allowed}'), result)
  427. template = "\#{ticket.create}"
  428. result = described_class.new(
  429. {
  430. ticket: ticket,
  431. },
  432. 'en-us',
  433. template,
  434. ).render
  435. assert_equal(CGI.escapeHTML('#{ticket.create / not allowed}'), result)
  436. template = "\#{ticket.new}"
  437. result = described_class.new(
  438. {
  439. ticket: ticket,
  440. },
  441. 'en-us',
  442. template,
  443. ).render
  444. assert_equal(CGI.escapeHTML('#{ticket.new / not allowed}'), result)
  445. template = "\#{ticket.update_att}"
  446. result = described_class.new(
  447. {
  448. ticket: ticket,
  449. },
  450. 'en-us',
  451. template,
  452. ).render
  453. assert_equal(CGI.escapeHTML('#{ticket.update_att / not allowed}'), result)
  454. template = "\#{ticket.all}"
  455. result = described_class.new(
  456. {
  457. ticket: ticket,
  458. },
  459. 'en-us',
  460. template,
  461. ).render
  462. assert_equal(CGI.escapeHTML('#{ticket.all / not allowed}'), result)
  463. template = "\#{ticket.find}"
  464. result = described_class.new(
  465. {
  466. ticket: ticket,
  467. },
  468. 'en-us',
  469. template,
  470. ).render
  471. assert_equal(CGI.escapeHTML('#{ticket.find / not allowed}'), result)
  472. template = "\#{ticket.where}"
  473. result = described_class.new(
  474. {
  475. ticket: ticket,
  476. },
  477. 'en-us',
  478. template,
  479. ).render
  480. assert_equal(CGI.escapeHTML('#{ticket.where / not allowed}'), result)
  481. template = "\#{ticket. destroy}"
  482. result = described_class.new(
  483. {
  484. ticket: ticket,
  485. },
  486. 'en-us',
  487. template,
  488. ).render
  489. assert_equal(CGI.escapeHTML('#{ticket.destroy / not allowed}'), result)
  490. template = "\#{ticket.\n destroy}"
  491. result = described_class.new(
  492. {
  493. ticket: ticket,
  494. },
  495. 'en-us',
  496. template,
  497. ).render
  498. assert_equal(CGI.escapeHTML("\#{ticket.destroy / not allowed}"), result)
  499. template = "\#{ticket.\t destroy}"
  500. result = described_class.new(
  501. {
  502. ticket: ticket,
  503. },
  504. 'en-us',
  505. template,
  506. ).render
  507. assert_equal(CGI.escapeHTML("\#{ticket.destroy / not allowed}"), result)
  508. template = "\#{ticket.\r destroy}"
  509. result = described_class.new(
  510. {
  511. ticket: ticket,
  512. },
  513. 'en-us',
  514. template,
  515. ).render
  516. assert_equal(CGI.escapeHTML("\#{ticket.destroy / not allowed}"), result)
  517. end
  518. test 'methods with single Integer parameter' do
  519. template = "\#{ticket.title.first(3)}"
  520. result = described_class.new(
  521. {
  522. ticket: ticket,
  523. },
  524. 'en-us',
  525. template,
  526. ).render
  527. assert_equal(CGI.escapeHTML('<b>'), result)
  528. template = "\#{ticket.title.last(4)}"
  529. result = described_class.new(
  530. {
  531. ticket: ticket,
  532. },
  533. 'en-us',
  534. template,
  535. ).render
  536. assert_equal(CGI.escapeHTML('</b>'), result)
  537. template = "\#{ticket.title.slice(3, 4)}"
  538. result = described_class.new(
  539. {
  540. ticket: ticket,
  541. },
  542. 'en-us',
  543. template,
  544. ).render
  545. assert_equal(CGI.escapeHTML("\#{ticket.title.slice(3,4) / invalid parameter: 3,4}"), result)
  546. template = "\#{ticket.title.first('some invalid parameter')}"
  547. result = described_class.new(
  548. {
  549. ticket: ticket,
  550. },
  551. 'en-us',
  552. template,
  553. ).render
  554. assert_equal("\#{ticket.title.first(someinvalidparameter) / invalid parameter: someinvalidparameter}", result)
  555. template = "\#{ticket.title.chomp(`cat /etc/passwd`)}"
  556. result = described_class.new(
  557. {
  558. ticket: ticket,
  559. },
  560. 'en-us',
  561. template,
  562. ).render
  563. assert_equal("\#{ticket.title.chomp(`cat/etc/passwd`) / not allowed}", result)
  564. end
  565. end