· 8 years ago · Oct 25, 2017, 04:34 AM
1<sara xmlns="http://www.automic.com/sara/snsc">
2 <references>
3 <variable_types>
4 <var_type value="1">Yes / No</var_type>
5 <var_type value="2">Multi Line Text</var_type>
6 <var_type value="3">Multiple Choice</var_type>
7 <var_type value="4">Numeric Scale</var_type>
8 <var_type value="18">Lookup Select Box</var_type>
9 <var_type value="5">Select Box</var_type>
10 <var_type value="6">Single Line Text</var_type>
11 <var_type value="7">CheckBox</var_type>
12 <var_type value="8">Reference</var_type>
13 <var_type value="9">Date</var_type>
14 <var_type value="10">Date/Time</var_type>
15 <var_type value="11">Label</var_type>
16 <var_type value="12">Break</var_type>
17 <var_type value="14">Macro</var_type>
18 <var_type value="15">UI Page</var_type>
19 <var_type value="16">Wide Single Line Text</var_type>
20 <var_type value="17">Macro with Label</var_type>
21 <var_type value="21">List Collector</var_type>
22 <var_type value="22">Lookup Multiple Choice</var_type>
23 <var_type value="23">HTML</var_type>
24 </variable_types>
25 </references>
26 <package name="snsc" version="1.0-SNAPSHOT">
27 <description/>
28
29 <system_properties>
30 <category>
31 <name>Automic</name>
32 <title>This category consists of all SARA OAuth client settings</title>
33 <properties>
34 <property>
35 <suffix>mid_server</suffix>
36 <description>MID Server name to use</description>
37 <type>string</type>
38 <value/>
39 <ignore_cache>false</ignore_cache>
40 <private>false</private>
41 </property>
42 <property>
43 <suffix>workflow_timeout</suffix>
44 <description>Specifies the time during that the status of service/workflow is checked continuesly. The interval of checking is specified by the parameter x_ausgh_snsc.workflow_delay. If the value equals 0, the duration time will be forever, however the number of executing activities in a workflow context is limited by Max activity count. To change the maximum number of workflow activities:
451. Navigate to Workflow > Workflow Editor.
462. Check out a workflow.
473. In the title bar, click the Workflow Properties icon.
484. Click the Activities tab.
495. In the Max activity count field, enter a value that accommodates the expected number of executing activities for the workflow.
506. Click Update.
51*Note: This value is second(s).</description>
52 <type>string</type>
53 <value>0</value>
54 <ignore_cache>false</ignore_cache>
55 <private>false</private>
56 </property>
57 <property>
58 <suffix>workflow_delay</suffix>
59 <description>Specifies the interval of checking a workflow/service's status. If the value equals 0, the time interval will be 60.
60*Note: This value is second(s).</description>
61 <type>string</type>
62 <value>20</value>
63 <ignore_cache>false</ignore_cache>
64 <private>false</private>
65 </property>
66 <property>
67 <suffix>rest_request_timeout</suffix>
68 <description>Specifies the amount of time the instance waits for a response from the web service provider. If the value equals 0, the timeout will be 60.
69*Note: This value is second(s).</description>
70 <type>string</type>
71 <value>120</value>
72 <ignore_cache>false</ignore_cache>
73 <private>false</private>
74 </property>
75 <property>
76 <suffix>service_active</suffix>
77 <description>The default active status of services after importing. Can be "true" for active and "false" for inactive.</description>
78 <type>boolean</type>
79 <value>true</value>
80 <ignore_cache>false</ignore_cache>
81 <private>false</private>
82 </property>
83 </properties>
84 </category>
85</system_properties>
86
87
88 <tables>
89 <table>
90 <name>x_ausgh_snsc_sara_oauth</name>
91 <label>Sara OAuth</label>
92 <extends_table/>
93 <user_role>x_ausgh_snsc.user</user_role>
94 <is_extendable>false</is_extendable>
95 <dictionary_entries>
96 <column>
97 <name>u_access_token</name>
98 <type>string</type>
99 <label>Access Token</label>
100 <max_length>1000</max_length>
101 <hint>Access token from OAuth</hint>
102 </column>
103 <column>
104 <name>u_refresh_token</name>
105 <type>string</type>
106 <label>Refresh Token</label>
107 <max_length>1000</max_length>
108 <hint>Refresh token from OAuth</hint>
109 </column>
110 <column>
111 <name>u_token_expiry</name>
112 <type>string</type>
113 <label>Token Expiry</label>
114 <max_length>40</max_length>
115 <hint>The lived time of token from OAuth</hint>
116 </column>
117 <column>
118 <name>u_token_type</name>
119 <type>string</type>
120 <label>Token Type</label>
121 <max_length>40</max_length>
122 <hint>The type of token from OAuth</hint>
123 </column>
124 <column>
125 <name>u_user</name>
126 <type>string</type>
127 <label>Technical User</label>
128 <max_length>1000</max_length>
129 <display>true</display>
130 <hint>The AE technical user own this token</hint>
131 </column>
132 </dictionary_entries>
133 </table>
134 <table>
135 <name>x_ausgh_snsc_sara_cat_item</name>
136 <label>Sara Catalog Item</label>
137 <extends_table>sc_cat_item</extends_table>
138 <user_role>x_ausgh_snsc.user</user_role>
139 <is_extendable>false</is_extendable>
140 <dictionary_entries>
141 <column>
142 </column>
143 </dictionary_entries>
144 </table>
145 <table>
146 <name>x_ausgh_snsc_sara_variable</name>
147 <label>Sara Variable</label>
148 <extends_table>item_option_new</extends_table>
149 <user_role>x_ausgh_snsc.user</user_role>
150 <is_extendable>false</is_extendable>
151 <dictionary_entries>
152 <column>
153 <name>u_name</name>
154 <type>string</type>
155 <label>Actual Name</label>
156 <max_length>1000</max_length>
157 <display>true</display>
158 <hint>The actual name of variable in AE</hint>
159 </column>
160 <column>
161 <name>u_readonly</name>
162 <type>boolean</type>
163 <label>Read Only</label>
164 <max_length>40</max_length>
165 <hint>This is read-only field or not</hint>
166 </column>
167 <column>
168 <name>u_is_password</name>
169 <type>boolean</type>
170 <label>Is Password</label>
171 <max_length>40</max_length>
172 <hint>This field is marked as password or not</hint>
173 </column>
174 <column>
175 <name>u_is_lookup</name>
176 <type>boolean</type>
177 <label>Is Lookup Control</label>
178 <max_length>40</max_length>
179 <hint>This control is lookup control or not</hint>
180 </column>
181 <column>
182 <name>u_hash</name>
183 <type>string</type>
184 <label>Sara Variable Hash</label>
185 <max_length>32</max_length>
186 <hint>The hash of current lookup values of control from SAPI</hint>
187 </column>
188 </dictionary_entries>
189 </table>
190 <table>
191 <name>x_ausgh_snsc_sara_definition</name>
192 <label>Sara Definition</label>
193 <extends_table/>
194 <user_role>x_ausgh_snsc.user</user_role>
195 <is_extendable>false</is_extendable>
196 <dictionary_entries>
197 <column>
198 <name>u_name</name>
199 <type>string</type>
200 <label>Name</label>
201 <max_length>1000</max_length>
202 <display>true</display>
203 <hint>Name of catalog item or category</hint>
204 </column>
205 <column>
206 <name>u_consume_url</name>
207 <type>string</type>
208 <label>Consume URL</label>
209 <max_length>1000</max_length>
210 <hint>Consume URL of SAPI service</hint>
211 </column>
212 <column>
213 <name>u_sc_item</name>
214 <type>reference</type>
215 <label>Service Catalog Item</label>
216 <max_length>32</max_length>
217 <reference>sc_cat_item</reference>
218 <reference_cascade_rule>delete</reference_cascade_rule>
219 <hint>The corresponding Catalog item in sc_cat_item table</hint>
220 </column>
221 <column>
222 <name>u_service_catalog_category</name>
223 <type>reference</type>
224 <label>Service Catalog Category</label>
225 <max_length>32</max_length>
226 <reference>sc_category</reference>
227 <reference_cascade_rule>delete</reference_cascade_rule>
228 <hint>The corresponding Category in sc_cateogry table</hint>
229 </column>
230 <column>
231 <name>u_var_set</name>
232 <type>reference</type>
233 <label>Sara Variable Set</label>
234 <max_length>32</max_length>
235 <reference>item_option_new_set</reference>
236 <hint>The corresponding Variable Set in item_option_new_set table</hint>
237 </column>
238 <column>
239 <name>u_parent</name>
240 <type>reference</type>
241 <label>Parent Category</label>
242 <max_length>32</max_length>
243 <reference>sc_category</reference>
244 <hint>Reference to parent category, for catalog item it's the parent category (or catalog in SAPI term), for category it's the target category when it was imported.</hint>
245 </column>
246 <column>
247 <name>u_type</name>
248 <type>string</type>
249 <label>Sara Type</label>
250 <max_length>40</max_length>
251 <hint>Type of entity. Can be catalog, service, category</hint>
252 </column>
253 <column>
254 <name>u_hash</name>
255 <type>string</type>
256 <label>Sara Object Hash</label>
257 <max_length>32</max_length>
258 <hint>The hash of response data from SAPI for Catalog Item</hint>
259 </column>
260 <column>
261 <name>u_active</name>
262 <type>boolean</type>
263 <label>Active</label>
264 <max_length>40</max_length>
265 <hint/>
266 </column>
267 </dictionary_entries>
268 </table>
269 <table>
270 <name>x_ausgh_snsc_sara_lookup</name>
271 <label>Sara Lookup</label>
272 <extends_table/>
273 <user_role>catalog</user_role>
274 <is_extendable>false</is_extendable>
275 <dictionary_entries>
276 <column>
277 <name>u_key</name>
278 <type>string</type>
279 <label>Key</label>
280 <max_length>203</max_length>
281 <hint>The key value of lookup value</hint>
282 </column>
283 <column>
284 <name>u_display_name</name>
285 <type>string</type>
286 <label>Display Name</label>
287 <display>true</display>
288 <max_length>1023</max_length>
289 <hint>The display name value of lookup value</hint>
290 </column>
291 <column>
292 <name>u_control_id</name>
293 <type>reference</type>
294 <label>Lookup Control ID</label>
295 <max_length>32</max_length>
296 <reference>x_ausgh_snsc_sara_variable</reference>
297 <reference_cascade_rule>delete</reference_cascade_rule>
298 <hint>The sys_id of control which owns this lookup value</hint>
299 </column>
300 </dictionary_entries>
301 </table>
302 <table>
303 <name>x_ausgh_snsc_sara_config</name>
304 <label>Sara Configuration</label>
305 <extends_table/>
306 <user_role>x_ausgh_snsc.user</user_role>
307 <is_extendable>false</is_extendable>
308 <dictionary_entries>
309 <column>
310 <name>u_client_id</name>
311 <type>string</type>
312 <label>OAuth Client ID</label>
313 <max_length>1000</max_length>
314 <display>true</display>
315 <hint>Identity of OAuth client</hint>
316 </column>
317 <column>
318 <name>u_client_secret</name>
319 <type>string</type>
320 <label>OAuth Client Secret</label>
321 <max_length>1000</max_length>
322 <hint>OAuth client secret string</hint>
323 </column>
324 <column>
325 <name>u_technical_user</name>
326 <type>string</type>
327 <label>Technical User</label>
328 <max_length>1000</max_length>
329 <hint>The Technical User for authenticating with OAuth Server</hint>
330 </column>
331 <column>
332 <name>u_sapi_endpoint</name>
333 <type>string</type>
334 <label>SAPI Endpoint</label>
335 <max_length>1000</max_length>
336 <hint>URL to SAPI root endpoint</hint>
337 </column>
338 <column>
339 <name>u_token_endpoint</name>
340 <type>string</type>
341 <label>OAuth Token Endpoint</label>
342 <max_length>1000</max_length>
343 <hint>Endpoint for token requesting/refreshing</hint>
344 </column>
345 <column>
346 <name>u_auth_endpoint</name>
347 <type>string</type>
348 <label>OAuth Authorization Endpoint</label>
349 <max_length>1000</max_length>
350 <hint>Authorization endpoint for OAuth authentication</hint>
351 </column>
352 </dictionary_entries>
353 </table>
354
355 <table>
356 <name>x_ausgh_snsc_sc_catalog_ist</name>
357 <label>Service Catalog ImportSet</label>
358 <extends_table>sys_import_set_row</extends_table>
359 <is_extendable>false</is_extendable>
360 <dictionary_entries>
361 <column>
362 <name>id</name>
363 <type>string</type>
364 <label>Id</label>
365 <max_length>32</max_length>
366 <hint>Id</hint>
367 </column>
368 <column>
369 <name>title</name>
370 <type>translated_field</type>
371 <label>Title</label>
372 <max_length>100</max_length>
373 <hint>Title</hint>
374 <mandatory>true</mandatory>
375 <display>true</display>
376 </column>
377 <column>
378 <name>active</name>
379 <type>boolean</type>
380 <label>Active</label>
381 <max_length>40</max_length>
382 <hint/>
383 </column>
384 <column>
385 <name>description</name>
386 <type>translated_text</type>
387 <label>Description</label>
388 <max_length>4000</max_length>
389 <hint>Description</hint>
390 </column>
391 </dictionary_entries>
392 </table>
393 <table>
394 <name>x_ausgh_snsc_sc_category_ist</name>
395 <label>Service Category ImportSet</label>
396 <extends_table>sys_import_set_row</extends_table>
397 <is_extendable>false</is_extendable>
398 <dictionary_entries>
399 <column>
400 <name>id</name>
401 <type>string</type>
402 <label>Id</label>
403 <max_length>32</max_length>
404 <hint>Id</hint>
405 </column>
406 <column>
407 <name>title</name>
408 <type>translated_text</type>
409 <label>Title</label>
410 <max_length>100</max_length>
411 <hint>Title</hint>
412 <mandatory>true</mandatory>
413 <display>true</display>
414 </column>
415 <column>
416 <name>homepage_renderer</name>
417 <type>string</type>
418 <label>Homepage Renderer</label>
419 <max_length>32</max_length>
420 <hint>Homepage Renderer</hint>
421 </column>
422 <column>
423 <name>active</name>
424 <type>boolean</type>
425 <label>Active</label>
426 <max_length>40</max_length>
427 <hint/>
428 </column>
429 <column>
430 <name>description</name>
431 <type>translated_text</type>
432 <label>Description</label>
433 <max_length>4000</max_length>
434 <hint>Description</hint>
435 </column>
436 <column>
437 <name>parent</name>
438 <type>string</type>
439 <label>Parent</label>
440 <max_length>32</max_length>
441 <hint>Parent</hint>
442 </column>
443 <column>
444 <name>sc_catalog</name>
445 <type>string</type>
446 <label>Catalog</label>
447 <max_length>32</max_length>
448 <hint>Catalog</hint>
449 </column>
450
451 </dictionary_entries>
452 </table>
453 <table>
454 <name>x_ausgh_snsc_sara_cat_item_ist</name>
455 <label>Catalog Item ImportSet</label>
456 <extends_table>sys_import_set_row</extends_table>
457 <is_extendable>false</is_extendable>
458 <dictionary_entries>
459 <column>
460 <name>id</name>
461 <type>string</type>
462 <label>Id</label>
463 <max_length>32</max_length>
464 <hint>Id</hint>
465 </column>
466 <column>
467 <name>name</name>
468 <type>translated_text</type>
469 <label>Name</label>
470 <max_length>100</max_length>
471 <hint>Name</hint>
472 <mandatory>true</mandatory>
473 <display>true</display>
474 </column>
475 <column>
476 <name>category</name>
477 <type>string</type>
478 <label>Category Reference</label>
479 <max_length>32</max_length>
480 <hint>Category Reference</hint>
481 </column>
482 <column>
483 <name>active</name>
484 <type>boolean</type>
485 <label>Active</label>
486 <max_length>40</max_length>
487 <hint/>
488 </column>
489 <column>
490 <name>short_description</name>
491 <type>translated_text</type>
492 <label>Short Description</label>
493 <max_length>200</max_length>
494 <hint>Short Description</hint>
495 </column>
496 <column>
497 <name>description</name>
498 <type>translated_html</type>
499 <label>Description</label>
500 <max_length>8000</max_length>
501 <hint>Description</hint>
502 </column>
503 <column>
504 <name>custom_cart</name>
505 <type>string</type>
506 <label>Custom Cart</label>
507 <max_length>32</max_length>
508 <hint>Custom Cart Reference</hint>
509 </column>
510 <column>
511 <name>use_sc_layout</name>
512 <type>boolean</type>
513 <label>Use Catalog Layout</label>
514 <max_length>40</max_length>
515 <hint/>
516 </column>
517 <column>
518 <name>no_quantity</name>
519 <type>boolean</type>
520 <label>No Quantity</label>
521 <max_length>40</max_length>
522 <hint/>
523 </column>
524 <column>
525 <name>workflow</name>
526 <type>string</type>
527 <label>Workflow</label>
528 <max_length>32</max_length>
529 <hint>Workflow Reference</hint>
530 </column>
531 <column>
532 <name>sc_catalogs</name>
533 <type>string</type>
534 <label>Catalogs</label>
535 <max_length>4000</max_length>
536 <hint>Catalogs</hint>
537 </column>
538 </dictionary_entries>
539 </table>
540 <table>
541 <name>x_ausgh_snsc_item_option_new_set_ist</name>
542 <label>Variable Set ImportSet</label>
543 <extends_table>sys_import_set_row</extends_table>
544 <is_extendable>false</is_extendable>
545 <dictionary_entries>
546 <column>
547 <name>id</name>
548 <type>string</type>
549 <label>Id</label>
550 <max_length>32</max_length>
551 <hint>Id</hint>
552 </column>
553 <column>
554 <name>name</name>
555 <type>string</type>
556 <label>Name</label>
557 <max_length>40</max_length>
558 <hint>Name</hint>
559 <mandatory>true</mandatory>
560 <display>true</display>
561 </column>
562 <column>
563 <name>description</name>
564 <type>string</type>
565 <label>Description</label>
566 <max_length>4000</max_length>
567 <hint>Description</hint>
568 </column>
569 <column>
570 <name>title</name>
571 <type>translated_field</type>
572 <label>Title</label>
573 <max_length>80</max_length>
574 <hint>Title</hint>
575 </column>
576 <column>
577 <name>sys_name</name>
578 <type>string</type>
579 <label>Display Name</label>
580 <max_length>255</max_length>
581 <hint>Display Name</hint>
582 </column>
583 <column>
584 <name>display_title</name>
585 <type>boolean</type>
586 <label>Display Title</label>
587 <max_length>40</max_length>
588 <hint/>
589 </column>
590 </dictionary_entries>
591 </table>
592 <table>
593 <name>x_ausgh_snsc_io_set_item_ist</name>
594 <label>Catalog Variable Set ImportSet</label>
595 <extends_table>sys_import_set_row</extends_table>
596 <is_extendable>false</is_extendable>
597 <dictionary_entries>
598 <column>
599 <name>id</name>
600 <type>string</type>
601 <label>Id</label>
602 <max_length>32</max_length>
603 <hint>Id</hint>
604 </column>
605 <column>
606 <name>sc_cat_item</name>
607 <type>string</type>
608 <label>Catalog Item</label>
609 <max_length>32</max_length>
610 <hint>Catalog Item</hint>
611 <mandatory>true</mandatory>
612 <display>true</display>
613 </column>
614 <column>
615 <name>variable_set</name>
616 <type>string</type>
617 <label>Variable Set</label>
618 <max_length>32</max_length>
619 <hint>Variable Set</hint>
620 <mandatory>true</mandatory>
621 </column>
622 </dictionary_entries>
623 </table>
624 <table>
625 <name>x_ausgh_snsc_sara_definition_ist</name>
626 <label>Sara Definition ImportSet</label>
627 <user_role>x_ausgh_snsc.user</user_role>
628 <is_extendable>false</is_extendable>
629 <extends_table>sys_import_set_row</extends_table>
630 <dictionary_entries>
631 <column>
632 <name>id</name>
633 <type>string</type>
634 <label>Id</label>
635 <max_length>32</max_length>
636 <hint>Id</hint>
637 </column>
638 <column>
639 <name>u_name</name>
640 <type>string</type>
641 <label>Name</label>
642 <max_length>1000</max_length>
643 <display>true</display>
644 <hint>Name of catalog item or category</hint>
645 <mandatory>true</mandatory>
646 </column>
647 <column>
648 <name>u_consume_url</name>
649 <type>string</type>
650 <label>Consume URL</label>
651 <max_length>1000</max_length>
652 <hint>Consume URL of SAPI service</hint>
653 </column>
654 <column>
655 <name>u_sc_item</name>
656 <type>string</type>
657 <label>Service Catalog Item</label>
658 <max_length>32</max_length>
659 <hint>The corresponding Catalog item in sc_cat_item table</hint>
660 </column>
661 <column>
662 <name>u_service_catalog_category</name>
663 <type>string</type>
664 <label>Service Catalog Category</label>
665 <max_length>32</max_length>
666 <hint>The corresponding Category in sc_cateogry table</hint>
667 </column>
668 <column>
669 <name>u_var_set</name>
670 <type>string</type>
671 <label>Sara Variable Set</label>
672 <max_length>32</max_length>
673 <hint>The corresponding Variable Set in item_option_new_set table</hint>
674 </column>
675 <column>
676 <name>u_parent</name>
677 <type>string</type>
678 <label>Parent Category</label>
679 <max_length>32</max_length>
680 <hint>Reference to parent category, for catalog item it's the parent category (or catalog in SAPI term), for category it's the target category when it was imported.</hint>
681 </column>
682 <column>
683 <name>u_type</name>
684 <type>string</type>
685 <label>Sara Type</label>
686 <max_length>40</max_length>
687 <hint>Type of entity. Can be catalog, service, category</hint>
688 </column>
689 <column>
690 <name>u_hash</name>
691 <type>string</type>
692 <label>Sara Object Hash</label>
693 <max_length>32</max_length>
694 <hint>The hash of response data from SAPI for Catalog Item</hint>
695 </column>
696 <column>
697 <name>u_active</name>
698 <type>boolean</type>
699 <label>Active</label>
700 <max_length>40</max_length>
701 <hint/>
702 </column>
703 </dictionary_entries>
704 </table>
705 <table>
706 <name>x_ausgh_snsc_sara_variable_ist</name>
707 <label>Sara Variable ImportSet</label>
708 <extends_table>sys_import_set_row</extends_table>
709 <user_role>x_ausgh_snsc.user</user_role>
710 <is_extendable>false</is_extendable>
711 <dictionary_entries>
712 <column>
713 <name>id</name>
714 <type>string</type>
715 <label>Id</label>
716 <max_length>32</max_length>
717 <hint>Id</hint>
718 </column>
719 <column>
720 <name>u_name</name>
721 <type>string</type>
722 <label>Actual Name</label>
723 <max_length>1000</max_length>
724 <display>true</display>
725 <hint>The actual name of variable in AE</hint>
726 <mandatory>true</mandatory>
727 <display>true</display>
728 </column>
729 <column>
730 <name>u_readonly</name>
731 <type>boolean</type>
732 <label>Read Only</label>
733 <max_length>40</max_length>
734 <hint>This is read-only field or not</hint>
735 </column>
736 <column>
737 <name>u_is_password</name>
738 <type>boolean</type>
739 <label>Is Password</label>
740 <max_length>40</max_length>
741 <hint>This field is marked as password or not</hint>
742 </column>
743 <column>
744 <name>u_is_lookup</name>
745 <type>boolean</type>
746 <label>Is Lookup Control</label>
747 <max_length>40</max_length>
748 <hint>This control is lookup control or not</hint>
749 </column>
750 <column>
751 <name>u_hash</name>
752 <type>string</type>
753 <label>Sara Variable Hash</label>
754 <max_length>32</max_length>
755 <hint>The hash of current lookup values of control from SAPI</hint>
756 </column>
757 <column>
758 <name>variable_set</name>
759 <type>string</type>
760 <label>Variable Set</label>
761 <max_length>32</max_length>
762 <hint>Variable Set</hint>
763 </column>
764 <column>
765 <name>type</name>
766 <type>string</type>
767 <label>Type</label>
768 <max_length>40</max_length>
769 <hint>Type</hint>
770 </column>
771 <column>
772 <name>macro</name>
773 <type>string</type>
774 <label>Macro</label>
775 <max_length>32</max_length>
776 <hint>Macro</hint>
777 </column>
778 <column>
779 <name>name</name>
780 <type>string</type>
781 <label>Name</label>
782 <max_length>40</max_length>
783 <hint>Name</hint>
784 </column>
785 <column>
786 <name>cat_item</name>
787 <type>string</type>
788 <label>Catalog Item</label>
789 <max_length>32</max_length>
790 <hint>Catalog Item</hint>
791 </column>
792 <column>
793 <name>help_text</name>
794 <type>translated_text</type>
795 <label>Help text</label>
796 <max_length>4000</max_length>
797 <hint>Help text</hint>
798 </column>
799 <column>
800 <name>show_help</name>
801 <type>boolean</type>
802 <label>Show help</label>
803 <max_length>40</max_length>
804 <hint>Show help</hint>
805 </column>
806 <column>
807 <name>include_none</name>
808 <type>boolean</type>
809 <label>Include none</label>
810 <max_length>40</max_length>
811 <hint>Include none</hint>
812 </column>
813 <column>
814 <name>default_value</name>
815 <type>string</type>
816 <label>Default value</label>
817 <max_length>512</max_length>
818 <hint>Default value</hint>
819 </column>
820 <column>
821 <name>question_text</name>
822 <type>translated_field</type>
823 <label>Question text</label>
824 <max_length>255</max_length>
825 <hint>Question text</hint>
826 </column>
827 <column>
828 <name>mandatory</name>
829 <type>boolean</type>
830 <label>Mandatory</label>
831 <max_length>40</max_length>
832 <hint>Mandatory</hint>
833 </column>
834 <column>
835 <name>list_table</name>
836 <type>list_table</type>
837 <label>List table</label>
838 <max_length>80</max_length>
839 <hint>List table</hint>
840 </column>
841 <column>
842 <name>attributes</name>
843 <type>string</type>
844 <label>Variable attributes</label>
845 <max_length>255</max_length>
846 <hint>Variable attributes</hint>
847 </column>
848 <column>
849 <name>lookup_table</name>
850 <type>table_name</type>
851 <label>Lookup from table</label>
852 <max_length>80</max_length>
853 <hint>Lookup from table</hint>
854 </column>
855 <column>
856 <name>lookup_value</name>
857 <type>field_name</type>
858 <label>Lookup value field</label>
859 <max_length>80</max_length>
860 <hint>Lookup value field</hint>
861 </column>
862 <column>
863 <name>reference_qual</name>
864 <type>string</type>
865 <label>Reference qual</label>
866 <max_length>255</max_length>
867 <hint>Reference qual</hint>
868 </column>
869 <column>
870 <name>active</name>
871 <type>boolean</type>
872 <label>Read Only</label>
873 <max_length>40</max_length>
874 <hint>Active</hint>
875 </column>
876 <column>
877 <name>order</name>
878 <type>integer</type>
879 <label>Order</label>
880 <max_length>40</max_length>
881 <hint>Order</hint>
882 </column>
883 </dictionary_entries>
884 </table>
885 <table>
886 <name>x_ausgh_snsc_sara_lookup_ist</name>
887 <label>Sara Lookup ImportSet</label>
888 <extends_table>sys_import_set_row</extends_table>
889 <user_role>catalog</user_role>
890 <is_extendable>false</is_extendable>
891 <dictionary_entries>
892 <column>
893 <name>id</name>
894 <type>string</type>
895 <label>Id</label>
896 <max_length>32</max_length>
897 <hint>Id</hint>
898 </column>
899 <column>
900 <name>u_key</name>
901 <type>string</type>
902 <label>Key</label>
903 <max_length>203</max_length>
904 <hint>The key value of lookup value</hint>
905 <mandatory>true</mandatory>
906 <display>true</display>
907 </column>
908 <column>
909 <name>u_display_name</name>
910 <type>string</type>
911 <label>Display Name</label>
912 <display>true</display>
913 <max_length>1023</max_length>
914 <hint>The display name value of lookup value</hint>
915 </column>
916 <column>
917 <name>u_control_id</name>
918 <type>string</type>
919 <label>Lookup Control ID</label>
920 <max_length>32</max_length>
921 <hint>The sys_id of control which owns this lookup value</hint>
922 </column>
923 </dictionary_entries>
924 </table>
925</tables>
926
927
928 <transform_maps>
929 <transform_map>
930 <name>x_ausgh_snsc_sc_catalog_transform_map</name>
931 <source_table>x_ausgh_snsc_sc_catalog_ist</source_table>
932 <target_table>sc_catalog</target_table>
933 <copy_empty_fields>false</copy_empty_fields>
934 <active>true</active>
935 <run_business_rules>false</run_business_rules>
936 <fields>
937 <field>
938 <source_field>id</source_field>
939 <target_field>sys_id</target_field>
940 <coalesce>true</coalesce>
941 </field>
942 <field>
943 <source_field>title</source_field>
944 </field>
945 <field>
946 <source_field>active</source_field>
947 </field>
948 <field>
949 <source_field>description</source_field>
950 </field>
951 </fields>
952 </transform_map>
953 <transform_map>
954 <name>x_ausgh_snsc_sc_category_transform_map</name>
955 <source_table>x_ausgh_snsc_sc_category_ist</source_table>
956 <target_table>sc_category</target_table>
957 <copy_empty_fields>false</copy_empty_fields>
958 <active>true</active>
959 <run_business_rules>false</run_business_rules>
960 <fields>
961 <field>
962 <source_field>id</source_field>
963 <target_field>sys_id</target_field>
964 <coalesce>true</coalesce>
965 </field>
966 <field>
967 <source_field>title</source_field>
968 </field>
969 <field>
970 <source_field>homepage_renderer</source_field>
971 </field>
972 <field>
973 <source_field>active</source_field>
974 </field>
975 <field>
976 <source_field>description</source_field>
977 </field>
978 <field>
979 <source_field>parent</source_field>
980 <reference_value_field>sys_id</reference_value_field>
981 <choice_action>reject</choice_action>
982 </field>
983 <field>
984 <source_field>sc_catalog</source_field>
985 <reference_value_field>sys_id</reference_value_field>
986 </field>
987 </fields>
988 </transform_map>
989 <transform_map>
990 <name>x_ausgh_snsc_sc_cat_item_transform_map</name>
991 <source_table>x_ausgh_snsc_sara_cat_item_ist</source_table>
992 <target_table>x_ausgh_snsc_sara_cat_item</target_table>
993 <active>true</active>
994 <run_business_rules>false</run_business_rules>
995 <copy_empty_fields>false</copy_empty_fields>
996 <fields>
997 <field>
998 <source_field>id</source_field>
999 <target_field>sys_id</target_field>
1000 <coalesce>true</coalesce>
1001 </field>
1002 <field>
1003 <source_field>name</source_field>
1004 </field>
1005 <field>
1006 <source_field>category</source_field>
1007 <choice_action>reject</choice_action>
1008 <reference_value_field>sys_id</reference_value_field>
1009 </field>
1010 <field>
1011 <source_field>active</source_field>
1012 </field>
1013 <field>
1014 <source_field>short_description</source_field>
1015 </field>
1016 <field>
1017 <source_field>description</source_field>
1018 </field>
1019 <field>
1020 <source_field>custom_cart</source_field>
1021 <reference_value_field>sys_id</reference_value_field>
1022 <choice_action>reject</choice_action>
1023 </field>
1024 <field>
1025 <source_field>use_sc_layout</source_field>
1026 </field>
1027 <field>
1028 <source_field>no_quantity</source_field>
1029 </field>
1030 <field>
1031 <source_field>workflow</source_field>
1032 <reference_value_field>sys_id</reference_value_field>
1033 <choice_action>reject</choice_action>
1034 </field>
1035 <field>
1036 <source_field>sc_catalogs</source_field>
1037 </field>
1038 </fields>
1039 </transform_map>
1040 <transform_map>
1041 <name>x_ausgh_snsc_item_option_new_set_transform_map</name>
1042 <source_table>x_ausgh_snsc_item_option_new_set_ist</source_table>
1043 <target_table>item_option_new_set</target_table>
1044 <active>true</active>
1045 <run_business_rules>false</run_business_rules>
1046 <copy_empty_fields>false</copy_empty_fields>
1047 <fields>
1048 <field>
1049 <source_field>id</source_field>
1050 <target_field>sys_id</target_field>
1051 <coalesce>true</coalesce>
1052 </field>
1053 <field>
1054 <source_field>name</source_field>
1055 </field>
1056 <field>
1057 <source_field>description</source_field>
1058 </field>
1059 <field>
1060 <source_field>title</source_field>
1061 </field>
1062 <field>
1063 <source_field>sys_name</source_field>
1064 </field>
1065 <field>
1066 <source_field>display_title</source_field>
1067 </field>
1068 </fields>
1069 </transform_map>
1070 <transform_map>
1071 <name>x_ausgh_snsc_io_set_item_transform_map</name>
1072 <source_table>x_ausgh_snsc_io_set_item_ist</source_table>
1073 <target_table>io_set_item</target_table>
1074 <active>true</active>
1075 <run_business_rules>false</run_business_rules>
1076 <copy_empty_fields>false</copy_empty_fields>
1077 <fields>
1078 <field>
1079 <source_field>id</source_field>
1080 <target_field>sys_id</target_field>
1081 <coalesce>true</coalesce>
1082 </field>
1083 <field>
1084 <source_field>sc_cat_item</source_field>
1085 <reference_value_field>sys_id</reference_value_field>
1086 <choice_action>reject</choice_action>
1087 </field>
1088 <field>
1089 <source_field>variable_set</source_field>
1090 <reference_value_field>sys_id</reference_value_field>
1091 <choice_action>reject</choice_action>
1092 </field>
1093 </fields>
1094 </transform_map>
1095 <transform_map>
1096 <name>x_ausgh_snsc_sara_definition_transform_map</name>
1097 <source_table>x_ausgh_snsc_sara_definition_ist</source_table>
1098 <target_table>x_ausgh_snsc_sara_definition</target_table>
1099 <active>true</active>
1100 <run_business_rules>false</run_business_rules>
1101 <copy_empty_fields>false</copy_empty_fields>
1102 <fields>
1103 <field>
1104 <source_field>id</source_field>
1105 <target_field>sys_id</target_field>
1106 <coalesce>true</coalesce>
1107 </field>
1108 <field>
1109 <source_field>u_name</source_field>
1110 </field>
1111 <field>
1112 <source_field>u_consume_url</source_field>
1113 </field>
1114 <field>
1115 <source_field>u_sc_item</source_field>
1116 <reference_value_field>sys_id</reference_value_field>
1117 <choice_action>reject</choice_action>
1118 </field>
1119 <field>
1120 <source_field>u_service_catalog_category</source_field>
1121 <reference_value_field>sys_id</reference_value_field>
1122 <choice_action>reject</choice_action>
1123 </field>
1124 <field>
1125 <source_field>u_var_set</source_field>
1126 <reference_value_field>sys_id</reference_value_field>
1127 <choice_action>reject</choice_action>
1128 </field>
1129 <field>
1130 <source_field>u_parent</source_field>
1131 <reference_value_field>sys_id</reference_value_field>
1132 <choice_action>ignore</choice_action>
1133 </field>
1134 <field>
1135 <source_field>u_type</source_field>
1136 </field>
1137 <field>
1138 <source_field>u_hash</source_field>
1139 </field>
1140 <field>
1141 <source_field>u_active</source_field>
1142 </field>
1143 </fields>
1144 </transform_map>
1145 <transform_map>
1146 <name>x_ausgh_snsc_sara_variable_transform_map</name>
1147 <source_table>x_ausgh_snsc_sara_variable_ist</source_table>
1148 <target_table>x_ausgh_snsc_sara_variable</target_table>
1149 <active>true</active>
1150 <run_business_rules>false</run_business_rules>
1151 <copy_empty_fields>false</copy_empty_fields>
1152 <fields>
1153 <field>
1154 <source_field>id</source_field>
1155 <target_field>sys_id</target_field>
1156 <coalesce>true</coalesce>
1157 </field>
1158 <field>
1159 <source_field>u_name</source_field>
1160 </field>
1161 <field>
1162 <source_field>u_readonly</source_field>
1163 </field>
1164 <field>
1165 <source_field>u_is_password</source_field>
1166 </field>
1167 <field>
1168 <source_field>u_is_lookup</source_field>
1169 </field>
1170 <field>
1171 <source_field>u_hash</source_field>
1172 </field>
1173 <field>
1174 <source_field>variable_set</source_field>
1175 <reference_value_field>id</reference_value_field>
1176 <choice_action>reject</choice_action>
1177 </field>
1178 <field>
1179 <source_field>type</source_field>
1180 </field>
1181 <field>
1182 <source_field>macro</source_field>
1183 </field>
1184 <field>
1185 <source_field>name</source_field>
1186 </field>
1187 <field>
1188 <source_field>cat_item</source_field>
1189 <reference_value_field>sys_id</reference_value_field>
1190 <choice_action>reject</choice_action>
1191 </field>
1192 <field>
1193 <source_field>help_text</source_field>
1194 </field>
1195 <field>
1196 <source_field>show_help</source_field>
1197 </field>
1198 <field>
1199 <source_field>include_none</source_field>
1200 </field>
1201 <field>
1202 <source_field>default_value</source_field>
1203 </field>
1204 <field>
1205 <source_field>question_text</source_field>
1206 </field>
1207 <field>
1208 <source_field>mandatory</source_field>
1209 </field>
1210 <field>
1211 <source_field>list_table</source_field>
1212 </field>
1213 <field>
1214 <source_field>attributes</source_field>
1215 </field>
1216 <field>
1217 <source_field>lookup_table</source_field>
1218 </field>
1219 <field>
1220 <source_field>lookup_value</source_field>
1221 </field>
1222 <field>
1223 <source_field>reference_qual</source_field>
1224 </field>
1225 <field>
1226 <source_field>active</source_field>
1227 </field>
1228 <field>
1229 <source_field>order</source_field>
1230 </field>
1231 </fields>
1232 </transform_map>
1233 <transform_map>
1234 <name>x_ausgh_snsc_sara_lookup_transform_map</name>
1235 <source_table>x_ausgh_snsc_sara_lookup_ist</source_table>
1236 <target_table>x_ausgh_snsc_sara_lookup</target_table>
1237 <active>true</active>
1238 <run_business_rules>false</run_business_rules>
1239 <copy_empty_fields>true</copy_empty_fields>
1240 <fields>
1241 <field>
1242 <source_field>id</source_field>
1243 <target_field>sys_id</target_field>
1244 <coalesce>true</coalesce>
1245 </field>
1246 <field>
1247 <source_field>u_key</source_field>
1248 </field>
1249 <field>
1250 <source_field>u_display_name</source_field>
1251 </field>
1252 <field>
1253 <source_field>u_control_id</source_field>
1254 <reference_value_field>sys_id</reference_value_field>
1255 <choice_action>ignore</choice_action>
1256 </field>
1257 </fields>
1258 </transform_map>
1259</transform_maps>
1260
1261
1262 <script_includes>
1263 <script_include>
1264 <name>SaraCommon</name>
1265 <script><![CDATA[/**
1266 * This class is comprised of global parameters in SARA connector. It shouldn't be instantiated
1267 * and fields will be accessed in static-like fashion (think Java), eg.: SaraCommon.username
1268 */
1269var SaraCommon = Class.create();
1270SaraCommon.prototype = {
1271 initialize: function () {},
1272
1273 type: 'SaraCommon'
1274};
1275
1276SaraCommon.PROP_PREFIX = 'x_ausgh_snsc';
1277SaraCommon.OAUTH_IMPORT_SUCCESS = 0;
1278SaraCommon.OAUTH_AUTHENTICATION_FAILED = 1;
1279SaraCommon.OAUTH_INVALID_TOKEN = 2;
1280SaraCommon.OAUTH_TOKEN_EXPIRED = 3;
1281
1282SaraCommon.DEFAULT_CATALOG = 'Service Catalog';
1283SaraCommon.DEFAULT_AUTOMIC_CATALOG = 'Automic Service Catalog';
1284SaraCommon.DEFAULT_CATEGORY = 'Automic Services';
1285SaraCommon.CATALOGS_LIMIT = 1000;
1286SaraCommon.SERVICES_LIMIT = 10;
1287
1288SaraCommon.WORKFLOW_STATUS_CODE = {
1289 ENDED_OK: 1900
1290};
1291
1292SaraCommon.ROLES = {
1293 ADMIN: 'x_ausgh_snsc.admin',
1294 USER: 'x_ausgh_snsc.user'
1295};
1296
1297SaraCommon.CUSTOM_CART_NAME = '';
1298
1299SaraCommon.VAR_TYPE = {
1300 YES_NO: 1,
1301 MULTI_LINE_TEXT: 2,
1302 MULTI_CHOICE: 3,
1303 NUM_SCALE: 4,
1304 SELECT_BOX: 5,
1305 SINGLE_LINE_TEXT: 6,
1306 CHECK_BOX: 7,
1307 REFERENCE: 8,
1308 DATE: 9,
1309 DATE_TIME: 10,
1310 LABEL: 11,
1311 BREAK: 12,
1312 MACRO: 14,
1313 UI_PAGE: 15,
1314 WIDE_SINGLE_LINE_TEXT: 16,
1315 MACRO_WITH_LABEL: 17,
1316 LOOKUP_SELECT_BOX: 18,
1317 CONTAINER_START: 19,
1318 CONTAINER_END: 20,
1319 LIST_COLLECTOR: 21,
1320 LOOKUP_MULTI_CHOICE: 22,
1321 HTML: 23
1322};
1323
1324SaraCommon.CONTROL_NAME = {
1325 CLIENT_SCRIPTS: 'sara_client_scripts',
1326 HIDDEN_CONTROL: 'sara_hidden_control'
1327};
1328
1329SaraCommon.SCOPED_APP = 'x_ausgh_snsc';
1330
1331SaraCommon.SYSTEM_PROPERTY_NAME = {
1332 MID_SERVER: 'mid_server',
1333 REST_REQUEST_TIMEOUT: 'rest_request_timeout',
1334 SERVICE_ACTIVE: 'service_active',
1335 WORKFLOW_TIMEOUT: 'workflow_timeout',
1336 WORKFLOW_DELAY: 'workflow_delay'
1337};
1338
1339SaraCommon.CONFIG_NAME = {
1340 CLIENT_ID: 'client_id',
1341 CLIENT_SECRET: 'client_secret',
1342 TECHNICAL_USER: 'technical_user',
1343 SAPI_ENDPOINT: 'sapi_endpoint',
1344 TOKEN_ENDPOINT: 'token_endpoint',
1345 AUTH_ENDPOINT: 'auth_endpoint'
1346};
1347
1348SaraCommon.REST_NAME = {
1349 SAPI: 'Sara - SAPI Services',
1350 OAUTH: 'Sara - OAuth Services'
1351};
1352
1353// List of properties will be kept when syncing services
1354SaraCommon.KEEP_SERIVCE_PROPERTIES = [];
1355
1356SaraCommon.TABLE_NAME = {
1357 //Sara tables
1358 SARA_CONFIG: 'x_ausgh_snsc_sara_config',
1359 SARA_DEFINITION: 'x_ausgh_snsc_sara_definition',
1360 SARA_INSTALL_LOG: 'u_snsc_install_log',
1361 SARA_LOOKUP: 'x_ausgh_snsc_sara_lookup',
1362 SARA_OAUTH: 'x_ausgh_snsc_sara_oauth',
1363 SARA_VARIABLE: 'x_ausgh_snsc_sara_variable',
1364 SARA_CAT_ITEM: 'x_ausgh_snsc_sara_cat_item',
1365 //ImportSet tables,
1366 SN_CATALOG_IST: 'x_ausgh_snsc_sc_catalog_ist',
1367 SN_CATEGORY_IST: 'x_ausgh_snsc_sc_category_ist',
1368 SN_VARIABLE_SET_IST: 'x_ausgh_snsc_item_option_new_set_ist',
1369 SN_VARIABLE_SET_ITEM_IST: 'x_ausgh_snsc_io_set_item_ist',
1370 SARA_DEFINITION_IST: 'x_ausgh_snsc_sara_definition_ist',
1371 SARA_VARIABLE_IST: 'x_ausgh_snsc_sara_variable_ist',
1372 SARA_LOOKUP_IST: 'x_ausgh_snsc_sara_lookup_ist',
1373 SARA_CAT_ITEM_IST: 'x_ausgh_snsc_sara_cat_item_ist',
1374 //ServiceNow tables
1375 SN_APPLICATION: 'sys_app',
1376 SN_APPLICATION_CATEGORY: 'sys_app_category',
1377 SN_APPLICATION_FILE: 'sys_app_file',
1378 SN_APPLICATION_MENU: 'sys_app_application',
1379 SN_APPLICATION_MODULE: 'sys_app_module',
1380 SN_AUTO_SCRIPT: 'sysauto_script',
1381 SN_CATALOG: 'sc_catalog',
1382 SN_CATALOG_ITEM: 'sc_cat_item',
1383 SN_CATALOG_ITEM_WIZARD: 'sc_cat_item_wizard',
1384 SN_CATALOG_SCRIPT_CLIENT: 'catalog_script_client',
1385 SN_CATEGORY: 'sc_category',
1386 SN_DB_OBJECT: 'sys_db_object',
1387 SN_DICTIONARY: 'sys_dictionary',
1388 SN_DOCUMENTATION: 'sys_documentation',
1389 SN_ECC_QUEUE: 'ecc_queue',
1390 SN_FIX_SCRIPT: 'sys_script_fix',
1391 SN_HOMEPAGE_RENDERER: 'sc_homepage_renderer',
1392 SN_JOURNAL_FIELD: 'sys_journal_field',
1393 SN_METADATA: 'sys_metadata',
1394 SN_PROCESSOR: 'sys_processor',
1395 SN_PROPERTIES: 'sys_properties',
1396 SN_PROPERTIES_CATEGORY: 'sys_properties_category',
1397 SN_PROPERTIES_CATEGORY_RELATIONSHIP: 'sys_properties_category_m2m',
1398 SN_REST_MESSAGE: 'sys_rest_message',
1399 SN_REST_MESSAGE_FN: 'sys_rest_message_fn',
1400 SN_REST_MESSAGE_FN_HEADERS: 'sys_rest_message_fn_headers',
1401 SN_REST_MESSAGE_HEADERS: 'sys_rest_message_headers',
1402 SN_ROLE: 'sys_user_role',
1403 SN_SECURITY_ACL: 'sys_security_acl',
1404 SN_SECURITY_ACL_ROLE: 'sys_security_acl_role',
1405 SN_SCRIPT_INCLUDES: 'sys_script_include',
1406 SN_UI_MACRO: 'sys_ui_macro',
1407 SN_UI_PAGE: 'sys_ui_page',
1408 SN_UI_SCRIPT: 'sys_ui_script',
1409 SN_USER: 'sys_user',
1410 SN_USER_GROUP: 'sys_user_group',
1411 SN_VARIABLE: 'item_option_new',
1412 SN_VARIABLE_SET: 'item_option_new_set',
1413 SN_VARIABLE_SET_ITEM: 'io_set_item',
1414 SN_VARIABLE_VALUE: 'sys_variable_value',
1415 SN_WIZARD: 'expert',
1416 SN_WIZARD_CLIENT_SCRIPT: 'expert_script_client',
1417 SN_WIZARD_PANEL: 'expert_panel',
1418 SN_WIZARD_PANEL_TRANSITION: 'expert_panel_transition',
1419 SN_WIZARD_PANEL_VARIABLE: 'expert_panel_variable',
1420 SN_WIZARD_VARIABLE: 'expert_variable',
1421 SN_WORKFLOW: 'wf_workflow',
1422 SN_WORKFLOW_ACTIVITY: 'wf_activity',
1423 SN_WORKFLOW_ACTIVITY_DEFINITION: 'wf_activity_definition',
1424 SN_WORKFLOW_ACTIVITY_VARIABLE: 'wf_activity_variable',
1425 SN_WORKFLOW_CONDITION: 'wf_condition',
1426 SN_WORKFLOW_STAGE: 'wf_stage',
1427 SN_WORKFLOW_TRANSITION: 'wf_transition',
1428 SN_WORKFLOW_VERSION: 'wf_workflow_version',
1429 SN_TRANSFORM_MAP: 'sys_transform_map'
1430};
1431
1432SaraCommon.AUDIT = {
1433 APPROVAL_HISTORY: 'SNSC_SN_APPROVAL_HISTORY',
1434 APPROVAL_TIMESTAMP: 'SNSC_SN_APPROVAL_TIMESTAMP',
1435 ORDER_ID : 'SNSC_SN_ORDER_ID',
1436 ORDER_NAME: 'SNSC_SN_ORDER_NAME',
1437 ORDER_TIMESTAMP: 'SNSC_SN_ORDER_TIMESTAMP'
1438};
1439]]></script>
1440 <description>This class is comprised of global parameters in SARA connector. It shouldn't be instantiated and fields will be accessed in static-like fashion (think Java), eg.: SaraCommon.username</description>
1441 <active>true</active>
1442 <client_callable>false</client_callable>
1443 <access>public</access>
1444 </script_include>
1445
1446 <script_include>
1447 <name>SaraConfig</name>
1448 <script><![CDATA[/**
1449 * Helper class provides convenient methods to work with SNSC configuration table
1450 */
1451var SaraConfig = Class.create();
1452SaraConfig.prototype = {
1453 initialize: function () {
1454 this.glideHelper = new SaraGlideHelper();
1455
1456 this.DEFAULT_CONFIG_VALUES = {};
1457 this.DEFAULT_CONFIG_VALUES[SaraCommon.CONFIG_NAME.CLIENT_ID] = 'AESYSTEMNAME/1/SERVICE_NOW';
1458 this.DEFAULT_CONFIG_VALUES[SaraCommon.CONFIG_NAME.CLIENT_SECRET] = 'AES_12345';
1459 this.DEFAULT_CONFIG_VALUES[SaraCommon.CONFIG_NAME.TECHNICAL_USER] = 'TECHNICAL_USER';
1460 this.DEFAULT_CONFIG_VALUES[SaraCommon.CONFIG_NAME.SAPI_ENDPOINT] = 'https://mysapihost/';
1461 this.DEFAULT_CONFIG_VALUES[SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT] = 'https://oauthhost/oauth2/token';
1462 this.DEFAULT_CONFIG_VALUES[SaraCommon.CONFIG_NAME.AUTH_ENDPOINT] = 'https://oauthhost/oauth2/auth';
1463 },
1464
1465 /**
1466 * Store SARA OAuth client configuration to System Properties
1467 * @param {object} config The configuration of OAuth Client
1468 * - @key {String} SaraCommon.CONFIG_NAME.CLIENT_ID Identity of OAuth client
1469 * - @key {String} SaraCommon.CONFIG_NAME.CLIENT_SECRET OAuth client secret string
1470 * - @key {String} SaraCommon.CONFIG_NAME.TECHNICAL_USER Technical user
1471 * - @key {String} SaraCommon.CONFIG_NAME.SAPI_ENDPOINT URL to SAPI root endpoint
1472 * - @key {String} SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT Endpoint for token requesting/refreshing
1473 * - @key {String} SaraCommon.CONFIG_NAME.AUTH_ENDPOINT Authorization endpoint for OAuth authentication
1474 */
1475 storeClientConfig: function (config) {
1476 if (!gs.hasRole(SaraCommon.ROLES.ADMIN)) {
1477 var message = 'You dont\'t have sufficient permission to do this action. Allowed role: ' + SaraCommon.ROLES.ADMIN;
1478 throw new Error(message);
1479 }
1480 // Clean the old config before storing new one
1481 this.glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_CONFIG, {}, true);
1482
1483 var configData = {};
1484
1485 for (var key in config) {
1486 configData['u_' + key] = config[key];
1487 }
1488
1489 // Store new config
1490 this.glideHelper.persistData(SaraCommon.TABLE_NAME.SARA_CONFIG, configData);
1491 },
1492
1493 /**
1494 * Get the object contains SARA client configuration in following order: Client ID, Client Secret, Technical User,
1495 * SAPI Endpoint, Token Endpoint, Authorization Endpoint
1496 * @return {Object}
1497 */
1498 getClientConfig: function () {
1499 var saraConfig = this.glideHelper.getData(SaraCommon.TABLE_NAME.SARA_CONFIG, {}, true)[0];
1500 var configData = {};
1501
1502 if (saraConfig) {
1503 for (var key in SaraCommon.CONFIG_NAME) {
1504 var name = SaraCommon.CONFIG_NAME[key];
1505
1506 configData[name] = saraConfig['u_' + name];
1507 }
1508 } else {
1509 configData = this.DEFAULT_CONFIG_VALUES;
1510 }
1511
1512 return configData;
1513 },
1514
1515 /**
1516 * Get base bath of SAPI endpoint
1517 * @return {String}
1518 */
1519 getBasePath: function () {
1520 var configData = this.getClientConfig();
1521
1522 return configData[SaraCommon.CONFIG_NAME.SAPI_ENDPOINT];
1523 },
1524
1525 /**
1526 * Get technical user name
1527 * @param {String}
1528 */
1529 getTechnicalUser: function () {
1530 var configData = this.getClientConfig();
1531
1532 return configData[SaraCommon.CONFIG_NAME.TECHNICAL_USER];
1533 },
1534
1535 type: 'SaraConfig'
1536};
1537]]></script>
1538 <description>Helper class provides convenient methods to work with SNSC configuration table</description>
1539 <active>true</active>
1540 <client_callable>false</client_callable>
1541 <access>public</access>
1542 </script_include>
1543 <script_include>
1544 <name>SaraConsumerImportSet</name>
1545 <script><![CDATA[/**
1546 * Sara consumer class to discover all SAPI catalogs, services and import them into SN as the corresponding catalog categories and items
1547 */
1548var SaraConsumerImportSet = Class.create();
1549SaraConsumerImportSet.prototype = {
1550 initialize: function (tracker) {
1551 if (tracker !== null && tracker !== undefined) {
1552 this.tracker = tracker;
1553 }
1554
1555 // initialize dependencies
1556 var midServer = SaraUtils.getMIDServer();
1557 this.restClient = new SaraRESTClient();
1558 this.restClient.setMIDServer(midServer);
1559
1560 this.username = new SaraConfig().getTechnicalUser();
1561
1562 // inject restClient to the OAuth client instance
1563 this.oauthClient = new SaraOAuthClient(this.restClient);
1564 this.tokens = this.oauthClient.getUserTokens(this.username);
1565
1566 // inject glideHelper
1567 this.glideHelper = new SaraGlideHelper();
1568
1569 this.dal = new SaraConsumerDAL();
1570
1571 this.LOGGER = new SaraLog(this);
1572
1573 /**
1574 * Object store catalogs data of SAPI after discovering
1575 * @structure:
1576 * {
1577 * @{catalogName}: @{SaraModel.CatalogCategory},
1578 * ...
1579 * }
1580 */
1581 this.catalogsData = {};
1582
1583 /**
1584 * Object store services data of SAPI after discovering
1585 * @structure:
1586 * {
1587 * @{catalogName}: {
1588 * @{serviceName}: @{SaraModel.CatalogItem},
1589 * ...
1590 * },
1591 * ...
1592 * }
1593 */
1594 this.servicesData = {};
1595
1596 // Object store catalogs and services number after discovering
1597 this.countData = {
1598 catalogsCount: 0,
1599 servicesCount: 0
1600 };
1601
1602 this.statusCode = '';
1603 this.errorMessage = '';
1604 this.errorUrl = '';
1605 },
1606
1607 /**
1608 * Discover then import the data
1609 * @param {String} targetId The id of category which services will be imported in
1610 * @return {String} The log message
1611 */
1612 discoverAndImport: function (targetId) {
1613 var LOGGER = this.LOGGER;
1614 var response = this.discover();
1615 var message = '';
1616
1617 if (response.error) {
1618 LOGGER.info('Discover data from SAPI not successfully!');
1619 return null;
1620 } else {
1621 message += SaraUtils.formatString('Imported {0} catalog(s) and {1} service(s)!', this.countData.catalogsCount, this.countData.servicesCount);
1622 gs.info("this.catalogsData = " + SaraJSON.stringify(this.catalogsData));
1623 gs.info("this.servicesData = " + SaraJSON.stringify(this.servicesData));
1624
1625 this.doImport(targetId);
1626
1627 return message;
1628 }
1629 },
1630
1631 /**
1632 * Discover SAPI consumer URL, create corresponding list of Catalog Category and Catalog Item
1633 * @return {Object}
1634 * - @key {Boolean} error
1635 * - @key {Object} response
1636 */
1637 discover: function () {
1638 var LOGGER = this.LOGGER;
1639
1640 LOGGER.info('Starting discover...');
1641
1642 // Check permission before do any discover
1643 var checkData = this.checkPermission();
1644 if (checkData.error) {
1645 this.statusCode = 0;
1646 this.errorMessage = checkData.error;
1647 LOGGER.error(checkData.error);
1648 LOGGER.info('Ended discover!');
1649
1650 return checkData;
1651 }
1652
1653 // Log configuration
1654 var configData = new SaraConfig().getClientConfig();
1655 LOGGER.info('OAuth Configuration:\n' +
1656 ' - Client ID = {0}, \n' +
1657 ' - Client Secret = ***, \n' +
1658 ' - Technical User = {1}, \n' +
1659 ' - SAPI Endpoint = {2}, \n' +
1660 ' - Token Endpoint = {3}, \n' +
1661 ' - Authorization Endpoint = {4}, \n' +
1662 ' - MID Server = {5}',
1663 configData[SaraCommon.CONFIG_NAME.CLIENT_ID],
1664 configData[SaraCommon.CONFIG_NAME.TECHNICAL_USER],
1665 configData[SaraCommon.CONFIG_NAME.SAPI_ENDPOINT],
1666 configData[SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT],
1667 configData[SaraCommon.CONFIG_NAME.AUTH_ENDPOINT],
1668 SaraUtils.getMIDServer()
1669 );
1670
1671 /* ================================================================================================
1672 * Discover root
1673 * ================================================================================================ */
1674 this.logMessage('Discovering SAPI root...');
1675
1676 var rootData = this.discoverRoot();
1677
1678 // Set percent of progress
1679 this.incrementPercent(5);
1680
1681 if (rootData.error) {
1682 LOGGER.info('Ended discover!');
1683 return rootData;
1684 }
1685
1686 var message = "";
1687 rootData = rootData.jsonData;
1688 if (!rootData._links || !rootData._links.catalogs[0]) {
1689 message = 'No catalog consumer URL found, skip discover!';
1690 this.errorMessage = message;
1691 LOGGER.error(message);
1692 LOGGER.info('Ended discover!');
1693
1694 return rootData;
1695 }
1696 LOGGER.info('Found SAPI Catalogs url: {0}', rootData._links.catalogs[0].href);
1697
1698
1699 /* ================================================================================================
1700 * Discover catalogs
1701 * ================================================================================================ */
1702 this.logMessage('Discovering catalogs...');
1703
1704 var catalogsData = this.discoverCatalogs(rootData._links.catalogs[0].href);
1705
1706 // Set percent of progress
1707 this.incrementPercent(5);
1708
1709 if (catalogsData.error) {
1710 LOGGER.info('Ended discover!');
1711 return catalogsData;
1712 }
1713
1714 catalogsData = catalogsData.jsonData;
1715 if (!catalogsData._links || !catalogsData._links.catalog || !catalogsData._links.catalog[0]) {
1716 message = 'No SAPI catalog found, skip discover!';
1717 this.errorMessage = message;
1718 LOGGER.error(message);
1719 LOGGER.info('Ended discover!');
1720
1721 return catalogsData;
1722 }
1723
1724 /* ================================================================================================
1725 * Discover services
1726 * ================================================================================================ */
1727 var totalCatalogs = this.countData.catalogsCount;
1728 this.percentPerCatalog = 40 / totalCatalogs;
1729
1730 for (var i in catalogsData._links.catalog) {
1731 var catalog = catalogsData._links.catalog[i];
1732 var catalogTitle = catalog.title || catalog.href.replace(/^.*\/(.*)$/, '$1');
1733
1734 this.logMessage('Discovering services of "{0}" catalog...', catalogTitle);
1735
1736 // Set limit for catalogUrl
1737 var catalogUrl = this.getLimitLink(catalog.href, 'services');
1738 var servicesData = this.discoverServices(catalogUrl, catalogTitle, true);
1739
1740 // Set percent of progress
1741 this.incrementPercent(this.percentPerCatalog);
1742
1743 if (servicesData && servicesData.error) {
1744 LOGGER.info('Ended discover!');
1745 return servicesData;
1746 }
1747 }
1748
1749 LOGGER.info('Ended discover!');
1750 return {
1751 error: false
1752 };
1753 },
1754
1755 /**
1756 * Discover root url of SAPI
1757 * @return {Object}
1758 * - @key {Boolean} error
1759 * - @key {Object} response
1760 * - @key {Object} jsonData
1761 */
1762 discoverRoot: function () {
1763 var LOGGER = this.LOGGER;
1764
1765 LOGGER.info('Starting discoverRoot...');
1766
1767 // Make request
1768 var response = this.makeSAPIRequest('/');
1769
1770 if (response.error) {
1771 LOGGER.error(response.error);
1772 LOGGER.info('Ended discoverRoot!');
1773
1774 return response;
1775 }
1776
1777 LOGGER.info('Ended discoverRoot!');
1778 return response;
1779 },
1780
1781 /**
1782 * Discover catalogs url of SAPI
1783 * @param {String} catalogsUrl
1784 * @return {Object}
1785 * - @key {Boolean} error
1786 * - @key {Object} response
1787 * - @key {Object} jsonData
1788 */
1789 discoverCatalogs: function (catalogsUrl) {
1790 var LOGGER = this.LOGGER;
1791
1792 LOGGER.info('Starting discoverCatalogs...');
1793
1794 // Set limit for catalogsUrl
1795 catalogsUrl = this.getLimitLink(catalogsUrl, 'catalog');
1796
1797 // Make request
1798 var response = this.makeSAPIRequest(catalogsUrl);
1799
1800 if (response.error) {
1801 LOGGER.error(response.error);
1802 LOGGER.info('Ended discoverCatalogs!');
1803
1804 return response;
1805 }
1806
1807 var jsonData = response.jsonData;
1808 this.countData.catalogsCount = jsonData.count;
1809 LOGGER.info('Found {0} SAPI Catalogs, start discover each catalog.', jsonData.count);
1810 LOGGER.info('Ended discoverCatalogs!');
1811
1812 return response;
1813 },
1814
1815
1816
1817 /**
1818 * Discover services from catalog url of SAPI
1819 * @param {String} catalogUrl
1820 * @param {String} catalogTitle
1821 * @param {Boolean} firstTime
1822 * @return {Object}
1823 * - @key {Boolean} error
1824 * - @key {Object} response
1825 * - @key {Object} jsonData
1826 */
1827 discoverServices: function (catalogUrl, catalogTitle, firstTime) {
1828 var LOGGER = this.LOGGER;
1829
1830 var name = catalogUrl.replace(/^.*\/(.*)$/, '$1');
1831 LOGGER.info('Found catalog "{0}" : {1}', name, catalogUrl);
1832
1833 LOGGER.info('Starting discoverServices...');
1834 // Add 'embed=service' flag for getting information of services inside catalog
1835 catalogUrl += '&embed=service';
1836
1837 // Make request
1838 var response = this.makeSAPIRequest(catalogUrl, true);
1839 if (response.error) {
1840 LOGGER.error(response.error);
1841 LOGGER.info('Ended discoverServices!');
1842
1843 return response;
1844 }
1845
1846 // Handle response from SAPI
1847 var catalogData = response.jsonData;
1848 var catalogName = catalogData.name;
1849
1850 // This jsonData will be used for generating hash
1851 var hashData = response.jsonData2;
1852
1853 // Do this stuff when first discover
1854 if (firstTime) {
1855 // Reference catalog object of SNSC
1856 var catalogCategory = new SaraModel.CatalogCategory();
1857 catalogCategory.setTitle(catalogTitle);
1858 catalogCategory.setName(catalogName);
1859 catalogCategory.setParent('');
1860 catalogCategory.setActive(true);
1861 catalogCategory.setDescription(catalogData.shortDescription);
1862
1863 // Push catalog object to catalogsData and countData
1864 LOGGER.info('Push catalog object to catalogsData and countData');
1865 this.catalogsData[catalogName] = catalogCategory;
1866 this.servicesData[catalogName] = {};
1867 this.countData.servicesCount += catalogData.count;
1868 }
1869
1870 var servicesData = this.getEmbeddedService(catalogData);
1871
1872 // Handle services data in '_embedded' resource
1873 if (servicesData) {
1874 var servicesLink = catalogData._links.service;
1875 var SERVICE_ACTIVE = SaraUtils.getSaraProperty(SaraCommon.SYSTEM_PROPERTY_NAME.SERVICE_ACTIVE) === 'true';
1876
1877 LOGGER.info('Found {0} service(s) of {1} at "{2}"', servicesData.length, catalogName, catalogUrl);
1878
1879 for (var i = 0; i < servicesData.length; i++) {
1880 var service = servicesData[i];
1881 var serviceTitle = servicesLink[i].title || servicesLink[i].href.replace(/^.*\/(.*)$/, '$1');
1882 var isActive = SERVICE_ACTIVE && service.active;
1883
1884 // Reference service object of SNSC
1885 var catalogItem = new SaraModel.CatalogItem();
1886 catalogItem.setName(serviceTitle || service.name);
1887 catalogItem.setActive(isActive);
1888 catalogItem.setWorkflow('Sara Service');
1889 catalogItem.setShortDesc(service.shortDescription);
1890 catalogItem.setDescription(SaraUtils.nl2br(service.description));
1891 catalogItem.setServiceName(service.name);
1892 catalogItem.setConsumeUrl(service._links.consume[0].href);
1893 catalogItem.setCustomCart(SaraCommon.CUSTOM_CART_NAME);
1894
1895 // Generate hash of catalogItem without 'range'
1896 var serviceData = this.getEmbeddedService(hashData, i);
1897 this.injectFieldOrders(serviceData);
1898 var hash = this.generateCatalogItemHash(serviceData);
1899 catalogItem.setHash(hash);
1900
1901 // Handle variables
1902 this.injectFieldOrders(service);
1903 var variables = [];
1904 for (var index in service.forms) {
1905 var form = service.forms[index];
1906
1907 var fields = form.fields;
1908 for (var index2 in fields) {
1909 var field = fields[index2];
1910 var variable = SaraUtils.createCatalogVariable(field);
1911 variables.push(variable);
1912 }
1913 }
1914 catalogItem.setVariables(variables);
1915
1916 // Push service object to servicesData
1917 this.servicesData[catalogName][service.name] = catalogItem;
1918 }
1919 } else {
1920 LOGGER.info('No services found in catalog (name = {0})', catalogName);
1921 }
1922
1923 LOGGER.info('Ended discoverServices!');
1924
1925 // Check the next page
1926 if (catalogData._links.next) {
1927 var nextUrl = catalogData._links.next[0].href;
1928 this.discoverServices(nextUrl, catalogTitle);
1929 }
1930 },
1931
1932 /**
1933 * Get embedded services from catalogData
1934 * @param {Object} catalogData
1935 * @return {Array<Object>|Null}
1936 */
1937 getEmbeddedService: function (catalogData, index) {
1938 if (catalogData._embedded && catalogData._embedded.service && catalogData._embedded.service[0]) {
1939 if (index !== undefined) {
1940 return catalogData._embedded.service[index];
1941 } else {
1942 return catalogData._embedded.service;
1943 }
1944 } else {
1945 return null;
1946 }
1947 },
1948
1949 /**
1950 * Import catalogs and services after discovering by using 'catalogsData' and 'servicesData'
1951 * @param {String} targetId The id of category which services will be imported in
1952 */
1953 doImport: function (targetId) {
1954 var LOGGER = this.LOGGER;
1955
1956 LOGGER.info('Starting doImport...');
1957
1958 if (this.countData.catalogsCount !== 0) {
1959 this.cleanupStagingTables();
1960
1961 this.logMessage('Importing {0} catalog(s)...', this.countData.catalogsCount);
1962 // If there's no target category specified, all catalogs will be imported as new ones in category named 'Automic Services'
1963 if (!targetId) {
1964 LOGGER.info('There is no target category, will import catalogs into default category (name = "{0}")', this.dal.getDefaultCategoryName());
1965 targetId = this.dal.getDefaultCategoryId();
1966 } else {
1967 LOGGER.info('Target category = "{0}" ...', targetId);
1968 }
1969
1970 this.importCategory(targetId);
1971
1972 if (this.countData.servicesCount !== 0) {
1973 this.logMessage('Importing {0} service(s)...', this.countData.servicesCount);
1974 this.importItem();
1975 } else {
1976 this.incrementPercent(25);
1977 LOGGER.info('There are no service be imported!');
1978 }
1979 } else {
1980 this.incrementPercent(50);
1981 LOGGER.info('There are no catalog be imported!');
1982 }
1983
1984 // Make sure that progress always is 100% when completed
1985 this.incrementPercent(100);
1986
1987 LOGGER.info('Ended doImport!');
1988 },
1989
1990 /**
1991 * Import catalog category by using 'catalogsData'
1992 * @param {String} targetCatId Target category id
1993 */
1994 importCategory: function (targetCatId) {
1995 var glideHelper = this.glideHelper;
1996 var LOGGER = this.LOGGER;
1997 var dal = this.dal;
1998
1999 LOGGER.info('Starting importCategory to category: ' + targetCatId);
2000
2001 var targetCategory = glideHelper.getData(SaraCommon.TABLE_NAME.SN_CATEGORY, {sys_id: targetCatId});
2002 if(!targetCategory) {
2003 throw "Target category not found " + targetCatId;
2004 }
2005
2006 var catalogId = targetCategory.sc_catalog;
2007 if(!catalogId) {
2008 catalogId = dal.getDefaultCatalogId();
2009 }
2010
2011 // Save target category id into SaraCommon.TABLE_NAME.SARA_DEFINITION table
2012 dal.saveRootImportCategoryToSaraDefinition(targetCatId);
2013
2014 // Get name of all catalogs in AE
2015 var catalogNames = [];
2016 for (var catalogName in this.catalogsData) {
2017 catalogNames.push(catalogName);
2018 }
2019 LOGGER.info('Catalogs in AE: {0}', catalogNames.join(', '));
2020
2021 this.syncSaraDefinitionCategories(targetCatId, catalogNames);
2022
2023 // Set percent of progress
2024 this.incrementPercent(5);
2025
2026 // Otherwise, check if there's same name category existing under target category
2027 for (catalogName in this.catalogsData) {
2028 var sapiCatalog = this.catalogsData[catalogName];
2029 sapiCatalog.setParent(targetCatId);
2030 this.logMessage('Importing SARA Catalog {0}', catalogName);
2031 LOGGER.info('Catalog {0}: {1}', catalogName, SaraJSON.stringify(sapiCatalog));
2032
2033 var categoryId;
2034
2035 // Check if there's same name category existing under target category
2036 var existingDefinition = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {
2037 'u_name': sapiCatalog.name,
2038 'u_parent': targetCatId,
2039 'u_type': 'catalog',
2040 'u_active': true
2041 });
2042
2043 if (existingDefinition) {
2044 LOGGER.info("existing category found {0}, update...", SaraJSON.stringify(existingDefinition));
2045
2046 categoryId = existingDefinition.u_service_catalog_category;
2047 var category = this.glideHelper.getData(SaraCommon.TABLE_NAME.SN_CATEGORY, {sys_id: categoryId});
2048 category.title = sapiCatalog.title;
2049 category.description = sapiCatalog.description;
2050 category.active = true;
2051 category.parent = targetCatId;
2052 dal.saveOrUpdateCategory(category);
2053
2054 sapiCatalog.setAsNew(false);
2055 sapiCatalog.setSysId(categoryId);
2056 sapiCatalog.setSNCatalog(category.sc_catalog);
2057 }
2058 else {
2059 LOGGER.info("existing category not found, creating...");
2060
2061 sapiCatalog.setAsNew(true);
2062 sapiCatalog.setSNCatalog(catalogId);
2063 definition = dal.saveCategoryToSaraDefinition(sapiCatalog);
2064 sapiCatalog.setSysId(definition.u_service_catalog_category);
2065 }
2066
2067 // Set percent of progress
2068 this.incrementPercent(this.percentPerCatalog);
2069 }
2070
2071 dal.refreshCategory(targetCatId);
2072
2073 LOGGER.info('Ended importCategory!');
2074 },
2075
2076 syncSaraDefinitionCategories: function(targetCatId, catalogNames) {
2077 var LOGGER = this.LOGGER;
2078 var dal = this.dal;
2079 // Get existed catalogs in SNSC
2080 var existedSaraCatalogs = this.glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {
2081 'u_parent': targetCatId,
2082 'u_type': 'catalog'
2083 }, true);
2084
2085 if (existedSaraCatalogs.length > 0) {
2086 this.LOGGER.info('Detecting the existed catalog in SNSC which doesn\'t exist anymore in AE');
2087
2088 // Remove the existed catalog in SNSC which doesn't exist anymore in AE
2089 for (var i = 0; i < existedSaraCatalogs.length; i++) {
2090 var existCatalog = existedSaraCatalogs[i];
2091 if (!SaraUtils.inArray(catalogNames, existCatalog.u_name)) {
2092 LOGGER.info('Catalog with name = {0} doesn\'t exist anymore in AE', existCatalog.u_name);
2093 dal.deactivateSaraDefinition(existCatalog);
2094 }
2095 }
2096 }
2097 },
2098
2099 /**
2100 * Import catalog item by using 'servicesData' property
2101 */
2102 importItem: function () {
2103 var LOGGER = this.LOGGER;
2104 var glideHelper = this.glideHelper;
2105 var dal = this.dal;
2106
2107 LOGGER.info('Starting importItems...');
2108
2109 for (var categoryName in this.servicesData) {
2110 var isCatalogNew = this.catalogsData[categoryName].isNew();
2111 var sapiCatalog = this.catalogsData[categoryName];
2112 var categoryId = sapiCatalog.getSysId();
2113 LOGGER.info("Importing sapi service to category (name = {0}, sys_id = {1})", categoryName, categoryId);
2114
2115 var items = this.servicesData[categoryName];
2116 var itemNames = [];
2117
2118 // Get existed catalog items in AE
2119 for (var itemName in items) {
2120 itemNames.push(itemName);
2121 }
2122 LOGGER.info('{0} catalog items under category "{1}": {2}', itemNames.length, categoryName, itemNames.join(', '));
2123
2124 // Get existed catalog items in SNSC
2125 var existedItems = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {
2126 'u_parent': categoryId,
2127 'u_type': 'service',
2128 'u_active': true
2129 }, true);
2130
2131 var existDefinition;
2132 if (existedItems.length > 0) {
2133 var msg = 'Detecting the existed catalog item in SNSC which doesn\'t exist anymore in AE...';
2134 this.logMessage(msg);
2135 LOGGER.info(msg);
2136
2137 // Remove the existed catalog item in SNSC which doesn't exist anymore in AE
2138 for (var i = 0; i < existedItems.length; i++) {
2139 existDefinition = existedItems[i];
2140 if (!SaraUtils.inArray(itemNames, existDefinition.u_name)) {
2141 LOGGER.info('Catalog item (name = {0}, parent sys_id = {1}) doesn\'t exist anymore in AE', existDefinition.u_name, existDefinition.u_parent);
2142 dal.deactivateSaraDefinition(existDefinition);
2143 }
2144 }
2145 }
2146
2147 for (itemName in items) {
2148 var importMsg = "Importing sapi service " + itemName;
2149 this.logMessage(importMsg);
2150 LOGGER.info(importMsg);
2151 var sapiService = items[itemName];
2152 LOGGER.info("Set sapi service catalog to " + sapiCatalog.getSNCatalog());
2153 sapiService.setSNCatalog(sapiCatalog.getSNCatalog());
2154 // Set catalog category sys_id for item
2155 sapiService.setCategory(categoryId);
2156
2157 if (isCatalogNew) {
2158 dal.saveSapiService(sapiService);
2159 continue;
2160 }
2161
2162 // Check existing item with same name and same parent category id = item.category
2163 existDefinition = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {
2164 'u_name': sapiService.getServiceName(),
2165 'u_parent': sapiService.getCategory(),
2166 'u_type': 'service'
2167 });
2168
2169 if (existDefinition) {
2170 LOGGER.info("existing definition found. Set u_active to true");
2171 existDefinition.u_active = true;
2172 this.dal.saveOrUpdateSaraDefinition(existDefinition);
2173
2174 // Check hash of saraItem and item
2175 LOGGER.debug('New and old hash: {0} - {1}', sapiService.getHash(), existDefinition.u_hash);
2176
2177 if (sapiService.getHash() === existDefinition.u_hash) {
2178 LOGGER.info('Item (name = {0}) is not changed. Start sync lookup...', existDefinition.u_name);
2179 new SaraSync().syncLookup(existDefinition, sapiService);
2180 LOGGER.info("Sync lookup done");
2181 } else {
2182 LOGGER.info('Item (name = {0}) is changed. Update', existDefinition.u_name);
2183
2184 dal.updateSapiService(existDefinition, sapiService);
2185 }
2186 } else {
2187 // Insert new as normal
2188 dal.saveSapiService(sapiService);
2189 }
2190 }
2191
2192 // Set percent of progress
2193 this.incrementPercent(this.percentPerCatalog);
2194 }
2195
2196 LOGGER.info('Ended importItem!');
2197 },
2198
2199 cleanupStagingTables: function() {
2200 var glideHelper = this.glideHelper;
2201 var LOGGER = this.LOGGER;
2202 var dal = this.dal;
2203 LOGGER.info("Start cleanup staing tables...");
2204
2205 LOGGER.info("Cleanup table {0}", SaraCommon.TABLE_NAME.SN_CATALOG_IST);
2206 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_CATALOG_IST, {}, true);
2207
2208 LOGGER.info("Cleanup table {0}", SaraCommon.TABLE_NAME.SN_CATEGORY_IST);
2209 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_CATEGORY_IST, {}, true);
2210
2211 LOGGER.info("Cleanup table {0}", SaraCommon.TABLE_NAME.SARA_CAT_ITEM_IST);
2212 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_CAT_ITEM_IST, {}, true);
2213
2214 LOGGER.info("Cleanup table {0}", SaraCommon.TABLE_NAME.SN_VARIABLE_SET_IST);
2215 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_VARIABLE_SET_IST, {}, true);
2216
2217 LOGGER.info("Cleanup table {0}", SaraCommon.TABLE_NAME.SN_VARIABLE_SET_ITEM_IST);
2218 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_VARIABLE_SET_ITEM_IST, {}, true);
2219
2220 LOGGER.info("Cleanup table {0}", SaraCommon.TABLE_NAME.SARA_DEFINITION_IST);
2221 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION_IST, {}, true);
2222
2223 LOGGER.info("Cleanup table {0}", SaraCommon.TABLE_NAME.SARA_VARIABLE_IST);
2224 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_VARIABLE_IST, {}, true);
2225
2226 LOGGER.info("Cleanup table {0}", SaraCommon.TABLE_NAME.SARA_LOOKUP_IST);
2227 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_LOOKUP_IST, {}, true);
2228
2229 LOGGER.info("Done!");
2230 },
2231
2232 /**
2233 * Refresh 'catalogsData' and 'servicesData':
2234 * - unsetAsNew() for 'catalogsData' item
2235 * - unsetParent() for 'catalogsData' item
2236 * - unsetSysId() for 'catalogsData' item
2237 * - unsetCategory() for 'servicesData' item
2238 */
2239 refreshImportedData: function () {
2240 var LOGGER = this.LOGGER;
2241
2242 LOGGER.info('Starting refreshImportedData...');
2243
2244 for (var catalogName in this.catalogsData) {
2245 var catalogData = this.catalogsData[catalogName];
2246
2247 catalogData.unsetAsNew();
2248 catalogData.unsetParent();
2249 catalogData.unsetSysId();
2250 }
2251
2252 for (catalogName in this.servicesData) {
2253 var items = this.servicesData[catalogName];
2254
2255 for (var itemName in items) {
2256 var item = items[itemName];
2257
2258 item.unsetCategory();
2259 }
2260 }
2261 LOGGER.info('Ended refreshImportedData!');
2262 },
2263
2264 /**
2265 * Clean up 'catalogsData' and 'servicesData'
2266 */
2267 cleanData: function () {
2268 this.catalogsData = {};
2269 this.servicesData = {};
2270 },
2271
2272 getCatalogsData: function () {
2273 return this.catalogsData;
2274 },
2275
2276 getCatalogData: function (catalogName) {
2277 return this.catalogsData[catalogName];
2278 },
2279
2280 getServicesData: function (catalogName) {
2281 if (catalogName) {
2282 return this.servicesData[catalogName];
2283 } else {
2284 return this.servicesData;
2285 }
2286 },
2287
2288 getStatusCode: function () {
2289 return this.statusCode;
2290 },
2291
2292 getErrorMessage: function () {
2293 return this.errorMessage;
2294 },
2295
2296 //-----------------------------------------------------------------
2297 //Utility methods
2298 //-----------------------------------------------------------------
2299
2300
2301 /**
2302 * Get link with limit parametter of catalog or service
2303 * @param {String} link Origin link
2304 * @param {String} type can be catalog or service
2305 * @param {String}
2306 */
2307 getLimitLink: function (link, type) {
2308 var limitString = 'limit=';
2309 limitString += type === 'catalog' ? SaraCommon.CATALOGS_LIMIT : SaraCommon.SERVICES_LIMIT;
2310
2311 if (link.indexOf('?') !== -1) {
2312 limitString = '&' + limitString;
2313 } else {
2314 limitString = '?' + limitString;
2315 }
2316
2317 return link + limitString;
2318 },
2319
2320 /**
2321 * Private method to check user permission.
2322 * @return {Object}
2323 * - @key {String} error
2324 */
2325 checkPermission: function () {
2326 var LOGGER = this.LOGGER;
2327
2328 var message = "";
2329 if (!gs.hasRole(SaraCommon.ROLES.ADMIN)) {
2330 message = 'You dont\'t have sufficient permission to do this action. Allowed role: ' + SaraCommon.ROLES.ADMIN;
2331
2332 LOGGER.error(message);
2333
2334 return {
2335 error: message
2336 };
2337 }
2338
2339 // check user tokens
2340 if (!this.tokens) {
2341 message = SaraUtils.formatString('No tokens found for user {0}. Skip import!', this.username);
2342
2343 LOGGER.error(message);
2344
2345 return {
2346 error: message
2347 };
2348 }
2349
2350 LOGGER.info('Tokens found for user {0}', this.username);
2351
2352 if (!this.tokens[3]) {
2353 this.tokens[3] = 'bearer';
2354 }
2355
2356 return {
2357 error: false
2358 };
2359 },
2360
2361 /**
2362 * Make request to SAPI and check the response data
2363 * @param {String} url
2364 * @param {Boolean} returnJSONData2
2365 * @return {Object}
2366 * - @key {Boolean} error
2367 * - @key {Object} response
2368 * - @key {Object} jsonData
2369 */
2370 makeSAPIRequest: function (url, returnJSONData2) {
2371 var LOGGER = this.LOGGER;
2372
2373 // Make request
2374 this.tokens = this.oauthClient.getUserTokens(this.username);
2375 var requestUrl = SaraUtils.buildUrl(url);
2376 var request = this.restClient.newSAPIRequest('get', requestUrl);
2377 request.addHeader('Authorization', this.tokens[3] + ' ' + this.tokens[0]);
2378
2379 // Get response
2380 var response = this.restClient.executeWithRefreshToken(request);
2381 var responseObject = response.getResponseObject();
2382
2383 if (response.haveError()) {
2384 this.statusCode = responseObject.statusCode;
2385 this.errorMessage = responseObject.errorMessage;
2386 this.errorUrl = url;
2387
2388 return {
2389 error: true,
2390 response: response
2391 };
2392 }
2393
2394 var result = {
2395 error: false,
2396 response: response,
2397 jsonData: responseObject.bodyObject
2398 };
2399
2400 if (returnJSONData2) {
2401 var jsonData2 = response.getBodyObject();
2402 result.jsonData2 = jsonData2;
2403 }
2404
2405 return result;
2406 },
2407
2408 /**
2409 * Increment specific percent more for tracker if have
2410 * @param {Number} percent
2411 */
2412 incrementPercent: function (percent) {
2413 var LOGGER = this.LOGGER;
2414 try {
2415 var canIncrease = (typeof this.tracker !== 'undefined') && (typeof this.tracker.incrementPercentComplete !== 'undefined');
2416
2417 if (canIncrease) {
2418 this.tracker.incrementPercentComplete(percent);
2419 }
2420 }
2421 catch(err) {
2422 LOGGER.debug("Cannot increase tracker: {0}", err);
2423 }
2424 },
2425
2426 /**
2427 * Log message for tracker can show what is happening inside of SaraConsumerImportSet when importing services.
2428 * You can format message like SaraUtils.formatString method
2429 */
2430 logMessage: function () {
2431 var LOGGER = this.LOGGER;
2432
2433 if ((typeof this.tracker !== 'undefined') && (typeof this.tracker.updateResult !== 'undefined')) {
2434 var message = SaraUtils.formatString.apply(this, arguments);
2435 try {
2436 this.tracker.updateResult({
2437 msg: message
2438 });
2439 } catch (e) {
2440 LOGGER.debug('Cannot log message for tracker: {0}', e);
2441 }
2442 }
2443 },
2444
2445 /**
2446 * Generate hash string of catalogItem. The hash will be generated from 'form' property
2447 * of catalogItem without 'range' property
2448 * @param {SaraModel.CatalogItem} catalogItemData
2449 * @return {String} hash
2450 */
2451 generateCatalogItemHash: function (catalogItemData) {
2452 for (var index in catalogItemData.forms) {
2453 var form = catalogItemData.forms[index];
2454 var fields = form.fields;
2455 for (var index2 in fields) {
2456 delete fields[index2].range;
2457 }
2458 }
2459 var serviceDataStr = SaraJSON.stringify(catalogItemData);
2460 this.LOGGER.info("Calculate hash for catalogItemData: " + serviceDataStr);
2461 var hash = SaraUtils.md5(serviceDataStr);
2462
2463 return hash;
2464 },
2465
2466 injectFieldOrders: function (catalogItemData) {
2467 var count = 0;
2468 for (var index in catalogItemData.forms) {
2469 var form = catalogItemData.forms[index];
2470
2471 var fields = form.fields;
2472 for (var index2 in fields) {
2473 fields[index2].order = count * 100;
2474 count++;
2475 }
2476 }
2477 },
2478
2479 type: 'SaraConsumerImportSet'
2480};
2481]]></script>
2482 <description>SaraConsumerImportSet class to discover all SAPI catalogs, services and import them into SN as the corresponding catalog categories and items using staging tables</description>
2483 <active>true</active>
2484 <client_callable>false</client_callable>
2485 <access>public</access>
2486 </script_include>
2487
2488 <script_include>
2489 <name>SaraConsumerDAL</name>
2490 <script><![CDATA[/**
2491 * Service Catalog Generator to import service definition to Service Catalog
2492 */
2493var SaraConsumerDAL = Class.create();
2494SaraConsumerDAL.prototype = {
2495 initialize: function () {
2496 this.glideHelper = new SaraGlideHelper();
2497 this.LOGGER = new SaraLog(this);
2498 this.TABLES = SaraCommon.TABLE_NAME;
2499 this.typeMaps = this.getTypeMaps();
2500 },
2501
2502 //---------------------------
2503 //Catalog
2504 //---------------------------
2505 getCatalog: function(title) {
2506 return this.glideHelper.getData(this.TABLES.SN_CATALOG, {
2507 'title': title
2508 });
2509 },
2510
2511 /**
2512 * param catalog:
2513 * id: optional - coalesce. sys_id will be transformed to id if presented
2514 * title: required
2515 * description: optional
2516 * active: required
2517 */
2518 saveOrUpdateCatalog: function(catalog) {
2519 SaraUtils.guardNotNullOrEmpty(catalog, "catalog must not be null or empty");
2520 SaraUtils.guardNotNullOrEmpty(catalog.title, "catalog title must not be null or empty");
2521
2522 this.saveOrUpdateEntity(catalog, "catalog");
2523
2524 var result = this.getCatalog(catalog.title);
2525 SaraUtils.guardNotNullOrEmpty(result, "Failed to save or update catalog " + catalog.title);
2526 return result;
2527 },
2528
2529 /**
2530 * Get catalog SaraCommon.DEFAULT_CATALOG, if save or update fail then fall back to SaraCommon.DEFAULT_AUTOMIC_CATALOG
2531 */
2532 getDefaultCatalogId: function() {
2533 if(this._defaultCatalogId) {
2534 return this._defaultCatalogId;
2535 }
2536 var catalog = this.getCatalog(SaraCommon.DEFAULT_CATALOG);
2537 var serviceCatalogId = catalog === undefined ? undefined : catalog.sys_id;
2538
2539 if (!serviceCatalogId) {
2540 // get the first catalog
2541 serviceCatalogId = this.glideHelper.getSysId(this.TABLES.SN_CATALOG);
2542
2543 // if there's no catalog, create a new one
2544 if (!serviceCatalogId) {
2545
2546 serviceCatalogId = this.saveOrUpdateCatalog({
2547 title: SaraCommon.DEFAULT_AUTOMIC_CATALOG,
2548 description: SaraCommon.DEFAULT_AUTOMIC_CATALOG,
2549 active: true
2550 }).sys_id;
2551 this.LOGGER.info("New catalog '" + SaraCommon.DEFAULT_AUTOMIC_CATALOG + "' was created");
2552 }
2553 }
2554 this._defaultCatalogId = serviceCatalogId;
2555
2556 return serviceCatalogId;
2557 },
2558
2559
2560 //---------------------------
2561 //Category
2562 //---------------------------
2563 getCategory: function(catalogId, title, parent) {
2564 var query = {title:title};
2565 if(catalogId) {
2566 query.sc_catalog = catalogId;
2567 }
2568 if(parent) {
2569 query.parent = parent;
2570 }
2571 return this.glideHelper.getData(this.TABLES.SN_CATEGORY, query);
2572 },
2573
2574 /**
2575 * param category:
2576 * id: optional. Blank for insert
2577 * sc_catalog: required
2578 * title: required
2579 * homepage_renderer: optinal
2580 * active: optional
2581 * description: optional
2582 * parent: optional
2583
2584 */
2585 saveOrUpdateCategory: function (category) {
2586 SaraUtils.guardNotNullOrEmpty(category, "category must not be null or empty");
2587 SaraUtils.guardNotNullOrEmpty(category.title, "category.title must not be null or empty");
2588
2589 this.saveOrUpdateEntity(category, "category");
2590
2591 var result = this.getCategory(undefined, category.title, category.parent);
2592 gs.info("result = " + SaraJSON.stringify(result));
2593 SaraUtils.guardNotNullOrEmpty(result, "category is not save or updated correctly");
2594
2595 return result;
2596 },
2597
2598 getDefaultCategoryId: function () {
2599 var glideHelper = this.glideHelper;
2600 var LOGGER = this.LOGGER;
2601
2602 var catalogId = this.getDefaultCatalogId();
2603 var categoryName = this.getDefaultCategoryName();
2604
2605 LOGGER.info('Using catalog {0}', glideHelper.getData(this.TABLES.SN_CATALOG, {'sys_id': catalogId}).title);
2606
2607 var defaultCategory = this.getCategory(catalogId, categoryName);
2608 var sysId = defaultCategory === null ? undefined : defaultCategory.sys_id;
2609
2610 if (!sysId) {
2611 // create default Automic Service category
2612 LOGGER.info('DefaultCategory (name = {0}) doesn\'t exist', categoryName);
2613 sysId = this.saveOrUpdateCategory({
2614 sc_catalog: catalogId,
2615 title: categoryName,
2616 description: categoryName,
2617 active: true
2618 }).sys_id;
2619 }
2620 else {
2621 LOGGER.info('Using DefaultCategory (name = {0})', categoryName);
2622 }
2623
2624 return sysId;
2625 },
2626
2627 getDefaultCategoryName: function() {
2628 return SaraCommon.DEFAULT_CATEGORY;
2629 },
2630
2631 deactivateCategory: function(categoryId) {
2632 var glideHelper = this.glideHelper;
2633 var LOGGER = this.LOGGER;
2634 if(!SaraUtils.isNullOrEmpty(categoryId)) {
2635 // Deactive category in 'SaraCommon.TABLE_NAME.SN_CATEGORY' table
2636 LOGGER.info('Deactivating category (sys_id = {0}) in table "{1}"', categoryId, SaraCommon.TABLE_NAME.SN_CATEGORY);
2637 var category = glideHelper.getData(this.TABLES.SN_CATEGORY, {sys_id: categoryId});
2638 category.active = false;
2639 this.saveOrUpdateCategory(category);
2640 LOGGER.info('Deactivated category (sys_id = {0}) in table "{1}"', categoryId, SaraCommon.TABLE_NAME.SN_CATEGORY);
2641 }
2642 },
2643
2644 refreshCategory: function(categoryId) {
2645 var LOGGER = this.LOGGER;
2646
2647 LOGGER.info('Refreshing target category (sys_id = {0})', categoryId);
2648 var updateData = {
2649 id: categoryId,
2650 active: false
2651 };
2652
2653 this.saveOrUpdateEntity(updateData, "category");
2654 updateData.active = true;
2655 this.saveOrUpdateEntity(updateData, "category");
2656 },
2657
2658
2659 //--------------------------
2660 //Catalog Item
2661 //--------------------------
2662 getCatalogItem: function(categoryId, name) {
2663 return this.glideHelper.getData(this.TABLES.SN_CATALOG_ITEM, {category: categoryId, name: name});
2664 },
2665
2666 /**
2667 * param catItem
2668 * id: optional. Blank for insert
2669 * name: required
2670 * category: required
2671 * active:
2672 * short_description:
2673 * description:
2674 * custom_cart:
2675 * use_sc_layout:
2676 * no_quantity:
2677 */
2678 saveOrUpdateCatalogItem: function(catItem) {
2679 SaraUtils.guardNotNullOrEmpty(catItem, "catItem must not be null or empty");
2680 SaraUtils.guardNotNullOrEmpty(catItem.category, "category must not be null or empty");
2681 SaraUtils.guardNotNullOrEmpty(catItem.name, "name must not be null or empty");
2682
2683 this.saveOrUpdateEntity(catItem, "cat_item");
2684
2685 var result = this.getCatalogItem(catItem.category, catItem.name);
2686 SaraUtils.guardNotNullOrEmpty(result, "catalog item is not save or updated correctly");
2687
2688 return result;
2689 },
2690
2691 saveSapiService: function(sapiService) {
2692 var glideHelper = this.glideHelper;
2693 var LOGGER = this.LOGGER;
2694
2695 LOGGER.info("Start save sapi service " + sapiService.name);
2696 SaraUtils.guardNotNullOrEmpty(sapiService, "sapiService must not be null or empty");
2697
2698 // Workflow sys_id of catalogItem if has
2699 var workflowSysId;
2700 if (sapiService.getWorkflow()) {
2701 workflowSysId = glideHelper.getSysId(SaraCommon.TABLE_NAME.SN_WORKFLOW, {
2702 'name': sapiService.getWorkflow()
2703 });
2704
2705 if(workflowSysId === null) {
2706 var errorMsg = 'There is no Workflow with name '+ sapiService.getWorkflow();
2707 LOGGER.error(errorMsg);
2708 return;
2709 }
2710 } else {
2711 LOGGER.error('There is no Workflow for consuming catalog item. Saving sapi service is aborted!');
2712 return;
2713 }
2714
2715 // Custom cart sys_id of catalogItem if has
2716 var customCartSysId;
2717 if (sapiService.getCustomCart()) {
2718 customCartSysId = glideHelper.getSysId(SaraCommon.TABLE_NAME.SN_UI_MACRO, {
2719 'name': sapiService.getCustomCart()
2720 });
2721 }
2722
2723 //create catalog item
2724 var catalogItemId = this.saveOrUpdateCatalogItem({
2725 'name': sapiService.getName(),
2726 'category': sapiService.getCategory(),
2727 'active': sapiService.isActive(),
2728 'short_description': sapiService.getShortDesc(),
2729 'description': sapiService.getDescription(),
2730 'workflow': workflowSysId,
2731 'custom_cart': customCartSysId,
2732 'use_sc_layout': false,
2733 'no_quantity': true,
2734 'sc_catalogs': sapiService.getSNCatalog()
2735 }).sys_id;
2736
2737 var varSetId = this.saveSapiServiceVariableSet(sapiService, catalogItemId);
2738
2739 // Add new row to SaraCommon.TABLE_NAME.SARA_DEFINITION table, holding additional info. about this services like consume URL, links
2740 // and reference to the variable set that contains Sara fields
2741 var definitionId = this.saveOrUpdateSaraDefinition({
2742 'u_sc_item': catalogItemId,
2743 'u_name': sapiService.getServiceName(),
2744 'u_consume_url': sapiService.getConsumeUrl(),
2745 'u_var_set': varSetId,
2746 'u_parent': sapiService.getCategory(),
2747 'u_type': 'service',
2748 'u_hash': sapiService.getHash(),
2749 'u_is_deleted': false,
2750 'u_active': true
2751 }).sys_id;
2752
2753 LOGGER.info('Saved definition for sapi service (name = "{0}", service name = {1}, sys_id = {2}) in "{3}" table',
2754 sapiService.getName(), sapiService.getServiceName(), definitionId, SaraCommon.TABLE_NAME.SARA_DEFINITION);
2755 },
2756
2757 updateSapiService: function(existDefinition, sapiService) {
2758 var glideHelper = this.glideHelper;
2759 var LOGGER = this.LOGGER;
2760 LOGGER.info('Updating catalog item (name = "{0}", sys_id = {1})...', sapiService.getServiceName(), existDefinition.u_sc_item);
2761 SaraUtils.guardNotNullOrEmpty(existDefinition, "existDefinition must not be null or empty");
2762 SaraUtils.guardNotNullOrEmpty(sapiService, "sapiService must not be null or empty");
2763
2764 var varSetId = this.saveSapiServiceVariableSet(sapiService, existDefinition.u_sc_item);
2765 LOGGER.info('Updated definition with new variable set and hash (sys_id = {0}, varset = {1} hash {2}) for catalog item in "{3}" table...',
2766 existDefinition.sys_id, varSetId, sapiService.getHash(), this.TABLES.SARA_DEFINITION);
2767
2768 existDefinition.u_var_set = varSetId;
2769 existDefinition.u_hash = sapiService.getHash();
2770 this.saveOrUpdateSaraDefinition(existDefinition);
2771
2772 var catItem = glideHelper.getData(this.TABLES.SN_CATALOG_ITEM, {sys_id: existDefinition.u_sc_item});
2773 LOGGER.info("Update catalog item active state according to Sapi service");
2774 catItem.active = sapiService.isActive();
2775 this.saveOrUpdateCatalogItem(catItem);
2776 },
2777
2778 //---------------------------
2779 //Variables and Variables Set
2780 //---------------------------
2781 saveSapiServiceVariableSet: function(sapiService, catalogItemId) {
2782 var glideHelper = this.glideHelper;
2783 var LOGGER = this.LOGGER;
2784 var varSetId = null;
2785
2786 // Process catalog variables
2787 if (sapiService.variables.length > 0) {
2788 var varSetName = SaraUtils.formatString('VarSet_{0}_{1}', SaraUtils.getTimeStamp(), SaraUtils.getRandom());
2789
2790 LOGGER.info('Saving variable set (name = {0})...', varSetName);
2791 varSetId = this.saveOrUpdateVariableSet( {
2792 'name': varSetName,
2793 'description': SaraUtils.formatString('Variable Set containing all variables belong to "{0}" ({1}) catalog item', sapiService.getName(), sapiService.getServiceName()),
2794 'title': SaraUtils.formatString('{0} Variable Set', sapiService.getName()),
2795 'display_title': true
2796 }).sys_id;
2797
2798 LOGGER.info('Saved variable set (name = {0})', varSetName);
2799
2800 //get existing variable set item
2801 var varSetItem = glideHelper.getData(SaraCommon.TABLE_NAME.SN_VARIABLE_SET_ITEM, {
2802 'sc_cat_item': catalogItemId
2803 });
2804
2805 if(!varSetItem) {
2806 varSetItem = {};
2807 }
2808 else {
2809 var oldVarSetId = varSetItem.variable_set;
2810 if(oldVarSetId !== varSetId) {
2811 this.deactivateVarSet(oldVarSetId);
2812 }
2813 }
2814 varSetItem.sc_cat_item = catalogItemId;
2815 varSetItem.variable_set = varSetId;
2816 // Create relation between variable set and catalog item by adding a record to SaraCommon.TABLE_NAME.SN_VARIABLE_SET_ITEM table
2817 LOGGER.info('Creating relation between variable set catalog item');
2818 this.saveOrUpdateVariableSetItem(varSetItem);
2819 LOGGER.info('Created relation between variable set catalog item');
2820
2821 // Creating Sara client scripts
2822 this.createSaraClientScripts(varSetId);
2823
2824 // Creating Sara hidden variable
2825 this.createSaraHiddenVariable(varSetId);
2826
2827 // process each variable in the set
2828 LOGGER.info('Importing {0} variables for variable set named "{1}"...', sapiService.variables.length, varSetName);
2829 for (var i = 0; i < sapiService.variables.length ; i++) {
2830 var variable = sapiService.variables[i];
2831 this.saveSapiServiceVariable(variable, null, varSetId);
2832 }
2833 LOGGER.info('Imported {0} variables for variable set (name = {1}, sys_id = {2})', sapiService.variables.length, varSetName, varSetId);
2834 } else {
2835 LOGGER.warn('There\' no variable found in catalog item (name = {0}). Skip syncLookup!', sapiService.getName());
2836 }
2837
2838 return varSetId;
2839 },
2840
2841 deactivateVarSet: function(varSetId) {
2842 var glideHelper = this.glideHelper;
2843 var LOGGER = this.LOGGER;
2844 LOGGER.info("Deactivating Variable Set: " + varSetId);
2845 SaraUtils.guardNotNullOrEmpty(varSetId, "varSetId must not be null or empty");
2846 var saraVariables = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_VARIABLE, {
2847 variable_set: varSetId
2848 }, true);
2849
2850 for(var i = 0; i < saraVariables.length; i++) {
2851 var saraVariable = saraVariables[i];
2852 saraVariable.active = false;
2853 LOGGER.info("Deactivate Sara Variable");
2854 this.saveOrUpdateVariable(saraVariable);
2855 }
2856 LOGGER.info("Deactivated Variable Set");
2857 },
2858
2859 /**
2860 * Save variable
2861 * @param {SaraModel.CatalogVariable} variable
2862 * @param {String} catalogItemId
2863 * @param {String} varSetId
2864 * @param {Object} optionals
2865 * @return {String} sys_id of saved variable
2866 */
2867 saveSapiServiceVariable: function(variable, catalogItemId, varSetId, optionals) {
2868 var glideHelper = this.glideHelper;
2869 var LOGGER = this.LOGGER;
2870
2871 LOGGER.info('Saving variable (name = {0}, type = {1}, isLookup = {2})...', variable.getName(), variable.getType(), variable.isLookup());
2872
2873 var variableData = {
2874 'name': variable.getName(),
2875 'type': variable.getType(),
2876 'u_is_lookup': variable.isLookup(),
2877 'u_hash': variable.getHash(),
2878 'order': variable.getOrder()
2879 };
2880
2881 if (catalogItemId) {
2882 variableData.cat_item = catalogItemId;
2883 } else if (varSetId) {
2884 variableData.variable_set = varSetId;
2885 }
2886
2887 if (variable.getDescription()) {
2888 variableData.help_text = variable.getDescription();
2889 variableData.show_help = true;
2890 }
2891
2892 // Include '-- None --' option if type is 'LOOKUP_SELECT_BOX' and there's no defaultValue
2893 if (variable.getType() === SaraCommon.VAR_TYPE.LOOKUP_SELECT_BOX && (!variable.getDefaultValue() || !variable.getDefaultValue()[0])) {
2894 variableData.include_none = true;
2895 }
2896
2897 // Add default value if have and default value is not array
2898 if (variable.getDefaultValue() && variable.getDefaultValue().length === 1 && variable.getType() !== SaraCommon.VAR_TYPE.LIST_COLLECTOR) {
2899 variableData.default_value = variable.getDefaultValue()[0];
2900 }
2901
2902 variableData.question_text = variable.getLabel();
2903 variableData.mandatory = variable.isRequired();
2904
2905 if (optionals) {
2906 for (var prop in optionals) {
2907 variableData[prop] = optionals[prop];
2908 }
2909 }
2910
2911 // Additional fields for Sara
2912 variableData.u_name = variable.getActualName();
2913 variableData.u_is_password = variable.isPassword();
2914
2915 // get 'catalog' user role
2916 var catalogRoleId = glideHelper.getSysId(SaraCommon.TABLE_NAME.SN_ROLE, {
2917 'name': 'catalog'
2918 });
2919
2920 LOGGER.info('Variable information: {0}', SaraJSON.stringify(variableData));
2921
2922 // Save variable to SaraCommon.TABLE_NAME.SARA_VARIABLE table
2923 var variableId = this.saveOrUpdateVariable(variableData).sys_id;
2924
2925 // Process variable range for all lookup controls
2926 if (variable.isLookup()) {
2927 LOGGER.info('Saving lookup table for lookup control (sys_id = {0})...', variableId);
2928
2929 // Default value for list collector is list of value id in range table
2930 var defaultValueForListCollector = [];
2931
2932 // Update data for lookup controls
2933 var updateData = {};
2934
2935 var ranges = variable.getRange();
2936 if (ranges) {
2937 updateData.u_is_lookup = "true";
2938 // Insert values to lookup table
2939 for (var i = 0; i < ranges.length; i++) {
2940 var rangeValue = ranges[i];
2941 var rangeId = this.saveOrUpdateSaraLookup({
2942 'u_key': rangeValue.Value,
2943 'u_display_name': rangeValue.Key,
2944 'u_control_id': variableId
2945 }).sys_id;
2946
2947 if (SaraUtils.inArray(variable.defaultValue, rangeValue.Key)) {
2948 defaultValueForListCollector.push(rangeId);
2949 }
2950 }
2951
2952 LOGGER.info('Insert {0} values to table "{1}" finished successfully.', ranges.length, SaraCommon.TABLE_NAME.SARA_LOOKUP);
2953 } else {
2954 LOGGER.info('Lookup values of {0} is null', variable.getName());
2955 }
2956
2957 if (variable.getType() === SaraCommon.VAR_TYPE.LIST_COLLECTOR) {
2958 updateData.list_table = SaraCommon.TABLE_NAME.SARA_LOOKUP;
2959 updateData.default_value = defaultValueForListCollector.join(',');
2960 updateData.attributes = 'no_filter=true';
2961 updateData.reference_qual = 'u_control_id=' + variableId;
2962 } else {
2963 updateData.lookup_table = SaraCommon.TABLE_NAME.SARA_LOOKUP;
2964 updateData.lookup_value = 'u_display_name';
2965 updateData.reference_qual = 'u_control_id=' + variableId;
2966 }
2967
2968 LOGGER.debug('Variable updated information: {0}', SaraJSON.stringify(updateData));
2969 updateData.id = variableId;
2970 updateData.name = variableData.name;
2971 updateData.variable_set = variableData.variable_set;
2972 this.saveOrUpdateVariable(updateData);
2973 LOGGER.info('Saved lookup table for lookup control (sys_id = {0})', variableId);
2974 }
2975
2976 LOGGER.info('Saved variable (name = {0}, type = {1}, isLookup = {2})', variable.getName(), variable.getType(), variable.isLookup());
2977
2978 return variableId;
2979 },
2980
2981 getVariableSet: function(name) {
2982 return this.glideHelper.getData(this.TABLES.SN_VARIABLE_SET, {name: name});
2983 },
2984
2985 /**
2986 * param varset
2987 * id: optional. Blank for insert
2988 * name: required
2989 * title:
2990 * description:
2991 * sys_name:
2992 */
2993 saveOrUpdateVariableSet: function(varset) {
2994 SaraUtils.guardNotNullOrEmpty(varset, "varset must not be null or empty");
2995 SaraUtils.guardNotNullOrEmpty(varset.name, "varset name must not be null or empty");
2996
2997 this.saveOrUpdateEntity(varset, "var_set");
2998
2999 var result = this.getVariableSet(varset.name);
3000 SaraUtils.guardNotNullOrEmpty(result, "variable set is not save or updated correctly: " + varset.name);
3001 return result;
3002 },
3003
3004 getVariableSetItem: function(sc_cat_item, variable_set) {
3005 return this.glideHelper.getData(this.TABLES.SN_VARIABLE_SET_ITEM, {sc_cat_item: sc_cat_item, variable_set: variable_set});
3006 },
3007
3008 saveOrUpdateVariableSetItem: function(varsetItem) {
3009 SaraUtils.guardNotNullOrEmpty(varsetItem, "varsetItem must not be null or empty");
3010 SaraUtils.guardNotNullOrEmpty(varsetItem.sc_cat_item, "varsetItem sc_cat_item must not be null or empty");
3011 SaraUtils.guardNotNullOrEmpty(varsetItem.variable_set, "varsetItem variable_set must not be null or empty");
3012
3013 this.saveOrUpdateEntity(varsetItem, "var_set_item");
3014
3015 var result = this.getVariableSetItem(varsetItem.sc_cat_item, varsetItem.variable_set);
3016 SaraUtils.guardNotNullOrEmpty(result, "variable set item is not save or updated correctly");
3017 return result;
3018 },
3019
3020 getVariable: function(variable_set, name) {
3021 return this.glideHelper.getData(this.TABLES.SARA_VARIABLE, {variable_set: variable_set, name: name});
3022 },
3023
3024 saveOrUpdateVariable: function(variable) {
3025 SaraUtils.guardNotNullOrEmpty(variable, "variable must not be null or empty");
3026 SaraUtils.guardNotNullOrEmpty(variable.variable_set, "variable variable_set must not be null or empty");
3027 SaraUtils.guardNotNullOrEmpty(variable.name, "variable name must not be null or empty");
3028
3029 this.saveOrUpdateEntity(variable, "sara_variable");
3030
3031 var result = this.getVariable(variable.variable_set, variable.name);
3032 SaraUtils.guardNotNullOrEmpty(result, "variable is not save or updated correctly");
3033 return result;
3034 },
3035
3036 getSaraLookup: function(u_control_id, u_key, u_display_name) {
3037 return this.glideHelper.getData(this.TABLES.SARA_LOOKUP, {u_control_id: u_control_id, u_key: u_key, u_display_name: u_display_name});
3038 },
3039
3040 saveOrUpdateSaraLookup: function(lookup) {
3041 SaraUtils.guardNotNullOrEmpty(lookup, "lookup must not be null or empty");
3042 SaraUtils.guardNotNullOrEmpty(lookup.u_key, "lookup u_key must not be null or empty");
3043
3044 this.saveOrUpdateEntity(lookup, "sara_lookup");
3045
3046 var controlId = lookup.u_control_id;
3047 if(controlId === "0") {
3048 controlId = "";
3049 }
3050 var result = this.getSaraLookup(lookup.u_control_id, lookup.u_key, lookup.u_display_name);
3051 SaraUtils.guardNotNullOrEmpty(result, "lookup is not save or updated correctly");
3052 return result;
3053 },
3054
3055 /**
3056 * Create Sara Client Scripts with type is Macro and using UI Macro name SaraCommon.CONTROL_NAME.CLIENT_SCRIPTS. This control help us to
3057 * include all SNSC client scripts
3058 * @param {String} varSetId The sys_id of variable set
3059 */
3060 createSaraClientScripts: function (varSetId) {
3061 var glideHelper = this.glideHelper;
3062 var LOGGER = this.LOGGER;
3063
3064 var macroSaraClientScripts = glideHelper.getData(SaraCommon.TABLE_NAME.SN_UI_MACRO, {
3065 'name': SaraCommon.CONTROL_NAME.CLIENT_SCRIPTS
3066 });
3067
3068 if (macroSaraClientScripts) {
3069 this.saveOrUpdateVariable({
3070 'name': SaraCommon.CONTROL_NAME.CLIENT_SCRIPTS,
3071 'type': SaraCommon.VAR_TYPE.MACRO,
3072 'u_is_lookup': false,
3073 'macro': macroSaraClientScripts.sys_id,
3074 'variable_set': varSetId
3075 });
3076 } else {
3077 LOGGER.info('There\' no UI Macro named "{0}". Creating Sara client scripts skipped!', SaraCommon.CONTROL_NAME.CLIENT_SCRIPTS);
3078 }
3079 },
3080
3081 /**
3082 * Create Sara Hidden Variable with type is Macro and using UI Macro name SaraCommon.CONTROL_NAME.HIDDEN_CONTROL. This control help us
3083 * to run x_ausgh_snsc.SaraVarSet.onLoad() method without creating Catalog Client Script for VariableSet
3084 * @param {String} varSetId The sys_id of variable set
3085 */
3086 createSaraHiddenVariable: function (varSetId) {
3087 var glideHelper = this.glideHelper;
3088 var LOGGER = this.LOGGER;
3089
3090 var macroSaraHiddenControl = glideHelper.getData(SaraCommon.TABLE_NAME.SN_UI_MACRO, {
3091 'name': SaraCommon.CONTROL_NAME.HIDDEN_CONTROL
3092 });
3093
3094 if (macroSaraHiddenControl) {
3095 this.saveOrUpdateVariable({
3096 'name': SaraCommon.CONTROL_NAME.HIDDEN_CONTROL,
3097 'type': SaraCommon.VAR_TYPE.MACRO,
3098 'u_is_lookup': false,
3099 'macro': macroSaraHiddenControl.sys_id,
3100 'variable_set': varSetId
3101 });
3102 } else {
3103 LOGGER.info('There\' no UI Macro named "{0}". Creating Sara hidden control skipped!', SaraCommon.CONTROL_NAME.HIDDEN_CONTROL);
3104 }
3105 },
3106
3107 //---------------------------
3108 //Sara Definition
3109 //---------------------------
3110 getSaraDefinition: function(name, parentCategoryId, type) {
3111 return this.glideHelper.getData(this.TABLES.SARA_DEFINITION, {
3112 'u_name': name,
3113 'u_parent': parentCategoryId,
3114 'u_type': type
3115 });
3116 },
3117
3118 /**
3119 * param saraDefinition
3120 * id:
3121 * u_name: required
3122 * u_consume_url:
3123 * u_sc_item:
3124 * u_service_catalog_category:
3125 * u_var_set:
3126 * u_parent: required
3127 * u_type: required
3128 * u_hash:
3129 * u_active
3130 */
3131 saveOrUpdateSaraDefinition: function(saraDefinition) {
3132 SaraUtils.guardNotNullOrEmpty(saraDefinition, "saraDefinition must not be null or empty");
3133 SaraUtils.guardNotNullOrEmpty(saraDefinition.u_name, "u_name must not be null or empty");
3134 SaraUtils.guardNotNullOrEmpty(saraDefinition.u_parent, "u_parent must not be null or empty");
3135 SaraUtils.guardNotNullOrEmpty(saraDefinition.u_type, "u_type must not be null or empty");
3136
3137 this.saveOrUpdateEntity(saraDefinition, "sara_definition");
3138
3139 var result = this.getSaraDefinition(saraDefinition.u_name, saraDefinition.u_parent, saraDefinition.u_type);
3140 SaraUtils.guardNotNullOrEmpty(result, "definition is not save or updated correctly");
3141 return result;
3142 },
3143
3144 /**
3145 * Save category into SaraCommon.TABLE_NAME.SARA_DEFINITION table
3146 * @param {String} categoryId
3147 */
3148 saveRootImportCategoryToSaraDefinition: function (categoryId) {
3149 var glideHelper = this.glideHelper;
3150 var LOGGER = this.LOGGER;
3151
3152 var targetCategory = glideHelper.getData(SaraCommon.TABLE_NAME.SN_CATEGORY, {
3153 'sys_id': categoryId
3154 });
3155
3156 var importedDefinition = this.getSaraDefinition(targetCategory.title, targetCategory.sys_id, 'category');
3157
3158 if (importedDefinition) {
3159 LOGGER.info('Services have been imported in target category (name = {0})!', targetCategory.title);
3160 return importedDefinition;
3161 } else {
3162 return this.saveOrUpdateSaraDefinition({
3163 u_name: targetCategory.title,
3164 u_parent: targetCategory.sys_id,
3165 u_type: 'category',
3166 u_active: true
3167 });
3168 }
3169 },
3170
3171 /**
3172 * Save category into SaraCommon.TABLE_NAME.SARA_DEFINITION table
3173 * @param {String} categoryId
3174 */
3175 saveCategoryToSaraDefinition: function (sapiCatalog) {
3176 var glideHelper = this.glideHelper;
3177 var LOGGER = this.LOGGER;
3178
3179 // Assign default homepage renderer
3180 var defaultRendererSysId = glideHelper.getSysId(SaraCommon.TABLE_NAME.SN_HOMEPAGE_RENDERER, {
3181 'name': 'Category Items'
3182 });
3183
3184 var categoryToSave = {
3185 title: sapiCatalog.getTitle(),
3186 description: sapiCatalog.getDescription(),
3187 active: sapiCatalog.isActive(),
3188 homepage_renderer: defaultRendererSysId,
3189 parent: sapiCatalog.getParent(),
3190 };
3191 var category = this.saveOrUpdateCategory(categoryToSave);
3192 LOGGER.info('Created Catalog category {0} (sys_id = {1})...', sapiCatalog.getTitle(), category.sys_id);
3193
3194 return this.saveOrUpdateSaraDefinition({
3195 'u_service_catalog_category': category.sys_id,
3196 'u_name': sapiCatalog.getName(),
3197 'u_consume_url': sapiCatalog.getConsumeUrl() || '',
3198 'u_parent': sapiCatalog.getParent(),
3199 'u_type': 'catalog',
3200 'u_description': sapiCatalog.getDescription(),
3201 'u_active': true
3202 });
3203 },
3204
3205 /**
3206 * Deactivate item in SaraCommon.TABLE_NAME.SARA_DEFINITION via import set
3207 * @param {Object} saraDefinition The catalog item which will be deactivated
3208 */
3209 deactivateSaraDefinition: function (saraDefinition) {
3210 SaraUtils.guardNotNullOrEmpty(saraDefinition, "saraDefinition must not be null or empty");
3211 var id = saraDefinition.sys_id || saraDefinition.id;
3212 SaraUtils.guardNotNullOrEmpty(id, "definition id must not be null or empty");
3213
3214 var glideHelper = this.glideHelper;
3215 var LOGGER = this.LOGGER;
3216
3217 LOGGER.info('Deactivating sara definition and its child definitions... (sys_id = {0}, u_name= {1}) in table "{2}"',
3218 saraDefinition.sys_id, saraDefinition.u_name, SaraCommon.TABLE_NAME.SARA_DEFINITION);
3219
3220 var categoryId = saraDefinition.u_service_catalog_category;
3221 this.deactivateCategory(categoryId);
3222
3223 var catItemId = saraDefinition.u_sc_item;
3224 this.deactivateCatalogItem(catItemId);
3225
3226 // Deactivate definition in SaraCommon.TABLE_NAME.SARA_DEFINITION table
3227 LOGGER.info('Deactivating sara definition...');
3228 saraDefinition.u_active = false;
3229 this.saveOrUpdateSaraDefinition(saraDefinition);
3230 LOGGER.info('Deactivated sara definition');
3231
3232 LOGGER.info('Deactivating child definitions...');
3233 var parentCategoryId = saraDefinition.u_service_catalog_category;
3234 if(SaraUtils.isNullOrEmpty(parentCategoryId)) {
3235 parentCategoryId = saraDefinition.u_parent;
3236 }
3237
3238 if(saraDefinition.u_type === 'category' || saraDefinition.u_type === 'catalog') {
3239 var nextLevelType = saraDefinition.u_type === 'category' ? 'catalog' : 'service';
3240 // Deactive items which have parent is this category
3241 var childDefinitions = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {
3242 'u_parent': parentCategoryId,
3243 'u_type': nextLevelType
3244 }, true);
3245
3246 if(childDefinitions.length === 0) {
3247 LOGGER.info("No child definition found");
3248 }
3249
3250 for (var i = 0; i < childDefinitions.length; i++) {
3251 var childDefinition = childDefinitions[i];
3252 this.deactivateSaraDefinition(childDefinition);
3253 }
3254 }
3255
3256 LOGGER.info('Deactivated sara definition and its child definitions');
3257 },
3258
3259 deactivateCatalogItem: function(catItemId) {
3260 var glideHelper = this.glideHelper;
3261 var LOGGER = this.LOGGER;
3262 if(!SaraUtils.isNullOrEmpty(catItemId)) {
3263 var catItem = glideHelper.getData(this.TABLES.SN_CATALOG_ITEM, {sys_id: catItemId});
3264 // Mark catalog item as deleted in SaraCommon.TABLE_NAME.SN_CATALOG_ITEM table
3265 LOGGER.info('Deactivating catalog item (sys_id = {0}, name = {1}) in table "{2}"', catItemId, catItem.name, SaraCommon.TABLE_NAME.SARA_CAT_ITEM);
3266 catItem.active = false;
3267 this.saveOrUpdateCatalogItem(catItem);
3268 LOGGER.info('Deactivated catalog item (sys_id = {0}, name = {1}) in table "{2}"', catItemId, catItem.name, SaraCommon.TABLE_NAME.SARA_CAT_ITEM);
3269 }
3270 },
3271
3272 saveOrUpdateEntity: function(entity, type) {
3273 SaraUtils.guardNotNullOrEmpty(entity, "entity cannot be null or empty");
3274 SaraUtils.guardNotNullOrEmpty(type, "type cannot be null or empty");
3275
3276 var LOGGER = this.LOGGER;
3277
3278 var mappingDefinition;
3279 for(var definedType in this.typeMaps) {
3280 if(type === definedType) {
3281 mappingDefinition = this.typeMaps[type];
3282 }
3283 }
3284
3285 if(mappingDefinition === undefined) {
3286 throw " Defined mapping for " + type + " not found.";
3287 }
3288
3289 //transfer properties to new data object
3290 var data = {};
3291
3292 for(var i = 0; i < mappingDefinition.fields.length; i++) {
3293 var fieldName = mappingDefinition.fields[i];
3294 if(entity[fieldName] !== undefined) {
3295 data[fieldName] = entity[fieldName];
3296 }
3297 else {
3298 if(fieldName === "active") {
3299 LOGGER.info("default active to true");
3300 data[fieldName] = true;
3301 }
3302 }
3303 }
3304
3305 if(!SaraUtils.isNullOrEmpty(entity.sys_id)) {
3306 data.id= entity.sys_id;
3307 }
3308
3309 this.LOGGER.info(" dal.saveOrUpdateEntity: Save or update entity: type = {0}, data = ({1}) -> staging table {2}", type, SaraJSON.stringify(data), mappingDefinition.stagingTable);
3310
3311 this.glideHelper.persistData(mappingDefinition.stagingTable, data);
3312
3313 this.LOGGER.info(" dal.saveOrUpdateEntity: done");
3314
3315 return data;
3316 },
3317
3318 getTypeMaps: function() {
3319 return {
3320 "catalog": {
3321 stagingTable: this.TABLES.SN_CATALOG_IST,
3322 table: this.TABLES.SN_CATALOG,
3323 fields: [
3324 "id",
3325 "title",
3326 "description",
3327 "active"]
3328 },
3329 "category": {
3330 stagingTable: this.TABLES.SN_CATEGORY_IST,
3331 table: this.TABLES.SN_CATEGORY,
3332 fields: [
3333 "id",
3334 "title",
3335 "homepage_renderer",
3336 "active",
3337 "description",
3338 "parent",
3339 "sc_catalog"]
3340 },
3341 "cat_item": {
3342 stagingTable: this.TABLES.SARA_CAT_ITEM_IST,
3343 table: this.TABLES.SARA_CAT_ITEM,
3344 fields: [
3345 "id",
3346 "name",
3347 "category",
3348 "active",
3349 "short_description",
3350 "description",
3351 "custom_cart",
3352 "use_sc_layout",
3353 "no_quantity",
3354 "workflow",
3355 "sc_catalogs"]
3356 },
3357 "var_set": {
3358 stagingTable: this.TABLES.SN_VARIABLE_SET_IST,
3359 table: this.TABLES.SN_VARIABLE_SET,
3360 fields: [
3361 "id",
3362 "name",
3363 "description",
3364 "title",
3365 "sys_name"
3366 ]
3367 },
3368 "var_set_item": {
3369 stagingTable: this.TABLES.SN_VARIABLE_SET_ITEM_IST,
3370 table: this.TABLES.SN_VARIABLE_SET_ITEM,
3371 fields: [
3372 "id",
3373 "sc_cat_item",
3374 "variable_set",
3375 ]
3376 },
3377 "sara_definition": {
3378 stagingTable: this.TABLES.SARA_DEFINITION_IST,
3379 table: this.TABLES.SARA_DEFINITION,
3380 fields: [
3381 "id",
3382 "u_name",
3383 "u_consume_url",
3384 "u_sc_item",
3385 "u_service_catalog_category",
3386 "u_var_set",
3387 "u_parent",
3388 "u_type",
3389 "u_hash",
3390 "u_active"]
3391 },
3392 "sara_variable": {
3393 stagingTable: this.TABLES.SARA_VARIABLE_IST,
3394 table: this.TABLES.SARA_VARIABLE,
3395 fields: [
3396 "id",
3397 "u_name",
3398 "u_readonly",
3399 "u_is_password",
3400 "u_is_lookup",
3401 "u_hash",
3402 "variable_set",
3403 "type",
3404 "macro",
3405 "name",
3406 "cat_item",
3407 "help_text",
3408 "show_help",
3409 "include_none",
3410 "default_value",
3411 "question_text",
3412 "mandatory",
3413 "list_table",
3414 "attributes",
3415 "lookup_table",
3416 "lookup_value",
3417 "reference_qual",
3418 "order",
3419 "active"]
3420 },
3421 "sara_lookup": {
3422 stagingTable: this.TABLES.SARA_LOOKUP_IST,
3423 table: this.TABLES.SARA_LOOKUP,
3424 fields: [
3425 "id",
3426 "u_key",
3427 "u_display_name",
3428 "u_control_id"]
3429 }
3430 };
3431 },
3432 type: 'SaraConsumerDAL'
3433};
3434]]></script>
3435 <description>Sara Consumer Data Access to read and import service definition to Service Catalog using staging tables</description>
3436 <active>true</active>
3437 <client_callable>false</client_callable>
3438 <access>public</access>
3439 </script_include>
3440
3441 <script_include>
3442 <name>SaraConsumerRunner</name>
3443 <script><![CDATA[/**
3444 * Runner for SaraConsumerImportSet
3445 */
3446var SaraConsumerRunner = Class.create();
3447SaraConsumerRunner.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
3448 start: function () {
3449 var LOGGER = new SaraLog(this);
3450
3451 var targetCatId = this.getParameter('sysparm_catid');
3452
3453 LOGGER.info('Starting SaraConsumerRunner for importing services into "{0}"...', targetCatId);
3454
3455 var worker = new GlideScriptedHierarchicalWorker();
3456 worker.setProgressName('Import Services');
3457 worker.setBackground(true);
3458 worker.setScriptIncludeName('x_ausgh_snsc.SaraConsumerWorker');
3459 worker.setScriptIncludeMethod('run');
3460 worker.putMethodArg('targetCatId', targetCatId);
3461 worker.start();
3462
3463 LOGGER.info('SaraConsumerWorker starts successfully!');
3464
3465 var progressID = worker.getProgressID();
3466
3467 LOGGER.info('ID of SaraConsumerWorker is {0}', progressID);
3468
3469 return progressID;
3470 },
3471
3472 type: 'SaraConsumerRunner'
3473
3474});
3475]]></script>
3476 <description>Worker for SaraConsumer</description>
3477 <active>true</active>
3478 <client_callable>true</client_callable>
3479 <access>public</access>
3480 </script_include>
3481
3482 <script_include>
3483 <name>SaraConsumerWorker</name>
3484 <script><![CDATA[/**
3485 * Worker for SaraConsumerImportSet
3486 */
3487var SaraConsumerWorker = Class.create();
3488SaraConsumerWorker.prototype = {
3489 initialize: function () {
3490 var LOGGER = this.LOGGER = new SaraLog(this);
3491 var tracker = null;
3492 try {
3493 tracker = GlideExecutionTracker.getLastRunning();
3494 } catch (e) {
3495 LOGGER.error('Error when getting tracker: {0}', e);
3496 }
3497
3498 this.tracker = tracker;
3499 },
3500
3501 run: function (targetCatId) {
3502 var LOGGER = this.LOGGER;
3503 if (targetCatId) {
3504 try {
3505 var consumer = new SaraConsumerImportSet(this.tracker);
3506 var result = consumer.discoverAndImport(targetCatId);
3507
3508 if (!result) {
3509 var statusCode = consumer.getStatusCode();
3510 var errorMessage = consumer.getErrorMessage();
3511
3512 if (statusCode != 200) {
3513 this.updateTrackerResult('Failed to import Automic services', true);
3514 this.tracker.fail('Got error: ' + statusCode + ' - ' + errorMessage);
3515 } else {
3516 this.updateTrackerResult('Got no service or catalog from server.', false);
3517 this.tracker.success('Got no service or catalog from server.');
3518 }
3519 } else {
3520 this.updateTrackerResult('Imported successfully', false, result);
3521 this.tracker.success('Imported successfully!');
3522 }
3523 } catch (err) {
3524 LOGGER.error('Failed to import Automic services', err);
3525 this.updateTrackerResult('Failed to import Automic services', true);
3526 this.tracker.fail(err);
3527 }
3528 } else {
3529 this.updateTrackerResult('Failed to import Automic services', true);
3530 this.tracker.fail('Target category id is null!');
3531 }
3532 },
3533
3534 /**
3535 * Update tracker result
3536 * @param {String} message The message content
3537 * @param {Boolean} error Error or not
3538 * @param {String} info The addition information
3539 */
3540 updateTrackerResult: function (message, error, info) {
3541 var LOGGER = this.LOGGER;
3542
3543 if (error) {
3544 LOGGER.error(message);
3545 } else {
3546 LOGGER.info(message);
3547 }
3548
3549 try {
3550 this.tracker.updateResult({
3551 msg: message,
3552 info: info
3553 });
3554 } catch (ex) {
3555 LOGGER.error('Error when updating result for tracker: {0}', ex);
3556 }
3557 },
3558
3559 type: 'SaraConsumerWorker'
3560
3561};
3562]]></script>
3563 <description>Runner for SaraConsumer</description>
3564 <active>true</active>
3565 <client_callable>false</client_callable>
3566 <access>public</access>
3567 </script_include>
3568
3569 <script_include>
3570 <name>SaraGlideHelper</name>
3571 <script><![CDATA[/**
3572 * Helper class provides convenient methods to work with ServiceNow data tables
3573 */
3574var SaraGlideHelper = Class.create();
3575SaraGlideHelper.prototype = {
3576 initialize: function () {},
3577
3578 /**
3579 * Common data persistent operation
3580 * @param {String} table The table name
3581 * @param {Object} entity Object represents the row to insert
3582 * @param {Boolean} referencing Insert with references or not
3583 * @return {String} sys_id of inserted row
3584 */
3585 persistData: function (table, entity, referencing) {
3586 var rec = this._getGlideRecord(table);
3587 rec.initialize();
3588
3589 for (key in entity) {
3590 var value = entity[key];
3591
3592 if (value === undefined || value === null) {
3593 value = '';
3594 }
3595
3596 // check if key contains 'sys_id'
3597 var idx = key.indexOf('.sys_id');
3598 if (idx > 0 && idx == key.length - 7) {
3599 var propName = key.substring(0, idx);
3600 rec[propName]['sys_id'] = value;
3601 } else {
3602 rec[key] = value;
3603 }
3604 }
3605
3606 if (referencing) {
3607 return rec.insertWithReferences();
3608 } else {
3609 return rec.insert();
3610 }
3611 },
3612
3613 /**
3614 * Updates record(s) in given table based on the query and entity object holds fields/values to update
3615 * @param {String} table Target table to update
3616 * @param {Object} queryObj Query object, property name is the field name to query, value is value to query
3617 * @param {Object} entity Entity holds fields and values to update
3618 * @param {Boolean} updateAll Update all matching record(s) or only the first one
3619 * @param {Boolean} referencing Update with references or not
3620 */
3621 updateData: function (table, queryObj, entity, updateAll, referencing) {
3622 var rec = this._getGlideRecord(table);
3623 this._buildQuery(rec, queryObj);
3624 rec.query();
3625
3626 while (rec.next()) {
3627 for (key in entity) {
3628 // check if key contains 'sys_id'
3629 var idx = key.indexOf('.sys_id');
3630 if (idx > 0 && idx == key.length - 7) {
3631 var propName = key.substring(0, idx);
3632 rec[propName]['sys_id'] = entity[key];
3633 } else {
3634 rec[key] = entity[key];
3635 }
3636 }
3637
3638 if (referencing) {
3639 rec.updateWithReferences();
3640 } else {
3641 rec.update();
3642 }
3643
3644 if (!updateAll) {
3645 break;
3646 }
3647 }
3648 },
3649
3650 /**
3651 * Retrieve sys_id of a record in given table by key=value query
3652 * @param {String} table The table name
3653 * @param {Object} queryObj The object holds the query, property name is the field name to query, value is value to query
3654 * @param {Boolean} getAll Get sys_id of all matching record(s) or only the first one
3655 * @return {String|Array<String>} sys_id that found, or null if no record found
3656 */
3657 getSysId: function (table, queryObj, getAll) {
3658 var rec = this._getGlideRecord(table);
3659 this._buildQuery(rec, queryObj);
3660 rec.query();
3661
3662 if (getAll) {
3663 var results = [];
3664 while (rec.next()) {
3665 results.push('' + rec['sys_id']);
3666 }
3667
3668 return results;
3669 } else {
3670 if (rec.next()) {
3671 return '' + rec['sys_id'];
3672 } else {
3673 return null;
3674 }
3675 }
3676 },
3677
3678 /**
3679 * Parse GlideRecordSecure into an object with same properties but value of properties will be converted to String. The
3680 * original properties will be store in '_origin' property
3681 * @param {GlideRecordSecure} rec The instance of GlideRecordSecure
3682 * @return {Object}
3683 */
3684 _parseRecord: function (rec) {
3685 var obj = {
3686 _origin: rec
3687 };
3688
3689 for (var key in rec) {
3690 try {
3691 obj[key] = '' + rec[key];
3692 } catch (e) {
3693 obj[key] = '' + rec[key].toString();
3694 }
3695 }
3696
3697 return obj;
3698 },
3699
3700 /**
3701 * Query data from given table and query condition, return objects contain information specified in list of key
3702 * @param {String} table The target table
3703 * @param {Object} queryObj The object holds the query, property name is the field name to query, value is value to query
3704 * @param {Boolean} getAll Get all matching record(s) or only the first one
3705 * @return {Array} Array of object
3706 */
3707 getData: function (table, queryObj, getAll) {
3708 var rec = this._getGlideRecord(table);
3709 this._buildQuery(rec, queryObj);
3710 rec.query();
3711
3712 if (getAll) {
3713 var result = [];
3714 while (rec.next()) {
3715 result.push(this._parseRecord(rec));
3716 }
3717
3718 return result;
3719 } else {
3720 if (rec.next()) {
3721 return this._parseRecord(rec);
3722 } else {
3723 return null;
3724 }
3725 }
3726 },
3727
3728 /**
3729 * Delete record(s) from given table based on a query condition
3730 * @param {String} table The target table
3731 * @param {Object} queryObj The object holds the query, property name is the field name to query, value is value to query
3732 * @param {Boolean} deleteAll Delete all matching record(s) or only the first one
3733 */
3734 deleteData: function (table, queryObj, deleteAll) {
3735 var rec = this._getGlideRecord(table);
3736 this._buildQuery(rec, queryObj);
3737
3738 if (deleteAll) {
3739 rec.deleteMultiple();
3740 } else {
3741 rec.query();
3742 if (rec.next()) {
3743 rec.deleteRecord();
3744 }
3745 }
3746 },
3747
3748 /**
3749 * Build query for GlideRecordSecure and also support Operators
3750 * @link http://wiki.servicenow.com/index.php?title=Using_GlideRecord_to_Query_Tables
3751 * @param {GlideRecordSecure} rec
3752 * @param {Object} queryObj
3753 * - @key {String} The field name
3754 * - @value {Array|String|Number} The field value. If array, value will be [Operator, Value]
3755 */
3756 _buildQuery: function (rec, queryObj) {
3757 for (var key in queryObj) {
3758 var value = queryObj[key];
3759
3760 if (typeof value === 'object' && value instanceof Array) {
3761 rec.addQuery(key, value[0], value[1]);
3762 } else {
3763 rec.addQuery(key, value);
3764 }
3765 }
3766 },
3767
3768 /**
3769 * Get instance of GlideRecordSecure
3770 * @param {String} table The target table
3771 * @return {GlideRecordSecure}
3772 */
3773 _getGlideRecord: function (table) {
3774 return new GlideRecordSecure(table);
3775 },
3776
3777 type: 'SaraGlideHelper'
3778};
3779]]></script>
3780 <description>Helper class provides convenient methods to work with ServiceNow data tables</description>
3781 <active>true</active>
3782 <client_callable>false</client_callable>
3783 <access>public</access>
3784 </script_include>
3785
3786 <script_include>
3787 <name>SaraJSON</name>
3788 <script><![CDATA[/**
3789 * Sara JSON Utilities
3790 */
3791var SaraJSON = Class.create();
3792SaraJSON.prototype = {
3793 initialize: function() {},
3794
3795 type: 'SaraJSON'
3796};
3797
3798/*
3799 JSON.js
3800 2013-05-26
3801
3802 Public Domain.
3803
3804 NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
3805
3806 See http://www.JSON.org/js.html
3807
3808
3809 This code should be minified before deployment.
3810 See http://javascript.crockford.com/jsmin.html
3811
3812 USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
3813 NOT CONTROL.
3814
3815
3816 This file creates a global JSON object containing two methods: stringify
3817 and parse.
3818
3819 JSON.stringify(value, replacer, space)
3820 value any JavaScript value, usually an object or array.
3821
3822 replacer an optional parameter that determines how object
3823 values are stringified for objects. It can be a
3824 function or an array of strings.
3825
3826 space an optional parameter that specifies the indentation
3827 of nested structures. If it is omitted, the text will
3828 be packed without extra whitespace. If it is a number,
3829 it will specify the number of spaces to indent at each
3830 level. If it is a string (such as '\t' or ' '),
3831 it contains the characters used to indent at each level.
3832
3833 This method produces a JSON text from a JavaScript value.
3834
3835 When an object value is found, if the object contains a toJSON
3836 method, its toJSON method will be called and the result will be
3837 stringified. A toJSON method does not serialize: it returns the
3838 value represented by the name/value pair that should be serialized,
3839 or undefined if nothing should be serialized. The toJSON method
3840 will be passed the key associated with the value, and this will be
3841 bound to the value
3842
3843 For example, this would serialize Dates as ISO strings.
3844
3845 Date.prototype.toJSON = function (key) {
3846 function f(n) {
3847 // Format integers to have at least two digits.
3848 return n < 10 ? '0' + n : n;
3849 }
3850
3851 return this.getUTCFullYear() + '-' +
3852 f(this.getUTCMonth() + 1) + '-' +
3853 f(this.getUTCDate()) + 'T' +
3854 f(this.getUTCHours()) + ':' +
3855 f(this.getUTCMinutes()) + ':' +
3856 f(this.getUTCSeconds()) + 'Z';
3857 };
3858
3859 You can provide an optional replacer method. It will be passed the
3860 key and value of each member, with this bound to the containing
3861 object. The value that is returned from your method will be
3862 serialized. If your method returns undefined, then the member will
3863 be excluded from the serialization.
3864
3865 If the replacer parameter is an array of strings, then it will be
3866 used to select the members to be serialized. It filters the results
3867 such that only members with keys listed in the replacer array are
3868 stringified.
3869
3870 Values that do not have JSON representations, such as undefined or
3871 functions, will not be serialized. Such values in objects will be
3872 dropped; in arrays they will be replaced with null. You can use
3873 a replacer function to replace those with JSON values.
3874 JSON.stringify(undefined) returns undefined.
3875
3876 The optional space parameter produces a stringification of the
3877 value that is filled with line breaks and indentation to make it
3878 easier to read.
3879
3880 If the space parameter is a non-empty string, then that string will
3881 be used for indentation. If the space parameter is a number, then
3882 the indentation will be that many spaces.
3883
3884 Example:
3885
3886 text = JSON.stringify(['e', {pluribus: 'unum'}]);
3887 // text is '["e",{"pluribus":"unum"}]'
3888
3889
3890 text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
3891 // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
3892
3893 text = JSON.stringify([new Date()], function (key, value) {
3894 return this[key] instanceof Date ?
3895 'Date(' + this[key] + ')' : value;
3896 });
3897 // text is '["Date(---current time---)"]'
3898
3899
3900 JSON.parse(text, reviver)
3901 This method parses a JSON text to produce an object or array.
3902 It can throw a SyntaxError exception.
3903
3904 The optional reviver parameter is a function that can filter and
3905 transform the results. It receives each of the keys and values,
3906 and its return value is used instead of the original value.
3907 If it returns what it received, then the structure is not modified.
3908 If it returns undefined then the member is deleted.
3909
3910 Example:
3911
3912 // Parse the text. Values that look like ISO date strings will
3913 // be converted to Date objects.
3914
3915 myData = JSON.parse(text, function (key, value) {
3916 var a;
3917 if (typeof value === 'string') {
3918 a =
3919 /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
3920 if (a) {
3921 return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
3922 +a[5], +a[6]));
3923 }
3924 }
3925 return value;
3926 });
3927
3928 myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
3929 var d;
3930 if (typeof value === 'string' &&
3931 value.slice(0, 5) === 'Date(' &&
3932 value.slice(-1) === ')') {
3933 d = new Date(value.slice(5, -1));
3934 if (d) {
3935 return d;
3936 }
3937 }
3938 return value;
3939 });
3940
3941
3942 This is a reference implementation. You are free to copy, modify, or
3943 redistribute.
3944 */
3945
3946/*jslint evil: true, regexp: true */
3947
3948/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
3949 call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
3950 getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
3951 lastIndex, length, parse, prototype, push, replace, slice, stringify,
3952 test, toJSON, toString, valueOf
3953 */
3954
3955(function(JSON) {
3956 'use strict';
3957
3958 function f(n) {
3959 // Format integers to have at least two digits.
3960 return n < 10 ? '0' + n : n;
3961 }
3962
3963 function toJSON(value) {
3964 if (value instanceof Date) {
3965 return isFinite(date.valueOf()) ? date.getUTCFullYear() + '-' +
3966 f(date.getUTCMonth() + 1) + '-' +
3967 f(date.getUTCDate()) + 'T' +
3968 f(date.getUTCHours()) + ':' +
3969 f(date.getUTCMinutes()) + ':' +
3970 f(date.getUTCSeconds()) + 'Z' : null;
3971 } else {
3972 switch (typeof value) {
3973 case 'string':
3974 case 'number':
3975 case 'boolean':
3976 return value.valueOf();
3977 }
3978 }
3979 }
3980
3981 var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
3982 escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
3983 gap,
3984 indent,
3985 meta = { // table of character substitutions
3986 '\b': '\\b',
3987 '\t': '\\t',
3988 '\n': '\\n',
3989 '\f': '\\f',
3990 '\r': '\\r',
3991 '"': '\\"',
3992 '\\': '\\\\'
3993 },
3994 rep;
3995
3996
3997 function quote(string) {
3998
3999 // If the string contains no control characters, no quote characters, and no
4000 // backslash characters, then we can safely slap some quotes around it.
4001 // Otherwise we must also replace the offending characters with safe escape
4002 // sequences.
4003
4004 escapable.lastIndex = 0;
4005 return escapable.test(string) ? '"' + string.replace(escapable, function(a) {
4006 var c = meta[a];
4007 return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
4008 }) + '"' : '"' + string + '"';
4009 }
4010
4011
4012 function str(key, holder) {
4013
4014 // Produce a string from holder[key].
4015
4016 var i, // The loop counter.
4017 k, // The member key.
4018 v, // The member value.
4019 length,
4020 mind = gap,
4021 partial,
4022 value = holder[key];
4023
4024 // If the value has a toJSON method, call it to obtain a replacement value.
4025
4026 if (value && typeof value === 'object' && typeof toJSON(value) === 'function') {
4027 value = toJSON(value, key);
4028 }
4029
4030 // If we were called with a replacer function, then call the replacer to
4031 // obtain a replacement value.
4032
4033 if (typeof rep === 'function') {
4034 value = rep.call(holder, key, value);
4035 }
4036
4037 // What happens next depends on the value's type.
4038
4039 switch (typeof value) {
4040 case 'string':
4041 return quote(value);
4042
4043 case 'number':
4044
4045 // JSON numbers must be finite. Encode non-finite numbers as null.
4046
4047 return isFinite(value) ? String(value) : 'null';
4048
4049 case 'boolean':
4050 case 'null':
4051
4052 // If the value is a boolean or null, convert it to a string. Note:
4053 // typeof null does not produce 'null'. The case is included here in
4054 // the remote chance that this gets fixed someday.
4055
4056 return String(value);
4057
4058 // If the type is 'object', we might be dealing with an object or an array or
4059 // null.
4060
4061 case 'object':
4062
4063 // Due to a specification blunder in ECMAScript, typeof null is 'object',
4064 // so watch out for that case.
4065
4066 /**
4067 * MUST to check the type of object is Array or not because if value = [''], !value always is true on Rhino
4068 * @modifiedBy: dhm@automic.com
4069 */
4070 if (!value && Object.prototype.toString.apply(value) !== '[object Array]') {
4071 return 'null';
4072 }
4073
4074 // Make an array to hold the partial results of stringifying this object value.
4075
4076 gap += indent;
4077 partial = [];
4078
4079 // Is the value an array?
4080
4081 if (Object.prototype.toString.apply(value) === '[object Array]') {
4082
4083 // The value is an array. Stringify every element. Use null as a placeholder
4084 // for non-JSON values.
4085
4086 length = value.length;
4087 for (i = 0; i < length; i += 1) {
4088 partial[i] = str(i, value) || 'null';
4089 }
4090
4091 // Join all of the elements together, separated with commas, and wrap them in
4092 // brackets.
4093
4094 v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']';
4095 gap = mind;
4096 return v;
4097 }
4098
4099 // If the replacer is an array, use it to select the members to be stringified.
4100
4101 if (rep && typeof rep === 'object') {
4102 length = rep.length;
4103 for (i = 0; i < length; i += 1) {
4104 if (typeof rep[i] === 'string') {
4105 k = rep[i];
4106 v = str(k, value);
4107 if (v) {
4108 partial.push(quote(k) + (gap ? ': ' : ':') + v);
4109 }
4110 }
4111 }
4112 } else {
4113
4114 // Otherwise, iterate through all of the keys in the object.
4115
4116 for (k in value) {
4117 if (Object.prototype.hasOwnProperty.call(value, k)) {
4118 v = str(k, value);
4119 if (v) {
4120 partial.push(quote(k) + (gap ? ': ' : ':') + v);
4121 }
4122 }
4123 }
4124 }
4125
4126 // Join all of the member texts together, separated with commas,
4127 // and wrap them in braces.
4128
4129 v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}';
4130 gap = mind;
4131 return v;
4132 }
4133 }
4134
4135 // If the JSON object does not yet have a stringify method, give it one.
4136
4137 if (typeof JSON.stringify !== 'function') {
4138 JSON.stringify = function(value, replacer, space) {
4139
4140 // The stringify method takes a value and an optional replacer, and an optional
4141 // space parameter, and returns a JSON text. The replacer can be a function
4142 // that can replace values, or an array of strings that will select the keys.
4143 // A default replacer method can be provided. Use of the space parameter can
4144 // produce text that is more easily readable.
4145
4146 var i;
4147 gap = '';
4148 indent = '';
4149
4150 // If the space parameter is a number, make an indent string containing that
4151 // many spaces.
4152
4153 if (typeof space === 'number') {
4154 for (i = 0; i < space; i += 1) {
4155 indent += ' ';
4156 }
4157
4158 // If the space parameter is a string, it will be used as the indent string.
4159
4160 } else if (typeof space === 'string') {
4161 indent = space;
4162 }
4163
4164 // If there is a replacer, it must be a function or an array.
4165 // Otherwise, throw an error.
4166
4167 rep = replacer;
4168 if (replacer && typeof replacer !== 'function' &&
4169 (typeof replacer !== 'object' ||
4170 typeof replacer.length !== 'number')) {
4171 throw new Error('JSON.stringify');
4172 }
4173
4174 // Make a fake root object containing our value under the key of ''.
4175 // Return the result of stringifying the value.
4176
4177 return str('', {
4178 '': value
4179 });
4180 };
4181 }
4182
4183 // Because with SCOPED_APP, we can't use 'eval' function as the original so we decided to use 'decode' function of
4184 // ServiceNow's JSON class for our 'SaraJSON.parse'
4185 if (typeof JSON.parse !== 'function') {
4186 JSON.parse = function(text, reviver) {
4187 return new global.JSON().decode(text, reviver);
4188 };
4189 }
4190
4191})(SaraJSON);
4192]]></script>
4193 <description>Sara JSON Utilities</description>
4194 <active>true</active>
4195 <client_callable>false</client_callable>
4196 <access>public</access>
4197 </script_include>
4198
4199 <script_include>
4200 <name>SaraLog</name>
4201 <script><![CDATA[/**
4202 * Log Utilities for Sara
4203 */
4204var SaraLog = Class.create();
4205SaraLog.prototype = {
4206 /**
4207 * Init logger
4208 * @param {Object|String} className The class name of object. Will be append after timestamp.
4209 * If is not String, will get the className from 'type' property of object
4210 */
4211 initialize: function (className) {
4212 this.className = typeof className === 'string' ? className : className.type;
4213 },
4214
4215 _log: function (message) {
4216 return SaraUtils.formatString('[{0}] [{1}] {2}', SaraUtils.getTimeStamp(), this.className, message.toString());
4217 },
4218
4219 info: function () {
4220 var message = SaraUtils.formatString.apply(this, arguments);
4221 message = this._log(message);
4222
4223 gs.info(message);
4224 },
4225
4226 debug: function () {
4227 var message = SaraUtils.formatString.apply(this, arguments);
4228 message = this._log(message);
4229
4230 gs.debug(message);
4231 },
4232
4233 error: function () {
4234 var message = SaraUtils.formatString.apply(this, arguments);
4235 message = this._log(message);
4236
4237 gs.error(message);
4238 },
4239
4240 warn: function () {
4241 var message = SaraUtils.formatString.apply(this, arguments);
4242 message = this._log(message);
4243
4244 gs.warn(message);
4245 },
4246
4247 type: 'SaraLog'
4248
4249};
4250]]></script>
4251 <description>Log Utilities for Sara</description>
4252 <active>true</active>
4253 <client_callable>false</client_callable>
4254 <access>public</access>
4255 </script_include>
4256
4257 <script_include>
4258 <name>SaraModel</name>
4259 <script><![CDATA[/**
4260 * SARA concepts modelling in Service Now
4261 */
4262var SaraModel = {}
4263
4264/**
4265 * CatalogItem object represents a SN service catalog item
4266 * @constructor
4267 */
4268SaraModel.CatalogItem = Class.create();
4269SaraModel.CatalogItem.prototype = {
4270 initialize: function () {},
4271
4272 setName: function (name) {
4273 this.name = name;
4274 },
4275
4276 getName: function () {
4277 return this.name;
4278 },
4279
4280 setCategory: function (category) {
4281 this.category = category;
4282 },
4283
4284 getCategory: function () {
4285 return this.category;
4286 },
4287
4288 unsetCategory: function () {
4289 delete this.category;
4290 },
4291
4292 setActive: function (active) {
4293 this.active = active;
4294 },
4295
4296 isActive: function () {
4297 return this.active;
4298 },
4299
4300 setWorkflow: function (workflow) {
4301 this.workflow = workflow;
4302 },
4303
4304 getWorkflow: function () {
4305 return this.workflow;
4306 },
4307
4308 setShortDesc: function (shortDesc) {
4309 this.shortDesc = shortDesc;
4310 },
4311
4312 getShortDesc: function (shortDesc) {
4313 return this.shortDesc;
4314 },
4315
4316 setDescription: function (description) {
4317 this.description = description;
4318 },
4319
4320 getDescription: function () {
4321 return this.description;
4322 },
4323
4324 setVariables: function (variables) {
4325 this.variables = variables;
4326 },
4327
4328 getVariables: function (variables) {
4329 return this.variables;
4330 },
4331
4332 setConsumeUrl: function (consumeUrl) {
4333 this.consumeUrl = consumeUrl;
4334 },
4335
4336 getConsumeUrl: function () {
4337 return this.consumeUrl;
4338 },
4339
4340 setServiceName: function (serviceName) {
4341 this.serviceName = serviceName;
4342 },
4343
4344 getServiceName: function () {
4345 return this.serviceName;
4346 },
4347
4348 setCustomCart: function (customCart) {
4349 this.customCart = customCart;
4350 },
4351
4352 getCustomCart: function () {
4353 return this.customCart;
4354 },
4355
4356 setSNCatalog: function(catalog) {
4357 this.sc_catalog = catalog;
4358 },
4359
4360 getSNCatalog: function() {
4361 return this.sc_catalog;
4362 },
4363
4364 setHash: function (hash) {
4365 this.hash = hash;
4366 },
4367
4368 getHash: function () {
4369 return this.hash;
4370 },
4371
4372 type: 'SaraModel.CatalogItem'
4373};
4374
4375/**
4376 * CatalogVariable object represents a SN service virable
4377 * @constructor
4378 */
4379SaraModel.CatalogVariable = Class.create();
4380SaraModel.CatalogVariable.prototype = {
4381 initialize: function () {},
4382
4383 setName: function (name) {
4384 this.name = name;
4385 },
4386
4387 getName: function () {
4388 return this.name;
4389 },
4390
4391 setType: function (type) {
4392 this.type = type;
4393 },
4394
4395 getType: function () {
4396 return this.type;
4397 },
4398
4399 setLabel: function (label) {
4400 this.label = label;
4401 },
4402
4403 getLabel: function () {
4404 return this.label;
4405 },
4406
4407 setDefaultValue: function (defaultValue) {
4408 this.defaultValue = defaultValue;
4409 },
4410
4411 getDefaultValue: function () {
4412 return this.defaultValue;
4413 },
4414
4415 setDescription: function (description) {
4416 this.description = description;
4417 },
4418
4419 getDescription: function () {
4420 return this.description;
4421 },
4422
4423 setRange: function (range) {
4424 this.range = range;
4425 },
4426
4427 getRange: function () {
4428 return this.range;
4429 },
4430
4431 setActualName: function (actualName) {
4432 this.actualName = actualName;
4433 },
4434
4435 getActualName: function () {
4436 return this.actualName;
4437 },
4438
4439 setAsPassword: function (asPassword) {
4440 this.asPassword = asPassword;
4441 },
4442
4443 isPassword: function (isPassword) {
4444 return this.asPassword;
4445 },
4446
4447 setRequired: function (required) {
4448 this.required = required;
4449 },
4450
4451 isRequired: function (required) {
4452 return this.required;
4453 },
4454
4455 setMultiSelect: function (multiSelect) {
4456 this.multiSelect = multiSelect;
4457 },
4458
4459 isMultiSelect: function (multiSelect) {
4460 return this.multiSelect;
4461 },
4462
4463 setAsLookup: function (asLookup) {
4464 this.asLookup = asLookup;
4465 },
4466
4467 isLookup: function () {
4468 return this.asLookup;
4469 },
4470
4471 setHash: function (hash) {
4472 this.hash = hash;
4473 },
4474
4475 getHash: function () {
4476 return this.hash;
4477 },
4478
4479 setOrder: function (order) {
4480 this.order = order;
4481 },
4482
4483 getOrder: function () {
4484 if(this.order)
4485 return this.order;
4486 return 0;
4487 },
4488
4489 type: 'SaraModel.CatalogVariable'
4490};
4491
4492/**
4493 * CatalogCategory object represents a SN service catalog category
4494 * @constructor
4495 */
4496SaraModel.CatalogCategory = Class.create();
4497SaraModel.CatalogCategory.prototype = {
4498 initialize: function () {},
4499
4500 setTitle: function (title) {
4501 this.title = title;
4502 },
4503
4504 getTitle: function () {
4505 return this.title;
4506 },
4507
4508 setName: function (name) {
4509 this.name = name;
4510 },
4511
4512 getName: function () {
4513 return this.name;
4514 },
4515
4516 setParent: function (parent) {
4517 this.parent = parent;
4518 },
4519
4520 getParent: function () {
4521 return this.parent;
4522 },
4523
4524 unsetParent: function () {
4525 delete this.parent;
4526 },
4527
4528 setActive: function (active) {
4529 this.active = active;
4530 },
4531
4532 isActive: function () {
4533 return this.active;
4534 },
4535
4536 setDescription: function (description) {
4537 this.description = description;
4538 },
4539
4540 getDescription: function () {
4541 return this.description;
4542 },
4543
4544 setConsumeUrl: function (consumeUrl) {
4545 this.consumeUrl = consumeUrl;
4546 },
4547
4548 getConsumeUrl: function () {
4549 return this.consumeUrl;
4550 },
4551
4552 setAsNew: function (asNew) {
4553 this.asNew = asNew;
4554 },
4555
4556 isNew: function () {
4557 return this.asNew;
4558 },
4559
4560 unsetAsNew: function () {
4561 delete this.asNew;
4562 },
4563
4564 setSysId: function (sysId) {
4565 this.sysId = sysId;
4566 },
4567
4568 getSysId: function () {
4569 return this.sysId;
4570 },
4571
4572 unsetSysId: function () {
4573 delete this.sysId;
4574 },
4575
4576 setSNCatalog: function(catalog) {
4577 this.sc_catalog = catalog;
4578 },
4579
4580 getSNCatalog: function() {
4581 return this.sc_catalog;
4582 },
4583
4584 type: 'SaraModel.CatalogCategory'
4585};
4586]]></script>
4587 <description>SARA concepts modelling in Service Now</description>
4588 <active>true</active>
4589 <client_callable>false</client_callable>
4590 <access>package_private</access>
4591 </script_include>
4592
4593 <script_include>
4594 <name>SaraOAuthAjax</name>
4595 <script><![CDATA[/**
4596 * AJAX facade for SaraOAuthClient
4597 */
4598var SaraOAuthAjax = Class.create();
4599SaraOAuthAjax.prototype = Object.extendsObject(global.AbstractAjaxProcessor, {
4600 /**
4601 * Get OAuth URL with redirection endpoint and client id in query string
4602 * @return {String}
4603 */
4604 getOAuthUrl: function () {
4605 var LOGGER = new SaraLog(this);
4606
4607 try {
4608 var clientId = this.getParameter('sysparm_client_id').toString();
4609 var technicalUser = this.getParameter('sysparm_technical_user').toString();
4610 var authEndpoint = this.getParameter('sysparm_auth_endpoint').toString();
4611 var redirectionEndpoint = SaraUtils.getRedirectionUrl();
4612
4613 LOGGER.info('auth_endpoint={0}; redirect_uri={1}; client_id={2}; technical_user={3}', authEndpoint, redirectionEndpoint, clientId, technicalUser);
4614
4615 return authEndpoint
4616 + '?redirect_uri=' + escape(redirectionEndpoint)
4617 + '&client_id=' + escape(clientId)
4618 + '&user_info=' + escape(technicalUser)
4619 + '&user_info_editable=false'
4620 + '&response_type=code';
4621 } catch (e) {
4622 this.logError(e);
4623 }
4624
4625 return;
4626 },
4627
4628 /**
4629 * Request token by using Username and password
4630 * @return {String}
4631 */
4632 requestToken: function () {
4633 var LOGGER = new SaraLog(this);
4634
4635 try {
4636 var username = this.getParameter('sysparm_username').toString();
4637 var password = this.getParameter('sysparm_password').toString();
4638 var technicalUser = this.getParameter('sysparm_technical_user').toString();
4639
4640 var oauthClient = new SaraOAuthClient();
4641 var tokens = oauthClient.requestToken(username, password);
4642
4643 LOGGER.info('Token: {0}', SaraJSON.stringify(tokens));
4644
4645 if (tokens && !tokens.error && tokens['access_token']) {
4646 oauthClient.storeUserTokens(technicalUser, tokens['access_token'], tokens['refresh_token'], tokens['expires_in'], tokens['token_type']);
4647 return 'ok';
4648 } else {
4649 return tokens.error ? tokens.error : (!tokens['access_token'] ? 'Empty result' : '');
4650 }
4651 } catch (e) {
4652 this.logError(e);
4653 }
4654
4655 return;
4656 },
4657
4658 /**
4659 * Request token by authorization code
4660 * @return {String}
4661 */
4662 requestTokenByCode: function () {
4663 var LOGGER = new SaraLog(this);
4664
4665 try {
4666 var code = this.getParameter('sysparm_code').toString();
4667 var technicalUser = this.getParameter('sysparm_technical_user').toString();
4668 LOGGER.info('Request token for user "{0}" by using code {1}', technicalUser, code);
4669
4670
4671 var config = {};
4672 config[SaraCommon.CONFIG_NAME.CLIENT_ID] = this.getParameter('sysparm_client_id').toString();
4673 config[SaraCommon.CONFIG_NAME.CLIENT_SECERT] = this.getParameter('sysparm_client_secret').toString();
4674 config[SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT] = this.getParameter('sysparm_token_endpoint').toString();
4675
4676 var oauthClient = new SaraOAuthClient();
4677 var tokens = oauthClient.requestTokenByCode(code, config);
4678
4679 LOGGER.info('Token info: {0}', SaraJSON.stringify(tokens));
4680
4681 if (tokens && !tokens.error && tokens['access_token']) {
4682 oauthClient.storeUserTokens(technicalUser, tokens['access_token'], tokens['refresh_token'], tokens['expires_in'], tokens['token_type']);
4683
4684 return 'ok';
4685 } else {
4686 return tokens.error ? tokens.error : (!tokens['access_token'] ? 'Empty result' : '');
4687 }
4688 } catch (e) {
4689 this.logError(e);
4690 }
4691
4692 return;
4693 },
4694
4695 /**
4696 * Get client configuration
4697 */
4698 getConfig: function () {
4699 var LOGGER = new SaraLog(this);
4700
4701 try {
4702 var configData = new SaraConfig().getClientConfig();
4703
4704 LOGGER.info('OAuth Configuration: \n'
4705 + ' - Client ID = {0} \n'
4706 + ' - Client Secret = *** \n'
4707 + ' - Technical User = {1} \n'
4708 + ' - SAPI Endpoint = {2} \n'
4709 + ' - Token Endpoint = {3} \n'
4710 + ' - Auth Endpoint = {4} \n',
4711 configData[SaraCommon.CONFIG_NAME.CLIENT_ID],
4712 configData[SaraCommon.CONFIG_NAME.TECHNICAL_USER],
4713 configData[SaraCommon.CONFIG_NAME.SAPI_ENDPOINT],
4714 configData[SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT],
4715 configData[SaraCommon.CONFIG_NAME.AUTH_ENDPOINT]
4716 );
4717
4718 var config = this.newItem('config');
4719 for (var key in SaraCommon.CONFIG_NAME) {
4720 var name = SaraCommon.CONFIG_NAME[key];
4721
4722 config.setAttribute(name, configData[name]);
4723 }
4724 } catch (e) {
4725 this.logError(e);
4726 }
4727
4728 return;
4729 },
4730
4731 /**
4732 * Validate access token key
4733 */
4734 validateToken: function () {
4735 var LOGGER = new SaraLog(this);
4736
4737 try {
4738 var technicalUser = this.getParameter('sysparm_technical_user').toString();
4739 var glideHelper = new SaraGlideHelper();
4740 var saraOAuth = glideHelper.getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SARA_OAUTH, {
4741 'u_user': technicalUser
4742 });
4743
4744 if (saraOAuth) {
4745 var token = saraOAuth['u_access_token'].toString();
4746 var sapiEndpoint = this.getParameter('sysparm_sapi_endpoint').toString();
4747 var oauthClient = new SaraOAuthClient();
4748 var result = oauthClient.validateToken(token, sapiEndpoint);
4749
4750 LOGGER.debug('Result of validating token: {0}', result.toString());
4751
4752 if (typeof result === 'boolean') {
4753 this.addItem('result', {
4754 isValid: result
4755 });
4756 } else {
4757 this.addItem('result', {
4758 message: result
4759 });
4760 }
4761 } else {
4762 LOGGER.info('Technical User "{1}" does not have tokens', technicalUser);
4763
4764 this.addItem('result', {
4765 isValid: false
4766 });
4767 }
4768
4769 } catch (e) {
4770 this.logError(e);
4771 }
4772
4773 return;
4774 },
4775
4776 /**
4777 * Log error
4778 * @param {Error} error
4779 * @param {SaraLog} LOGGER
4780 */
4781 logError: function (error, LOGGER) {
4782 LOGGER.error('{0}', error);
4783
4784 this.addItem('error', {
4785 message: error
4786 });
4787 },
4788
4789 /**
4790 * Add item in response
4791 * @param {String} itemName The name of item
4792 * @param {Object<String, String>} attributes The object contains item's attributes
4793 */
4794 addItem: function (itemName, attributes) {
4795 var item = this.newItem(itemName);
4796
4797 for (var name in attributes) {
4798 var value = attributes[name];
4799
4800 item.setAttribute(name, value);
4801 }
4802 },
4803
4804 type: 'SaraOAuthAjax'
4805});
4806]]></script>
4807 <description>AJAX facade for SaraOAuthClient</description>
4808 <active>true</active>
4809 <client_callable>true</client_callable>
4810 <access>package_private</access>
4811 </script_include>
4812
4813 <script_include>
4814 <name>SaraOAuthClient</name>
4815 <script><![CDATA[/**
4816 * This class contains all OAuth-relaled functions
4817 */
4818var SaraOAuthClient = Class.create();
4819SaraOAuthClient.prototype = {
4820 /**
4821 * Init new OAuth Client from SaraRESTClient object
4822 * @param {SaraRestCLient} restClient
4823 */
4824 initialize: function (restClient) {
4825 this.glideHelper = new SaraGlideHelper();
4826 this.saraConfig = new SaraConfig();
4827 this.LOGGER = new SaraLog(this);
4828
4829 if (!restClient) {
4830 this.restClient = new SaraRESTClient();
4831 this.restClient.setMIDServer(SaraUtils.getMIDServer());
4832 } else {
4833 this.restClient = restClient;
4834 }
4835 },
4836
4837 /**
4838 * Store user tokens into 'SaraCommon.TABLE_NAME.SARA_OAUTH' table
4839 * @param {String} username The username which owns tokens
4840 * @param {String} accessToken The access token of user
4841 * @param {String} refreshToken The refresh token of user
4842 * @param {String} tokenExpiry The expiry of token
4843 * @param {String} tokenType The type of token
4844 * @return {String} The sys_id of user tokens record
4845 */
4846 storeUserTokens: function (username, accessToken, refreshToken, tokenExpiry, tokenType) {
4847 var LOGGER = this.LOGGER;
4848
4849 if (!username) {
4850 LOGGER.info('Store user token: Username must not be empty!');
4851 return;
4852 }
4853
4854 if (!accessToken) {
4855 LOGGER.info('Error: Access token must be non-empty!');
4856 return;
4857 }
4858
4859 LOGGER.info('Preparing for storing user tokens...');
4860
4861 // Request tokens of user in 'SaraCommon.TABLE_NAME.SARA_OAUTH' table
4862 var saraOAuth = this.glideHelper.getData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4863 'u_user': username
4864 });
4865
4866 // If user's tokens are existed
4867 if (saraOAuth) {
4868 LOGGER.info('User\'s tokens are existed. Updating tokens...');
4869
4870 this.glideHelper.updateData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4871 'sys_id': saraOAuth['sys_id']
4872 }, {
4873 'u_access_token': accessToken,
4874 'u_refresh_token': refreshToken,
4875 'u_token_expiry': tokenExpiry,
4876 'u_token_type': tokenType
4877 });
4878
4879 return saraOAuth['sys_id'];
4880 } else {
4881 LOGGER.info('Storing user\'s tokens...');
4882
4883 return this.glideHelper.persistData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4884 'u_user': username,
4885 'u_access_token': accessToken,
4886 'u_refresh_token': refreshToken,
4887 'u_token_expiry': tokenExpiry,
4888 'u_token_type': tokenType
4889 });
4890 }
4891 },
4892
4893 /**
4894 * Get user tokens by username. The result will be [accessToken, refreshToken, tokenExpiry, tokenType, { createdAt, createdBy, updateAt, updateBy }]
4895 * @param {String} username
4896 * @return {Array<String|Object>}
4897 */
4898 getUserTokens: function (username) {
4899 var LOGGER = this.LOGGER;
4900
4901 if (!username) {
4902 return null;
4903 }
4904
4905 var saraOAuth = this.glideHelper.getData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4906 'u_user': username
4907 });
4908
4909 if (saraOAuth) {
4910 return [
4911 saraOAuth['u_access_token'],
4912 saraOAuth['u_refresh_token'],
4913 saraOAuth['u_token_expiry'],
4914 saraOAuth['u_token_type'], {
4915 'createdAt': saraOAuth['sys_created_on'],
4916 'createdBy': saraOAuth['sys_created_by'],
4917 'updatedAt': saraOAuth['sys_updated_on'],
4918 'updatedBy': saraOAuth['sys_updated_by']
4919 }
4920 ];
4921 } else {
4922 LOGGER.info('Tokens of "{0}" do not exist!', username);
4923 return null;
4924 }
4925 },
4926
4927 /**
4928 * Remove user tokens by username
4929 * @param {String} username
4930 * @return {String} The sys_id of deleted record
4931 */
4932 removeUserToken: function (username) {
4933 var LOGGER = this.LOGGER;
4934
4935 if (!username) {
4936 return null;
4937 }
4938
4939 var saraOAuth = this.glideHelper.getData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4940 'u_user': username
4941 });
4942
4943 if (saraOAuth) {
4944 saraOAuth = this.glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4945 'sys_id': saraOAuth['sys_id']
4946 });
4947
4948 return saraOAuth['sys_id'];
4949 } else {
4950 LOGGER.info('No token found for user "{0}"', username);
4951 return null;
4952 }
4953 },
4954
4955 /**
4956 * Requests user tokens, the request must use client_id/client_secret to authenticate (BASICally) against SARA server,
4957 * LDAP username/password and grant_type will be embedded in request's body
4958 * @param {String} username
4959 * @param {String} password
4960 * @return {Object} Object contains access token, refresh token, token expiry and token type
4961 */
4962 requestToken: function (username, password) {
4963 var LOGGER = this.LOGGER;
4964
4965 LOGGER.debug('Preparing for requesting tokens for SARA user {0}...', username);
4966
4967 var clientInfo = this.saraConfig.getClientConfig();
4968 var clientId = clientInfo[SaraCommon.CONFIG_NAME.CLIENT_ID];
4969 var clientSecret = clientInfo[SaraCommon.CONFIG_NAME.CLIENT_SECERT];
4970 var tokenEndpoint = clientInfo[SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT];
4971
4972 var request = this.restClient.newOAuthRequest('post', tokenEndpoint);
4973 request.setBasicAuth(clientId, clientSecret);
4974
4975 // Add POST body, set Content-Type header
4976 request.setContentType('application/x-www-form-urlencoded');
4977 var formEntity = {
4978 'grant_type': 'password',
4979 'username': username,
4980 'password': password
4981 };
4982 request.setFormContent(formEntity);
4983
4984 LOGGER.info('Requesting tokens for SARA user {0}...', username);
4985 var response = this.restClient.execute(request);
4986 var responseObject = response.getResponseObject();
4987
4988 if (response.haveError()) {
4989 LOGGER.info('Failed to request token for user {0}', username);
4990
4991 return {
4992 'error': responseObject.errorMessage,
4993 'error_description': responseObject.errorDescription
4994 }
4995 }
4996
4997 LOGGER.info('Successfully obtain token for user {0}', username);
4998 return responseObject.bodyObject;
4999 },
5000
5001 /**
5002 * Requests user tokens, the request must use client_id/client_secret to authenticate (BASICally) against SARA server,
5003 * LDAP redirect_uri/authorization_code and grant_type will be embedded in request's body
5004 * @param {String} code The authorization code which get from OAuth after logged-in successfully in Auth Endpoint
5005 * @param {Object} config The config of OAuth Server
5006 * @return {Object} Object contains access token, refresh token, token expiry and token type
5007 */
5008 requestTokenByCode: function (code, config) {
5009 var LOGGER = this.LOGGER;
5010
5011 LOGGER.debug('Preparing for requesting tokens by code "{0}"...', code);
5012
5013 var clientId = config[SaraCommon.CONFIG_NAME.CLIENT_ID];
5014 var clientSecret = config[SaraCommon.CONFIG_NAME.CLIENT_SECERT];
5015 var tokenEndpoint = config[SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT];
5016 var redirectionEndpoint = SaraUtils.getRedirectionUrl();
5017
5018 var request = this.restClient.newOAuthRequest('post', tokenEndpoint);
5019 request.setBasicAuth(clientId, clientSecret);
5020
5021 // Add POST body, set Content-Type header
5022 request.setContentType('application/x-www-form-urlencoded');
5023 var formEntity = {
5024 'grant_type': 'authorization_code',
5025 'redirect_uri': redirectionEndpoint,
5026 'code': code
5027 };
5028 request.setFormContent(formEntity);
5029
5030 LOGGER.info('Requesting tokens by code...');
5031 var response = this.restClient.execute(request);
5032 var responseObject = response.getResponseObject();
5033
5034 if (response.haveError()) {
5035 LOGGER.info('Failed to request token by code');
5036
5037 return {
5038 'error': responseObject.errorMessage,
5039 'error_description': responseObject.errorDescription
5040 }
5041 }
5042
5043 LOGGER.info('Successfully obtain token for user by code "{0}"', code);
5044 return responseObject.bodyObject;
5045 },
5046
5047 /**
5048 * Refresh user tokens
5049 * @param {String} username
5050 * @return {Object}
5051 */
5052 refreshToken: function (username) {
5053 var LOGGER = this.LOGGER;
5054
5055 // Get refresh tokens for this user from 'SaraCommon.TABLE_NAME.SARA_OAUTH' table
5056 var tokens = this.getUserTokens(username);
5057 if (!tokens || tokens.length < 1) {
5058 LOGGER.info('Tokens not found for user {0}', username);
5059 return null;
5060 }
5061
5062 LOGGER.info('Preparing for refreshing tokens for user {0}...', username);
5063
5064 // Use that refesh token to retrieve new tokens
5065 var clientInfo = this.saraConfig.getClientConfig();
5066 var clientId = clientInfo[SaraCommon.CONFIG_NAME.CLIENT_ID];
5067 var clientSecret = clientInfo[SaraCommon.CONFIG_NAME.CLIENT_SECRET];
5068 var tokenEndpoint = clientInfo[SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT];
5069 var request = this.restClient.newOAuthRequest('post', tokenEndpoint);
5070 request.setBasicAuth(clientId, clientSecret);
5071
5072 // Add POST body, set Content-Type header
5073 request.setContentType('application/x-www-form-urlencoded');
5074 request.setFormContent({
5075 'grant_type': 'refresh_token',
5076 'refresh_token': tokens[1]
5077 });
5078
5079 LOGGER.info('Refreshing tokens for user {0}...', username);
5080 var response = this.restClient.execute(request);
5081 var responseObject = response.getResponseObject();
5082
5083 if (response.haveError()) {
5084 LOGGER.info('Failed to refresh token for code');
5085
5086 return {
5087 'error': responseObject.errorMessage,
5088 'error_description': responseObject.errorDescription
5089 }
5090 }
5091
5092 LOGGER.info('Successfully refresh token for user {0}', username);
5093 return responseObject.bodyObject;
5094 },
5095
5096 /**
5097 * Validate access token key of user is invalid or expired
5098 * @param {String} token The access token key of user
5099 * @param {String} sapiEndpoint The SAPI endpoint
5100 * @return {Boolean|String}
5101 */
5102 validateToken: function (token, sapiEndpoint) {
5103 var LOGGER = this.LOGGER;
5104
5105 LOGGER.info('Preparing for validating token "{0}"...', token.toString());
5106
5107 var configData = this.saraConfig.getClientConfig();
5108 var request = this.restClient.newSAPIRequest('get', sapiEndpoint);
5109 request.addHeader('Authorization', 'bearer ' + token);
5110
5111 var response = this.restClient.executeWithRefreshToken(request);
5112 var responseObject = response.getResponseObject();
5113
5114 if (response.haveError()) {
5115 if (responseObject.statusCode !== 401) {
5116 var message = SaraUtils.formatString('Error when validating token! Error code: {0} - Error message: {1}', responseObject.statusCode, responseObject.errorMessage);
5117 LOGGER.error(message);
5118
5119 return message;
5120 } else {
5121 var username = this.saraConfig.getTechnicalUser();
5122 this.removeUserToken(username);
5123
5124 return false;
5125 }
5126 } else {
5127 return true;
5128 }
5129 },
5130
5131 type: 'SaraOAuthClient'
5132};
5133]]></script>
5134 <description>This class contains all OAuth-relaled functions</description>
5135 <active>true</active>
5136 <client_callable>false</client_callable>
5137 <access>public</access>
5138 </script_include>
5139
5140 <script_include>
5141 <name>SaraRESTClient</name>
5142 <script><![CDATA[/**
5143 * Wraps Service Now RESTMessage in a class to provide convenient methods interacting with SARA REST
5144 */
5145var SaraRESTClient = Class.create();
5146SaraRESTClient.prototype = {
5147 initialize: function () {
5148 this.LOGGER = new SaraLog(this);
5149 },
5150
5151 /**
5152 * Init new service request from SaraRESTMessage class
5153 * @param {String} name The name of the REST message record
5154 * @param {String} method The name of the HTTP method to use, such as GET or PUT
5155 * @param {String} endpoint The endpoint for the REST message
5156 * @param {Array<String>} basicAuthCreds The basic authentication headers for the REST message
5157 * @param {Array<Object>} headers The object contains headers for the REST message
5158 * @param {Array<Object>} stringParameters The object contains string parameters for the REST message
5159 * @param {Array<Object>} stringParametersNoEscape The object contains string parameters which will be not escaped for the REST message
5160 * @return {SaraRESTMessage}
5161 */
5162 newServiceRequest: function (name, method, endpoint, basicAuthCreds, headers, stringParameters, stringParametersNoEscape) {
5163 var restMsg = new SaraRESTMessage(name, method);
5164
5165 if (endpoint) {
5166 restMsg.setEndpoint(endpoint);
5167 }
5168
5169 if (this.midServer) {
5170 restMsg.setMIDServer(this.midServer);
5171 }
5172
5173 if (basicAuthCreds && basicAuthCreds.length > 1) {
5174 restMsg.setBasicAuth(basicAuthCreds[0], basicAuthCreds[1]);
5175 }
5176
5177 if (headers) {
5178 for (var i = 0, header; header = headers[i]; i++) {
5179 if (header['name']) {
5180 restMsg.addHeader(header['name'], header['value']);
5181 }
5182 }
5183 }
5184
5185 if (stringParameters) {
5186 for (var i = 0, stringParameter; stringParameter = stringParameters[i]; i++) {
5187 if (stringParameter['name']) {
5188 restMsg.setStringParameter(stringParameter['name'], stringParameter['value']);
5189 }
5190 }
5191 }
5192
5193 if (stringParametersNoEscape) {
5194 for (var i = 0, stringParameter; stringParameter = stringParametersNoEscape[i]; i++) {
5195 if (stringParameter['name']) {
5196 restMsg.setStringParameterNoEscape(stringParameter['name'], stringParameter['value']);
5197 }
5198 }
5199 }
5200
5201 return restMsg;
5202 },
5203
5204 /**
5205 * Init new SAPI service request from SaraRESTMessage class
5206 * @param {String} method The name of the HTTP method to use, such as GET or PUT
5207 * @param {String} endpoint The endpoint for the REST message
5208 * @param {Array<String>} basicAuthCreds The basic authentication headers for the REST message
5209 * @param {Array<Object>} headers The object contains headers for the REST message
5210 * @param {Array<Object>} stringParameters The object contains string parameters for the REST message
5211 * @param {Array<Object>} stringParametersNoEscape The object contains string parameters which will be not escaped for the REST message
5212 * @return {SaraRESTMessage}
5213 */
5214 newSAPIRequest: function (method, endpoint, basicAuthCreds, headers, stringParameters, stringParametersNoEscape) {
5215 return this.newServiceRequest(SaraCommon.REST_NAME.SAPI, method, endpoint, basicAuthCreds, headers)
5216 },
5217
5218 /**
5219 * Init new OAuth service request from SaraRESTMessage class
5220 * @param {String} method The name of the HTTP method to use, such as GET or PUT
5221 * @param {String} endpoint The endpoint for the REST message
5222 * @param {Array<String>} basicAuthCreds The basic authentication headers for the REST message
5223 * @param {Array<Object>} headers The object contains headers for the REST message
5224 * @param {Array<Object>} stringParameters The object contains string parameters for the REST message
5225 * @param {Array<Object>} stringParametersNoEscape The object contains string parameters which will be not escaped for the REST message
5226 * @return {SaraRESTMessage}
5227 */
5228 newOAuthRequest: function (method, endpoint, basicAuthCreds, headers, stringParameters, stringParametersNoEscape) {
5229 return this.newServiceRequest(SaraCommon.REST_NAME.OAUTH, method, endpoint, basicAuthCreds, headers)
5230 },
5231
5232 /**
5233 * Execute REST Message request
5234 * @param {SaraRESTMessage} saraRest Sara REST Message object
5235 * @return {SaraRESTResponse}
5236 */
5237 execute: function (saraRest) {
5238 var LOGGER = this.LOGGER;
5239
5240 LOGGER.info('Making {0} request to {1}...', saraRest.getMethod(), saraRest.getEndpoint());
5241 LOGGER.debug(saraRest.dump());
5242
5243 var response;
5244 if (this.midServer) {
5245 response = saraRest.executeViaMIDServer(this.midServer);
5246 } else {
5247 response = saraRest.execute();
5248 }
5249
5250 return response;
5251 },
5252
5253 /**
5254 * Execute REST Message request with automatically get new token if token is expired
5255 * @param {SaraRESTMessage} saraRest Sara REST Message object
5256 * @return {SaraRESTResponse}
5257 */
5258 executeWithRefreshToken: function (saraRest) {
5259 var LOGGER = this.LOGGER;
5260
5261 // First time request
5262 var response = this.execute(saraRest);
5263 var responseObject = response.getResponseObject();
5264
5265 if (response.haveError()) {
5266 if (responseObject.statusCode === 401) {
5267 LOGGER.info('Access token of user is invalid or expired');
5268
5269 var oauthClient = new SaraOAuthClient(this);
5270 var username = new SaraConfig().getTechnicalUser();
5271
5272 LOGGER.info('Trying to refresh token for user "{0}"...', username);
5273 var tokens = oauthClient.refreshToken(username);
5274
5275 if (tokens && !tokens.error) {
5276 LOGGER.info('Refresh token finished successfully.');
5277 oauthClient.storeUserTokens(username, tokens['access_token'], tokens['refresh_token'], tokens['expires_in'], tokens['token_type']);
5278
5279 // Request again with new token
5280 saraRest.addHeader('Authorization', 'bearer ' + tokens['access_token']);
5281 response = this.execute(saraRest);
5282 } else {
5283 LOGGER.error('Error when refreshing token');
5284
5285 if (!tokens) {
5286 LOGGER.info('Error: {0} - Error description: {1}', tokens.error, tokens.errorDescription);
5287 oauthClient.removeUserToken(username);
5288 }
5289 }
5290 }
5291 }
5292
5293 return response;
5294 },
5295
5296 /**
5297 * Set MID Server
5298 * @param {String} midServer The MID Server name
5299 */
5300 setMIDServer: function (midServer) {
5301 this.midServer = midServer;
5302 },
5303
5304 type: 'SaraRESTClient'
5305};
5306]]></script>
5307 <description>Wraps Service Now RESTMessage in a class to provide convenient methods interacting with SARA REST</description>
5308 <active>true</active>
5309 <client_callable>false</client_callable>
5310 <access>public</access>
5311 </script_include>
5312
5313 <script_include>
5314 <name>SaraRESTMessage</name>
5315 <script><![CDATA[/**
5316 * Wrap original ServiceNow's RESTMessageV2 class to make HTTP request
5317 */
5318var SaraRESTMessage = Class.create();
5319SaraRESTMessage.prototype = {
5320 /**
5321 * Init Sara REST Message object
5322 * @param {String} name Name of REST message record
5323 * @param {String} method The name of the HTTP method to use, such as GET or PUT
5324 */
5325 initialize: function (name, method) {
5326 method = method.toLowerCase();
5327 this.restMsg = new sn_ws.RESTMessageV2(name, method);
5328 this.name = name;
5329 this.method = method;
5330
5331 this.LOGGER = new SaraLog(this);
5332 },
5333
5334 /**
5335 * Set the content of the REST message body
5336 * @param {String} content The content of REST Message
5337 */
5338 setContent: function (content) {
5339 this.restMsg.setRequestBody(content);
5340 },
5341
5342 /**
5343 * Set form content for REST Message
5344 * @param {Object} formData The object contains form data
5345 */
5346 setFormContent: function (formData) {
5347 if (!formData) {
5348 return;
5349 }
5350
5351 var content = '';
5352
5353 for (var propName in formData) {
5354 var value = formData[propName];
5355
5356 if (value instanceof Array) {
5357 for (var i = 0; i < value.length; i++) {
5358 var _value = value[i];
5359
5360 content += (encodeURIComponent(propName) + '=' + encodeURIComponent(_value) + '&');
5361 }
5362 } else {
5363 content += (encodeURIComponent(propName) + '=' + encodeURIComponent(value) + '&');
5364 }
5365 }
5366
5367 if (content.length > 0) {
5368 content = content.substring(0, content.length - 1);
5369 this.setContent(content);
5370 }
5371 },
5372
5373 /**
5374 * Get the content of the REST message body
5375 * @return {String}
5376 */
5377 getContent: function () {
5378 return this.restMsg.getRequestBody();
5379 },
5380
5381 /**
5382 * Add headers for REST Message
5383 * @param {String} key The key of header
5384 * @param {*} value The value of header
5385 */
5386 addHeader: function (key, value) {
5387 var LOGGER = this.LOGGER;
5388
5389 LOGGER.debug('addHeader: key = "{0}" and value = "{1}"', key, value);
5390
5391 this.restMsg.setRequestHeader(key, value);
5392 },
5393
5394 /**
5395 * Add type for header named 'content-type'
5396 * @param {String} type The content type of REST Message
5397 */
5398 setContentType: function (type) {
5399 var LOGGER = this.LOGGER;
5400
5401 LOGGER.debug('setContentType: type = "{0}"', type);
5402
5403 this.addHeader('content-type', type);
5404 },
5405
5406 /**
5407 * Set basic authentication headers for the REST message
5408 * @param {String} usename
5409 * @param {String} password
5410 */
5411 setBasicAuth: function (username, password) {
5412 var LOGGER = this.LOGGER;
5413
5414 LOGGER.debug('setBasicAuth: username = "{0}" and password = "{1}"', username, password);
5415
5416 this.restMsg.setBasicAuth(username, password);
5417 },
5418
5419 /**
5420 * Set a REST message function variable to the specified value
5421 * @param {String} name The name of parameter
5422 * @param {String} value The value of parameter
5423 */
5424 setStringParameter: function (name, value) {
5425 var LOGGER = this.LOGGER;
5426
5427 LOGGER.debug('setStringParameter: name = "{0}" and value = "{1}"', name, value);
5428
5429 this.restMsg.setStringParameter(name, value);
5430 },
5431
5432 /**
5433 * Set a REST message function variable to the specified value without escaping XML reserved characters
5434 * @param {String} name The name of parameter
5435 * @param {String} value The value of parameter
5436 */
5437 setStringParameterNoEscape: function (name, value) {
5438 var LOGGER = this.LOGGER;
5439
5440 LOGGER.debug('setStringParameterNoEscape: name = "{0}" and value = "{1}"', name, value);
5441
5442 this.restMsg.setStringParameterNoEscape(name, value);
5443 },
5444
5445 /**
5446 * Set the endpoint for the REST message
5447 * @param {String} endpoint
5448 */
5449 setEndpoint: function (endpoint) {
5450 var LOGGER = this.LOGGER;
5451
5452 LOGGER.debug('setEndpoint: endpoint = "{0}"', endpoint);
5453
5454 this.restMsg.setEndpoint(endpoint);
5455 },
5456
5457 /**
5458 * Get the URL of the endpoint for the REST message.
5459 * @return {String}
5460 */
5461 getEndpoint: function () {
5462 return this.restMsg.getEndpoint();
5463 },
5464
5465 /**
5466 * Configure the REST message to communicate through a MID Server.
5467 * @param {String} midServer The name of MID Server
5468 */
5469 setMIDServer: function (midServer) {
5470 var LOGGER = this.LOGGER;
5471
5472 LOGGER.debug('setMIDServer: midServer = "{0}"', midServer);
5473
5474 this.restMsg.setMIDServer(midServer);
5475 },
5476
5477 /**
5478 * Send REST Message to endpoint
5479 * @return {}
5480 */
5481 execute: function () {
5482 return new SaraRESTResponse(this.restMsg.execute());
5483 },
5484
5485 /**
5486 * Execute REST request via MID Server
5487 * @param {String} midServer The name of MID Server
5488 */
5489 executeViaMIDServer: function (midServer) {
5490 var LOGGER = this.LOGGER;
5491
5492 if (midServer) {
5493 this.restMsg.setMIDServer(midServer);
5494 this.midServer = midServer;
5495 LOGGER.info('Using MID Server {0}', this.midServer);
5496 }
5497
5498 if (!this.midServer) {
5499 LOGGER.info('No MID Server defined for the request. Request is aborted!');
5500 return null;
5501 }
5502
5503 return new SaraRESTResponse(this.restMsg.execute(), true);
5504 },
5505
5506 /**
5507 * Get method name of this REST Message
5508 * @return {String}
5509 */
5510 getMethod: function () {
5511 return this.method.toUpperCase();
5512 },
5513
5514 /**
5515 * Dump information of REST Message
5516 */
5517 dump: function () {
5518 var LOGGER = this.LOGGER;
5519
5520 try {
5521 var str = this.getMethod() + ' ' + this.getEndpoint() + ' HTTP/1.1';
5522
5523 var headers = this.restMsg.getRequestHeaders();
5524 if (headers) {
5525 for (key in headers) {
5526 var value = headers[key];
5527
5528 if (!gs.nil(value)) {
5529 if (key === 'Authorization') {
5530 value = '**********************';
5531 }
5532
5533 str += SaraUtils.formatString('\n {0}: {1}', key, value);
5534 }
5535 }
5536 }
5537
5538 var content = this.getContent();
5539
5540 if (!gs.nil(content) && content !== 'undefined' && content) {
5541 str += SaraUtils.formatString('\n\n', content);
5542 }
5543
5544 return str;
5545 } catch (error) {
5546 LOGGER.info('Error in SaraRESTMessage.dump(): ' + error);
5547 }
5548 },
5549
5550 type: 'SaraRESTMessage'
5551};
5552]]></script>
5553 <description>Class extend from original ServiceNow's RESTMessage class to make HTTP request</description>
5554 <active>true</active>
5555 <client_callable>false</client_callable>
5556 <access>package_private</access>
5557 </script_include>
5558
5559 <script_include>
5560 <name>SaraRESTResponse</name>
5561 <script><![CDATA[/**
5562 * Wrap original ServiceNow's RESTResponseV2 class to handle response of RESTMessageV2
5563 */
5564var SaraRESTResponse = Class.create();
5565SaraRESTResponse.prototype = {
5566 /**
5567 * Init Sara REST Response object
5568 * @param {sn_ws.RESTResponseV2} response The response object of RESTResponseV2
5569 * @param {Boolean} useMIDServer Get response via MID Server or not
5570 */
5571 initialize: function (response, useMIDServer) {
5572 this.response = response;
5573
5574 var LOGGER = this.LOGGER = new SaraLog(this);
5575
5576 if (useMIDServer) {
5577 var timeout = SaraUtils.getSaraProperty(SaraCommon.SYSTEM_PROPERTY_NAME.REST_REQUEST_TIMEOUT);
5578 LOGGER.debug('Timeout for REST Message: {0}s', timeout);
5579 response.waitForResponse(timeout);
5580 }
5581
5582 if (response.haveError()) {
5583 LOGGER.info('Error when requesting REST Message: {0} - {1}', response.getErrorCode(), response.getErrorMessage());
5584 } else {
5585 LOGGER.info('Status code: {0}', response.getStatusCode());
5586 }
5587
5588 LOGGER.debug('Response body: {0}', response.getBody());
5589 },
5590
5591 /**
5592 * Set the amount of time the instance waits for the response
5593 * @param {Number} timeoutSecs The amount of time, in seconds, to wait for this response.
5594 */
5595 waitForResponse: function (timeoutSecs) {
5596 this.response.waitForResponse(timeoutSecs);
5597 },
5598
5599 /**
5600 * Get the numeric HTTP status code returned by the REST provider
5601 * @return {Number}
5602 */
5603 getStatusCode: function () {
5604 return this.response.getStatusCode();
5605 },
5606
5607 /**
5608 * Get the value for a specified header
5609 * @param {Number} timeoutSecs The name of the header that you want the value for, such as Set-Cookie.
5610 * @return {String}
5611 */
5612 getHeader: function (name) {
5613 return this.response.getHeader(name);
5614 },
5615
5616 /**
5617 * Get all headers returned in the REST response and the associated values
5618 * @return {Object}
5619 */
5620 getHeaders: function () {
5621 return this.response.getHeaders();
5622 },
5623
5624 /**
5625 * Get the content of the REST response body
5626 * @return {String}
5627 */
5628 getBody: function () {
5629 return this.response.getBody();
5630 },
5631
5632 /**
5633 * Indicate if there was an error during the REST transaction
5634 * @return {Boolean}
5635 */
5636 haveError: function () {
5637 return this.response.haveError();
5638 },
5639
5640 /**
5641 * Get the numeric error code if there was an error during the REST transaction. This error code is
5642 * specific to the ServiceNow platform, it is not an HTTP error code. Provide this error code if you
5643 * require assistance from ServiceNow Customer Support
5644 * @return {Number}
5645 */
5646 getErrorCode: function () {
5647 return this.response.getErrorCode();
5648 },
5649
5650 /**
5651 * Get the error message if there was an error during the REST transaction
5652 * @return {String}
5653 */
5654 getErrorMessage: function () {
5655 return this.response.getErrorMessage();
5656 },
5657
5658 /**
5659 * Get the fully-resolved query sent to the REST endpoint. This query contains the endpoint URL as well
5660 * as any values assigned to variables in the REST message
5661 */
5662 getQueryString: function () {
5663 return this, response.getQueryString();
5664 },
5665
5666 /**
5667 * Get response body with format is Object
5668 * @return {Object|Null}
5669 */
5670 getBodyObject: function () {
5671 var LOGGER = this.LOGGER;
5672
5673 var body = this.getBody();
5674 if (body) {
5675 try {
5676 body = SaraJSON.parse(body);
5677 } catch (ex) {
5678 LOGGER.error('Error when parsing response body to Object: {0}', ex);
5679 }
5680 }
5681
5682 return body;
5683 },
5684
5685 /**
5686 * Get response with format is Object. This response contains body object, status code, error message and
5687 * error description
5688 * @return {Object}
5689 */
5690 getResponseObject: function () {
5691 var bodyObject = this.getBodyObject();
5692 var statusCode = this.getStatusCode();
5693 var errorMessage = this.getErrorMessage();
5694 var errorDescription = this.getErrorMessage();
5695
5696 if (bodyObject) {
5697 if (bodyObject['error']) {
5698 errorMessage = bodyObject['error'];
5699 }
5700
5701 if (bodyObject['error_description']) {
5702 errorDescription = bodyObject['error_description'];
5703 }
5704 }
5705
5706 return {
5707 bodyObject: bodyObject,
5708 statusCode: statusCode,
5709 errorMessage: errorMessage,
5710 errorDescription: errorDescription
5711 }
5712 },
5713
5714 type: 'SaraRESTResponse'
5715};
5716]]></script>
5717 <description>Wrap original ServiceNow's RESTResponseV2 class to handle RESTMessageV2 response</description>
5718 <active>true</active>
5719 <client_callable>false</client_callable>
5720 <access>package_private</access>
5721 </script_include>
5722
5723 <script_include>
5724 <name>SaraSync</name>
5725 <script><![CDATA[/**
5726 * Sara Sync Utilities
5727 */
5728var SaraSync = Class.create();
5729SaraSync.prototype = {
5730 initialize: function () {
5731 this.glideHelper = new SaraGlideHelper();
5732 this.LOGGER = new SaraLog(this);
5733 this.dal = new SaraConsumerDAL();
5734 },
5735
5736 /**
5737 * Sync services and catalogs of all category which was imported services
5738 */
5739 syncServices: function () {
5740 var glideHelper = this.glideHelper;
5741 var LOGGER = this.LOGGER;
5742
5743 var importedCategories = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {
5744 'u_type': 'category'
5745 }, true);
5746
5747 if (importedCategories.length > 0) {
5748 LOGGER.info('There are {0} target category(s) which were imported services\n', importedCategories.length);
5749
5750 var consumer = new SaraConsumerImportSet();
5751 var response = consumer.discover();
5752
5753 if (response.error) {
5754 LOGGER.error('Discover data from SAPI not successfully. Syncing services is aborted!');
5755 return;
5756 } else {
5757 for (var i = 0; i < importedCategories.length; i++) {
5758 var importedCategory = importedCategories[i];
5759 LOGGER.info('Syncing target category (name = {0}, sys_id = {1})', importedCategory.u_name, importedCategory.u_parent);
5760
5761 consumer.doImport(importedCategory.u_parent);
5762 consumer.refreshImportedData();
5763
5764 LOGGER.info('Target category (name = {0}, sys_id = {1}) is synced!', importedCategory.u_name, importedCategory.u_parent);
5765 }
5766 }
5767 } else {
5768 LOGGER.warn('No target category found. Skip syncServices!');
5769 }
5770 },
5771
5772 /**
5773 * Sync all lookup values of catalog item
5774 * @param {String} saraItem The catalog item in SaraCommon.TABLE_NAME.SARA_DEFINITION
5775 * @param {SaraModel.CatalogItem} catalogItem
5776 */
5777 //saraCatalogItem, catalogItem
5778 syncLookup: function (existDefinition, sapiService) {
5779 var glideHelper = this.glideHelper;
5780 var LOGGER = this.LOGGER;
5781
5782 LOGGER.info('Starting syncLookup... definition: {0}; sapiService: {1}',
5783 SaraJSON.stringify(existDefinition), SaraJSON.stringify(sapiService));
5784
5785 if (sapiService.getVariables()) {
5786 // Get variable set of catalog item
5787 var varSetId = existDefinition.u_var_set;
5788 LOGGER.info('Found sys_id of variable set of {0} is: {1}', existDefinition.u_name, varSetId);
5789
5790 // Get lookup variables of variable set
5791 var saraLookupVariables = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_VARIABLE, {
5792 'variable_set': varSetId,
5793 'u_is_lookup': true
5794 }, true);
5795
5796 if (saraLookupVariables.length > 0) {
5797 LOGGER.info('Found {0} lookup variable(s) in variable set (sys_id = {1})', saraLookupVariables.length, varSetId);
5798
5799 for (var i = 0; i < saraLookupVariables.length; i++) {
5800 var saraVariable = saraLookupVariables[i];
5801 LOGGER.info("Processing variable: " + saraVariable.name);
5802 var variable = this.getVariable(sapiService, saraVariable.name);
5803 if(variable !== null) {
5804 this.updateLookupVariable(saraVariable, variable);
5805 }
5806 }
5807 } else {
5808 LOGGER.warn('No lookup variable found in variable set (sys_id = {0}). Skip syncLookup!', varSetId);
5809 }
5810 } else {
5811 LOGGER.warn('There\' no variable found in catalog (item name = {0}). Skip syncLookup!', existDefinition.u_name);
5812 }
5813
5814 LOGGER.info('Ended syncLookup!');
5815 },
5816
5817 /**
5818 * Get variable from instance of SaraModel.CatalogItem
5819 * @param {SaraModel.CatalogItem} catalogItem
5820 * @param {String} saraVariableName
5821 * @return {SaraModel.CatalogVariable||Null}
5822 */
5823 getVariable: function (sapiService, saraVariableName) {
5824 for (var i = 0; i < sapiService.variables.length; i++) {
5825 if (sapiService.variables[i].name === saraVariableName) {
5826 return sapiService.variables[i];
5827 }
5828 }
5829
5830 return null;
5831 },
5832
5833 /**
5834 * Update lookup variable
5835 * @param {Object} saraVariable The variable from SaraCommon.TABLE_NAME.SARA_DEFINITION, has 'sys_id', 'type', 'name', 'u_hash', 'list_table', 'lookup_table' and 'default_value'
5836 * @param {SaraModel.CatalogVariable} variable
5837 */
5838 updateLookupVariable: function (saraVariable, variable) {
5839 var glideHelper = this.glideHelper;
5840 var LOGGER = this.LOGGER;
5841
5842 LOGGER.info('New and old hash of variable "{0}": {1} - {2}', saraVariable.name, variable.getHash(), saraVariable.u_hash);
5843
5844 if (variable.getHash() === saraVariable.u_hash) {
5845 LOGGER.info('Lookup value of variable "{0}" is not changed!', saraVariable.name);
5846 } else {
5847 LOGGER.info('Lookup value of variable "{0}" is changed!', saraVariable.name);
5848
5849 this.deactivateOldLookupValues(saraVariable);
5850
5851 var newDefaultValues = [];
5852 var ranges = variable.getRange();
5853
5854 // Insert new range values
5855 for (var i = 0; i < ranges.length; i++) {
5856 var range = ranges[i];
5857 var rangeId = this.dal.saveOrUpdateSaraLookup({
5858 'u_key': range.Value,
5859 'u_display_name': range.Key,
5860 'u_control_id': saraVariable.sys_id
5861 }).sys_id;
5862
5863 if (SaraUtils.inArray(variable.getDefaultValue(), range.Key)) {
5864 if(variable.getType() === SaraCommon.VAR_TYPE.LIST_COLLECTOR) {
5865 newDefaultValues.push(rangeId);
5866 }
5867 else {
5868 newDefaultValues.push(range.Key);
5869 }
5870 }
5871 }
5872 LOGGER.info('Inserted new data of {0} in {1}!', saraVariable.name, SaraCommon.TABLE_NAME.SARA_LOOKUP);
5873
5874 if (saraVariable.default_value) {
5875 newDefaultValues = newDefaultValues.join(',');
5876
5877 saraVariable.default_value = newDefaultValues;
5878 saraVariable.u_hash = variable.getHash();
5879 this.dal.saveOrUpdateVariable(saraVariable);
5880
5881 LOGGER.info('Updated default value for variable (name = {0}, sys_id = {1}) with new default_value = {2}',
5882 saraVariable.name, saraVariable.sys_id, newDefaultValues);
5883 }
5884 }
5885 },
5886
5887 deactivateOldLookupValues: function(saraVariable) {
5888 var glideHelper = this.glideHelper;
5889 var LOGGER = this.LOGGER;
5890 // Remove the old data of lookup table
5891 var lookups = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_LOOKUP, {
5892 'u_control_id': saraVariable.sys_id
5893 }, true);
5894
5895 for(var i = 0; i < lookups.length; i++) {
5896 var lookup = lookups[i];
5897 lookup.u_control_id = "";
5898 this.dal.saveOrUpdateSaraLookup(lookup);
5899 }
5900
5901 LOGGER.info('Deactivated old data of {0} in {1}!', saraVariable.name, SaraCommon.TABLE_NAME.SARA_LOOKUP);
5902 },
5903
5904 type: 'SaraSync'
5905};
5906]]></script>
5907 <description>Sara Sync Utilities</description>
5908 <active>true</active>
5909 <client_callable>false</client_callable>
5910 <access>public</access>
5911 </script_include>
5912
5913 <script_include>
5914 <name>SaraUtils</name>
5915 <script><![CDATA[/**
5916 * Sara Utilities
5917 */
5918var SaraUtils = Class.create();
5919SaraUtils.prototype = {
5920 initialize: function () {},
5921
5922 type: 'SaraUtils'
5923};
5924
5925/**
5926 * Format strings
5927 * @param {String} string The template string
5928 * @param {String[]} args Zero or more objects to format, supplied either in a comma-delimited list or as an array
5929 */
5930SaraUtils.formatString = function (string) {
5931 if(!string) {
5932 return "";
5933 }
5934 var args = Array.prototype.slice.call(arguments, 1);
5935
5936 return string.replace(/\{(\d+)\}/g, function (match, number) {
5937 return typeof args[number] != 'undefined' ? args[number] : match;
5938 });
5939};
5940
5941/**
5942 * Get Sara property
5943 * @param {String} name Name of sara property
5944 * @return {String}
5945 */
5946SaraUtils.getSaraProperty = function (name) {
5947 var property = gs.getProperty(SaraCommon.PROP_PREFIX + '.' + name);
5948 if(property == null) {
5949 property = gs.getProperty(name);
5950 }
5951
5952 return property;
5953};
5954
5955/**
5956 * Get mid servcer
5957 * @return {String}
5958 */
5959SaraUtils.getMIDServer = function () {
5960 return SaraUtils.getSaraProperty(SaraCommon.SYSTEM_PROPERTY_NAME.MID_SERVER);
5961};
5962
5963/**
5964 * Get timestamp of current
5965 * @return {String}
5966 */
5967SaraUtils.getTimeStamp = function () {
5968 return new Date().valueOf();
5969};
5970
5971/**
5972 * Get random number
5973 * @return {String}
5974 */
5975SaraUtils.getRandom = function () {
5976 return Math.round(Math.random() * 987654321);
5977};
5978
5979/**
5980 * Diff time and return 'h, m, s'
5981 * @param {Number} time1 The first timestamp
5982 * @param {Number} time2 The second timestamp
5983 * @return {String}
5984 */
5985SaraUtils.diffTime = function (time1, time2) {
5986 var difference = time2 - time1;
5987
5988 var daysDifference = Math.floor(difference / 1000 / 60 / 60 / 24);
5989 difference -= daysDifference * 1000 * 60 * 60 * 24;
5990
5991 var hoursDifference = Math.floor(difference / 1000 / 60 / 60);
5992 difference -= hoursDifference * 1000 * 60 * 60;
5993
5994 var minutesDifference = Math.floor(difference / 1000 / 60);
5995 difference -= minutesDifference * 1000 * 60;
5996
5997 var secondsDifference = Math.floor(difference / 1000);
5998 difference -= secondsDifference * 1000;
5999
6000 var result = '';
6001
6002 if (daysDifference > 0) {
6003 result += daysDifference + 'd ';
6004 }
6005
6006 if (hoursDifference > 0) {
6007 result += hoursDifference + 'h ';
6008 }
6009
6010 if (minutesDifference > 0) {
6011 result += minutesDifference + 'm ';
6012 }
6013
6014 if (secondsDifference > 0) {
6015 result += secondsDifference + 's ';
6016 }
6017
6018 result += difference + 'ms';
6019
6020 return result;
6021};
6022
6023/**
6024 * Convert '\n' to '<br />' in string
6025 * @param {String} string
6026 * @return {String}
6027 */
6028SaraUtils.nl2br = function (string) {
6029 string = string || '';
6030
6031 return string.replace(/\n/g, '<br />');
6032};
6033
6034/**
6035 * Clean all data of SNSC
6036 */
6037SaraUtils.cleanup = function (filter) {
6038 if (!gs.hasRole(SaraCommon.ROLES.ADMIN)) {
6039 var message = 'You dont\'t have sufficient permission to do this action. Allowed role: ' + SaraCommon.ROLES.ADMIN;
6040 throw new Error(message);
6041 }
6042
6043 var glideHelper = new SaraGlideHelper();
6044 var LOGGER = new SaraLog('SaraUtils');
6045 var catItemIds = [];
6046 var varSetIds = [];
6047 var catCateIds = [];
6048 var targetCateIds = [];
6049
6050 filter = filter || {};
6051
6052 // Get list of catalog item from SaraCommon.TABLE_NAME.SARA_DEFINITION table
6053 var saraItems = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, filter, true);
6054
6055 if (saraItems.length > 0) {
6056 LOGGER.info('Found {0} item(s) in "{1}"', saraItems.length, SaraCommon.TABLE_NAME.SARA_DEFINITION);
6057
6058 for (var i = 0, saraItem; saraItem = saraItems[i]; i++) {
6059 if (saraItem['u_sc_item']) {
6060 catItemIds.push(saraItem['u_sc_item']);
6061 }
6062
6063 if (saraItem['u_var_set']) {
6064 varSetIds.push(saraItem['u_var_set']);
6065 }
6066
6067 if (saraItem['u_service_catalog_category']) {
6068 catCateIds.push(saraItem['u_service_catalog_category']);
6069 }
6070
6071 if (saraItem['u_type'] === 'category') {
6072 targetCateIds.push(saraItem['u_parent']);
6073 }
6074 }
6075
6076 var message = 'There are :';
6077 message += SaraUtils.formatString('\n - {0} catalog item(s)', catItemIds.length);
6078 message += SaraUtils.formatString('\n - {0} variable set(s)', varSetIds.length);
6079 message += SaraUtils.formatString('\n - {0} category(s)', catCateIds.length);
6080 message += SaraUtils.formatString('\n - {0} target category(s)', targetCateIds.length);
6081 LOGGER.info(message);
6082
6083 if (varSetIds.length > 0) {
6084 LOGGER.info('Removing {0} variable set(s)...', varSetIds.length);
6085
6086 for (var i = 0, varSetId; varSetId = varSetIds[i]; i++) {
6087 // Remove all variables belong to above variable sets
6088 LOGGER.info('Removing variables from variable set {0}...', varSetId);
6089 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_VARIABLE, {
6090 'variable_set': varSetId
6091 }, true);
6092
6093 // Remove all variable sets
6094 LOGGER.info('Removing variable set (sys_id = {0})...', varSetId);
6095 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_VARIABLE_SET, {
6096 'sys_id': varSetId
6097 }, true);
6098 }
6099 }
6100
6101 // Cleanup service catalog items
6102 if (catItemIds.length > 0) {
6103 LOGGER.info('Removing {0} catalog item(s)...', catItemIds.length);
6104
6105 for (var i = 0, catItemId; catItemId = catItemIds[i]; i++) {
6106 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_CAT_ITEM, {
6107 'sys_id': catItemId
6108 });
6109 }
6110 }
6111
6112 // Cleanup catalog categories
6113 if (catCateIds.length > 0) {
6114 LOGGER.info('Removing {0} catalog category(s)...', catCateIds.length);
6115
6116 for (var i = 0, catCateId; catCateId = catCateIds[i]; i++) {
6117 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_CATEGORY, {
6118 'sys_id': catCateId
6119 });
6120 }
6121 }
6122
6123 // Refresh target categories
6124 if (targetCateIds.length > 0) {
6125 LOGGER.info('Refreshing {0} target category(s)...', catCateIds.length);
6126
6127 for (var i = 0, targetCateId; targetCateId = targetCateIds[i]; i++) {
6128 glideHelper.updateData(SaraCommon.TABLE_NAME.SN_CATEGORY, {
6129 'sys_id': targetCateId
6130 }, {
6131 'active': false
6132 });
6133
6134 glideHelper.updateData(SaraCommon.TABLE_NAME.SN_CATEGORY, {
6135 'sys_id': targetCateId
6136 }, {
6137 'active': true
6138 });
6139
6140 LOGGER.info('Target category (sys_id = {0}) is refreshed.', targetCateId);
6141 }
6142 }
6143
6144 LOGGER.info('Cleaning up {0} table ...', SaraCommon.TABLE_NAME.SARA_DEFINITION);
6145 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {}, true);
6146
6147 LOGGER.info('Cleaning up {0} table ...', SaraCommon.TABLE_NAME.SARA_VARIABLE);
6148 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_VARIABLE, {}, true);
6149 } else {
6150 LOGGER.warn('There is no items in "{0}". Skip cleanup!', SaraCommon.TABLE_NAME.SARA_DEFINITION);
6151 }
6152};
6153
6154/**
6155 * Create catalog variable from field information
6156 * @param {Object} field
6157 * @return {SaraModel.CatalogVariable}
6158 */
6159SaraUtils.createCatalogVariable = function (field) {
6160 var defaultValue = '';
6161 var varType;
6162 var isLookupControl = false;
6163 var LOGGER = new SaraLog('SaraUtils');
6164
6165 if (field['default'] && field['default'].length > 0) {
6166 defaultValue = field['default'];
6167 }
6168
6169 switch (field.type) {
6170 case 'Label':
6171 varType = SaraCommon.VAR_TYPE.LABEL;
6172 break;
6173 case 'Number':
6174 // SN only have NUM_SCALE variable type but not suitable, just use string
6175 varType = SaraCommon.VAR_TYPE.SINGLE_LINE_TEXT;
6176 break;
6177 case 'String':
6178 varType = SaraCommon.VAR_TYPE.SINGLE_LINE_TEXT;
6179 break;
6180 case 'List':
6181 varType = field.multiSelect ? SaraCommon.VAR_TYPE.LIST_COLLECTOR : SaraCommon.VAR_TYPE.LOOKUP_SELECT_BOX;
6182 isLookupControl = true;
6183 break;
6184 case 'Time':
6185 varType = SaraCommon.VAR_TYPE.SINGLE_LINE_TEXT;
6186 break;
6187 case 'Date':
6188 varType = SaraCommon.VAR_TYPE.DATE;
6189 break;
6190 case 'Timestamp':
6191 varType = SaraCommon.VAR_TYPE.DATE_TIME;
6192 break;
6193 default:
6194 break;
6195 }
6196
6197 var catalogVariable = new SaraModel.CatalogVariable();
6198 catalogVariable.setName(this.legitVarName(field.name));
6199 catalogVariable.setType(varType);
6200 catalogVariable.setLabel(field.caption);
6201 catalogVariable.setDefaultValue(defaultValue);
6202 catalogVariable.setDescription(field.description);
6203 catalogVariable.setRange([]);
6204 catalogVariable.setAsLookup(isLookupControl);
6205
6206 if(field.order != null && field.order != undefined) {
6207 catalogVariable.setOrder(field.order);
6208 }
6209
6210 if (field.maskAsPassword) {
6211 catalogVariable.setAsPassword(field.maskAsPassword);
6212 }
6213
6214 if (field.range && field.range[0].values) {
6215 var rangeValue = field.range[0].values;
6216 catalogVariable.setRange(rangeValue);
6217
6218 // Generate range hash for variable
6219 var hash = SaraUtils.md5(SaraJSON.stringify(rangeValue));
6220 catalogVariable.setHash(hash);
6221 }
6222
6223 if (field.name) {
6224 catalogVariable.setActualName(field.name);
6225 }
6226
6227 if (field.required) {
6228 catalogVariable.setRequired(field.required);
6229 }
6230
6231 if (field.multiSelect) {
6232 catalogVariable.setMultiSelect(field.multiSelect);
6233 }
6234
6235 return catalogVariable;
6236};
6237
6238/**
6239 * Legitimates variable name that is not qualified business rule validate_variable_name
6240 * @param {String} varName
6241 * @return {String}
6242 */
6243SaraUtils.legitVarName = function (varName) {
6244 var firstLegal = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
6245 var firstLetter = varName.charAt(0);
6246 if (firstLegal.indexOf(firstLetter) == -1) {
6247 varName = 'v_' + varName;
6248 }
6249
6250 var legal = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789';
6251 for (var i = 0; i < varName.length; i++) {
6252 var letter = varName.charAt(i);
6253 if (legal.indexOf(letter) == -1) {
6254 // replace illegal char with _
6255 varName = varName.substr(0, i) + '_' + varName.substr(i + 1);
6256 }
6257 }
6258
6259 return varName;
6260};
6261
6262SaraUtils.getImportTargetCatRefQual = function(){
6263 var gh = new SaraGlideHelper();
6264
6265 var catalogs = gh.getData('sc_catalog', {}, true);
6266 var catalogIds = [];
6267 for(var i = 0; i < catalogs.length; i++) {
6268 catalogIds.push(catalogs[i].sys_id);
6269 }
6270
6271 var catalogFilter = ['IN', catalogIds.join(',')];
6272 gs.info('catalogFilter = ' + catalogFilter);
6273
6274 var result = 'sys_idIN';
6275 var cats = gh.getData('sc_category', {sc_catalog: catalogFilter}, true);
6276 var categoryIds = [];
6277
6278 for(i = 0;i < cats.length; i++) {
6279 var cat = cats[i];
6280 gs.info(SaraJSON.stringify(cat));
6281 categoryIds.push(cat.sys_id);
6282 }
6283 result += categoryIds.join(',');
6284
6285 return result;
6286};
6287
6288/**
6289 * Build url
6290 * @param {String} url
6291 * @return {String}
6292 */
6293SaraUtils.buildUrl = function (url) {
6294 if (!url) {
6295 url = '';
6296 }
6297
6298 var scheme;
6299 var pattern = /^https?:\/\//i;
6300 if (pattern.test(url)) {
6301 scheme = 'absolute';
6302 } else {
6303 scheme = 'relative';
6304 }
6305
6306 if (scheme === 'relative') {
6307 var basePath = new SaraConfig().getBasePath();
6308 if (basePath.charAt(basePath.length - 1) == '/' && url.substring(0, 1) == '/') {
6309 return basePath + url.substring(1);
6310 }
6311
6312 if (basePath.charAt(basePath.length - 1) != '/' && url.substring(0, 1) != '/') {
6313 return basePath + '/' + url;
6314 }
6315
6316 return basePath + url;
6317 }
6318
6319 if (url == '/') {
6320 return new SaraConfig().getBasePath();
6321 }
6322
6323 return url;
6324};
6325
6326/**
6327 * Gets index of item in array
6328 * @param {Array} array
6329 * @param {*} item
6330 * @return {Number}
6331 */
6332SaraUtils.indexOf = function (array, item) {
6333 for (var i = 0; i < array.length; ++i) {
6334 if (array[i] === item) {
6335 return i;
6336 }
6337 }
6338
6339 return -1;
6340};
6341
6342/**
6343 * Detects the array item is in array or not
6344 * @param {Array} array
6345 * @param {*} item
6346 * @return {Boolean}
6347 */
6348SaraUtils.inArray = function (array, item) {
6349 return SaraUtils.indexOf(array, item) !== -1;
6350};
6351
6352/**
6353 * Get redirection endpoint of current instance
6354 * @return {String} The redirection endpoint
6355 */
6356SaraUtils.getRedirectionUrl = function () {
6357 return gs.getProperty('glide.servlet.uri') + SaraCommon.SCOPED_APP + '_sara_oauth_callback.do';
6358};
6359
6360SaraUtils.guardNotNullOrEmpty = function(param, msg) {
6361 if(!param || param === null || param === "") {
6362 throw msg;
6363 }
6364};
6365
6366SaraUtils.isNullOrEmpty = function(param) {
6367 if(!param || param === null || param === "") {
6368 return true;
6369 }
6370 return false;
6371};
6372
6373SaraUtils.md5 = function (string, key, raw) {
6374 /*
6375 * JavaScript MD5 1.0.1
6376 * https://github.com/blueimp/JavaScript-MD5
6377 *
6378 * Copyright 2011, Sebastian Tschan
6379 * https://blueimp.net
6380 *
6381 * Licensed under the MIT license:
6382 * http://www.opensource.org/licenses/MIT
6383 *
6384 * Based on
6385 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
6386 * Digest Algorithm, as defined in RFC 1321.
6387 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
6388 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
6389 * Distributed under the BSD License
6390 * See http://pajhome.org.uk/crypt/md5 for more info.
6391 */
6392 /*jslint bitwise: true */
6393 /*global unescape, define */
6394
6395 'use strict';
6396 /*
6397 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
6398 * to work around bugs in some JS interpreters.
6399 */
6400 function safe_add(x, y) {
6401 var lsw = (x & 0xFFFF) + (y & 0xFFFF),
6402 msw = (x >> 16) + (y >> 16) + (lsw >> 16);
6403 return (msw << 16) | (lsw & 0xFFFF);
6404 }
6405 /*
6406 * Bitwise rotate a 32-bit number to the left.
6407 */
6408 function bit_rol(num, cnt) {
6409 return (num << cnt) | (num >>> (32 - cnt));
6410 }
6411 /*
6412 * These functions implement the four basic operations the algorithm uses.
6413 */
6414 function md5_cmn(q, a, b, x, s, t) {
6415 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
6416 }
6417
6418 function md5_ff(a, b, c, d, x, s, t) {
6419 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
6420 }
6421
6422 function md5_gg(a, b, c, d, x, s, t) {
6423 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
6424 }
6425
6426 function md5_hh(a, b, c, d, x, s, t) {
6427 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
6428 }
6429
6430 function md5_ii(a, b, c, d, x, s, t) {
6431 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
6432 }
6433 /*
6434 * Calculate the MD5 of an array of little-endian words, and a bit length.
6435 */
6436 function binl_md5(x, len) {
6437 /* append padding */
6438 x[len >> 5] |= 0x80 << (len % 32);
6439 x[(((len + 64) >>> 9) << 4) + 14] = len;
6440 var i, olda, oldb, oldc, oldd,
6441 a = 1732584193,
6442 b = -271733879,
6443 c = -1732584194,
6444 d = 271733878;
6445 for (i = 0; i < x.length; i += 16) {
6446 olda = a;
6447 oldb = b;
6448 oldc = c;
6449 oldd = d;
6450 a = md5_ff(a, b, c, d, x[i], 7, -680876936);
6451 d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
6452 c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
6453 b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
6454 a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
6455 d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
6456 c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
6457 b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
6458 a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
6459 d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
6460 c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
6461 b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
6462 a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
6463 d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
6464 c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
6465 b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
6466 a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
6467 d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
6468 c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
6469 b = md5_gg(b, c, d, a, x[i], 20, -373897302);
6470 a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
6471 d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
6472 c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
6473 b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
6474 a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
6475 d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
6476 c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
6477 b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
6478 a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
6479 d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
6480 c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
6481 b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
6482 a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
6483 d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
6484 c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
6485 b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
6486 a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
6487 d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
6488 c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
6489 b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
6490 a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
6491 d = md5_hh(d, a, b, c, x[i], 11, -358537222);
6492 c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
6493 b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
6494 a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
6495 d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
6496 c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
6497 b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
6498 a = md5_ii(a, b, c, d, x[i], 6, -198630844);
6499 d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
6500 c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
6501 b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
6502 a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
6503 d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
6504 c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
6505 b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
6506 a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
6507 d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
6508 c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
6509 b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
6510 a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
6511 d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
6512 c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
6513 b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
6514 a = safe_add(a, olda);
6515 b = safe_add(b, oldb);
6516 c = safe_add(c, oldc);
6517 d = safe_add(d, oldd);
6518 }
6519 return [a, b, c, d];
6520 }
6521 /*
6522 * Convert an array of little-endian words to a string
6523 */
6524 function binl2rstr(input) {
6525 var i,
6526 output = '';
6527 for (i = 0; i < input.length * 32; i += 8) {
6528 output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
6529 }
6530 return output;
6531 }
6532 /*
6533 * Convert a raw string to an array of little-endian words
6534 * Characters >255 have their high-byte silently ignored.
6535 */
6536 function rstr2binl(input) {
6537 var i,
6538 output = [];
6539 output[(input.length >> 2) - 1] = undefined;
6540 for (i = 0; i < output.length; i += 1) {
6541 output[i] = 0;
6542 }
6543 for (i = 0; i < input.length * 8; i += 8) {
6544 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
6545 }
6546 return output;
6547 }
6548 /*
6549 * Calculate the MD5 of a raw string
6550 */
6551 function rstr_md5(s) {
6552 return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
6553 }
6554 /*
6555 * Calculate the HMAC-MD5, of a key and some data (raw strings)
6556 */
6557 function rstr_hmac_md5(key, data) {
6558 var i,
6559 bkey = rstr2binl(key),
6560 ipad = [],
6561 opad = [],
6562 hash;
6563 ipad[15] = opad[15] = undefined;
6564 if (bkey.length > 16) {
6565 bkey = binl_md5(bkey, key.length * 8);
6566 }
6567 for (i = 0; i < 16; i += 1) {
6568 ipad[i] = bkey[i] ^ 0x36363636;
6569 opad[i] = bkey[i] ^ 0x5C5C5C5C;
6570 }
6571 hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
6572 return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
6573 }
6574 /*
6575 * Convert a raw string to a hex string
6576 */
6577 function rstr2hex(input) {
6578 var hex_tab = '0123456789abcdef',
6579 output = '',
6580 x,
6581 i;
6582 for (i = 0; i < input.length; i += 1) {
6583 x = input.charCodeAt(i);
6584 output += hex_tab.charAt((x >>> 4) & 0x0F) +
6585 hex_tab.charAt(x & 0x0F);
6586 }
6587 return output;
6588 }
6589 /*
6590 * Encode a string as utf-8
6591 */
6592 function str2rstr_utf8(input) {
6593 return unescape(encodeURIComponent(input));
6594 }
6595 /*
6596 * Take string arguments and return either raw or hex encoded strings
6597 */
6598 function raw_md5(s) {
6599 return rstr_md5(str2rstr_utf8(s));
6600 }
6601
6602 function hex_md5(s) {
6603 return rstr2hex(raw_md5(s));
6604 }
6605
6606 function raw_hmac_md5(k, d) {
6607 return rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d));
6608 }
6609
6610 function hex_hmac_md5(k, d) {
6611 return rstr2hex(raw_hmac_md5(k, d));
6612 }
6613
6614 if (!key) {
6615 if (!raw) {
6616 return hex_md5(string);
6617 }
6618 return raw_md5(string);
6619 }
6620 if (!raw) {
6621 return hex_hmac_md5(key, string);
6622 }
6623
6624 return raw_hmac_md5(key, string);
6625};
6626]]></script>
6627 <description>Sara Utilities</description>
6628 <active>true</active>
6629 <client_callable>false</client_callable>
6630 <access>public</access>
6631 </script_include>
6632
6633 <script_include>
6634 <name>SaraTestBench</name>
6635 <script><![CDATA[/*
6636Test bench for Sara Scripts
6637Create manually in scope of Automic SNSC
6638Use background script to execute:
6639
6640var test = new SaraTestBench();
6641test.execute();
6642 */
6643var SaraTestBench = Class.create();
6644SaraTestBench.prototype = {
6645 initialize: function () {
6646 },
6647
6648 execute: function(){
6649 SaraTest.resetSummary();
6650
6651 SaraTransformMapTest.execute();
6652
6653 SaraConsumerDALTest.execute();
6654
6655 SaraConsumerImportTest.execute();
6656
6657 gs.info("=======================================================================================");
6658 gs.info("SUMMARY");
6659 gs.info("=======================================================================================");
6660 var summary = SaraTest.getSummary();
6661 gs.info("------ TOTAL: " + summary.total);
6662 gs.info("------ PASS: " + summary.pass);
6663 gs.info("------ FAIL: " + summary.fail);
6664 gs.info("------ IGNORE: " + summary.ignore);
6665 }
6666};
6667
6668var SaraConsumerDALTest = (function() {
6669 var gh = new SaraGlideHelper();
6670 var dal = new SaraConsumerDAL();
6671 return {
6672 execute: function() {
6673 gs.info("----------------------------------------------------------------------------");
6674 gs.info("Test SaraConsumerDAL");
6675 gs.info("----------------------------------------------------------------------------");
6676
6677 this.testGetCatalog();
6678 this.testSaveOrUpdateCatalog();
6679 this.testSaveOrUpdateCategory();
6680 this.testGetDefaultCategoryId();
6681 this.testSaveCategoryToSaraDefinition();
6682 this.testDeactivateSaraDefinition();
6683 },
6684
6685 testGetCatalog: function() {
6686 SaraTest.test("get catalog id by title", function() {
6687 var cat = dal.getCatalog("Service Catalog");
6688 SaraTest.assert(cat !== undefined, "catalog is get correctly");
6689 SaraTest.assert(cat.title === "Service Catalog", "title is get correctly");
6690 gs.info(SaraJSON.stringify(cat));
6691 });
6692 },
6693
6694 testSaveOrUpdateCatalog: function() {
6695 SaraTest.test("save or update catalog", function() {
6696 var catName = "snsc dal cat 1" + SaraUtils.getRandom();
6697 var desc = "test description";
6698
6699 var catId = dal.saveOrUpdateCatalog({
6700 title: catName,
6701 description: desc,
6702 active: true
6703 }).sys_id;
6704 SaraTest.assert(catId !== null, "catalog is persisted correctly");
6705
6706 var cat = gh.getData("sc_catalog", {sys_id: catId});
6707 gs.info(SaraJSON.stringify(cat));
6708 SaraTest.assert(cat !== null, "catalog is get correctly");
6709 SaraTest.assert(cat.title === catName, "title is set correctly");
6710 SaraTest.assert(cat.description === desc, "description is set correctly");
6711 SaraTest.assert(cat.active == "true", "active is set correctly");
6712
6713 gh.deleteData("sc_category", {sc_catalog: catId}, true);
6714 gh.deleteData("sc_catalog", {sys_id: catId}, true);
6715 });
6716 },
6717
6718 testSaveOrUpdateCategory: function() {
6719 SaraTest.test("save or update category", function() {
6720 var catName = "snsc dal cat 2" + SaraUtils.getRandom();
6721 var desc = "test description";
6722 var categoryName = "snsc dal category 2" + SaraUtils.getRandom();
6723 var categoryDescription = "category description";
6724 var categoryNewDescription = "category description new";
6725
6726 var catId = dal.saveOrUpdateCatalog({
6727 title: catName,
6728 description: desc,
6729 active: true
6730 }).sys_id;
6731
6732 var cat = {
6733 sc_catalog: catId,
6734 title: categoryName,
6735 description: categoryDescription,
6736 active: true};
6737 cat.description = categoryDescription;
6738 var category = dal.saveOrUpdateCategory(cat);
6739 gs.info("category: " + SaraJSON.stringify(category));
6740 SaraTest.assert(category !== null, "category is get correctly");
6741 SaraTest.assert(category.title === categoryName, "title is set correctly");
6742 SaraTest.assert(category.description === categoryDescription, "description is set correctly");
6743 SaraTest.assert(category.active == "true", "active is set correctly");
6744
6745 category.description = categoryNewDescription;
6746 category.active = false;
6747 dal.saveOrUpdateCategory(category);
6748
6749 var result = gh.getData("sc_category", {sys_id: category.sys_id});
6750 gs.info("result: " + SaraJSON.stringify(result));
6751
6752 SaraTest.assert(result.description === categoryNewDescription, "description is updated correctly");
6753 SaraTest.assert(result.active == "false", "active is updated correctly");
6754
6755 gh.deleteData("sc_category", {sc_catalog: catId}, true);
6756 gh.deleteData("sc_catalog", {sys_id: catId}, true);
6757 });
6758 },
6759
6760 testGetDefaultCategoryId: function() {
6761 SaraTest.test("get default category", function () {
6762 var catId = dal.getDefaultCategoryId();
6763 var category = gh.getData("sc_category", {sys_id: catId});
6764
6765 SaraTest.assert(category !== null, "getDetaultCategoryId return valid category id");
6766 gs.info(SaraJSON.stringify(category));
6767 });
6768 },
6769
6770 testSaveCategoryToSaraDefinition: function() {
6771 SaraTest.test("save category to sara definition", function() {
6772 var catName = "snsc dal cat 3" + SaraUtils.getRandom();
6773 var desc = "test description";
6774
6775 var categoryName = "snsc dal category 3" + SaraUtils.getRandom();
6776 var categoryDescription = "category description";
6777
6778 var catId = dal.saveOrUpdateCatalog({
6779 title: catName,
6780 description: desc,
6781 active: true
6782 }).sys_id;
6783
6784 var category = dal.saveOrUpdateCategory({
6785 sc_catalog: catId,
6786 title: categoryName,
6787 description: categoryDescription,
6788 active: true
6789 });
6790
6791 var definitionId = dal.saveRootImportCategoryToSaraDefinition(category.sys_id).sys_id;
6792 var definition = gh.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: definitionId});
6793 gs.info(SaraJSON.stringify(definition));
6794
6795 SaraTest.assert(definition !== null, "definition is saved correctly");
6796 SaraTest.assert(definition.u_name === categoryName, "u_name is saved correctly");
6797 SaraTest.assert(definition.u_parent === category.sys_id, "u_parent is saved correctly");
6798 SaraTest.assert(definition.u_type === 'category', "u_type is saved correctly");
6799 SaraTest.assert(definition.u_active == 'true', "active is saved correctly");
6800
6801 gh.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: definitionId}, true);
6802 gh.deleteData("sc_category", {sc_catalog: catId}, true);
6803 gh.deleteData("sc_catalog", {sys_id: catId}, true);
6804 });
6805 },
6806
6807 testDeactivateSaraDefinition: function() {
6808 SaraTest.test("deactivate sara definition", function() {
6809 var catName = "snsc dal cat 6" + SaraUtils.getRandom();
6810 var desc = "test description";
6811 var categoryName = "snsc dal category 6" + SaraUtils.getRandom();
6812 var categoryDescription = "category description";
6813 var catalogItemName = "snsc dal catalog item 6";
6814
6815 var parentDefinitionName = "snsc definition 6 parent" + SaraUtils.getRandom();
6816 var definitionName = "snsc definition 6" + SaraUtils.getRandom();
6817
6818 var catId = dal.saveOrUpdateCatalog({
6819 title: catName,
6820 description: desc,
6821 active: true
6822 }).sys_id;
6823 var category = dal.saveOrUpdateCategory({
6824 title: categoryName,
6825 description: categoryDescription,
6826 sc_catalog: catId
6827 });
6828 var catalogItem = dal.saveOrUpdateCatalogItem({
6829 category: category.sys_id,
6830 name: catalogItemName,
6831 active: true
6832 });
6833
6834 var parentDefinition = dal.saveOrUpdateSaraDefinition({
6835 u_name: parentDefinitionName,
6836 u_active: true,
6837 u_consume_url: "http://testurl.com",
6838 u_parent: category.sys_id,
6839 u_type: 'catalog'
6840 });
6841
6842 var definition = dal.saveOrUpdateSaraDefinition({
6843 u_name: definitionName,
6844 u_active: true,
6845 u_consume_url: "http://testurl.com",
6846 u_parent: category.sys_id,
6847 u_type: 'service',
6848 u_sc_item: catalogItem.sys_id,
6849 u_hash: '123'
6850 });
6851
6852 SaraTest.assert(parentDefinition.u_active == 'true', "parent definition is active");
6853 SaraTest.assert(definition.u_active == 'true', "definition is active");
6854
6855 gs.info("parent definition: " + SaraJSON.stringify(parentDefinition));
6856 gs.info("definition: " + SaraJSON.stringify(definition));
6857
6858 dal.deactivateSaraDefinition(parentDefinition);
6859
6860 definition = gh.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: definition.sys_id});
6861 parentDefinition = gh.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: parentDefinition.sys_id});
6862
6863 category = gh.getData("sc_category", {sys_id: category.sys_id});
6864 gs.info("category: " + SaraJSON.stringify(category));
6865
6866 catalogItem = gh.getData("sc_cat_item", {sys_id: catalogItem.sys_id});
6867 gs.info("catalogItem: " + SaraJSON.stringify(catalogItem));
6868
6869 SaraTest.assert(catalogItem.name === catalogItemName,"get correct catalog item");
6870 SaraTest.assert(catalogItem.active == 'false',"catalog item is deactivated");
6871 SaraTest.assert(definition.u_name === definitionName,"get correct definition");
6872 SaraTest.assert(definition.u_active == 'false',"definition is deactivated");
6873 SaraTest.assert(parentDefinition.u_name === parentDefinitionName,"get correct parent definition");
6874 SaraTest.assert(parentDefinition.u_active == 'false',"parent definition is deactivated");
6875
6876
6877 gh.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: definition.sys_id}, true);
6878 gh.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: parentDefinition.sys_id}, true);
6879 //gh.deleteData("sc_cat_item", {category: category.sys_id}, true);
6880 gh.deleteData("sc_category", {sc_catalog: catId}, true);
6881 gh.deleteData("sc_catalog", {sys_id: catId}, true);
6882 });
6883 }
6884 };
6885})();
6886
6887var SaraConsumerImportTest = (function() {
6888 var logger = new SaraLog("SaraGlideHelperTest");
6889 var glideHelper = new SaraGlideHelper();
6890 var categoryName = "snsc test import " + SaraUtils.getRandom();
6891 var consumer = new SaraConsumerImportSet();
6892 var categoryId = null;
6893 var catalogId;
6894 var category;
6895 var dal = new SaraConsumerDAL();
6896 var catItem1 = null;
6897
6898 return {
6899 execute: function() {
6900 gs.info("----------------------------------------------------------------------------");
6901 gs.info("Test SaraConsumerImportSet");
6902 gs.info("----------------------------------------------------------------------------");
6903
6904 this.initialize();
6905
6906 this.testImportCategory();
6907
6908 this.testImportItem();
6909
6910 this.testSyncLookup();
6911
6912 this.tearDown();
6913 },
6914
6915 initialize: function() {
6916 catalogId = glideHelper.getData("sc_catalog", { title: "Service Catalog" }).sys_id;
6917
6918 category = dal.saveOrUpdateCategory({
6919 title: categoryName,
6920 description: "test",
6921 sc_catalog: catalogId,
6922 active: true
6923 });
6924 gs.info("created category: " + category);
6925
6926 gs.info("category to be imported: " + categoryName);
6927
6928 categoryId = category.sys_id;
6929 },
6930
6931 getMockCatalogData: function() {
6932 var catalogsData = {
6933 "DEMO":{
6934 "title":"Automic Demo Services",
6935 "active":true,
6936 "description":"Automic Demo Services",
6937 "parent":"",
6938 "name":"DEMO"},
6939 "DEMO2":{
6940 "title":"DEMO2",
6941 "active":true,
6942 "description":"",
6943 "parent":"",
6944 "name":"DEMO2"}};
6945
6946 //mock catalog data for testing
6947 for(var ctgName in catalogsData) {
6948 this.wrapCategoryData(catalogsData[ctgName]);
6949 }
6950
6951 return catalogsData;
6952 },
6953
6954 getMockupServicesData: function() {
6955 var servicesData = {
6956 "DEMO": {
6957 "PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.ACTIVATE_SNSC_SERVICE.NEW.1":
6958 {
6959 "variables": [
6960 { "description": "", "label": "Currency", "defaultValue": ["EUR"], "type": 18, "required": true, "range": [{ "Value": "EUR", "Key": "EUR" }, { "Value": "US$", "Key": "US$" }], "hash": "d4dcdddf0d7831ecaf23643ce1d4d4b7", "asLookup": true, "name": "EOM_CURRENCY_", "actualName": "EOM_CURRENCY#" },
6961 { "description": "", "label": "Previous Month(s) included", "defaultValue": ["3"], "type": 6, "required": true, "range": [], "asLookup": false, "name": "EOM_MONTHBACK_", "actualName": "EOM_MONTHBACK#" },
6962 { "description": "", "label": "Components", "defaultValue": ["Current Account"], "type": 21, "required": true, "range": [{ "Value": "Current Account", "Key": "Current Account" }, { "Value": "General Ledger", "Key": "General Ledger" }, { "Value": "Loans", "Key": "Loans" }, { "Value": "Mortgage", "Key": "Mortgage" }, { "Value": "Treasury", "Key": "Treasury" }], "hash": "2eb7e44c8b0b12acae8e8322f8b376d3", "asLookup": true, "multiSelect": true, "name": "EOM_COMPONENTS_", "actualName": "EOM_COMPONENTS#" },
6963 { "description": "", "label": "Region", "defaultValue": ["America"], "type": 18, "required": true, "range": [{ "Value": "Africa", "Key": "Africa" }, { "Value": "America", "Key": "America" }, { "Value": "Asia", "Key": "Asia" }, { "Value": "Australia", "Key": "Australia" }, { "Value": "Europe", "Key": "Europe" }], "hash": "a093352aac40b86d0245f2c14e3afc21", "asLookup": true, "name": "EOM_REGION_", "actualName": "EOM_REGION#" },
6964 { "description": "", "label": "Units", "defaultValue": ["Development"], "type": 21, "required": true, "range": [{ "Value": "Development", "Key": "Development" }, { "Value": "Headquarter", "Key": "Headquarter" }, { "Value": "Production", "Key": "Production" }, { "Value": "Research", "Key": "Research" }, { "Value": "Sales", "Key": "Sales" }], "hash": "e6b832d4aef3952cb8120e59d8e1eeaf", "asLookup": true, "multiSelect": true, "name": "EOM_UNITS_", "actualName": "EOM_UNITS#" }
6965 ], "description": "Moves the Demo Service to the /SERVICES/SNSC_DEMO folder (must be created beforehand) so that SAPI can publish it and Service Now can display it", "workflow": "Sara Service", "serviceName": "PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.ACTIVATE_SNSC_SERVICE.NEW.1", "consumeUrl": "/services/PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.ACTIVATE_SNSC_SERVICE.NEW.1/consume", "hash": "34cb7f82e66c1829423e5e77a6356a5b", "active": true, "shortDesc": "Activate SNSC Service", "customCart": "", "name": "Activate SNSC Service" },
6966 "PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.DEACTIVATE_SNSC_SERVICE.NEW.1":
6967 {
6968 "variables": [], "description": "Moves the SNSC Demo service back to the packages folder so that it is no longer visible by SAPI and Service Now", "workflow": "Sara Service", "serviceName": "PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.DEACTIVATE_SNSC_SERVICE.NEW.1", "consumeUrl": "/services/PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.DEACTIVATE_SNSC_SERVICE.NEW.1/consume", "hash": "5d70dace54e578249482379fde08a8ef", "active": true, "shortDesc": "Deactivate SNSC Service", "customCart": "", "name": "Deactivate SNSC Service" }
6969 },
6970 "DEMO2": {
6971 "PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.DEMO_SERVICE.NEW.1": {
6972 "variables": [
6973 { "description": "", "label": "Currency", "defaultValue": ["EUR"], "type": 18, "required": true, "range": [{ "Value": "EUR", "Key": "EUR" }, { "Value": "US$", "Key": "US$" }], "hash": "d4dcdddf0d7831ecaf23643ce1d4d4b7", "asLookup": true, "name": "EOM_CURRENCY_", "actualName": "EOM_CURRENCY#" },
6974 { "description": "", "label": "Previous Month(s) included", "defaultValue": ["3"], "type": 6, "required": true, "range": [], "asLookup": false, "name": "EOM_MONTHBACK_", "actualName": "EOM_MONTHBACK#" },
6975 { "description": "", "label": "Components", "defaultValue": ["Current Account"], "type": 21, "required": true, "range": [{ "Value": "Current Account", "Key": "Current Account" }, { "Value": "General Ledger", "Key": "General Ledger" }, { "Value": "Loans", "Key": "Loans" }, { "Value": "Mortgage", "Key": "Mortgage" }, { "Value": "Treasury", "Key": "Treasury" }], "hash": "2eb7e44c8b0b12acae8e8322f8b376d3", "asLookup": true, "multiSelect": true, "name": "EOM_COMPONENTS_", "actualName": "EOM_COMPONENTS#" },
6976 { "description": "", "label": "Region", "defaultValue": ["America"], "type": 18, "required": true, "range": [{ "Value": "Africa", "Key": "Africa" }, { "Value": "America", "Key": "America" }, { "Value": "Asia", "Key": "Asia" }, { "Value": "Australia", "Key": "Australia" }, { "Value": "Europe", "Key": "Europe" }], "hash": "a093352aac40b86d0245f2c14e3afc21", "asLookup": true, "name": "EOM_REGION_", "actualName": "EOM_REGION#" },
6977 { "description": "", "label": "Units", "defaultValue": ["Development"], "type": 21, "required": true, "range": [{ "Value": "Development", "Key": "Development" }, { "Value": "Headquarter", "Key": "Headquarter" }, { "Value": "Production", "Key": "Production" }, { "Value": "Research", "Key": "Research" }, { "Value": "Sales", "Key": "Sales" }], "hash": "e6b832d4aef3952cb8120e59d8e1eeaf", "asLookup": true, "multiSelect": true, "name": "EOM_UNITS_", "actualName": "EOM_UNITS#" }
6978 ], "description": "End of Month processing demo with various promptsets and elements", "workflow": "Sara Service", "serviceName": "PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.DEMO_SERVICE.NEW.1", "consumeUrl": "/services/PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.DEMO_SERVICE.NEW.1/consume", "hash": "1258a64471bc8a44b9ce46f2b88a1145", "active": true, "shortDesc": "End of Month Demo", "customCart": "", "name": "End of Month Demo" }
6979 }};
6980
6981 //mock service data for testing
6982 for (var catalogName in servicesData) {
6983 var catalog = servicesData[catalogName];
6984 for(var serviceName in catalog) {
6985 this.wrapServiceData(catalog[serviceName]);
6986 }
6987 }
6988
6989 return servicesData;
6990 },
6991
6992 wrapCategoryData: function(dataObj) {
6993 dataObj.__proto__ = new SaraModel.CatalogCategory();
6994 },
6995
6996 wrapServiceData: function(dataObj) {
6997 dataObj.__proto__ = new SaraModel.CatalogItem();
6998 if(dataObj.variables && dataObj.variables instanceof Array) {
6999 for(var i = 0; i < dataObj.variables.length; i ++) {
7000 dataObj.variables[i].__proto__ = new SaraModel.CatalogVariable();
7001 }
7002 }
7003 },
7004
7005 testImportCategory: function () {
7006 consumer.catalogsData = this.getMockCatalogData();
7007 SaraTest.test("test import categories, de-activate definition removed from AE, update existing definition and create new definition", function () {
7008 var categoryName2 = "snsc test import " + SaraUtils.getRandom();
7009 var categoryName3 = "snsc test import " + SaraUtils.getRandom();
7010
7011 var definitionName = "snsc test import " + SaraUtils.getRandom();
7012 var categoryDescription = "testImportCategory category description";
7013
7014 var category2 = dal.saveOrUpdateCategory({
7015 title: categoryName2,
7016 description: categoryDescription,
7017 sc_catalog: catalogId,
7018 active: true
7019 });
7020
7021
7022 var definition = dal.saveOrUpdateSaraDefinition({
7023 u_name: definitionName,
7024 u_active: true,
7025 u_consume_url: "http://testurl.com",
7026 u_parent: category.sys_id,
7027 u_type: 'catalog',
7028 u_service_catalog_category: category2.sys_id
7029 });
7030
7031 var category3 = dal.saveOrUpdateCategory({
7032 title: categoryName3,
7033 description: categoryDescription,
7034 sc_catalog: catalogId,
7035 active: true
7036 });
7037
7038 var demoDefinition = dal.saveOrUpdateSaraDefinition({
7039 u_name: "DEMO",
7040 u_active: true,
7041 u_consume_url: "oldurl",
7042 u_parent: category.sys_id,
7043 u_type: 'catalog',
7044 u_service_catalog_category: category3.sys_id
7045 });
7046
7047 gs.info("done prepare test data");
7048 //create new definition and make sure that it will be de-activate during synchronization
7049 consumer.importCategory(categoryId);
7050
7051 var resultDefinition = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, { u_name: definitionName, u_parent: category.sys_id });
7052 SaraTest.assert(resultDefinition.u_active == "false", "Definition does not exist in AE should be de-activated");
7053
7054 category2 = glideHelper.getData(SaraCommon.TABLE_NAME.SN_CATEGORY, { sys_id: category2.sys_id });
7055 SaraTest.assert(category2.active == "false", "Category linked to definition does not exist in AE should be de-activated");
7056
7057 category3 = glideHelper.getData(SaraCommon.TABLE_NAME.SN_CATEGORY, { sys_id: category3.sys_id });
7058 SaraTest.assert(category3.parent == category.sys_id, "parent of category linked to definition exist is updated");
7059 SaraTest.assert(category3.title == "Automic Demo Services", "title of category linked to definition exist is updated");
7060 SaraTest.assert(category3.description == "Automic Demo Services", "description of category linked to definition exist is updated");
7061 });
7062 },
7063
7064 testImportItem: function() {
7065 consumer.servicesData = this.getMockupServicesData();
7066
7067 SaraTest.test("test import items", function() {
7068 consumer.importItem();
7069
7070 gs.info("get sub category of " + categoryId);
7071 //get catalog items under import category
7072 var subCategories = glideHelper.getData("sc_category", {parent: categoryId, active: true}, true);
7073 gs.info("sub categories: " + SaraJSON.stringify(subCategories));
7074 SaraTest.assertEqual(subCategories.length, 2, "2 categories are created");
7075 var category1 = subCategories[0].title === "DEMO2" ? subCategories[1] : subCategories[0];
7076 var catItemsOfCategory1 = glideHelper.getData("sc_cat_item", {category: category1.sys_id}, true);
7077
7078 SaraTest.assertEqual(catItemsOfCategory1.length, 2, "2 catalog item under category " + category1.title);
7079
7080 gs.info("catItemsOfCategory1: " + SaraJSON.stringify(catItemsOfCategory1));
7081 catItem1 = catItemsOfCategory1[0].name === "Activate SNSC Service" ? catItemsOfCategory1[0] : catItemsOfCategory1[1];
7082 var itemVarSet = glideHelper.getData("io_set_item", {sc_cat_item: catItem1.sys_id});
7083 var varSet = glideHelper.getData("item_option_new_set", {sys_id: itemVarSet.variable_set});
7084 gs.info(" varSet of the item: " + SaraJSON.stringify(varSet));
7085 var variables = glideHelper.getData("x_ausgh_snsc_sara_variable", {variable_set: varSet.sys_id}, true);
7086 gs.info(" variables of the item: " + SaraJSON.stringify(variables));
7087 SaraTest.assert(variables.length == 7, "5 + 2 variables are created");
7088 });
7089 },
7090
7091 testSyncLookup: function() {
7092 var newSapiService = {
7093 "variables": [
7094 { "description": "", "label": "Currency", "defaultValue": ["EUR"], "type": 18, "required": true, "range": [{ "Value": "EUR", "Key": "EUR" }, { "Value": "US$", "Key": "US$" }], "hash": "d4dcdddf0d7831ecaf23643ce1dd4b8", "asLookup": true, "name": "EOM_CURRENCY_", "actualName": "EOM_CURRENCY#" },
7095 { "description": "", "label": "CMB", "defaultValue": ["value1"], "type": 18, "required": true, "range": [{ "Value": "value1", "Key": "value1" }, { "Value": "value2", "Key": "value2" }], "hash": "d4dcdddf0d7831ecaf23643ce1d4g4b6", "asLookup": true, "name": "CMB_NEW_LOOKUP", "actualName": "CMB_NEW_LOOKUP#" },
7096 { "description": "", "label": "Previous Month(s) included", "defaultValue": ["3"], "type": 6, "required": true, "range": [], "asLookup": false, "name": "EOM_MONTHBACK_", "actualName": "EOM_MONTHBACK#" },
7097 { "description": "", "label": "Components", "defaultValue": ["Current Account"], "type": 21, "required": true, "range": [{ "Value": "Current Account", "Key": "Current Account" }, { "Value": "General Ledger", "Key": "General Ledger" }, { "Value": "Loans", "Key": "Loans" }, { "Value": "Mortgage", "Key": "Mortgage" }, { "Value": "Treasury", "Key": "Treasury" }], "hash": "2eb7e44c8b0b12acae8e8322f8b376d3", "asLookup": true, "multiSelect": true, "name": "EOM_COMPONENTS_", "actualName": "EOM_COMPONENTS#" },
7098 { "description": "", "label": "Region", "defaultValue": ["America"], "type": 18, "required": true, "range": [{ "Value": "Africa", "Key": "Africa" }, { "Value": "America", "Key": "America" }, { "Value": "Asia", "Key": "Asia" }, { "Value": "Australia", "Key": "Australia" }, { "Value": "Europe", "Key": "Europe" }], "hash": "a093ddd352aac40b86d0245f2c14e3afc21", "asLookup": true, "name": "EOM_REGION_", "actualName": "EOM_REGION#" },
7099 { "description": "", "label": "Units", "defaultValue": ["Development"], "type": 21, "required": true, "range": [{ "Value": "Development", "Key": "Development" }, { "Value": "Headquarter", "Key": "Headquarter" }, { "Value": "Production", "Key": "Production" }, { "Value": "Research", "Key": "Research" }, { "Value": "Sales", "Key": "Sales" }], "hash": "e6b832d4aef3952cb8120e59d8e1eeaf", "asLookup": true, "multiSelect": true, "name": "EOM_UNITS_", "actualName": "EOM_UNITS#" }
7100 ], "description": "Moves the Demo Service to the /SERVICES/SNSC_DEMO folder (must be created beforehand) so that SAPI can publish it and Service Now can display it", "workflow": "Sara Service", "serviceName": "PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.ACTIVATE_SNSC_SERVICE.NEW.1", "consumeUrl": "/services/PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.ACTIVATE_SNSC_SERVICE.NEW.1/consume", "hash": "34cb7f82e66c1829423e5e77a6356a5b", "active": true, "shortDesc": "Activate SNSC Service", "customCart": "", "name": "Activate SNSC Service" };
7101 this.wrapServiceData(newSapiService);
7102
7103 SaraTest.test("test sync lookup", function() {
7104 var saraSync = new SaraSync();
7105 gs.info("catItem1: " + SaraJSON.stringify(catItem1));
7106 var definition = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {u_sc_item:catItem1.sys_id });
7107 gs.info("newSapiService: " + SaraJSON.stringify(newSapiService));
7108 saraSync.syncLookup(definition, newSapiService);
7109 });
7110 },
7111
7112 tearDown: function() {
7113 SaraUtils.cleanup( { u_parent: category.sys_id });
7114 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, { u_parent: category.sys_id }, true);
7115 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_CATEGORY, { parent: categoryId }, true);
7116 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_CATEGORY, { title: ["CONTAINS", "snsc test import"] }, true);
7117 }
7118 };
7119})();
7120
7121var SaraTransformMapTest = (function(){
7122 var logger = new SaraLog("SaraGlideHelperTest");
7123 var glideHelper = new SaraGlideHelper();
7124
7125 var catalogId = glideHelper.getSysId("sc_catalog", {title: "Service Catalog"});
7126 gs.info("catelog id: " + catalogId);
7127
7128 var getCategory = function(title) {
7129 return glideHelper.getData("sc_category", {title: title });
7130 };
7131
7132 var deleteCategory = function(title, deleteAll) {
7133 glideHelper.deleteData("sc_category", {title: title },deleteAll);
7134 glideHelper.deleteData("x_ausgh_snsc_sc_category_ist", {title: title },deleteAll);
7135 };
7136
7137 var createCategory = function(title, active, description, parent) {
7138 glideHelper.persistData("x_ausgh_snsc_sc_category_ist", {
7139 title: title,
7140 active: active,
7141 description: description,
7142 parent: parent,
7143 sc_catalog: catalogId
7144 });
7145 };
7146
7147 return {
7148 execute: function() {
7149 gs.info("----------------------------------------------------------------------------");
7150 gs.info("Test transform map definitions");
7151 gs.info("----------------------------------------------------------------------------");
7152
7153 this.testPersistCatalog();
7154 this.testPersistCategory();
7155 this.testPersistCatalogItem();
7156 this.testPersistVariableSet();
7157 this.testPersistCatelogVariableSet();
7158 this.testPersistSaraDefinition();
7159 },
7160
7161 testPersistCatalog: function() {
7162 var catalogName = "snsc test catalog";
7163 glideHelper.deleteData("sc_catalog", {"title": catalogName});
7164
7165 SaraTest.test("Persist catalog via Importset", function() {
7166 glideHelper.persistData("x_ausgh_snsc_sc_catalog_ist", {
7167 title: catalogName,
7168 description: "test description",
7169 active: "true"
7170 });
7171
7172 var catalog = glideHelper.getData("sc_catalog", {"title": catalogName});
7173
7174 SaraTest.assert(catalog !== null, "catalog is transformed correctly");
7175 SaraTest.assert(catalog.title === catalogName, "catalog title is transformed correctly");
7176 SaraTest.assert(catalog.description === "test description", "catalog description is transformed correctly");
7177 gs.info("active: " + catalog.active);
7178 SaraTest.assert(catalog.active, "catalog active is transformed correctly");
7179 });
7180
7181 SaraTest.test("Update catalog via Importset", function() {
7182 var catalog = glideHelper.getData("sc_catalog", {title: catalogName});
7183 var data = {
7184 id: catalog.sys_id,
7185 description: "new description 2",
7186 active: false
7187 };
7188 glideHelper.persistData("x_ausgh_snsc_sc_catalog_ist", data);
7189
7190 var newCatalog = glideHelper.getData("sc_catalog", {"title": catalogName});
7191 gs.info("new catalog: " + SaraJSON.stringify(newCatalog));
7192 SaraTest.assert(newCatalog !== null, "catalog is transformed correctly, title is not overrided");
7193 SaraTest.assert(newCatalog.description === "new description 2", "catalog description is updated correctly");
7194 gs.info("active: " + newCatalog.active);
7195 SaraTest.assert(newCatalog.active == "false", "catalog active is updated correctly");
7196 });
7197 },
7198
7199 testPersistCategory: function() {
7200 var categoryName1 = "snsc test catagory";
7201 var categoryName2 = "snsc test sub catagory";
7202 deleteCategory(categoryName1, true);
7203 deleteCategory(categoryName2, true);
7204
7205 SaraTest.test("Persist category via Importset", function() {
7206 var category = getCategory(categoryName1);
7207 SaraTest.assert(category === null, "category must not exists");
7208 var category2 = getCategory(categoryName2);
7209 SaraTest.assert(category2 === null, "sub category must not exists");
7210
7211 createCategory(categoryName1,true,"test description", null);
7212 category = getCategory(categoryName1);
7213 gs.info(SaraJSON.stringify(category));
7214 SaraTest.assert(category !== null, "Category ImportSet should be transform to category table");
7215 SaraTest.assert(category.title === categoryName1, "Assert title transform correctly");
7216
7217 //create via importset table
7218 createCategory(categoryName2,true,"test sub description", category.sys_id);
7219 //get real data
7220 category2 = getCategory(categoryName2);
7221 SaraTest.assert(category2 !== null, "Sub category ImportSet should be transform to category table");
7222 SaraTest.assert(category2.title === categoryName2, "Assert title transform correctly");
7223
7224 var parent = glideHelper.getData("sc_category", {sys_id:category2.parent});
7225 SaraTest.assert(parent !== null, "Assert parent transform correctly");
7226 SaraTest.assert(parent.title === categoryName1, "Assert parent transform correctly");
7227 });
7228
7229 SaraTest.test("Save category with same name but different parent should create new category", function() {
7230 //create another category with different parent and assert that new item is
7231 //inserted to target table
7232 gs.info("create another record with name " + categoryName2);
7233 createCategory(categoryName2,true,"test description 2");
7234 var records = glideHelper.getData("sc_category", {title:categoryName2}, true);
7235 SaraTest.assert(records.length === 2, "new category is created");
7236 });
7237 },
7238
7239 testPersistCatalogItem: function() {
7240 var gh = glideHelper;
7241 var name = "snsc sample catelog item" + SaraUtils.getRandom();
7242 gs.info("catelog item name: " + name);
7243 var description = "whatever";
7244 var short_description = "short descriprion";
7245 var categoryName = "snsc item category";
7246 var category = null;
7247
7248 SaraTest.test("Persist catalog item via Importset", function(){
7249 //prepare data
7250 deleteCategory(categoryName, true);
7251 createCategory(categoryName, true, "");
7252 category = getCategory(categoryName);
7253 gs.info("category id: " + category.sys_id);
7254 SaraTest.assert(category !== null, "category is created successfully");
7255
7256 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7257 name: name,
7258 description: description,
7259 short_description: short_description,
7260 use_sc_layout: true,
7261 no_quantity: true,
7262 category: category.sys_id,
7263 active: true
7264 });
7265 var item = gh.getData("sc_cat_item", {name: name});
7266 SaraTest.assert(item.name === name, "item is transformed correctly");
7267 SaraTest.assert(item.description === description, "description is transformed correctly");
7268 SaraTest.assert(item.short_description === short_description, "short_description is transformed correctly");
7269 SaraTest.assert(item.use_sc_layout == "true", "use_sc_layout is transformed correctly");
7270 SaraTest.assert(item.no_quantity == "true", "no_quantity is transformed correctly");
7271 SaraTest.assert(item.active == "true", "active is transformed correctly");
7272 SaraTest.assert(item.category === category.sys_id, "category is transformed correctly");
7273 });
7274
7275 SaraTest.test("Catalog item same name different category should create new", function() {
7276 var newCategoryName = categoryName + SaraUtils.getRandom();
7277 createCategory(newCategoryName, true, "");
7278 var newCat = getCategory(newCategoryName);
7279 gs.info("new category id: " + newCat.sys_id);
7280 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7281 name: name,
7282 description: "new description",
7283 short_description: "new short description",
7284 use_sc_layout: false,
7285 no_quantity: false,
7286 category: newCat.sys_id,
7287 active: false
7288 });
7289
7290 var records = gh.getData("sc_cat_item", {name: name}, true);
7291 SaraTest.assert(records.length === 2, "new item is created");
7292 });
7293
7294 SaraTest.test("Update catalog item via Importset", function(){
7295 var existingItem = gh.getData("sc_cat_item", {
7296 name: name,
7297 category: category.sys_id
7298 });
7299
7300 SaraTest.assert(existingItem !== undefined, "existing item is get correctly");
7301
7302 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7303 id: existingItem.sys_id,
7304 name: name,
7305 description: "new description",
7306 short_description: "new short description",
7307 use_sc_layout: false,
7308 no_quantity: false,
7309 category: category.sys_id,
7310 active: false
7311 });
7312 var items = gh.getData("sc_cat_item", {name: name, category: category.sys_id}, true);
7313 SaraTest.assert(items.length === 1, "no new item is created");
7314
7315 var item = items[0];
7316 SaraTest.assert(item.name === name, "item is transformed correctly");
7317 SaraTest.assert(item.description === "new description", "description is transformed correctly");
7318 SaraTest.assert(item.short_description === "new short description", "short_description is transformed correctly");
7319 SaraTest.assert(item.use_sc_layout == "false", "use_sc_layout is transformed correctly");
7320 SaraTest.assert(item.no_quantity == "false", "no_quantity is transformed correctly");
7321 SaraTest.assert(item.active == "false", "active is transformed correctly");
7322 SaraTest.assert(item.category === category.sys_id, "category is transformed correctly");
7323 });
7324 },
7325
7326 testPersistVariableSet: function() {
7327 var varSetName = "snsc test variable set " + SaraUtils.getRandom();
7328 var varSetTitle = "title";
7329 var varSetDescription = "test description";
7330 var varSetDisplayName = "display name";
7331
7332 var varSetTitleNew = "title new";
7333 var varSetDescriptionNew = "test description new";
7334 var varSetDisplayNameNew = "display name new";
7335
7336 glideHelper.deleteData("item_option_new_set", {"name": ["CONTAINS", "snsc test"]}, true);
7337
7338 SaraTest.test("Persist variable set via Importset", function() {
7339 glideHelper.persistData("x_ausgh_snsc_item_option_new_set_ist", {
7340 name: varSetName,
7341 title: varSetTitle,
7342 description: varSetDescription,
7343 sys_name: varSetDisplayName
7344 });
7345
7346 var varSet = glideHelper.getData("item_option_new_set", {"name": varSetName});
7347
7348 SaraTest.assert(varSet !== null, "varSet is transformed correctly");
7349 SaraTest.assert(varSet.name === varSetName, "var set name is transformed correctly");
7350 SaraTest.assert(varSet.title === varSetTitle, "var set title is transformed correctly");
7351 SaraTest.assert(varSet.description === varSetDescription, "var set description is transformed correctly");
7352 SaraTest.assert(varSet.sys_name === varSetDisplayName, "var set display name is transformed correctly");
7353 });
7354
7355 SaraTest.test("Update var set via Importset", function() {
7356 var existingVarSet = glideHelper.getData("item_option_new_set", {name: varSetName});
7357 SaraTest.assert(existingVarSet !== undefined, "var set is get correctly");
7358
7359 glideHelper.persistData("x_ausgh_snsc_item_option_new_set_ist", {
7360 id: existingVarSet.sys_id,
7361 name: varSetName,
7362 title: varSetTitleNew,
7363 description: varSetDescriptionNew
7364 });
7365
7366 var varSets = glideHelper.getData("item_option_new_set", {"name": varSetName}, true);
7367
7368 SaraTest.assert(varSets.length === 1, "no new item is get correctly");
7369 var varSet = varSets[0];
7370 SaraTest.assert(varSet !== null, "varSet is transformed correctly");
7371 SaraTest.assert(varSet.name === varSetName, "var set name is transformed correctly");
7372 SaraTest.assert(varSet.title === varSetTitleNew, "var set title is updated correctly");
7373 SaraTest.assert(varSet.description === varSetDescriptionNew, "var set description is updated correctly");
7374 });
7375 },
7376
7377 testPersistCatelogVariableSet : function() {
7378 var varSetName = "snsc test variable set " + SaraUtils.getRandom();
7379 var varSetTitle = "title";
7380 var varSetDescription = "test description";
7381 var varSetDisplayName = "display name";
7382
7383 var newCategoryName = "snsc category " + SaraUtils.getRandom();
7384
7385 var catItemName = "snsc cat item " + SaraUtils.getRandom();
7386
7387 var gh = glideHelper;
7388
7389 gh.deleteData("item_option_new_set", {"name": ["CONTAINS", "snsc test"]}, true);
7390
7391 SaraTest.test("Persist catalog variable set via Importset", function() {
7392 gh.persistData("x_ausgh_snsc_item_option_new_set_ist", {
7393 name: varSetName,
7394 title: varSetTitle,
7395 description: varSetDescription,
7396 display_name: varSetDisplayName
7397 });
7398
7399 var varSet = glideHelper.getData("item_option_new_set", {"name": varSetName});
7400
7401 SaraTest.assert(varSet !== null, "varSet is transformed correctly");
7402
7403 createCategory(newCategoryName);
7404 var newCat = getCategory(newCategoryName);
7405
7406 gs.info("new category id: " + newCat.sys_id);
7407
7408 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7409 name: catItemName,
7410 description: "new description",
7411 short_description: "new short description",
7412 use_sc_layout: true,
7413 no_quantity: true,
7414 category: newCat.sys_id,
7415 active: true
7416 });
7417
7418 var catItem = gh.getData("sc_cat_item", {name: catItemName, category: newCat.sys_id});
7419 SaraTest.assert(catItem !== undefined, "cat item is transformed successfully");
7420
7421 //link item and varset via import set
7422 gh.persistData("x_ausgh_snsc_io_set_item_ist", {sc_cat_item: catItem.sys_id, variable_set: varSet.sys_id});
7423 //get real
7424 var catVarSet = gh.getData("io_set_item", {sc_cat_item: catItem.sys_id, variable_set: varSet.sys_id});
7425
7426 SaraTest.assert(catVarSet !== null, "catalog item variable is transformed correctly");
7427 SaraTest.assert(catVarSet.sc_cat_item === catItem.sys_id, "cat item is set correctly");
7428 SaraTest.assert(catVarSet.variable_set === varSet.sys_id, "var set is set correctly");
7429 });
7430 },
7431
7432 testPersistSaraDefinition : function() {
7433 var newCategoryName = "snsc test category " + SaraUtils.getRandom();
7434 var parentCategoryName = "snsc test parent category " + SaraUtils.getRandom();
7435
7436 var varSetName = "snsc test var set" + SaraUtils.getRandom();
7437
7438 var definitionName1 = "snsc test" + SaraUtils.getRandom();
7439 var definitionName2 = "snsc test" + SaraUtils.getRandom();
7440 var definitionName3 = "snsc test" + SaraUtils.getRandom();
7441
7442 var catItemName1 = "snsc test cat item" + SaraUtils.getRandom();
7443
7444 var consume_url1 = "http://automictest.com";
7445 var consume_url2 = "http://automictest2.com";
7446 var hash1 = "FDSGHERGGGGFGFGDGFS";
7447 var hash2 = "FDSFFSDHASAFGFGDGFS";
7448
7449 var gh = glideHelper;
7450
7451 gh.deleteData("x_ausgh_snsc_sara_definition", {"name": ["CONTAINS", "snsc test"]}, true);
7452
7453 SaraTest.test("Persist sara definition for catalog item via Importset", function() {
7454 createCategory(parentCategoryName);
7455 var parentCat = getCategory(parentCategoryName);
7456 SaraTest.assert(parentCat !== null, "parentCat is transformed correctly");
7457
7458 createCategory(newCategoryName);
7459 var newCat = getCategory(newCategoryName);
7460 SaraTest.assert(newCat !== null, "newCat is transformed correctly");
7461
7462 //create var set
7463 gh.persistData("x_ausgh_snsc_item_option_new_set_ist", {
7464 name: varSetName,
7465 title: "title",
7466 description: "description",
7467 display_name: "whatever"
7468 });
7469
7470 var varSet = gh.getData("item_option_new_set", {"name": varSetName});
7471 SaraTest.assert(varSet !== null, "varSet is transformed correctly");
7472
7473 //create catalog item
7474 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7475 name: catItemName1,
7476 description: "new description",
7477 short_description: "new short description",
7478 use_sc_layout: true,
7479 no_quantity: true,
7480 category: newCat.sys_id,
7481 active: true
7482 });
7483
7484 var catItem = gh.getData("sc_cat_item", {name: catItemName1, category: newCat.sys_id});
7485 SaraTest.assert(catItem !== null, "catItem is transformed correctly");
7486
7487 gh.persistData("x_ausgh_snsc_sara_definition_ist", {
7488 u_name: definitionName1,
7489 u_consume_url: consume_url1,
7490 u_sc_item: catItem.sys_id,
7491 u_service_catalog_category: newCat.sys_id,
7492 u_var_set: varSet.sys_id,
7493 u_parent: parentCat.sys_id,
7494 u_type: "service",
7495 u_hash: hash1
7496 });
7497 var saraDefinition = gh.getData("x_ausgh_snsc_sara_definition_ist", {u_name: definitionName1, u_parent: parentCat.sys_id});
7498
7499 SaraTest.assert(saraDefinition !== null, "saraDefinition is transformed correctly");
7500 gs.info("saraDefinition: " + SaraJSON.stringify(saraDefinition));
7501 SaraTest.assert(saraDefinition.u_name === definitionName1, "u_name is transformed correctly");
7502 SaraTest.assert(saraDefinition.u_consume_url === consume_url1, "consume_url is transformed correctly");
7503 SaraTest.assert(saraDefinition.u_sc_item === catItem.sys_id, "u_sc_item is transformed correctly");
7504 SaraTest.assert(saraDefinition.u_service_catalog_category === newCat.sys_id, "u_service_catalog_category is transformed correctly");
7505 SaraTest.assert(saraDefinition.u_var_set === varSet.sys_id, "u_var_set is transformed correctly");
7506 SaraTest.assert(saraDefinition.u_parent === parentCat.sys_id, "u_parent is transformed correctly");
7507 SaraTest.assert(saraDefinition.u_type === "service", "u_type is transformed correctly");
7508 SaraTest.assert(saraDefinition.u_hash === hash1, "u_hash is transformed correctly");
7509 });
7510 }
7511 };
7512})();
7513
7514var SaraTest = (function() {
7515 var indent = "";
7516 var logger = new SaraLog("SaraTest");
7517 var pass = 0;
7518 var fail = 0;
7519 var isIgnore = false;
7520 var ignored = 0;
7521 var continueOnError = true;
7522
7523 var log = function() {
7524 logger.info.apply(logger,arguments);
7525 };
7526
7527 return {
7528 resetSummary: function() {
7529 pass = 0;
7530 fail = 0;
7531 ignored = 0;
7532 },
7533
7534 disableContinueOnError:function() {
7535 continueOnError = false;
7536 },
7537
7538 getSummary: function() {
7539 return {
7540 pass: pass,
7541 fail: fail,
7542 ignore: ignored,
7543 total: pass + fail + ignored
7544 };
7545 },
7546
7547 ignore: function() {
7548 isIgnore = true;
7549 },
7550
7551 assert: function(value, desc) {
7552 var prefix = ">>>PASS: ";
7553 if(!value) {
7554 prefix = "<<<FAIL: ";
7555 }
7556 logger.info("{0}{1}{2}", indent, prefix, desc);
7557 if(!value) {
7558 var exceptionMsg = prefix + desc;
7559 throw new Error(exceptionMsg);
7560 }
7561 },
7562 assertEqual: function(actual, expected, desc) {
7563 var failed = false;
7564 var prefix = ">>>PASS: ";
7565 if(actual != expected) {
7566 prefix = "<<<FAIL: ";
7567 failed = true;
7568 }
7569 logger.info("{0}{1}{2}", indent, prefix, desc);
7570 if(failed) {
7571 logger.info("Expected: {0}; Actual: {1}", expected, actual);
7572 }
7573 if(failed) {
7574 var exceptionMsg = prefix + desc + "; Expected:" + expected + "; Actual: " + actual
7575
7576 throw new Error(exceptionMsg);
7577 }
7578 },
7579 test: function(name, fn) {
7580 indent = "";
7581 logger.info("********************************");
7582 if(isIgnore) {
7583 logger.info("[IGNORE] {0}", name);
7584 isIgnore = false;
7585 ignored++;
7586 return;
7587 }
7588 logger.info("[TEST CASE] {0}", name);
7589 indent = " ";
7590
7591 if(continueOnError) {
7592 try {
7593 fn();
7594 pass++;
7595 }
7596 catch(err) {
7597 gs.error(err);
7598 fail++;
7599 }
7600 }
7601 else {
7602 fn();
7603 pass++;
7604 }
7605
7606 indent = "";
7607 },
7608 type: "SaraTest"
7609 };
7610})();
7611]]></script>
7612 <description>Sara Test Bench</description>
7613 <active>true</active>
7614 <client_callable>false</client_callable>
7615 <access>public</access>
7616 </script_include>
7617</script_includes>
7618
7619
7620 <ui_scripts>
7621 <ui_script>
7622 <script_name>SaraVarSet</script_name>
7623 <script><![CDATA[/**
7624 * Catalog client script for SaraVariableSet
7625 */
7626var x_ausgh_snsc = x_ausgh_snsc || {};
7627x_ausgh_snsc.SaraVarSet = x_ausgh_snsc.SaraVarSet || {};
7628
7629(function (SaraVarSet) {
7630 'use strict';
7631
7632 /**
7633 * OnLoad event handler for Sara variable set
7634 */
7635 SaraVarSet.onLoad = function () {
7636 SaraVarSet.initListCollector();
7637 SaraVarSet.setSelectBoxWidth();
7638 };
7639
7640 /**
7641 * Init collector filter
7642 */
7643 SaraVarSet.initListCollector = function () {
7644 x_ausgh_snsc.log('Start: SaraVarSet.initListCollector');
7645 var messageTables = $$('[id$=_select_0_add_remove_message_table]');
7646 var listWrappers = $$('.list_name');
7647
7648 for (var i = 0, table; table = messageTables[i]; i++) {
7649 var name = table.id.replace('_select_0_add_remove_message_table', '');
7650 var wrapper = listWrappers[i];
7651 var target;
7652 var id;
7653
7654 if (wrapper) {
7655 target = wrapper;
7656 } else {
7657 target = table;
7658 }
7659
7660 id = target.nextSibling.id.replace('IO:', '');
7661
7662 SaraVarSet.getListCollectorData(id, name);
7663 }
7664
7665 x_ausgh_snsc.log('End: SaraVarSet.initListCollector');
7666 };
7667
7668 /**
7669 * Get list collector data from lookup table
7670 * @param {String} id The sys_id of list collector
7671 * @param {String} name The name of list collector
7672 */
7673 SaraVarSet.getListCollectorData = function (id, name) {
7674 var filterFn = name + 'g_filter';
7675 var acRequestFn = name + 'acRequest';
7676
7677 if (window[filterFn] === undefined || window[acRequestFn] === undefined) {
7678 setTimeout(function () {
7679 SaraVarSet.getListCollectorData(id, name);
7680 }, 100);
7681 return;
7682 }
7683
7684 window[filterFn].reset();
7685 window[filterFn].setQuery('u_control_id=' + id);
7686 window[acRequestFn](null);
7687 };
7688
7689 /**
7690 * Make all selecbox's width is 250px for preventing the broken of layout when value of option is too long
7691 */
7692 SaraVarSet.setSelectBoxWidth = function () {
7693 x_ausgh_snsc.log('Start: SaraVarSet.setSelectBoxWidth');
7694 var selectboxes = $$('select.cat_item_option');
7695
7696 for (var i = 0, selectbox; selectbox = selectboxes[i]; i++) {
7697 selectbox.style.width = '250px';
7698 }
7699
7700 x_ausgh_snsc.log('End: SaraVarSet.setSelectBoxWidth');
7701 };
7702
7703})(x_ausgh_snsc.SaraVarSet);
7704]]></script>
7705 <description>Catalog client script for SaraVariableSet</description>
7706 <active>true</active>
7707 <global>false</global>
7708 </ui_script>
7709 <ui_script>
7710 <script_name>SaraCommon</script_name>
7711 <script><![CDATA[/**
7712 * Common client properties for Sara
7713 */
7714var SaraCommon = SaraCommon || {};
7715
7716var x_ausgh_snsc = x_ausgh_snsc || {};
7717x_ausgh_snsc.SaraCommon = x_ausgh_snsc.SaraCommon || {};
7718
7719x_ausgh_snsc.log = function () {
7720 if (typeof (console) !== 'undefined') {
7721 if (navigator.appName === 'Microsoft Internet Explorer') {
7722 if (arguments.length == 1) {
7723 console.log('[SARA]', arguments[0]);
7724 } else if (arguments.length === 2) {
7725 console.log('[SARA]', arguments[0], arguments[1]);
7726 } else if (arguments.length > 2) {
7727 console.log('[SARA]', arguments[0], arguments[1], arguments[2]);
7728 }
7729 } else {
7730 console.log('[SARA]', arguments);
7731 }
7732 }
7733};
7734
7735x_ausgh_snsc.config = x_ausgh_snsc.config || {};
7736
7737(function (SaraCommon) {
7738 'use strict';
7739
7740 SaraCommon.SCOPED_APP = 'x_ausgh_snsc';
7741
7742 SaraCommon.CONFIG_NAME = {
7743 CLIENT_ID: 'client_id',
7744 CLIENT_SECRET: 'client_secret',
7745 TECHNICAL_USER: 'technical_user',
7746 SAPI_ENDPOINT: 'sapi_endpoint',
7747 TOKEN_ENDPOINT: 'token_endpoint',
7748 AUTH_ENDPOINT: 'auth_endpoint'
7749 };
7750
7751 SaraCommon.CONTROL_NAME = {
7752 CLIENT_SCRIPTS: 'sara_client_scripts',
7753 HIDDEN_CONTROL: 'sara_hidden_control'
7754 };
7755
7756})(x_ausgh_snsc.SaraCommon);
7757]]></script>
7758 <description>Common client properties for Sara</description>
7759 <active>true</active>
7760 <global>false</global>
7761 </ui_script>
7762 <ui_script>
7763 <script_name>SaraOAuth</script_name>
7764 <script><![CDATA[/**
7765 * Client script for OAuth integration
7766 */
7767var x_ausgh_snsc = x_ausgh_snsc || {};
7768x_ausgh_snsc.SaraOAuth = x_ausgh_snsc.SaraOAuth || {};
7769
7770(function (SaraOAuth) {
7771 'use strict';
7772
7773 /**
7774 * Login to OAuth server for authentication
7775 * @param {String} clientId The client ID of OAuth Server
7776 * @param {String} technicalUser The tecnical user who owns the tokens
7777 * @param {String} authEndpoint The authorization endpoint of OAuth Server
7778 * @param {Object} callback The callback object contains onSuccess and onFail handler
7779 */
7780 SaraOAuth.login = function (clientId, technicalUser, authEndpoint, callback) {
7781 if (confirm('Technical User does not have tokens or Technical User\'s tokens are empty, invalid or expired. Do you want to open OAuth Authorization popup for getting new tokens?')) {
7782 SaraOAuth.processSuccess = null;
7783 SaraOAuth.processFail = null;
7784
7785 if (SaraOAuth.win) {
7786 SaraOAuth.win.close();
7787 }
7788 SaraOAuth.win = null;
7789
7790 var ga = new x_ausgh_snsc.SaraGlideAjax('SaraOAuthAjax', 'Getting OAuth url...');
7791 ga.addParam('sysparm_name', 'getOAuthUrl');
7792 ga.addParam('sysparm_client_id', clientId);
7793 ga.addParam('sysparm_technical_user', technicalUser);
7794 ga.addParam('sysparm_auth_endpoint', authEndpoint);
7795 ga.getXML(function (response) {
7796 if (callback && callback.onSuccess && typeof (callback.onSuccess) == 'function') {
7797 SaraOAuth.processSuccess = callback.onSuccess;
7798 }
7799
7800 if (callback && callback.onFail && typeof (callback.onFail) == 'function') {
7801 SaraOAuth.processFail = callback.onFail;
7802 }
7803
7804 var w = 500;
7805 var h = 600;
7806
7807 var left = (screen.width / 2) - (w / 2);
7808 var top = (screen.height / 2) - (h / 2);
7809
7810 var url = response.responseXML.documentElement.getAttribute('answer');
7811 SaraOAuth.win = window.open(url, 'aelogin', 'width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
7812 });
7813 }
7814 };
7815
7816 /**
7817 * Process response from OAuth server. If is 'ok', will call SaraOAuth.processSuccess callback.
7818 * If is not 'ok', will log the answer and alert message.
7819 * @param {*} response The response
7820 */
7821 SaraOAuth.processResponse = function (response) {
7822 if (SaraOAuth.win) {
7823 SaraOAuth.win.close();
7824 }
7825
7826 x_ausgh_snsc.log('Callback response is: ' + response);
7827
7828 if (response === 'ok') {
7829 if (SaraOAuth.processSuccess && typeof (SaraOAuth.processSuccess) == 'function') {
7830 SaraOAuth.processSuccess();
7831 }
7832 } else {
7833 var msg;
7834
7835 if (typeof (response) == 'string' && response.match('^function') != 'function') {
7836 msg = x_ausgh_snsc.SaraUtils.formatString('Token request finished unsuccessfully{0}. Please try again later or contact administrators.', response ? (', error: ' + response) : '');
7837 } else {
7838 msg = 'Token request finished unsuccessfully! Please try again later or contact administrators.';
7839 }
7840
7841 alert(msg);
7842
7843 if (SaraOAuth.processFail && typeof (SaraOAuth.processFail) == 'function') {
7844 SaraOAuth.processFail();
7845 }
7846
7847 x_ausgh_snsc.log(msg);
7848 }
7849 };
7850
7851 /**
7852 * Get configuration
7853 * @param {Function} callback The callback will be called when getting configuration
7854 * successfully with parametter is object with same keys with x_ausgh_snsc.SaraCommon.CONFIG_NAME
7855 */
7856 SaraOAuth.getConfig = function (callback) {
7857 var configData = {};
7858 var ga = new x_ausgh_snsc.SaraGlideAjax('SaraOAuthAjax', 'Getting OAuth configuration...');
7859 ga.addParam('sysparm_name', 'getConfig');
7860
7861 ga.getXML(function (resp) {
7862 var config = resp.responseXML.getElementsByTagName('config')[0];
7863
7864 for (var key in x_ausgh_snsc.SaraCommon.CONFIG_NAME) {
7865 var name = x_ausgh_snsc.SaraCommon.CONFIG_NAME[key];
7866
7867 configData[name] = config.getAttribute(name);
7868 }
7869
7870 callback.call(this, configData);
7871 });
7872 };
7873
7874 /**
7875 * Check OAuth Token of current technical user is invalid, expired or empty
7876 * @param {String} technicalUser The tecnical user who owns the tokens
7877 * @param {String} sapiEndpoint The SAPI endpoint
7878 * @param {Boolean} hideWizardSubmit Hide submit button of wizard or not when token is empty, expired
7879 * or invalid
7880 * @param {Object<String, Function>} callback The callback object contains callbacks when valid,
7881 * invalid, error:
7882 * - onValid(); // Will be called when tokens are existed and valid.
7883 * - onInvalid(); // Will be called when tokens are existed but invalid.
7884 * - onError(errorMessage); // Will be called when have any error. 'errorMessage' is error message
7885 * - onExisted(); // Will be called if current technical user has tokens but not validate the token yet.
7886 * SaraCommon.TABLE_NAME.SARA_OAUTH table
7887 */
7888 SaraOAuth.checkOAuthToken = function (technicalUser, sapiEndpoint, hideWizardSubmit, callback) {
7889 x_ausgh_snsc.log('checkOAuthToken', technicalUser, sapiEndpoint, hideWizardSubmit, callback);
7890
7891 var ga = new x_ausgh_snsc.SaraGlideAjax('SaraOAuthAjax', 'Validating token...');
7892 ga.addParam('sysparm_name', 'validateToken');
7893 ga.addParam('sysparm_technical_user', technicalUser);
7894 ga.addParam('sysparm_sapi_endpoint', sapiEndpoint);
7895
7896 ga.getXML(function (resp) {
7897 var result = resp.responseXML.getElementsByTagName('result')[0];
7898
7899 if (result) {
7900 var isValid = result.getAttribute('isValid');
7901
7902 // Valid
7903 if (isValid === 'true') {
7904 if (hideWizardSubmit) {
7905 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(true);
7906 }
7907
7908 x_ausgh_snsc.log('Access token is valid');
7909
7910 if (typeof callback.onValid === 'function') {
7911 callback.onValid.call(this);
7912 }
7913
7914 // Invalid
7915 } else if (isValid === 'false') {
7916 if (hideWizardSubmit) {
7917 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(false);
7918 }
7919
7920 x_ausgh_snsc.log('Access token is invalid');
7921
7922 if (typeof callback.onInvalid === 'function') {
7923 callback.onInvalid.call(this);
7924 }
7925
7926 // Error
7927 } else {
7928 var errorMessage = result.getAttribute('message');
7929 x_ausgh_snsc.log(errorMessage);
7930
7931
7932 if (typeof callback.onError === 'function') {
7933 callback.onError.call(this, errorMessage);
7934 }
7935 }
7936 } else {
7937 var error = resp.responseXML.getElementsByTagName('error')[0];
7938 var errorMessage;
7939
7940 if (error) {
7941 errorMessage = error.getAttribute('message');
7942 }
7943
7944 if (typeof callback.onError === 'function') {
7945 callback.onError.call(this, errorMessage);
7946 }
7947 }
7948 });
7949 };
7950
7951})(x_ausgh_snsc.SaraOAuth);
7952]]></script>
7953 <description>Client script for OAuth integration</description>
7954 <active>true</active>
7955 <global>false</global>
7956 </ui_script>
7957 <ui_script>
7958 <script_name>SaraUtils</script_name>
7959 <script><![CDATA[/**
7960 * Sara Utilities
7961 */
7962var x_ausgh_snsc = x_ausgh_snsc || {};
7963x_ausgh_snsc.SaraUtils = x_ausgh_snsc.SaraUtils || {};
7964
7965(function (SaraUtils) {
7966 'use strict';
7967
7968 /**
7969 * Format strings
7970 * @method format
7971 * @param {String} string The template string
7972 * @param {String[]} args Zero or more objects to format, supplied either in a comma-delimited list or as an array
7973 */
7974 SaraUtils.formatString = function (string) {
7975 var args = Array.prototype.slice.call(arguments, 1);
7976
7977 return string.replace(/{(\d+)}/g, function (match, number) {
7978 return typeof args[number] != 'undefined' ? args[number] : match;
7979 });
7980 };
7981
7982 /**
7983 * Get parameter value in current URL
7984 * @param {String} name The name of parameter
7985 * @return {String}
7986 */
7987 SaraUtils.getParmVal = function (name) {
7988 name = name.replace(/[\[]/, '\\\[').replace(/[\]]/, '\\\]');
7989 var regexS = '[\\?&]' + name + '=([^&#]*)';
7990 var regex = new RegExp(regexS);
7991 var results = regex.exec(window.location.href);
7992
7993 if (results == null) {
7994 return '';
7995 } else {
7996 return unescape(results[1]);
7997 }
7998 };
7999
8000 /**
8001 * Hide/show submit button of wizard
8002 * @param {Boolean} isVisible Submit button is visible or not
8003 */
8004 SaraUtils.setWizardSubmitVisible = function (isVisible) {
8005 document.getElementById('expert_next').style.display = isVisible ? '' : 'none';
8006 };
8007
8008 /**
8009 * Set visible of a form control
8010 * @param {String} name Name of control
8011 * @param {Boolean} isVisible Control is hidden or visible
8012 */
8013 SaraUtils.setFormControlVisible = function (name, isVisible) {
8014 if (g_form) {
8015 g_form.setDisplay(name, isVisible);
8016 }
8017 }
8018
8019})(x_ausgh_snsc.SaraUtils);
8020]]></script>
8021 <description>Sara Utilities</description>
8022 <active>true</active>
8023 <global>false</global>
8024 </ui_script>
8025 <ui_script>
8026 <script_name>SaraGlideAjax</script_name>
8027 <script><![CDATA[/**
8028 * Helper class wraps GlideAjax class of ServiceNow and provide Loading Dialog with custom title
8029 */
8030var x_ausgh_snsc = x_ausgh_snsc || {};
8031x_ausgh_snsc.SaraGlideAjax = x_ausgh_snsc.SaraGlideAjax || Class.create();
8032
8033(function (SaraGlideAjax) {
8034 'use strict';
8035
8036 SaraGlideAjax.prototype = {
8037 /**
8038 * Initialize SaraGlideAjax
8039 * @param {String} className The class name of callable Script Include
8040 * @param {String} title The title of loading dialog
8041 */
8042 initialize: function (className, title) {
8043 this.title = title;
8044 this.ga = new GlideAjax(className);
8045 this.ga.addParam('sysparm_scope', x_ausgh_snsc.SaraCommon.SCOPED_APP);
8046 this.className = className;
8047 },
8048
8049 /**
8050 * Add parameter for GlideAjax
8051 * @param {String} key The key of parameter
8052 * @param {String} value The value of parameter
8053 */
8054 addParam: function (key, value) {
8055 this.ga.addParam(key, value);
8056 },
8057
8058 /**
8059 * Get XML response from server
8060 * @param {Function} callback The callback will be call after getting response from server
8061 */
8062 getXML: function (callback) {
8063 var loadingDialog = new GlideDialogWindow('hierarchical_progress_viewer');
8064 loadingDialog.hideCloseButton();
8065 loadingDialog.setTitle(this.title);
8066
8067 var className = this.className;
8068 x_ausgh_snsc.log('Sending request to ' + className + '...');
8069
8070 this.ga.getXML(function (response) {
8071 loadingDialog.destroy();
8072 x_ausgh_snsc.log('Got response from ' + className, response);
8073
8074 if (typeof callback === 'function') {
8075 callback.apply(this, arguments);
8076 }
8077 });
8078 },
8079
8080 type: 'SaraGlideAjax'
8081 };
8082
8083})(x_ausgh_snsc.SaraGlideAjax);
8084]]></script>
8085 <description>Helper class wraps GlideAjax class of ServiceNow and provide Loading Dialog with custom title</description>
8086 <active>true</active>
8087 <global>false</global>
8088 </ui_script>
8089</ui_scripts>
8090
8091
8092 <ui_pages>
8093 <ui_page>
8094 <name>sara_oauth_callback</name>
8095 <description>OAuth Redirection Endpoint</description>
8096 <category>general</category>
8097 <html><![CDATA[<?xml version="1.0" encoding="utf-8" ?>
8098<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
8099 <g:requires name="x_ausgh_snsc.SaraCommon.jsdbx" params="cache=$[jvar_stamp]" />
8100 <g:requires name="x_ausgh_snsc.SaraGlideHelper.jsdbx" params="cache=$[jvar_stamp]" />
8101 <g:requires name="x_ausgh_snsc.SaraGlideAjax.jsdbx" params="cache=$[jvar_stamp]" />
8102 <g:requires name="x_ausgh_snsc.SaraOAuth.jsdbx" params="cache=$[jvar_stamp]" />
8103 <g:requires name="x_ausgh_snsc.SaraUtils.jsdbx" params="cache=$[jvar_stamp]" />
8104 <g:requires name="x_ausgh_snsc.SaraVarSet.jsdbx" params="cache=$[jvar_stamp]" />
8105
8106 <g:ui_form>
8107 <p>
8108 <label>Please wait, processing...</label>
8109 </p>
8110 </g:ui_form>
8111</j:jelly>
8112]]></html>
8113 <client_script><![CDATA[var parentWin = (window.opener && window.opener.x_ausgh_snsc.SaraOAuth) ? window.opener : window.parent;
8114
8115if (!parentWin || !parentWin.x_ausgh_snsc || !parentWin.x_ausgh_snsc.SaraOAuth || !parentWin.x_ausgh_snsc.SaraOAuth.processResponse || typeof(parentWin.x_ausgh_snsc.SaraOAuth.processResponse) !== 'function') {
8116 window.location.href = '/home.do';
8117} else {
8118 var code = x_ausgh_snsc.SaraUtils.getParmVal('code');
8119 x_ausgh_snsc.log('Code: ' + code);
8120
8121 if (code) {
8122 var clientId = parentWin.x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_ID];
8123 var clientSecret = parentWin.x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_SECRET];
8124 var technicalUser = parentWin.x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER];
8125 var tokenEndpoint = parentWin.x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT];
8126
8127 x_ausgh_snsc.log('Client ID: ' + clientId, 'Client Secret: ' + clientSecret, 'Token Endpoint: ' + tokenEndpoint)
8128
8129 // Invoke x_ausgh_snsc.SaraOAuthAjax to exchange code for tokens
8130 x_ausgh_snsc.log('Init GlideAjax for requesting token by code...');
8131 var ga = new x_ausgh_snsc.SaraGlideAjax('SaraOAuthAjax', 'Requesting token by code...');
8132 ga.addParam('sysparm_name', 'requestTokenByCode');
8133 ga.addParam('sysparm_code', code);
8134 ga.addParam('sysparm_client_id', clientId);
8135 ga.addParam('sysparm_client_secret', clientSecret);
8136 ga.addParam('sysparm_technical_user', technicalUser);
8137 ga.addParam('sysparm_token_endpoint', tokenEndpoint);
8138
8139 ga.getXML(function (response) {
8140 var answer = response.responseXML.documentElement.getAttribute('answer');
8141 parentWin.x_ausgh_snsc.SaraOAuth.processResponse(answer);
8142 });
8143 } else {
8144 x_ausgh_snsc.log('Code is empty!');
8145 parentWin.x_ausgh_snsc.SaraOAuth.processResponse();
8146 }
8147}
8148]]></client_script>
8149 <processing_script/>
8150 </ui_page>
8151</ui_pages>
8152
8153
8154 <ui_macros>
8155 <ui_macro>
8156 <name>sara_hidden_control</name>
8157 <description>UI Marco for Sara Hidden Control</description>
8158 <category>catalog</category>
8159 <active>true</active>
8160 <media_type/>
8161 <xml><![CDATA[<?xml version="1.0" encoding="utf-8" ?>
8162<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
8163 <script type="text/javascript">
8164 $j(function () {
8165 x_ausgh_snsc.SaraUtils.setFormControlVisible(x_ausgh_snsc.SaraCommon.CONTROL_NAME.HIDDEN_CONTROL, false);
8166 x_ausgh_snsc.SaraVarSet.onLoad();
8167 });
8168 </script>
8169</j:jelly>
8170]]></xml>
8171 </ui_macro>
8172 <ui_macro>
8173 <name>sara_client_scripts</name>
8174 <description/>
8175 <category>catalog</category>
8176 <active>true</active>
8177 <media_type/>
8178 <xml><![CDATA[<?xml version="1.0" encoding="utf-8" ?>
8179<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
8180 <g:requires name="x_ausgh_snsc.SaraCommon.jsdbx" params="cache=$[jvar_stamp]" />
8181 <g:requires name="x_ausgh_snsc.SaraGlideAjax.jsdbx" params="cache=$[jvar_stamp]" />
8182 <g:requires name="x_ausgh_snsc.SaraOAuth.jsdbx" params="cache=$[jvar_stamp]" />
8183 <g:requires name="x_ausgh_snsc.SaraUtils.jsdbx" params="cache=$[jvar_stamp]" />
8184 <g:requires name="x_ausgh_snsc.SaraVarSet.jsdbx" params="cache=$[jvar_stamp]" />
8185
8186 <script type="text/javascript">
8187 $j(function () {
8188 x_ausgh_snsc.SaraUtils.setFormControlVisible(x_ausgh_snsc.SaraCommon.CONTROL_NAME.CLIENT_SCRIPTS, false);
8189 });
8190 </script>
8191</j:jelly>
8192]]></xml>
8193 </ui_macro>
8194</ui_macros>
8195
8196
8197 <workflows>
8198 <workflow>
8199 <name>Sara Service</name>
8200 <description>Sara Service workflow</description>
8201 <start>begin</start>
8202 <table>sc_req_item</table>
8203 <active>true</active>
8204 <published>true</published>
8205 <max_activity_count>1000000</max_activity_count>
8206
8207
8208 <stages>
8209 <stage>
8210 <name>Initializing</name>
8211 <order>100</order>
8212 <value>initializing</value>
8213 <ola/>
8214 </stage>
8215 <stage>
8216 <name>Transferring</name>
8217 <order>200</order>
8218 <value>transferring</value>
8219 <ola/>
8220 </stage>
8221 <stage>
8222 <name>Transferred</name>
8223 <order>300</order>
8224 <value>transferred</value>
8225 <ola/>
8226 </stage>
8227 <stage>
8228 <name>Transfer Failed</name>
8229 <order>300</order>
8230 <value>transfer_failed</value>
8231 <ola/>
8232 </stage>
8233 <stage>
8234 <name>Consume Failed</name>
8235 <order>400</order>
8236 <value>consume_failed</value>
8237 <ola/>
8238 </stage>
8239 <stage>
8240 <name>Running</name>
8241 <order>500</order>
8242 <value>running</value>
8243 <ola/>
8244 </stage>
8245 <stage>
8246 <name>Ended OK</name>
8247 <order>900</order>
8248 <value>ended_ok</value>
8249 <ola/>
8250 </stage>
8251 <stage>
8252 <name>Ended Failed</name>
8253 <order>900</order>
8254 <value>ended_failed</value>
8255 <ola/>
8256 </stage>
8257 <stage>
8258 <name>Completed</name>
8259 <order>1000</order>
8260 <value>completed</value>
8261 <ola/>
8262 </stage>
8263</stages>
8264
8265
8266
8267 <activities>
8268 <activity>
8269 <name>Begin</name>
8270 <activity_definition>Begin</activity_definition>
8271 <stage/>
8272 <width/>
8273 <height/>
8274 <x>1</x>
8275 <y>1</y>
8276 <snsc_name>begin</snsc_name>
8277 </activity>
8278
8279 <activity>
8280 <name>Check item's price is 0 or not?</name>
8281 <activity_definition>If</activity_definition>
8282 <stage/>
8283 <width/>
8284 <height/>
8285 <x>1</x>
8286 <y>2</y>
8287 <snsc_name>check_price</snsc_name>
8288 <variables>
8289 <variable>
8290 <name>script</name>
8291 <value><![CDATA[function ifScript() {
8292 var item = (new x_ausgh_snsc.SaraGlideHelper()).getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SN_CATALOG_ITEM, {
8293 'sys_id': current.cat_item.sys_id
8294 });
8295
8296 if ((item.price.toString()) === '0') {
8297 return 'yes';
8298 }
8299
8300 return 'no';
8301}
8302
8303answer = ifScript();
8304]]></value>
8305 </variable>
8306 <variable>
8307 <name>advanced</name>
8308 <value>1</value>
8309 </variable>
8310 </variables>
8311 </activity>
8312
8313 <activity>
8314 <name>Waiting for approval</name>
8315 <activity_definition>Approval - Group</activity_definition>
8316 <stage/>
8317 <width/>
8318 <height/>
8319 <x>1</x>
8320 <y>3</y>
8321 <snsc_name>waiting_for_approval</snsc_name>
8322 <variables>
8323 <variable>
8324 <name>wait_for</name>
8325 <value>first_any</value>
8326 </variable>
8327 <variable>
8328 <name>reject_handling</name>
8329 <value>reject</value>
8330 </variable>
8331 </variables>
8332 </activity>
8333
8334 <activity>
8335 <name>Approved</name>
8336 <activity_definition>Approval Action</activity_definition>
8337 <stage/>
8338 <width/>
8339 <height/>
8340 <x>2</x>
8341 <y>3</y>
8342 <snsc_name>approved</snsc_name>
8343 <variables>
8344 <variable>
8345 <name>action</name>
8346 <value>approved</value>
8347 </variable>
8348 </variables>
8349 </activity>
8350
8351 <activity>
8352 <name>Rejected</name>
8353 <activity_definition>Approval Action</activity_definition>
8354 <stage/>
8355 <width/>
8356 <height/>
8357 <x>1</x>
8358 <y>4</y>
8359 <snsc_name>rejected</snsc_name>
8360 <variables>
8361 <variable>
8362 <name>action</name>
8363 <value>rejected</value>
8364 </variable>
8365 </variables>
8366 </activity>
8367
8368 <activity>
8369 <name>Initializing</name>
8370 <activity_definition>Timer</activity_definition>
8371 <stage>initializing</stage>
8372 <width/>
8373 <height/>
8374 <x>3</x>
8375 <y>3</y>
8376 <snsc_name>initializing</snsc_name>
8377 <variables>
8378 <variable>
8379 <name>timer_type</name>
8380 <value>script</value>
8381 </variable>
8382 <variable>
8383 <name>script</name>
8384 <value><![CDATA[workflow.info('Initializing ...');
8385var currentUser = current.opened_by.user_name.toString();
8386workflow.info('Workflow started by {0}', currentUser);
8387workflow.scratchpad.openedBy = currentUser;
8388
8389var technicalUser = new x_ausgh_snsc.SaraConfig().getTechnicalUser();
8390workflow.info('Technical user: {0}', technicalUser);
8391workflow.scratchpad.technicalUser = technicalUser;
8392
8393// Set 'answer' to the number of seconds this timer should wait
8394answer = 2;
8395]]></value>
8396 </variable>
8397 </variables>
8398 </activity>
8399
8400 <activity>
8401 <name>Invoke Consume URL</name>
8402 <activity_definition>Run Script</activity_definition>
8403 <stage>transferring</stage>
8404 <width/>
8405 <height/>
8406 <x>4</x>
8407 <y>3</y>
8408 <snsc_name>invoke_consume</snsc_name>
8409 <variables>
8410 <variable>
8411 <name>script</name>
8412 <value><![CDATA[var restClient = new x_ausgh_snsc.SaraRESTClient();
8413restClient.setMIDServer(x_ausgh_snsc.SaraUtils.getMIDServer());
8414var oauthClient = new x_ausgh_snsc.SaraOAuthClient(restClient);
8415var glideHelper = new x_ausgh_snsc.SaraGlideHelper();
8416
8417// Get tokens, store tokens in workflow scratchpad
8418var tokens = oauthClient.getUserTokens(workflow.scratchpad.technicalUser);
8419
8420if (!tokens) {
8421 workflow.info('Cannot find access tokens for this user "{0}". Order will be skipped', workflow.scratchpad.technicalUser);
8422} else {
8423 workflow.scratchpad.executionHref = null;
8424 workflow.scratchpad.isTransfered = false;
8425
8426 // get service name & consume URL
8427 var serviceName, consumeUrl, varSetId;
8428 var catId = current.cat_item.sys_id;
8429 var saraItem = glideHelper.getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SARA_DEFINITION, {
8430 'u_sc_item': catId
8431 });
8432
8433 if (saraItem) {
8434 serviceName = saraItem['u_name'];
8435 consumeUrl = saraItem['u_consume_url'];
8436 varSetId = saraItem['u_var_set'];
8437
8438 consumeUrl = x_ausgh_snsc.SaraUtils.buildUrl(consumeUrl);
8439
8440 workflow.info('Service name = {0}', serviceName);
8441 workflow.info('Consume URL = {0}', consumeUrl);
8442 workflow.info('Cat item = {0}', current.cat_item.name);
8443
8444 var payload = {};
8445 var payloadFields = {};
8446 payload.fieldvalues = payloadFields;
8447
8448 if (varSetId) {
8449 var saraVariables = glideHelper.getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SARA_VARIABLE, {
8450 'variable_set': varSetId
8451 }, true);
8452
8453 for (var i = 0, variable; variable = saraVariables[i]; i++) {
8454 var variableName = variable['name'];
8455
8456 if (variableName !== x_ausgh_snsc.SaraCommon.CONTROL_NAME.CLIENT_SCRIPTS
8457 && variableName !== x_ausgh_snsc.SaraCommon.CONTROL_NAME.HIDDEN_CONTROL
8458 && variable['u_name']) {
8459
8460 var currentVariable = current.variables[variableName];
8461 var currentValue;
8462
8463 if (variable['type'] === x_ausgh_snsc.SaraCommon.VAR_TYPE.LIST_COLLECTOR.toString()) {
8464 var values = currentVariable.toString().split(',');
8465 currentValue = [];
8466
8467 for (var j = 0, value; value = values[j]; j++) {
8468 var realValue = glideHelper.getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SARA_LOOKUP, {
8469 'sys_id': value
8470 });
8471
8472 currentValue.push(realValue['u_display_name']);
8473 }
8474 } else {
8475 currentValue = [currentVariable.getDisplayValue()];
8476 }
8477
8478 payloadFields[variable['u_name']] = currentValue;
8479 }
8480 }
8481 } else {
8482 workflow.info('There is no variables in catalog item (sys_id = {0})', catId);
8483 }
8484
8485 //---------------- audit information ---------------
8486 workflow.info('Add audit information');
8487
8488 var payloadParams = {};
8489 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.ORDER_ID] = current.request.number.toString();
8490 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.ORDER_TIMESTAMP] = current.sys_created_on.toString();
8491 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.ORDER_NAME] = current.sys_created_by.toString();
8492
8493 var approvalHistory = '<<Auto Approval>>';
8494
8495 if(current.approval_history != null) {
8496 var journal = glideHelper.getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SN_JOURNAL_FIELD, {
8497 'element_id' : current.sys_id
8498 });
8499 if(journal != null) {
8500 approvalHistory = journal.value.toString();
8501 }
8502 }
8503
8504 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.APPROVAL_HISTORY] = approvalHistory;
8505 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.APPROVAL_TIMESTAMP] = current.approval_set.toString();
8506
8507 payload.parametervalues = payloadParams;
8508 //--------------- /audit information ---------------
8509
8510 var payloadStr = x_ausgh_snsc.SaraJSON.stringify(payload);
8511 workflow.info(payloadStr);
8512
8513 // Make request
8514 if (serviceName) {
8515 workflow.info('Invoking consume URL...');
8516
8517 var request = restClient.newSAPIRequest('post', consumeUrl);
8518 request.setContent('${payload}');
8519 request.addHeader('content-type', 'application/json;charset=UTF-8');
8520 request.setStringParameterNoEscape('payload', payloadStr);
8521
8522 // Add Authorization header
8523 request.addHeader('Authorization', tokens[3] + ' ' + tokens[0]);
8524
8525 var response = restClient.executeWithRefreshToken(request);
8526 var responseObject = response.getResponseObject();
8527
8528 if (response.haveError()) {
8529 workflow.info('Order process FAILED.');
8530 } else {
8531 workflow.info('Successfully transfered.');
8532 workflow.info('Response: {0}', response.getBody());
8533 var resObj = x_ausgh_snsc.SaraJSON.parse(response.getBody());
8534 var runId = resObj['runID'];
8535
8536 workflow.scratchpad.isTransfered = true;
8537
8538 if (runId !== undefined) {
8539 var executionHref = resObj['_links']['self']['href'];
8540 workflow.info('Got runId: {0}', runId.toString());
8541 workflow.info('Got execution href: {0}', executionHref);
8542 workflow.scratchpad.runId = runId;
8543 workflow.scratchpad.executionHref = executionHref;
8544
8545 // save runId to the 'correlation_id' column of current record in 'sc_req_item' table
8546 current['correlation_id'] = '' + runId;
8547 current.update();
8548 } else {
8549 workflow.info(resObj.message);
8550 }
8551 }
8552
8553 } else {
8554 workflow.info('Failed to make consume request as no service definition was defined.');
8555 }
8556 } else {
8557 workflow.info('Catalog item (sys_id = {0}) doesn\'t existed any more in {1}!', [catId, x_ausgh_snsc.SaraCommon.TABLE_NAME.SARA_DEFINITION]);
8558 }
8559}
8560]]></value>
8561 </variable>
8562 </variables>
8563 </activity>
8564
8565 <activity>
8566 <name>Check transfer result</name>
8567 <activity_definition>If</activity_definition>
8568 <stage>transferred</stage>
8569 <width/>
8570 <height/>
8571 <x>5</x>
8572 <y>3</y>
8573 <snsc_name>check_transfer</snsc_name>
8574 <variables>
8575 <variable>
8576 <name>script</name>
8577 <value><![CDATA[// This script needs to set answer to 'yes' or 'no' to indicate the state of the activity.
8578//
8579// For example,
8580//
8581answer = ifScript();
8582
8583function ifScript() {
8584 return (workflow.scratchpad.isTransfered == true ? 'yes' : 'no');
8585}
8586]]></value>
8587 </variable>
8588 <variable>
8589 <name>advanced</name>
8590 <value>1</value>
8591 </variable>
8592 </variables>
8593 </activity>
8594
8595 <activity>
8596 <name>Transfer Request Failed</name>
8597 <activity_definition>Log Message</activity_definition>
8598 <stage>transfer_failed</stage>
8599 <width/>
8600 <height/>
8601 <x>5</x>
8602 <y>4</y>
8603 <snsc_name>transfer_failed</snsc_name>
8604 <variables>
8605 <variable>
8606 <name>message</name>
8607 <value>Transfer request failed, order skipped.</value>
8608 </variable>
8609 </variables>
8610 </activity>
8611
8612 <activity>
8613 <name>Check consume result</name>
8614 <activity_definition>If</activity_definition>
8615 <stage>transferred</stage>
8616 <width/>
8617 <height/>
8618 <x>6</x>
8619 <y>4</y>
8620 <snsc_name>check_consume</snsc_name>
8621 <variables>
8622 <variable>
8623 <name>script</name>
8624 <value><![CDATA[// This script needs to set answer to 'yes' or 'no' to indicate the state of the activity.
8625//
8626// For example,
8627//
8628answer = ifScript();
8629
8630function ifScript() {
8631 return (workflow.scratchpad.executionHref != null ? 'yes' : 'no');
8632}
8633]]></value>
8634 </variable>
8635 <variable>
8636 <name>advanced</name>
8637 <value>1</value>
8638 </variable>
8639 </variables>
8640 </activity>
8641
8642 <activity>
8643 <name>Consume Request Failed</name>
8644 <activity_definition>Log Message</activity_definition>
8645 <stage>consume_failed</stage>
8646 <width/>
8647 <height/>
8648 <x>6</x>
8649 <y>5</y>
8650 <snsc_name>consume_failed</snsc_name>
8651 <variables>
8652 <variable>
8653 <name>message</name>
8654 <value>Consume request failed, order skipped.</value>
8655 </variable>
8656 </variables>
8657 </activity>
8658
8659 <activity>
8660 <name>Workflow Timer</name>
8661 <activity_definition>Timer</activity_definition>
8662 <stage>running</stage>
8663 <width/>
8664 <height/>
8665 <x>7</x>
8666 <y>5</y>
8667 <snsc_name>workflow_timer</snsc_name>
8668 <variables>
8669 <variable>
8670 <name>timer_type</name>
8671 <value>script</value>
8672 </variable>
8673 <variable>
8674 <name>script</name>
8675 <value><![CDATA[if (workflow.scratchpad.delay === undefined) {
8676 var delay = +x_ausgh_snsc.SaraUtils.getSaraProperty(SaraCommon.SYSTEM_PROPERTY_NAME.WORKFLOW_DELAY);
8677 var timeout = +x_ausgh_snsc.SaraUtils.getSaraProperty(SaraCommon.SYSTEM_PROPERTY_NAME.WORKFLOW_TIMEOUT);
8678
8679 // If delay time in config is equal or lesser than 0, let make it '60'
8680 if (delay <= 0) {
8681 delay = 60;
8682 }
8683
8684 // Make sure that timeout minimum always be '0'
8685 if (timeout < 0) {
8686 timeout = 0;
8687 }
8688
8689 workflow.scratchpad.counter = 1;
8690 workflow.scratchpad.maxCount = (timeout / delay) + 1;
8691 workflow.scratchpad.delay = delay;
8692 workflow.scratchpad.timeout = timeout;
8693}
8694
8695answer = workflow.scratchpad.delay;
8696]]></value>
8697 </variable>
8698 </variables>
8699 </activity>
8700
8701 <activity>
8702 <name>Retrieve Execution Status</name>
8703 <activity_definition>Run Script</activity_definition>
8704 <stage>running</stage>
8705 <width/>
8706 <height/>
8707 <x>8</x>
8708 <y>5</y>
8709 <snsc_name>retrieve_status</snsc_name>
8710 <variables>
8711 <variable>
8712 <name>script</name>
8713 <value><![CDATA[var restClient = new x_ausgh_snsc.SaraRESTClient();
8714restClient.setMIDServer(x_ausgh_snsc.SaraUtils.getMIDServer());
8715var oauthClient = new x_ausgh_snsc.SaraOAuthClient(restClient);
8716var executionHref = x_ausgh_snsc.SaraUtils.buildUrl(workflow.scratchpad.executionHref);
8717
8718workflow.scratchpad.ended = 'unknown';
8719
8720// Get tokens, store tokens in workflow scratchpad
8721var tokens = oauthClient.getUserTokens(workflow.scratchpad.technicalUser);
8722var request = restClient.newSAPIRequest('get', executionHref);
8723request.addHeader('Authorization', tokens[3] + ' ' + tokens[0]);
8724
8725workflow.info('[{0}] Waiting for execution checking response ...', workflow.scratchpad.counter);
8726var response = restClient.executeWithRefreshToken(request);
8727var responseObject = response.getResponseObject();
8728
8729if (response.haveError()) {
8730 workflow.warn('Status code: {0}, error message: {1}', [responseObject.statusCode, responseObject.errorMessage]);
8731
8732 workflow.info('Stop retrieving execution status now.');
8733} else {
8734 workflow.info('Response received: {0}', response.getBody());
8735 var resObj = responseObject.bodyObject;
8736 var statusCode = resObj.statusCode;
8737 workflow.info('Status code: {0}, statusText: {1}', [statusCode.toString(), resObj.statusText]);
8738
8739 if (statusCode >= 1800) {
8740 if (statusCode === x_ausgh_snsc.SaraCommon.WORKFLOW_STATUS_CODE.ENDED_OK) {
8741 workflow.info('Execution finished successfully!');
8742 workflow.scratchpad.ended = 'ENDED_OK';
8743 } else {
8744 workflow.scratchpad.ended = statusCode + ' - ' + resObj.statusText;
8745 }
8746 }
8747}
8748
8749workflow.scratchpad.counter++;
8750]]></value>
8751 </variable>
8752 </variables>
8753 </activity>
8754
8755 <activity>
8756 <name>Check Timeout</name>
8757 <activity_definition>If</activity_definition>
8758 <stage>running</stage>
8759 <width/>
8760 <height/>
8761 <x>9</x>
8762 <y>5</y>
8763 <snsc_name>check_timeout</snsc_name>
8764 <variables>
8765 <variable>
8766 <name>script</name>
8767 <value><![CDATA[function ifScript() {
8768 var counter = workflow.scratchpad.counter;
8769 var maxCount = workflow.scratchpad.maxCount;
8770 var timeout = workflow.scratchpad.timeout;
8771
8772 if (timeout === 0) {
8773 if (workflow.scratchpad.ended !== 'unknown') {
8774 return 'yes';
8775 }
8776 } else {
8777 if (counter <= maxCount) {
8778 if (workflow.scratchpad.ended !== 'unknown') {
8779 return 'yes';
8780 }
8781 } else {
8782 return 'yes';
8783 }
8784 }
8785
8786 return 'no';
8787}
8788
8789answer = ifScript();
8790]]></value>
8791 </variable>
8792 <variable>
8793 <name>advanced</name>
8794 <value>1</value>
8795 </variable>
8796 </variables>
8797 </activity>
8798
8799 <activity>
8800 <name>Check Execution Result</name>
8801 <activity_definition>If</activity_definition>
8802 <stage>running</stage>
8803 <width/>
8804 <height/>
8805 <x>10</x>
8806 <y>6</y>
8807 <snsc_name>check_result</snsc_name>
8808 <variables>
8809 <variable>
8810 <name>script</name>
8811 <value><![CDATA[// This script needs to set answer to 'yes' or 'no' to indicate the state of the activity.
8812
8813answer = ifScript();
8814
8815function ifScript() {
8816 return (workflow.scratchpad.ended == 'ENDED_OK' ? 'yes' : 'no');
8817}
8818]]></value>
8819 </variable>
8820 <variable>
8821 <name>advanced</name>
8822 <value>1</value>
8823 </variable>
8824 </variables>
8825 </activity>
8826
8827 <activity>
8828 <name>Ended Failed</name>
8829 <activity_definition>Log Message</activity_definition>
8830 <stage>ended_failed</stage>
8831 <width/>
8832 <height/>
8833 <x>10</x>
8834 <y>7</y>
8835 <snsc_name>ended_failed</snsc_name>
8836 <variables>
8837 <variable>
8838 <name>message</name>
8839 <value>Workflow finished NOT OK.</value>
8840 </variable>
8841 </variables>
8842 </activity>
8843
8844 <activity>
8845 <name>Ended OK</name>
8846 <activity_definition>Log Message</activity_definition>
8847 <stage>ended_ok</stage>
8848 <width/>
8849 <height/>
8850 <x>11</x>
8851 <y>7</y>
8852 <snsc_name>ended_ok</snsc_name>
8853 <variables>
8854 <variable>
8855 <name>message</name>
8856 <value>Workflow finished successfully.</value>
8857 </variable>
8858 </variables>
8859 </activity>
8860
8861 <activity>
8862 <name>End</name>
8863 <activity_definition>End</activity_definition>
8864 <stage>completed</stage>
8865 <width/>
8866 <height/>
8867 <x>2</x>
8868 <y>8</y>
8869 <snsc_name>end</snsc_name>
8870 </activity>
8871</activities>
8872
8873
8874
8875 <transitions>
8876
8877 <transition>
8878 <from>begin</from>
8879 <to>check_price</to>
8880 <condition>
8881 <name>Always</name>
8882 <condition>true</condition>
8883 <order>1</order>
8884 <description/>
8885 </condition>
8886 </transition>
8887
8888
8889 <transition>
8890 <from>check_price</from>
8891 <to>waiting_for_approval</to>
8892 <condition>
8893 <name>No</name>
8894 <condition>activity.result == 'no'</condition>
8895 <order>1</order>
8896 <description/>
8897 </condition>
8898 </transition>
8899
8900
8901 <transition>
8902 <from>check_price</from>
8903 <to>approved</to>
8904 <condition>
8905 <name>Yes</name>
8906 <condition>activity.result == 'yes'</condition>
8907 <order>1</order>
8908 <description/>
8909 </condition>
8910 </transition>
8911
8912
8913 <transition>
8914 <from>waiting_for_approval</from>
8915 <to>rejected</to>
8916 <condition>
8917 <name>Rejected</name>
8918 <condition>activity.result == 'rejected'</condition>
8919 <order>1</order>
8920 <description/>
8921 </condition>
8922 </transition>
8923
8924
8925 <transition>
8926 <from>rejected</from>
8927 <to>end</to>
8928 <condition>
8929 <name>Always</name>
8930 <condition>true</condition>
8931 <order>1</order>
8932 <description/>
8933 </condition>
8934 </transition>
8935
8936
8937 <transition>
8938 <from>waiting_for_approval</from>
8939 <to>approved</to>
8940 <condition>
8941 <name>Approved</name>
8942 <condition>activity.result == 'approved' || activity.result == 'skipped'</condition>
8943 <order>1</order>
8944 <description/>
8945 </condition>
8946 </transition>
8947
8948
8949 <transition>
8950 <from>approved</from>
8951 <to>initializing</to>
8952 <condition>
8953 <name>Always</name>
8954 <condition>true</condition>
8955 <order>1</order>
8956 <description/>
8957 </condition>
8958 </transition>
8959
8960
8961 <transition>
8962 <from>initializing</from>
8963 <to>invoke_consume</to>
8964 <condition>
8965 <name>Always</name>
8966 <condition>true</condition>
8967 <order>1</order>
8968 <description/>
8969 </condition>
8970 </transition>
8971
8972
8973 <transition>
8974 <from>invoke_consume</from>
8975 <to>check_transfer</to>
8976 <condition>
8977 <name>Always</name>
8978 <condition>true</condition>
8979 <order>1</order>
8980 <description/>
8981 </condition>
8982 </transition>
8983
8984
8985 <transition>
8986 <from>check_transfer</from>
8987 <to>transfer_failed</to>
8988 <condition>
8989 <name>No</name>
8990 <condition>activity.result == 'no'</condition>
8991 <order>1</order>
8992 <description/>
8993 </condition>
8994 </transition>
8995
8996
8997 <transition>
8998 <from>transfer_failed</from>
8999 <to>end</to>
9000 <condition>
9001 <name>Always</name>
9002 <condition>true</condition>
9003 <order>1</order>
9004 <description/>
9005 </condition>
9006 </transition>
9007
9008
9009 <transition>
9010 <from>check_transfer</from>
9011 <to>check_consume</to>
9012 <condition>
9013 <name>Yes</name>
9014 <condition>activity.result == 'yes'</condition>
9015 <order>1</order>
9016 <description/>
9017 </condition>
9018 </transition>
9019
9020
9021 <transition>
9022 <from>check_consume</from>
9023 <to>consume_failed</to>
9024 <condition>
9025 <name>No</name>
9026 <condition>activity.result == 'no'</condition>
9027 <order>1</order>
9028 <description/>
9029 </condition>
9030 </transition>
9031
9032
9033 <transition>
9034 <from>consume_failed</from>
9035 <to>end</to>
9036 <condition>
9037 <name>Always</name>
9038 <condition>true</condition>
9039 <order>1</order>
9040 <description/>
9041 </condition>
9042 </transition>
9043
9044
9045 <transition>
9046 <from>check_consume</from>
9047 <to>workflow_timer</to>
9048 <condition>
9049 <name>Yes</name>
9050 <condition>activity.result == 'yes'</condition>
9051 <order>1</order>
9052 <description/>
9053 </condition>
9054 </transition>
9055
9056
9057 <transition>
9058 <from>workflow_timer</from>
9059 <to>retrieve_status</to>
9060 <condition>
9061 <name>Always</name>
9062 <condition>true</condition>
9063 <order>1</order>
9064 <description/>
9065 </condition>
9066 </transition>
9067
9068
9069 <transition>
9070 <from>retrieve_status</from>
9071 <to>check_timeout</to>
9072 <condition>
9073 <name>Always</name>
9074 <condition>true</condition>
9075 <order>1</order>
9076 <description/>
9077 </condition>
9078 </transition>
9079
9080
9081 <transition>
9082 <from>check_timeout</from>
9083 <to>workflow_timer</to>
9084 <condition>
9085 <name>No</name>
9086 <condition>activity.result == 'no'</condition>
9087 <order>2</order>
9088 <description/>
9089 </condition>
9090 </transition>
9091
9092
9093 <transition>
9094 <from>check_timeout</from>
9095 <to>check_result</to>
9096 <condition>
9097 <name>Yes</name>
9098 <condition>activity.result == 'yes'</condition>
9099 <order>1</order>
9100 <description/>
9101 </condition>
9102 </transition>
9103
9104
9105 <transition>
9106 <from>check_result</from>
9107 <to>ended_failed</to>
9108 <condition>
9109 <name>No</name>
9110 <condition>activity.result == 'no'</condition>
9111 <order>2</order>
9112 <description/>
9113 </condition>
9114 </transition>
9115
9116
9117 <transition>
9118 <from>ended_failed</from>
9119 <to>end</to>
9120 <condition>
9121 <name>Always</name>
9122 <condition>true</condition>
9123 <order>1</order>
9124 <description/>
9125 </condition>
9126 </transition>
9127
9128
9129 <transition>
9130 <from>check_result</from>
9131 <to>ended_ok</to>
9132 <condition>
9133 <name>Yes</name>
9134 <condition>activity.result == 'yes'</condition>
9135 <order>1</order>
9136 <description/>
9137 </condition>
9138 </transition>
9139
9140
9141 <transition>
9142 <from>ended_ok</from>
9143 <to>end</to>
9144 <condition>
9145 <name>Always</name>
9146 <condition>true</condition>
9147 <order>1</order>
9148 <description/>
9149 </condition>
9150 </transition>
9151</transitions>
9152
9153 </workflow>
9154</workflows>
9155
9156
9157 <fix_scripts>
9158 <fix_script>
9159 <name>Sara - Create Scheduler for auto-sync</name>
9160 <description>Create Scheduler for auto-sync service and lookup value</description>
9161 <active>true</active>
9162 <run_once>true</run_once>
9163 <script><![CDATA[var glideHelper = new x_ausgh_snsc.SaraGlideHelper();
9164
9165glideHelper.persistData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SN_AUTO_SCRIPT, {
9166 'name': 'SaraAutoSync',
9167 'script': 'new x_ausgh_snsc.SaraSync().syncServices();',
9168 'active': true,
9169 'run_type': 'periodically',
9170 'run_period': '02:00:00',
9171 'sys_class_name': 'sysauto_script',
9172 'run_dayofweek': 1
9173});
9174]]></script>
9175 </fix_script>
9176 <fix_script>
9177 <name>Sara - Remove Scheduler for auto-sync</name>
9178 <description>Remove Scheduler for auto-sync service and lookup value</description>
9179 <active>true</active>
9180 <run_once>true</run_once>
9181 <script><![CDATA[var glideHelper = new x_ausgh_snsc.SaraGlideHelper();
9182
9183glideHelper.deleteData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SN_AUTO_SCRIPT, {
9184 'name': 'SaraAutoSync'
9185}, true);
9186]]></script>
9187 </fix_script>
9188</fix_scripts>
9189
9190
9191 <schedulers>
9192 <scheduler>
9193 <name>SaraAutoSync</name>
9194 <active>false</active>
9195 <run_type>periodically</run_type>
9196 <run_period>02:00:00</run_period>
9197 <sys_class_name>sysauto_script</sys_class_name>
9198 <run_dayofweek>1</run_dayofweek>
9199 <script>new x_ausgh_snsc.SaraSync().syncServices();</script>
9200 </scheduler>
9201</schedulers>
9202
9203
9204 <wizards>
9205 <wizard>
9206 <name>Automic OAuth Configuration</name>
9207 <type>expert</type>
9208 <banner_type>fixed</banner_type>
9209 <roles>x_ausgh_snsc.admin</roles>
9210 <first_panel>OAuth Client</first_panel>
9211 <variables>
9212 <variable>
9213 <name>sara_client_scripts</name>
9214 <type>14</type>
9215 <class>expert_variable</class>
9216 <question>Sara Client Scripts</question>
9217 <order>0</order>
9218 <mandatory>false</mandatory>
9219 <active>true</active>
9220 <panel>Config OAuth Client</panel>
9221 <macro>sara_client_scripts</macro>
9222 </variable>
9223 <variable>
9224 <name>client_id</name>
9225 <type>6</type>
9226 <class>expert_variable</class>
9227 <question>Client ID</question>
9228 <order>100</order>
9229 <mandatory>true</mandatory>
9230 <active>true</active>
9231 <panel>Config OAuth Client</panel>
9232 <show_help>true</show_help>
9233 <help_tag>More information</help_tag>
9234 <help_text>Identity of OAuth client (AE system name / client number / user name). Example: AE/777/SERVICE_NOW. Typically the ID of the ServiceNow instance registered with OAuth server.</help_text>
9235 </variable>
9236 <variable>
9237 <name>client_secret</name>
9238 <type>6</type>
9239 <class>expert_variable</class>
9240 <question>Client Secret</question>
9241 <order>200</order>
9242 <mandatory>true</mandatory>
9243 <active>true</active>
9244 <panel>Config OAuth Client</panel>
9245 <show_help>true</show_help>
9246 <help_tag>More information</help_tag>
9247 <help_text>Secret phrase of OAuth client user. Example: AES_12345, the value will be encrypted in ServiceNow.</help_text>
9248 </variable>
9249 <variable>
9250 <name>technical_user</name>
9251 <type>6</type>
9252 <class>expert_variable</class>
9253 <question>Technical User</question>
9254 <order>300</order>
9255 <mandatory>true</mandatory>
9256 <active>true</active>
9257 <panel>Config OAuth Client</panel>
9258 <show_help>true</show_help>
9259 <help_tag>More information</help_tag>
9260 <help_text>User Name/Department. Example: TECHSYNC/AUTOMIC</help_text>
9261 </variable>
9262 <variable>
9263 <name>sapi_endpoint</name>
9264 <type>6</type>
9265 <class>expert_variable</class>
9266 <question>SAPI Endpoint</question>
9267 <order>400</order>
9268 <mandatory>true</mandatory>
9269 <active>true</active>
9270 <panel>Config OAuth Client</panel>
9271 <show_help>true</show_help>
9272 <help_tag>More information</help_tag>
9273 <help_text>Root endpoint URL of SAPI, the URL from which SNSC will start discovering services. Example: http://mycompany.com/sapi. Protocol indication (http/https) is required. If SAPI is not public accessible, mid_server must be specified under Sara System Properties > x_ausgh_snsc.mid_server</help_text>
9274 </variable>
9275 <variable>
9276 <name>token_endpoint</name>
9277 <type>6</type>
9278 <class>expert_variable</class>
9279 <question>Token Endpoint</question>
9280 <order>500</order>
9281 <mandatory>true</mandatory>
9282 <active>true</active>
9283 <panel>Config OAuth Client</panel>
9284 <show_help>true</show_help>
9285 <help_tag>More information</help_tag>
9286 <help_text>Endpoint for token requesting/refreshing URL. Example: http://mycompany.com/oauth2/token. Protocol indication (http/https) is required. If OAuth Server is not public accessible, mid_server must be specified under Sara System Properties > x_ausgh_snsc.mid_server</help_text>
9287 </variable>
9288 <variable>
9289 <name>auth_endpoint</name>
9290 <type>6</type>
9291 <class>expert_variable</class>
9292 <question>Authorization Endpoint</question>
9293 <order>600</order>
9294 <mandatory>true</mandatory>
9295 <active>true</active>
9296 <panel>Config OAuth Client</panel>
9297 <show_help>true</show_help>
9298 <help_tag>More information</help_tag>
9299 <help_text>Authorization endpoint URL. Example: http://mycompany.com/oauth2/auth. Protocol indication (http/https) is required.. If OAuth Server is not public accessible, mid_server must be specified under Sara System Properties > x_ausgh_snsc.mid_server</help_text>
9300 </variable>
9301 </variables>
9302
9303 <panels>
9304 <panel>
9305 <name>Config OAuth Client</name>
9306 <title>Config OAuth Client</title>
9307 <class>expert_panel</class>
9308 <description>Config OAuth Server Endpoints, Client ID, Client Secret, SAPI Endpoint and Technical User for SNSC. OAuth login popup will be shown in case Technical User doesn't have tokens or Technical User's tokens are empty, invalid or expired.</description>
9309 <previous_message>Previous</previous_message>
9310 <next_message>Store OAuth Client Settings</next_message>
9311 <complete_message>Done</complete_message>
9312 <client_script>
9313 <name>SARA OAuth Client OnLoad</name>
9314 <active>true</active>
9315 <type>onLoad</type>
9316 <script><![CDATA[function onLoad() {
9317 g_form.getControl(x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_SECRET).type = 'password';
9318 x_ausgh_snsc.oldConfig = {};
9319
9320 x_ausgh_snsc.SaraOAuth.getConfig(function (configData) {
9321 for (var name in configData) {
9322 var value = configData[name];
9323
9324 g_form.setValue(name, value);
9325 x_ausgh_snsc.oldConfig[name] = value;
9326 }
9327 });
9328}
9329]]></script>
9330 </client_script>
9331 <client_script>
9332 <name>SARA OAuth Client OnSubmit</name>
9333 <active>true</active>
9334 <type>onSubmit</type>
9335 <script><![CDATA[function onSubmit() {
9336 if (x_ausgh_snsc.isTokenValid) {
9337 return true;
9338 } else {
9339 var isChange = false;
9340 for (var name in x_ausgh_snsc.oldConfig) {
9341 if (x_ausgh_snsc.oldConfig[name] !== g_form.getValue(name).toString() && name !== x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT) {
9342 isChange = true;
9343 break;
9344 }
9345 }
9346
9347 if (isChange && !x_ausgh_snsc.notChange) {
9348 getToken();
9349 } else {
9350 // Clean all existing messages
9351 g_form.clearMessages();
9352
9353 // Check if Sara tokens exist for Technical User
9354 var technicalUser = g_form.getValue(x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER).toString();
9355 var sapiEndpoint = g_form.getValue(x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT).toString();
9356 x_ausgh_snsc.SaraOAuth.checkOAuthToken(technicalUser, sapiEndpoint, false, {
9357 onValid: function () {
9358 x_ausgh_snsc.isTokenValid = true;
9359 g_expert.next();
9360 },
9361 onInvalid: function () {
9362 x_ausgh_snsc.isTokenValid = false;
9363 getToken();
9364 },
9365 onError: function (errorMessage) {
9366 x_ausgh_snsc.isTokenValid = false;
9367 g_form.addErrorMessage(errorMessage);
9368 }
9369 });
9370 }
9371 }
9372
9373 return false;
9374}
9375
9376function getToken() {
9377 x_ausgh_snsc.log('Preparing for openning OAuth login popup...');
9378
9379 for (var key in x_ausgh_snsc.SaraCommon.CONFIG_NAME) {
9380 var name = x_ausgh_snsc.SaraCommon.CONFIG_NAME[key];
9381
9382 x_ausgh_snsc.config[name] = g_form.getValue(name).toString();
9383 }
9384
9385 x_ausgh_snsc.SaraOAuth.login(
9386 x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_ID],
9387 x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER],
9388 x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.AUTH_ENDPOINT], {
9389 onSuccess: function () {
9390 x_ausgh_snsc.notChange = true;
9391 g_expert.next();
9392 }
9393 }
9394 );
9395}
9396]]></script>
9397 </client_script>
9398 </panel>
9399 <panel>
9400 <name>Config OAuth Client Completed</name>
9401 <title>Config OAuth Client Completed</title>
9402 <class>expert_panel</class>
9403 <description/>
9404 <previous_message>Previous</previous_message>
9405 <next_message>Next</next_message>
9406 <complete_message>Done</complete_message>
9407 </panel>
9408 </panels>
9409
9410 <transitions>
9411 <transition>
9412 <from>Config OAuth Client</from>
9413 <to>Config OAuth Client Completed</to>
9414 <order>100</order>
9415 <condition/>
9416 <transition_script><![CDATA[var LOGGER = new x_ausgh_snsc.SaraLog('sara_oauth_client_transition');
9417
9418gs.addInfoMessage('Client ID = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_ID]
9419 + ', Client Secret = ***'
9420 + ', Technical User = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER]
9421 + ', SAPI Endpoint = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT]
9422 + ', Token Endpoint = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT]
9423 + ', Authorization Endpoint = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.AUTH_ENDPOINT]);
9424
9425var saraConfig = new x_ausgh_snsc.SaraConfig();
9426try {
9427 var configData = {};
9428 for (var key in x_ausgh_snsc.SaraCommon.CONFIG_NAME) {
9429 var name = x_ausgh_snsc.SaraCommon.CONFIG_NAME[key];
9430
9431 configData[name] = wizard[name];
9432 }
9433
9434 saraConfig.storeClientConfig(configData);
9435 LOGGER.info('OAuth Configuration updated:\n'
9436 + ' - Client ID = {0}, \n'
9437 + ' - Client Secret = ***, \n'
9438 + ' - Technical User = {1} \n'
9439 + ' - SAPI Endpoint = {2}, \n'
9440 + ' - Token Endpoint = {3}, \n'
9441 + ' - Authorization Endpoint = {4}',
9442 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_ID],
9443 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER],
9444 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT],
9445 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT],
9446 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.AUTH_ENDPOINT]
9447 );
9448
9449 gs.addInfoMessage('Successfully update Automic OAuth client settings');
9450} catch (err) {
9451 LOGGER.info('Error on update Automic OAuth client settings: {0}', err);
9452
9453 gs.addInfoMessage('Failed to update Automic OAuth client settings');
9454}
9455]]></transition_script>
9456 </transition>
9457 </transitions>
9458 </wizard>
9459
9460 <wizard>
9461 <name>Automic Import Services</name>
9462 <type>expert</type>
9463 <banner_type>fixed</banner_type>
9464 <roles>x_ausgh_snsc.admin</roles>
9465 <first_panel>Import Services</first_panel>
9466 <variables>
9467 <variable>
9468 <name>sara_client_scripts</name>
9469 <type>14</type>
9470 <class>expert_variable</class>
9471 <question>Sara Client Scripts</question>
9472 <order>0</order>
9473 <mandatory>false</mandatory>
9474 <active>true</active>
9475 <panel>Import Services</panel>
9476 <macro>sara_client_scripts</macro>
9477 </variable>
9478 <variable>
9479 <name>sara_message</name>
9480 <type>6</type>
9481 <class>expert_variable</class>
9482 <question>Sara Message</question>
9483 <order>100</order>
9484 <mandatory>false</mandatory>
9485 <active>true</active>
9486 <panel>Import Services</panel>
9487 </variable>
9488 <variable>
9489 <name>sara_target_category</name>
9490 <type>18</type>
9491 <class>expert_variable</class>
9492 <question>Select Target Category</question>
9493 <order>200</order>
9494 <mandatory>true</mandatory>
9495 <active>true</active>
9496 <lookup_table>sc_category</lookup_table>
9497 <lookup_value>sys_id</lookup_value>
9498 <lookup_label>title</lookup_label>
9499 <panel>Import Services</panel>
9500 <reference_qual>javascript:x_ausgh_snsc.SaraUtils.getImportTargetCatRefQual()</reference_qual>
9501 </variable>
9502 </variables>
9503
9504 <panels>
9505 <panel>
9506 <name>Import Services</name>
9507 <title>Import Services</title>
9508 <class>expert_panel</class>
9509 <description>Import SARA services to Service Catalog. Error messages will be shown in case Technical User doesn't have tokens or Technical User's tokens empty, invalid or expired.</description>
9510 <previous_message>Previous</previous_message>
9511 <next_message>Import Services</next_message>
9512 <complete_message>Done</complete_message>
9513 <client_script>
9514 <name>Import Services OnLoad</name>
9515 <active>true</active>
9516 <type>onLoad</type>
9517 <script><![CDATA[function onLoad() {
9518 x_ausgh_snsc.SaraUtils.setFormControlVisible('sara_message', false);
9519 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(false);
9520
9521 x_ausgh_snsc.SaraOAuth.getConfig(function (configData) {
9522 for (var key in configData) {
9523 var value = configData[key];
9524
9525 x_ausgh_snsc.config[key] = value;
9526
9527 if (!value) {
9528 g_form.addErrorMessage('OAuth Configuration "' + key + '" is empty. Please check the current OAuth configuration.');
9529 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(false);
9530 break;
9531 }
9532 }
9533
9534 setTimeout(function () {
9535 checkToken();
9536 }, 100);
9537 });
9538}
9539
9540function checkToken() {
9541 var technicalUser = x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER];
9542 var sapiEndpoint = x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT];
9543 x_ausgh_snsc.SaraOAuth.checkOAuthToken(technicalUser, sapiEndpoint, true, {
9544 onValid: function () {
9545 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(true);
9546 },
9547 onInvalid: function () {
9548 g_form.addErrorMessage('Tokens are empty, invalid or expired! Please contact your administrator for resolving this problem.');
9549 },
9550 onError: function (errorMessage) {
9551 g_form.addErrorMessage(errorMessage);
9552 }
9553 });
9554}
9555]]></script>
9556 </client_script>
9557 <client_script>
9558 <name>Import Services OnSubmit</name>
9559 <active>true</active>
9560 <type>onSubmit</type>
9561 <script><![CDATA[function onSubmit() {
9562 if (x_ausgh_snsc.isOk) {
9563 return true;
9564 }
9565
9566 var importDialog = new GlideDialogWindow('hierarchical_progress_viewer');
9567 importDialog.setPreference('sysparm_ajax_processor', 'x_ausgh_snsc.SaraConsumerRunner');
9568 importDialog.setPreference('sysparm_catid', g_form.getValue('sara_target_category').toString());
9569 importDialog.setSize(400, 300);
9570 importDialog.setTitle('Importing service...');
9571
9572 importDialog.on('executionComplete', function (trackerObj) {
9573 x_ausgh_snsc.log('executionComplete', trackerObj);
9574 if (trackerObj.result && trackerObj.result.info) {
9575 importDialog.setTitle(trackerObj.result.msg);
9576 g_form.setValue('sara_message', trackerObj.result.info);
9577
9578 x_ausgh_snsc.isOk = true;
9579 x_ausgh_snsc.log('Go to next panel', x_ausgh_snsc.isOk);
9580 g_expert.next();
9581
9582
9583 x_ausgh_snsc.log('Destroy diablog', importDialog);
9584 importDialog.destroy();
9585 }
9586 });
9587
9588 importDialog.on("renderStatus", function (trackerObj) {
9589 x_ausgh_snsc.log('renderStatus', trackerObj);
9590
9591 if (trackerObj && trackerObj.result && trackerObj.result.msg) {
9592 importDialog.setTitle(trackerObj.result.msg);
9593 }
9594 });
9595
9596 // Render the viewer
9597 importDialog.render();
9598
9599 return false;
9600}
9601]]></script>
9602 </client_script>
9603 </panel>
9604 <panel>
9605 <name>Import Services Completed</name>
9606 <title>Import Services Completed</title>
9607 <class>expert_panel</class>
9608 <description/>
9609 <previous_message>Previous</previous_message>
9610 <next_message>Next</next_message>
9611 <complete_message>Done</complete_message>
9612 </panel>
9613 </panels>
9614
9615 <transitions>
9616 <transition>
9617 <from>Import Services</from>
9618 <to>Import Services Completed</to>
9619 <order>100</order>
9620 <condition>[sara_target_category]!=^EQ</condition>
9621 <transition_script><![CDATA[gs.addInfoMessage(wizard.sara_message.toString());
9622]]></transition_script>
9623 </transition>
9624 </transitions>
9625 </wizard>
9626
9627 <wizard>
9628 <name>Automic Clean-up</name>
9629 <type>expert</type>
9630 <banner_type>fixed</banner_type>
9631 <roles>x_ausgh_snsc.admin</roles>
9632 <first_panel>Automic Cleanup</first_panel>
9633 <variables>
9634 <variable/>
9635 </variables>
9636
9637 <panels>
9638 <panel>
9639 <name>Cleanup Catalog Items</name>
9640 <title>Cleanup Catalog Items</title>
9641 <class>expert_panel</class>
9642 <description>Cleanup all Automic SARA stuffs. This will delete all subcategories and service items.</description>
9643 <previous_message>Previous</previous_message>
9644 <next_message>Cleanup</next_message>
9645 <complete_message>Done</complete_message>
9646 </panel>
9647 <panel>
9648 <name>Cleanup Catalog Items Completed</name>
9649 <title>Cleanup Catalog Items Completed</title>
9650 <class>expert_panel</class>
9651 <description>Cleanup successfully!</description>
9652 <previous_message>Previous</previous_message>
9653 <next_message>Next</next_message>
9654 <complete_message>Done</complete_message>
9655 </panel>
9656 </panels>
9657
9658 <transitions>
9659 <transition>
9660 <from>Cleanup Catalog Items</from>
9661 <to>Cleanup Catalog Items Completed</to>
9662 <order>100</order>
9663 <condition/>
9664 <transition_script>
9665 <![CDATA[x_ausgh_snsc.SaraUtils.cleanup();]]>
9666 </transition_script>
9667 </transition>
9668 </transitions>
9669 </wizard>
9670</wizards>
9671
9672
9673 <processors>
9674 <processor>
9675 <name>SaraUpdateStatus</name>
9676 <type>script</type>
9677 <active>true</active>
9678 <description>Sara REST api for updating status of worflow remotely</description>
9679 <path>sara_update_status</path>
9680 <script><![CDATA[var LOGGER = new x_ausgh_snsc.SaraLog('SaraUpdateStatus');
9681var runId = g_request.getParameter('runId');
9682var status = g_request.getParameter('status');
9683var error = 0;
9684var result = {};
9685
9686LOGGER.info('SaraUpdateStatus: RunId = {0}, Status = {1}', runId, status);
9687LOGGER.info('SaraUpdateStatus: Request user = ' + gs.getUserName());
9688
9689if (!runId) {
9690 error += 1;
9691}
9692
9693if (!status) {
9694 error += 1;
9695}
9696
9697if (error === 0) {
9698 runId = +runId;
9699
9700 if (isNaN(runId)) {
9701 result = {
9702 code: 99,
9703 message: 'The runId must be digits!'
9704 };
9705 } else {
9706 var glideHelper = new x_ausgh_snsc.SaraGlideHelper();
9707 var reqItem = glideHelper.getData('sc_req_item', {
9708 'correlation_id': runId.toString()
9709 });
9710
9711 if (reqItem) {
9712 LOGGER.info('Found current request item (correlation_id = {0}, sys_id = {1})', runId, reqItem['sys_id']);
9713
9714 try {
9715 glideHelper.updateData('sc_req_item', {
9716 'sys_id': reqItem['sys_id']
9717 }, {
9718 'comments': status,
9719 'display_state': status
9720 });
9721
9722 result = {
9723 code: 200,
9724 message: 'Update OK!',
9725 sysId: reqItem['sys_id']
9726 };
9727 } catch (e) {
9728 result = {
9729 code: 99,
9730 message: err
9731 };
9732 }
9733 } else {
9734 var message = x_ausgh_snsc.SaraUtils.formatString('No request item (correlation_id = {0}) found! Update status failed.', runId);
9735 LOGGER.info(message);
9736
9737 result = {
9738 code: 99,
9739 message: message
9740 };
9741 }
9742 }
9743} else {
9744 result = {
9745 code: 99,
9746 message: 'The runId and status must be not null!'
9747 }
9748}
9749
9750var response = x_ausgh_snsc.SaraJSON.stringify(result);
9751
9752LOGGER.debug('SaraUpdateStatus: {0}', response);
9753
9754g_processor.writeOutput('application/json', response);
9755]]></script>
9756 </processor>
9757</processors>
9758
9759
9760 <snsc_application>
9761 <application>
9762 <name>Automic SNSC</name>
9763 <short_description>Automic ServiceNow Service Connector Application</short_description>
9764 <active>true</active>
9765 <user_role>x_ausgh_snsc.user</user_role>
9766 <version>1.0.2</version>
9767 <menu>u_ausgh_snsc_menu</menu>
9768 <scope>x_ausgh_snsc</scope>
9769 </application>
9770 <application_menu>
9771 <name>u_ausgh_snsc_menu</name>
9772 <active>true</active>
9773 <category>Custom Applications</category>
9774 <title>Automic SNSC</title>
9775 <roles>x_ausgh_snsc.user,x_ausgh_snsc.admin</roles>
9776 <hint>Automic ServiceNow Service Connector Application</hint>
9777 </application_menu>
9778 <user_roles>
9779 <user_role>
9780 <name>x_ausgh_snsc.user</name>
9781 <description>User role for SNSC application</description>
9782 </user_role>
9783 <user_role>
9784 <name>x_ausgh_snsc.admin</name>
9785 <description>Admin role for SNSC application</description>
9786 <includes_roles>x_ausgh_snsc.user</includes_roles>
9787 </user_role>
9788 </user_roles>
9789</snsc_application>
9790
9791
9792 <modules>
9793 <module>
9794 <title>Automic Configuration</title>
9795 <order>0</order>
9796 <active>true</active>
9797 <link_type>SEPARATOR</link_type>
9798 <roles>x_ausgh_snsc.admin</roles>
9799 </module>
9800 <module>
9801 <title>Automic Clean-up</title>
9802 <reference>wizard</reference>
9803 <reference_name>Automic Clean-up</reference_name>
9804 <order>10</order>
9805 <active>true</active>
9806 <link_type>DIRECT</link_type>
9807 <query>/expert_shell.do?sysparm_sys_id=@{sys_id}&sysparm_initial=true</query>
9808 <roles>x_ausgh_snsc.admin</roles>
9809 </module>
9810 <module>
9811 <title>Automic Import Services</title>
9812 <reference>wizard</reference>
9813 <reference_name>Automic Import Services</reference_name>
9814 <order>20</order>
9815 <active>true</active>
9816 <link_type>DIRECT</link_type>
9817 <query>/expert_shell.do?sysparm_sys_id=@{sys_id}&sysparm_initial=true</query>
9818 <roles>x_ausgh_snsc.admin</roles>
9819 </module>
9820 <module>
9821 <title>Automic OAuth Configuration</title>
9822 <reference>wizard</reference>
9823 <reference_name>Automic OAuth Configuration</reference_name>
9824 <order>30</order>
9825 <active>true</active>
9826 <link_type>DIRECT</link_type>
9827 <query>/expert_shell.do?sysparm_sys_id=@{sys_id}&sysparm_initial=true</query>
9828 <roles>x_ausgh_snsc.admin</roles>
9829 </module>
9830 <module>
9831 <title>Automic SNSC Components</title>
9832 <order>100</order>
9833 <active>true</active>
9834 <link_type>SEPARATOR</link_type>
9835 </module>
9836 <module>
9837 <title>Sara Tables</title>
9838 <order>110</order>
9839 <active>true</active>
9840 <link_type>LIST</link_type>
9841 <table_name>sys_db_object</table_name>
9842 <filter>nameSTARTSWITHx_ausgh_snsc_</filter>
9843 </module>
9844 <module>
9845 <title>Sara Transform Maps</title>
9846 <order>115</order>
9847 <active>true</active>
9848 <link_type>LIST</link_type>
9849 <table_name>sys_transform_map</table_name>
9850 <filter>nameSTARTSWITHx_ausgh_snsc_</filter>
9851 </module>
9852 <module>
9853 <title>Sara System Properties</title>
9854 <reference>system_property</reference>
9855 <reference_name>Automic</reference_name>
9856 <order>120</order>
9857 <active>true</active>
9858 <link_type>DIRECT</link_type>
9859 <query>/sys_properties_category.do?sys_id=@{sys_id}</query>
9860 </module>
9861 <module>
9862 <title>Sara Script Includes</title>
9863 <order>130</order>
9864 <active>true</active>
9865 <link_type>LIST</link_type>
9866 <table_name>sys_script_include</table_name>
9867 <filter>nameSTARTSWITHSara</filter>
9868 </module>
9869 <module>
9870 <title>Sara UI Scripts</title>
9871 <order>140</order>
9872 <active>true</active>
9873 <link_type>LIST</link_type>
9874 <table_name>sys_ui_script</table_name>
9875 <filter>nameSTARTSWITHx_ausgh_snsc.Sara</filter>
9876 </module>
9877 <module>
9878 <title>Sara UI Pages</title>
9879 <order>150</order>
9880 <active>true</active>
9881 <link_type>LIST</link_type>
9882 <table_name>sys_ui_page</table_name>
9883 <filter>nameSTARTSWITHsara_</filter>
9884 </module>
9885 <module>
9886 <title>Sara UI Macros</title>
9887 <order>160</order>
9888 <active>true</active>
9889 <link_type>LIST</link_type>
9890 <table_name>sys_ui_macro</table_name>
9891 <filter>nameSTARTSWITHsara_</filter>
9892 </module>
9893 <module>
9894 <title>Sara Processors</title>
9895 <order>170</order>
9896 <active>true</active>
9897 <link_type>LIST</link_type>
9898 <table_name>sys_processor</table_name>
9899 <filter>nameSTARTSWITHSara</filter>
9900 </module>
9901 <module>
9902 <title>Sara Wizards</title>
9903 <order>180</order>
9904 <active>true</active>
9905 <link_type>LIST</link_type>
9906 <table_name>expert</table_name>
9907 <filter>nameSTARTSWITHAutomic</filter>
9908 </module>
9909 <module>
9910 <title>Sara Schedulers</title>
9911 <order>190</order>
9912 <active>true</active>
9913 <link_type>LIST</link_type>
9914 <table_name>sysauto</table_name>
9915 <filter>nameSTARTSWITHSara</filter>
9916 </module>
9917 <module>
9918 <title>Sara REST Messages</title>
9919 <order>200</order>
9920 <active>true</active>
9921 <link_type>LIST</link_type>
9922 <table_name>sys_rest_message</table_name>
9923 <filter>nameSTARTSWITHSara</filter>
9924 </module>
9925 <module>
9926 <title>Support</title>
9927 <order>900</order>
9928 <active>true</active>
9929 <link_type>SEPARATOR</link_type>
9930 </module>
9931 <module>
9932 <title>Used ServiceNow's Tables</title>
9933 <order>910</order>
9934 <active>true</active>
9935 <link_type>LIST</link_type>
9936 <table_name>sys_db_object</table_name>
9937 <query>name=sc_category^ORname=item_option_new_set^ORname=io_set_item^ORname=sysauto_script^ORname=item_option_new</query>
9938 </module>
9939 <module>
9940 <title>Sara Transform History</title>
9941 <order>915</order>
9942 <active>true</active>
9943 <link_type>LIST</link_type>
9944 <table_name>sys_import_set_run</table_name>
9945 <query>sys_transform_mapSTARTSWITHx_ausgh_snsc</query>
9946 </module>
9947 <module>
9948 <title>Contact Us</title>
9949 <order>920</order>
9950 <active>true</active>
9951 <link_type>DIRECT</link_type>
9952 <query>https://automic.com/contact-us</query>
9953 </module>
9954 <module>
9955 <title>Support</title>
9956 <order>930</order>
9957 <active>true</active>
9958 <link_type>DIRECT</link_type>
9959 <query>https://automic.force.com/support</query>
9960 </module>
9961</modules>
9962
9963
9964 <rest_messages>
9965 <rest_message>
9966 <name>Sara - SAPI Services</name>
9967 <description>Sara Outbound Web Service for SAPI</description>
9968 <rest_endpoint>${sapiEndpoint}</rest_endpoint>
9969 <methods>
9970 <method>
9971 <function_name>GET</function_name>
9972 <http_method>GET</http_method>
9973 </method>
9974 <method>
9975 <function_name>POST</function_name>
9976 <http_method>POST</http_method>
9977 </method>
9978 <method>
9979 <function_name>PUT</function_name>
9980 <http_method>PUT</http_method>
9981 </method>
9982 <method>
9983 <function_name>DELETE</function_name>
9984 <http_method>DELETE</http_method>
9985 </method>
9986 </methods>
9987 </rest_message>
9988 <rest_message>
9989 <name>Sara - OAuth Services</name>
9990 <description>Sara Outbound Web Service for OAuth</description>
9991 <rest_endpoint>${oauthEndpoint}</rest_endpoint>
9992 <methods>
9993 <method>
9994 <function_name>GET</function_name>
9995 <http_method>GET</http_method>
9996 </method>
9997 <method>
9998 <function_name>POST</function_name>
9999 <http_method>POST</http_method>
10000 </method>
10001 <method>
10002 <function_name>PUT</function_name>
10003 <http_method>PUT</http_method>
10004 </method>
10005 <method>
10006 <function_name>DELETE</function_name>
10007 <http_method>DELETE</http_method>
10008 </method>
10009 </methods>
10010 </rest_message>
10011</rest_messages>
10012
10013 </package>
10014</sara>