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