· 8 years ago · Oct 23, 2017, 04:06 PM
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 // If user's tokens are existed
4861 if (saraOAuth) {
4862 LOGGER.info('User\'s tokens are existed. Updating tokens...');
4863
4864 this.glideHelper.updateData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4865 'sys_id': saraOAuth['sys_id']
4866 }, {
4867 'u_access_token': accessToken,
4868 'u_refresh_token': refreshToken,
4869 'u_token_expiry': tokenExpiry,
4870 'u_token_type': tokenType
4871 });
4872
4873 return saraOAuth['sys_id'];
4874 } else {
4875 LOGGER.info('Storing user\'s tokens...');
4876
4877 return this.glideHelper.persistData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4878 'u_user': username,
4879 'u_access_token': accessToken,
4880 'u_refresh_token': refreshToken,
4881 'u_token_expiry': tokenExpiry,
4882 'u_token_type': tokenType
4883 });
4884 }
4885 },
4886
4887 /**
4888 * Get user tokens by username. The result will be [accessToken, refreshToken, tokenExpiry, tokenType, { createdAt, createdBy, updateAt, updateBy }]
4889 * @param {String} username
4890 * @return {Array<String|Object>}
4891 */
4892 getUserTokens: function (username) {
4893 var LOGGER = this.LOGGER;
4894
4895 if (!username) {
4896 return null;
4897 }
4898
4899 var saraOAuth = this.glideHelper.getData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4900 'u_user': username
4901 });
4902
4903 if (saraOAuth) {
4904 return [
4905 saraOAuth['u_access_token'],
4906 saraOAuth['u_refresh_token'],
4907 saraOAuth['u_token_expiry'],
4908 saraOAuth['u_token_type'], {
4909 'createdAt': saraOAuth['sys_created_on'],
4910 'createdBy': saraOAuth['sys_created_by'],
4911 'updatedAt': saraOAuth['sys_updated_on'],
4912 'updatedBy': saraOAuth['sys_updated_by']
4913 }
4914 ];
4915 } else {
4916 LOGGER.info('Tokens of "{0}" do not exist!', username);
4917 return null;
4918 }
4919 },
4920
4921 /**
4922 * Remove user tokens by username
4923 * @param {String} username
4924 * @return {String} The sys_id of deleted record
4925 */
4926 removeUserToken: function (username) {
4927 var LOGGER = this.LOGGER;
4928
4929 if (!username) {
4930 return null;
4931 }
4932
4933 var saraOAuth = this.glideHelper.getData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4934 'u_user': username
4935 });
4936
4937 if (saraOAuth) {
4938 saraOAuth = this.glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4939 'sys_id': saraOAuth['sys_id']
4940 });
4941
4942 return saraOAuth['sys_id'];
4943 } else {
4944 LOGGER.info('No token found for user "{0}"', username);
4945 return null;
4946 }
4947 },
4948
4949 /**
4950 * Requests user tokens, the request must use client_id/client_secret to authenticate (BASICally) against SARA server,
4951 * LDAP username/password and grant_type will be embedded in request's body
4952 * @param {String} username
4953 * @param {String} password
4954 * @return {Object} Object contains access token, refresh token, token expiry and token type
4955 */
4956 requestToken: function (username, password) {
4957 var LOGGER = this.LOGGER;
4958
4959 LOGGER.debug('Preparing for requesting tokens for SARA user {0}...', username);
4960
4961 var clientInfo = this.saraConfig.getClientConfig();
4962 var clientId = clientInfo[SaraCommon.CONFIG_NAME.CLIENT_ID];
4963 var clientSecret = clientInfo[SaraCommon.CONFIG_NAME.CLIENT_SECERT];
4964 var tokenEndpoint = clientInfo[SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT];
4965
4966 var request = this.restClient.newOAuthRequest('post', tokenEndpoint);
4967 request.setBasicAuth(clientId, clientSecret);
4968
4969 // Add POST body, set Content-Type header
4970 request.setContentType('application/x-www-form-urlencoded');
4971 var formEntity = {
4972 'grant_type': 'password',
4973 'username': username,
4974 'password': password
4975 };
4976 request.setFormContent(formEntity);
4977
4978 LOGGER.info('Requesting tokens for SARA user {0}...', username);
4979 var response = this.restClient.execute(request);
4980 var responseObject = response.getResponseObject();
4981
4982 if (response.haveError()) {
4983 LOGGER.info('Failed to request token for user {0}', username);
4984
4985 return {
4986 'error': responseObject.errorMessage,
4987 'error_description': responseObject.errorDescription
4988 }
4989 }
4990
4991 LOGGER.info('Successfully obtain token for user {0}', username);
4992 return responseObject.bodyObject;
4993 },
4994
4995 /**
4996 * Requests user tokens, the request must use client_id/client_secret to authenticate (BASICally) against SARA server,
4997 * LDAP redirect_uri/authorization_code and grant_type will be embedded in request's body
4998 * @param {String} code The authorization code which get from OAuth after logged-in successfully in Auth Endpoint
4999 * @param {Object} config The config of OAuth Server
5000 * @return {Object} Object contains access token, refresh token, token expiry and token type
5001 */
5002 requestTokenByCode: function (code, config) {
5003 var LOGGER = this.LOGGER;
5004
5005 LOGGER.debug('Preparing for requesting tokens by code "{0}"...', code);
5006
5007 var clientId = config[SaraCommon.CONFIG_NAME.CLIENT_ID];
5008 var clientSecret = config[SaraCommon.CONFIG_NAME.CLIENT_SECERT];
5009 var tokenEndpoint = config[SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT];
5010 var redirectionEndpoint = SaraUtils.getRedirectionUrl();
5011
5012 var request = this.restClient.newOAuthRequest('post', tokenEndpoint);
5013 request.setBasicAuth(clientId, clientSecret);
5014
5015 // Add POST body, set Content-Type header
5016 request.setContentType('application/x-www-form-urlencoded');
5017 var formEntity = {
5018 'grant_type': 'authorization_code',
5019 'redirect_uri': redirectionEndpoint,
5020 'code': code
5021 };
5022 request.setFormContent(formEntity);
5023
5024 LOGGER.info('Requesting tokens by code...');
5025 var response = this.restClient.execute(request);
5026 var responseObject = response.getResponseObject();
5027
5028 if (response.haveError()) {
5029 LOGGER.info('Failed to request token by code');
5030
5031 return {
5032 'error': responseObject.errorMessage,
5033 'error_description': responseObject.errorDescription
5034 }
5035 }
5036
5037 LOGGER.info('Successfully obtain token for user by code "{0}"', code);
5038 return responseObject.bodyObject;
5039 },
5040
5041 /**
5042 * Refresh user tokens
5043 * @param {String} username
5044 * @return {Object}
5045 */
5046 refreshToken: function (username) {
5047 var LOGGER = this.LOGGER;
5048
5049 // Get refresh tokens for this user from 'SaraCommon.TABLE_NAME.SARA_OAUTH' table
5050 var tokens = this.getUserTokens(username);
5051 if (!tokens || tokens.length < 1) {
5052 LOGGER.info('Tokens not found for user {0}', username);
5053 return null;
5054 }
5055
5056 LOGGER.info('Preparing for refreshing tokens for user {0}...', username);
5057
5058 // Use that refesh token to retrieve new tokens
5059 var clientInfo = this.saraConfig.getClientConfig();
5060 var clientId = clientInfo[SaraCommon.CONFIG_NAME.CLIENT_ID];
5061 var clientSecret = clientInfo[SaraCommon.CONFIG_NAME.CLIENT_SECRET];
5062 var tokenEndpoint = clientInfo[SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT];
5063 var request = this.restClient.newOAuthRequest('post', tokenEndpoint);
5064 request.setBasicAuth(clientId, clientSecret);
5065
5066 // Add POST body, set Content-Type header
5067 request.setContentType('application/x-www-form-urlencoded');
5068 request.setFormContent({
5069 'grant_type': 'refresh_token',
5070 'refresh_token': tokens[1]
5071 });
5072
5073 LOGGER.info('Refreshing tokens for user {0}...', username);
5074 var response = this.restClient.execute(request);
5075 var responseObject = response.getResponseObject();
5076
5077 if (response.haveError()) {
5078 LOGGER.info('Failed to refresh token for code');
5079
5080 return {
5081 'error': responseObject.errorMessage,
5082 'error_description': responseObject.errorDescription
5083 }
5084 }
5085
5086 LOGGER.info('Successfully refresh token for user {0}', username);
5087 return responseObject.bodyObject;
5088 },
5089
5090 /**
5091 * Validate access token key of user is invalid or expired
5092 * @param {String} token The access token key of user
5093 * @param {String} sapiEndpoint The SAPI endpoint
5094 * @return {Boolean|String}
5095 */
5096 validateToken: function (token, sapiEndpoint) {
5097 var LOGGER = this.LOGGER;
5098
5099 LOGGER.info('Preparing for validating token "{0}"...', token.toString());
5100
5101 var configData = this.saraConfig.getClientConfig();
5102 var request = this.restClient.newSAPIRequest('get', sapiEndpoint);
5103 request.addHeader('Authorization', 'bearer ' + token);
5104
5105 var response = this.restClient.executeWithRefreshToken(request);
5106 var responseObject = response.getResponseObject();
5107
5108 if (response.haveError()) {
5109 if (responseObject.statusCode !== 401) {
5110 var message = SaraUtils.formatString('Error when validating token! Error code: {0} - Error message: {1}', responseObject.statusCode, responseObject.errorMessage);
5111 LOGGER.error(message);
5112
5113 return message;
5114 } else {
5115 var username = this.saraConfig.getTechnicalUser();
5116 this.removeUserToken(username);
5117
5118 return false;
5119 }
5120 } else {
5121 return true;
5122 }
5123 },
5124
5125 type: 'SaraOAuthClient'
5126};
5127]]></script>
5128 <description>This class contains all OAuth-relaled functions</description>
5129 <active>true</active>
5130 <client_callable>false</client_callable>
5131 <access>public</access>
5132 </script_include>
5133
5134 <script_include>
5135 <name>SaraRESTClient</name>
5136 <script><![CDATA[/**
5137 * Wraps Service Now RESTMessage in a class to provide convenient methods interacting with SARA REST
5138 */
5139var SaraRESTClient = Class.create();
5140SaraRESTClient.prototype = {
5141 initialize: function () {
5142 this.LOGGER = new SaraLog(this);
5143 },
5144
5145 /**
5146 * Init new service request from SaraRESTMessage class
5147 * @param {String} name The name of the REST message record
5148 * @param {String} method The name of the HTTP method to use, such as GET or PUT
5149 * @param {String} endpoint The endpoint for the REST message
5150 * @param {Array<String>} basicAuthCreds The basic authentication headers for the REST message
5151 * @param {Array<Object>} headers The object contains headers for the REST message
5152 * @param {Array<Object>} stringParameters The object contains string parameters for the REST message
5153 * @param {Array<Object>} stringParametersNoEscape The object contains string parameters which will be not escaped for the REST message
5154 * @return {SaraRESTMessage}
5155 */
5156 newServiceRequest: function (name, method, endpoint, basicAuthCreds, headers, stringParameters, stringParametersNoEscape) {
5157 var restMsg = new SaraRESTMessage(name, method);
5158
5159 if (endpoint) {
5160 restMsg.setEndpoint(endpoint);
5161 }
5162
5163 if (this.midServer) {
5164 restMsg.setMIDServer(this.midServer);
5165 }
5166
5167 if (basicAuthCreds && basicAuthCreds.length > 1) {
5168 restMsg.setBasicAuth(basicAuthCreds[0], basicAuthCreds[1]);
5169 }
5170
5171 if (headers) {
5172 for (var i = 0, header; header = headers[i]; i++) {
5173 if (header['name']) {
5174 restMsg.addHeader(header['name'], header['value']);
5175 }
5176 }
5177 }
5178
5179 if (stringParameters) {
5180 for (var i = 0, stringParameter; stringParameter = stringParameters[i]; i++) {
5181 if (stringParameter['name']) {
5182 restMsg.setStringParameter(stringParameter['name'], stringParameter['value']);
5183 }
5184 }
5185 }
5186
5187 if (stringParametersNoEscape) {
5188 for (var i = 0, stringParameter; stringParameter = stringParametersNoEscape[i]; i++) {
5189 if (stringParameter['name']) {
5190 restMsg.setStringParameterNoEscape(stringParameter['name'], stringParameter['value']);
5191 }
5192 }
5193 }
5194
5195 return restMsg;
5196 },
5197
5198 /**
5199 * Init new SAPI service request from SaraRESTMessage class
5200 * @param {String} method The name of the HTTP method to use, such as GET or PUT
5201 * @param {String} endpoint The endpoint for the REST message
5202 * @param {Array<String>} basicAuthCreds The basic authentication headers for the REST message
5203 * @param {Array<Object>} headers The object contains headers for the REST message
5204 * @param {Array<Object>} stringParameters The object contains string parameters for the REST message
5205 * @param {Array<Object>} stringParametersNoEscape The object contains string parameters which will be not escaped for the REST message
5206 * @return {SaraRESTMessage}
5207 */
5208 newSAPIRequest: function (method, endpoint, basicAuthCreds, headers, stringParameters, stringParametersNoEscape) {
5209 return this.newServiceRequest(SaraCommon.REST_NAME.SAPI, method, endpoint, basicAuthCreds, headers)
5210 },
5211
5212 /**
5213 * Init new OAuth service request from SaraRESTMessage class
5214 * @param {String} method The name of the HTTP method to use, such as GET or PUT
5215 * @param {String} endpoint The endpoint for the REST message
5216 * @param {Array<String>} basicAuthCreds The basic authentication headers for the REST message
5217 * @param {Array<Object>} headers The object contains headers for the REST message
5218 * @param {Array<Object>} stringParameters The object contains string parameters for the REST message
5219 * @param {Array<Object>} stringParametersNoEscape The object contains string parameters which will be not escaped for the REST message
5220 * @return {SaraRESTMessage}
5221 */
5222 newOAuthRequest: function (method, endpoint, basicAuthCreds, headers, stringParameters, stringParametersNoEscape) {
5223 return this.newServiceRequest(SaraCommon.REST_NAME.OAUTH, method, endpoint, basicAuthCreds, headers)
5224 },
5225
5226 /**
5227 * Execute REST Message request
5228 * @param {SaraRESTMessage} saraRest Sara REST Message object
5229 * @return {SaraRESTResponse}
5230 */
5231 execute: function (saraRest) {
5232 var LOGGER = this.LOGGER;
5233
5234 LOGGER.info('Making {0} request to {1}...', saraRest.getMethod(), saraRest.getEndpoint());
5235 LOGGER.debug(saraRest.dump());
5236
5237 var response;
5238 if (this.midServer) {
5239 response = saraRest.executeViaMIDServer(this.midServer);
5240 } else {
5241 response = saraRest.execute();
5242 }
5243
5244 return response;
5245 },
5246
5247 /**
5248 * Execute REST Message request with automatically get new token if token is expired
5249 * @param {SaraRESTMessage} saraRest Sara REST Message object
5250 * @return {SaraRESTResponse}
5251 */
5252 executeWithRefreshToken: function (saraRest) {
5253 var LOGGER = this.LOGGER;
5254
5255 // First time request
5256 var response = this.execute(saraRest);
5257 var responseObject = response.getResponseObject();
5258
5259 if (response.haveError()) {
5260 if (responseObject.statusCode === 401) {
5261 LOGGER.info('Access token of user is invalid or expired');
5262
5263 var oauthClient = new SaraOAuthClient(this);
5264 var username = new SaraConfig().getTechnicalUser();
5265
5266 LOGGER.info('Trying to refresh token for user "{0}"...', username);
5267 var tokens = oauthClient.refreshToken(username);
5268
5269 if (tokens && !tokens.error) {
5270 LOGGER.info('Refresh token finished successfully.');
5271 oauthClient.storeUserTokens(username, tokens['access_token'], tokens['refresh_token'], tokens['expires_in'], tokens['token_type']);
5272
5273 // Request again with new token
5274 saraRest.addHeader('Authorization', 'bearer ' + tokens['access_token']);
5275 response = this.execute(saraRest);
5276 } else {
5277 LOGGER.error('Error when refreshing token');
5278
5279 if (!tokens) {
5280 LOGGER.info('Error: {0} - Error description: {1}', tokens.error, tokens.errorDescription);
5281 oauthClient.removeUserToken(username);
5282 }
5283 }
5284 }
5285 }
5286
5287 return response;
5288 },
5289
5290 /**
5291 * Set MID Server
5292 * @param {String} midServer The MID Server name
5293 */
5294 setMIDServer: function (midServer) {
5295 this.midServer = midServer;
5296 },
5297
5298 type: 'SaraRESTClient'
5299};
5300]]></script>
5301 <description>Wraps Service Now RESTMessage in a class to provide convenient methods interacting with SARA REST</description>
5302 <active>true</active>
5303 <client_callable>false</client_callable>
5304 <access>public</access>
5305 </script_include>
5306
5307 <script_include>
5308 <name>SaraRESTMessage</name>
5309 <script><![CDATA[/**
5310 * Wrap original ServiceNow's RESTMessageV2 class to make HTTP request
5311 */
5312var SaraRESTMessage = Class.create();
5313SaraRESTMessage.prototype = {
5314 /**
5315 * Init Sara REST Message object
5316 * @param {String} name Name of REST message record
5317 * @param {String} method The name of the HTTP method to use, such as GET or PUT
5318 */
5319 initialize: function (name, method) {
5320 method = method.toLowerCase();
5321 this.restMsg = new sn_ws.RESTMessageV2(name, method);
5322 this.name = name;
5323 this.method = method;
5324
5325 this.LOGGER = new SaraLog(this);
5326 },
5327
5328 /**
5329 * Set the content of the REST message body
5330 * @param {String} content The content of REST Message
5331 */
5332 setContent: function (content) {
5333 this.restMsg.setRequestBody(content);
5334 },
5335
5336 /**
5337 * Set form content for REST Message
5338 * @param {Object} formData The object contains form data
5339 */
5340 setFormContent: function (formData) {
5341 if (!formData) {
5342 return;
5343 }
5344
5345 var content = '';
5346
5347 for (var propName in formData) {
5348 var value = formData[propName];
5349
5350 if (value instanceof Array) {
5351 for (var i = 0; i < value.length; i++) {
5352 var _value = value[i];
5353
5354 content += (encodeURIComponent(propName) + '=' + encodeURIComponent(_value) + '&');
5355 }
5356 } else {
5357 content += (encodeURIComponent(propName) + '=' + encodeURIComponent(value) + '&');
5358 }
5359 }
5360
5361 if (content.length > 0) {
5362 content = content.substring(0, content.length - 1);
5363 this.setContent(content);
5364 }
5365 },
5366
5367 /**
5368 * Get the content of the REST message body
5369 * @return {String}
5370 */
5371 getContent: function () {
5372 return this.restMsg.getRequestBody();
5373 },
5374
5375 /**
5376 * Add headers for REST Message
5377 * @param {String} key The key of header
5378 * @param {*} value The value of header
5379 */
5380 addHeader: function (key, value) {
5381 var LOGGER = this.LOGGER;
5382
5383 LOGGER.debug('addHeader: key = "{0}" and value = "{1}"', key, value);
5384
5385 this.restMsg.setRequestHeader(key, value);
5386 },
5387
5388 /**
5389 * Add type for header named 'content-type'
5390 * @param {String} type The content type of REST Message
5391 */
5392 setContentType: function (type) {
5393 var LOGGER = this.LOGGER;
5394
5395 LOGGER.debug('setContentType: type = "{0}"', type);
5396
5397 this.addHeader('content-type', type);
5398 },
5399
5400 /**
5401 * Set basic authentication headers for the REST message
5402 * @param {String} usename
5403 * @param {String} password
5404 */
5405 setBasicAuth: function (username, password) {
5406 var LOGGER = this.LOGGER;
5407
5408 LOGGER.debug('setBasicAuth: username = "{0}" and password = "{1}"', username, password);
5409
5410 this.restMsg.setBasicAuth(username, password);
5411 },
5412
5413 /**
5414 * Set a REST message function variable to the specified value
5415 * @param {String} name The name of parameter
5416 * @param {String} value The value of parameter
5417 */
5418 setStringParameter: function (name, value) {
5419 var LOGGER = this.LOGGER;
5420
5421 LOGGER.debug('setStringParameter: name = "{0}" and value = "{1}"', name, value);
5422
5423 this.restMsg.setStringParameter(name, value);
5424 },
5425
5426 /**
5427 * Set a REST message function variable to the specified value without escaping XML reserved characters
5428 * @param {String} name The name of parameter
5429 * @param {String} value The value of parameter
5430 */
5431 setStringParameterNoEscape: function (name, value) {
5432 var LOGGER = this.LOGGER;
5433
5434 LOGGER.debug('setStringParameterNoEscape: name = "{0}" and value = "{1}"', name, value);
5435
5436 this.restMsg.setStringParameterNoEscape(name, value);
5437 },
5438
5439 /**
5440 * Set the endpoint for the REST message
5441 * @param {String} endpoint
5442 */
5443 setEndpoint: function (endpoint) {
5444 var LOGGER = this.LOGGER;
5445
5446 LOGGER.debug('setEndpoint: endpoint = "{0}"', endpoint);
5447
5448 this.restMsg.setEndpoint(endpoint);
5449 },
5450
5451 /**
5452 * Get the URL of the endpoint for the REST message.
5453 * @return {String}
5454 */
5455 getEndpoint: function () {
5456 return this.restMsg.getEndpoint();
5457 },
5458
5459 /**
5460 * Configure the REST message to communicate through a MID Server.
5461 * @param {String} midServer The name of MID Server
5462 */
5463 setMIDServer: function (midServer) {
5464 var LOGGER = this.LOGGER;
5465
5466 LOGGER.debug('setMIDServer: midServer = "{0}"', midServer);
5467
5468 this.restMsg.setMIDServer(midServer);
5469 },
5470
5471 /**
5472 * Send REST Message to endpoint
5473 * @return {}
5474 */
5475 execute: function () {
5476 return new SaraRESTResponse(this.restMsg.execute());
5477 },
5478
5479 /**
5480 * Execute REST request via MID Server
5481 * @param {String} midServer The name of MID Server
5482 */
5483 executeViaMIDServer: function (midServer) {
5484 var LOGGER = this.LOGGER;
5485
5486 if (midServer) {
5487 this.restMsg.setMIDServer(midServer);
5488 this.midServer = midServer;
5489 LOGGER.info('Using MID Server {0}', this.midServer);
5490 }
5491
5492 if (!this.midServer) {
5493 LOGGER.info('No MID Server defined for the request. Request is aborted!');
5494 return null;
5495 }
5496
5497 return new SaraRESTResponse(this.restMsg.execute(), true);
5498 },
5499
5500 /**
5501 * Get method name of this REST Message
5502 * @return {String}
5503 */
5504 getMethod: function () {
5505 return this.method.toUpperCase();
5506 },
5507
5508 /**
5509 * Dump information of REST Message
5510 */
5511 dump: function () {
5512 var LOGGER = this.LOGGER;
5513
5514 try {
5515 var str = this.getMethod() + ' ' + this.getEndpoint() + ' HTTP/1.1';
5516
5517 var headers = this.restMsg.getRequestHeaders();
5518 if (headers) {
5519 for (key in headers) {
5520 var value = headers[key];
5521
5522 if (!gs.nil(value)) {
5523 if (key === 'Authorization') {
5524 value = '**********************';
5525 }
5526
5527 str += SaraUtils.formatString('\n {0}: {1}', key, value);
5528 }
5529 }
5530 }
5531
5532 var content = this.getContent();
5533
5534 if (!gs.nil(content) && content !== 'undefined' && content) {
5535 str += SaraUtils.formatString('\n\n', content);
5536 }
5537
5538 return str;
5539 } catch (error) {
5540 LOGGER.info('Error in SaraRESTMessage.dump(): ' + error);
5541 }
5542 },
5543
5544 type: 'SaraRESTMessage'
5545};
5546]]></script>
5547 <description>Class extend from original ServiceNow's RESTMessage class to make HTTP request</description>
5548 <active>true</active>
5549 <client_callable>false</client_callable>
5550 <access>package_private</access>
5551 </script_include>
5552
5553 <script_include>
5554 <name>SaraRESTResponse</name>
5555 <script><![CDATA[/**
5556 * Wrap original ServiceNow's RESTResponseV2 class to handle response of RESTMessageV2
5557 */
5558var SaraRESTResponse = Class.create();
5559SaraRESTResponse.prototype = {
5560 /**
5561 * Init Sara REST Response object
5562 * @param {sn_ws.RESTResponseV2} response The response object of RESTResponseV2
5563 * @param {Boolean} useMIDServer Get response via MID Server or not
5564 */
5565 initialize: function (response, useMIDServer) {
5566 this.response = response;
5567
5568 var LOGGER = this.LOGGER = new SaraLog(this);
5569
5570 if (useMIDServer) {
5571 var timeout = SaraUtils.getSaraProperty(SaraCommon.SYSTEM_PROPERTY_NAME.REST_REQUEST_TIMEOUT);
5572 LOGGER.debug('Timeout for REST Message: {0}s', timeout);
5573 response.waitForResponse(timeout);
5574 }
5575
5576 if (response.haveError()) {
5577 LOGGER.info('Error when requesting REST Message: {0} - {1}', response.getErrorCode(), response.getErrorMessage());
5578 } else {
5579 LOGGER.info('Status code: {0}', response.getStatusCode());
5580 }
5581
5582 LOGGER.debug('Response body: {0}', response.getBody());
5583 },
5584
5585 /**
5586 * Set the amount of time the instance waits for the response
5587 * @param {Number} timeoutSecs The amount of time, in seconds, to wait for this response.
5588 */
5589 waitForResponse: function (timeoutSecs) {
5590 this.response.waitForResponse(timeoutSecs);
5591 },
5592
5593 /**
5594 * Get the numeric HTTP status code returned by the REST provider
5595 * @return {Number}
5596 */
5597 getStatusCode: function () {
5598 return this.response.getStatusCode();
5599 },
5600
5601 /**
5602 * Get the value for a specified header
5603 * @param {Number} timeoutSecs The name of the header that you want the value for, such as Set-Cookie.
5604 * @return {String}
5605 */
5606 getHeader: function (name) {
5607 return this.response.getHeader(name);
5608 },
5609
5610 /**
5611 * Get all headers returned in the REST response and the associated values
5612 * @return {Object}
5613 */
5614 getHeaders: function () {
5615 return this.response.getHeaders();
5616 },
5617
5618 /**
5619 * Get the content of the REST response body
5620 * @return {String}
5621 */
5622 getBody: function () {
5623 return this.response.getBody();
5624 },
5625
5626 /**
5627 * Indicate if there was an error during the REST transaction
5628 * @return {Boolean}
5629 */
5630 haveError: function () {
5631 return this.response.haveError();
5632 },
5633
5634 /**
5635 * Get the numeric error code if there was an error during the REST transaction. This error code is
5636 * specific to the ServiceNow platform, it is not an HTTP error code. Provide this error code if you
5637 * require assistance from ServiceNow Customer Support
5638 * @return {Number}
5639 */
5640 getErrorCode: function () {
5641 return this.response.getErrorCode();
5642 },
5643
5644 /**
5645 * Get the error message if there was an error during the REST transaction
5646 * @return {String}
5647 */
5648 getErrorMessage: function () {
5649 return this.response.getErrorMessage();
5650 },
5651
5652 /**
5653 * Get the fully-resolved query sent to the REST endpoint. This query contains the endpoint URL as well
5654 * as any values assigned to variables in the REST message
5655 */
5656 getQueryString: function () {
5657 return this, response.getQueryString();
5658 },
5659
5660 /**
5661 * Get response body with format is Object
5662 * @return {Object|Null}
5663 */
5664 getBodyObject: function () {
5665 var LOGGER = this.LOGGER;
5666
5667 var body = this.getBody();
5668 if (body) {
5669 try {
5670 body = SaraJSON.parse(body);
5671 } catch (ex) {
5672 LOGGER.error('Error when parsing response body to Object: {0}', ex);
5673 }
5674 }
5675
5676 return body;
5677 },
5678
5679 /**
5680 * Get response with format is Object. This response contains body object, status code, error message and
5681 * error description
5682 * @return {Object}
5683 */
5684 getResponseObject: function () {
5685 var bodyObject = this.getBodyObject();
5686 var statusCode = this.getStatusCode();
5687 var errorMessage = this.getErrorMessage();
5688 var errorDescription = this.getErrorMessage();
5689
5690 if (bodyObject) {
5691 if (bodyObject['error']) {
5692 errorMessage = bodyObject['error'];
5693 }
5694
5695 if (bodyObject['error_description']) {
5696 errorDescription = bodyObject['error_description'];
5697 }
5698 }
5699
5700 return {
5701 bodyObject: bodyObject,
5702 statusCode: statusCode,
5703 errorMessage: errorMessage,
5704 errorDescription: errorDescription
5705 }
5706 },
5707
5708 type: 'SaraRESTResponse'
5709};
5710]]></script>
5711 <description>Wrap original ServiceNow's RESTResponseV2 class to handle RESTMessageV2 response</description>
5712 <active>true</active>
5713 <client_callable>false</client_callable>
5714 <access>package_private</access>
5715 </script_include>
5716
5717 <script_include>
5718 <name>SaraSync</name>
5719 <script><![CDATA[/**
5720 * Sara Sync Utilities
5721 */
5722var SaraSync = Class.create();
5723SaraSync.prototype = {
5724 initialize: function () {
5725 this.glideHelper = new SaraGlideHelper();
5726 this.LOGGER = new SaraLog(this);
5727 this.dal = new SaraConsumerDAL();
5728 },
5729
5730 /**
5731 * Sync services and catalogs of all category which was imported services
5732 */
5733 syncServices: function () {
5734 var glideHelper = this.glideHelper;
5735 var LOGGER = this.LOGGER;
5736
5737 var importedCategories = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {
5738 'u_type': 'category'
5739 }, true);
5740
5741 if (importedCategories.length > 0) {
5742 LOGGER.info('There are {0} target category(s) which were imported services\n', importedCategories.length);
5743
5744 var consumer = new SaraConsumerImportSet();
5745 var response = consumer.discover();
5746
5747 if (response.error) {
5748 LOGGER.error('Discover data from SAPI not successfully. Syncing services is aborted!');
5749 return;
5750 } else {
5751 for (var i = 0; i < importedCategories.length; i++) {
5752 var importedCategory = importedCategories[i];
5753 LOGGER.info('Syncing target category (name = {0}, sys_id = {1})', importedCategory.u_name, importedCategory.u_parent);
5754
5755 consumer.doImport(importedCategory.u_parent);
5756 consumer.refreshImportedData();
5757
5758 LOGGER.info('Target category (name = {0}, sys_id = {1}) is synced!', importedCategory.u_name, importedCategory.u_parent);
5759 }
5760 }
5761 } else {
5762 LOGGER.warn('No target category found. Skip syncServices!');
5763 }
5764 },
5765
5766 /**
5767 * Sync all lookup values of catalog item
5768 * @param {String} saraItem The catalog item in SaraCommon.TABLE_NAME.SARA_DEFINITION
5769 * @param {SaraModel.CatalogItem} catalogItem
5770 */
5771 //saraCatalogItem, catalogItem
5772 syncLookup: function (existDefinition, sapiService) {
5773 var glideHelper = this.glideHelper;
5774 var LOGGER = this.LOGGER;
5775
5776 LOGGER.info('Starting syncLookup... definition: {0}; sapiService: {1}',
5777 SaraJSON.stringify(existDefinition), SaraJSON.stringify(sapiService));
5778
5779 if (sapiService.getVariables()) {
5780 // Get variable set of catalog item
5781 var varSetId = existDefinition.u_var_set;
5782 LOGGER.info('Found sys_id of variable set of {0} is: {1}', existDefinition.u_name, varSetId);
5783
5784 // Get lookup variables of variable set
5785 var saraLookupVariables = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_VARIABLE, {
5786 'variable_set': varSetId,
5787 'u_is_lookup': true
5788 }, true);
5789
5790 if (saraLookupVariables.length > 0) {
5791 LOGGER.info('Found {0} lookup variable(s) in variable set (sys_id = {1})', saraLookupVariables.length, varSetId);
5792
5793 for (var i = 0; i < saraLookupVariables.length; i++) {
5794 var saraVariable = saraLookupVariables[i];
5795 LOGGER.info("Processing variable: " + saraVariable.name);
5796 var variable = this.getVariable(sapiService, saraVariable.name);
5797 if(variable !== null) {
5798 this.updateLookupVariable(saraVariable, variable);
5799 }
5800 }
5801 } else {
5802 LOGGER.warn('No lookup variable found in variable set (sys_id = {0}). Skip syncLookup!', varSetId);
5803 }
5804 } else {
5805 LOGGER.warn('There\' no variable found in catalog (item name = {0}). Skip syncLookup!', existDefinition.u_name);
5806 }
5807
5808 LOGGER.info('Ended syncLookup!');
5809 },
5810
5811 /**
5812 * Get variable from instance of SaraModel.CatalogItem
5813 * @param {SaraModel.CatalogItem} catalogItem
5814 * @param {String} saraVariableName
5815 * @return {SaraModel.CatalogVariable||Null}
5816 */
5817 getVariable: function (sapiService, saraVariableName) {
5818 for (var i = 0; i < sapiService.variables.length; i++) {
5819 if (sapiService.variables[i].name === saraVariableName) {
5820 return sapiService.variables[i];
5821 }
5822 }
5823
5824 return null;
5825 },
5826
5827 /**
5828 * Update lookup variable
5829 * @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'
5830 * @param {SaraModel.CatalogVariable} variable
5831 */
5832 updateLookupVariable: function (saraVariable, variable) {
5833 var glideHelper = this.glideHelper;
5834 var LOGGER = this.LOGGER;
5835
5836 LOGGER.info('New and old hash of variable "{0}": {1} - {2}', saraVariable.name, variable.getHash(), saraVariable.u_hash);
5837
5838 if (variable.getHash() === saraVariable.u_hash) {
5839 LOGGER.info('Lookup value of variable "{0}" is not changed!', saraVariable.name);
5840 } else {
5841 LOGGER.info('Lookup value of variable "{0}" is changed!', saraVariable.name);
5842
5843 this.deactivateOldLookupValues(saraVariable);
5844
5845 var newDefaultValues = [];
5846 var ranges = variable.getRange();
5847
5848 // Insert new range values
5849 for (var i = 0; i < ranges.length; i++) {
5850 var range = ranges[i];
5851 var rangeId = this.dal.saveOrUpdateSaraLookup({
5852 'u_key': range.Value,
5853 'u_display_name': range.Key,
5854 'u_control_id': saraVariable.sys_id
5855 }).sys_id;
5856
5857 if (SaraUtils.inArray(variable.getDefaultValue(), range.Key)) {
5858 if(variable.getType() === SaraCommon.VAR_TYPE.LIST_COLLECTOR) {
5859 newDefaultValues.push(rangeId);
5860 }
5861 else {
5862 newDefaultValues.push(range.Key);
5863 }
5864 }
5865 }
5866 LOGGER.info('Inserted new data of {0} in {1}!', saraVariable.name, SaraCommon.TABLE_NAME.SARA_LOOKUP);
5867
5868 if (saraVariable.default_value) {
5869 newDefaultValues = newDefaultValues.join(',');
5870
5871 saraVariable.default_value = newDefaultValues;
5872 saraVariable.u_hash = variable.getHash();
5873 this.dal.saveOrUpdateVariable(saraVariable);
5874
5875 LOGGER.info('Updated default value for variable (name = {0}, sys_id = {1}) with new default_value = {2}',
5876 saraVariable.name, saraVariable.sys_id, newDefaultValues);
5877 }
5878 }
5879 },
5880
5881 deactivateOldLookupValues: function(saraVariable) {
5882 var glideHelper = this.glideHelper;
5883 var LOGGER = this.LOGGER;
5884 // Remove the old data of lookup table
5885 var lookups = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_LOOKUP, {
5886 'u_control_id': saraVariable.sys_id
5887 }, true);
5888
5889 for(var i = 0; i < lookups.length; i++) {
5890 var lookup = lookups[i];
5891 lookup.u_control_id = "";
5892 this.dal.saveOrUpdateSaraLookup(lookup);
5893 }
5894
5895 LOGGER.info('Deactivated old data of {0} in {1}!', saraVariable.name, SaraCommon.TABLE_NAME.SARA_LOOKUP);
5896 },
5897
5898 type: 'SaraSync'
5899};
5900]]></script>
5901 <description>Sara Sync Utilities</description>
5902 <active>true</active>
5903 <client_callable>false</client_callable>
5904 <access>public</access>
5905 </script_include>
5906
5907 <script_include>
5908 <name>SaraUtils</name>
5909 <script><![CDATA[/**
5910 * Sara Utilities
5911 */
5912var SaraUtils = Class.create();
5913SaraUtils.prototype = {
5914 initialize: function () {},
5915
5916 type: 'SaraUtils'
5917};
5918
5919/**
5920 * Format strings
5921 * @param {String} string The template string
5922 * @param {String[]} args Zero or more objects to format, supplied either in a comma-delimited list or as an array
5923 */
5924SaraUtils.formatString = function (string) {
5925 if(!string) {
5926 return "";
5927 }
5928 var args = Array.prototype.slice.call(arguments, 1);
5929
5930 return string.replace(/\{(\d+)\}/g, function (match, number) {
5931 return typeof args[number] != 'undefined' ? args[number] : match;
5932 });
5933};
5934
5935/**
5936 * Get Sara property
5937 * @param {String} name Name of sara property
5938 * @return {String}
5939 */
5940SaraUtils.getSaraProperty = function (name) {
5941 var property = gs.getProperty(SaraCommon.PROP_PREFIX + '.' + name);
5942 if(property == null) {
5943 property = gs.getProperty(name);
5944 }
5945
5946 return property;
5947};
5948
5949/**
5950 * Get mid servcer
5951 * @return {String}
5952 */
5953SaraUtils.getMIDServer = function () {
5954 return SaraUtils.getSaraProperty(SaraCommon.SYSTEM_PROPERTY_NAME.MID_SERVER);
5955};
5956
5957/**
5958 * Get timestamp of current
5959 * @return {String}
5960 */
5961SaraUtils.getTimeStamp = function () {
5962 return new Date().valueOf();
5963};
5964
5965/**
5966 * Get random number
5967 * @return {String}
5968 */
5969SaraUtils.getRandom = function () {
5970 return Math.round(Math.random() * 987654321);
5971};
5972
5973/**
5974 * Diff time and return 'h, m, s'
5975 * @param {Number} time1 The first timestamp
5976 * @param {Number} time2 The second timestamp
5977 * @return {String}
5978 */
5979SaraUtils.diffTime = function (time1, time2) {
5980 var difference = time2 - time1;
5981
5982 var daysDifference = Math.floor(difference / 1000 / 60 / 60 / 24);
5983 difference -= daysDifference * 1000 * 60 * 60 * 24;
5984
5985 var hoursDifference = Math.floor(difference / 1000 / 60 / 60);
5986 difference -= hoursDifference * 1000 * 60 * 60;
5987
5988 var minutesDifference = Math.floor(difference / 1000 / 60);
5989 difference -= minutesDifference * 1000 * 60;
5990
5991 var secondsDifference = Math.floor(difference / 1000);
5992 difference -= secondsDifference * 1000;
5993
5994 var result = '';
5995
5996 if (daysDifference > 0) {
5997 result += daysDifference + 'd ';
5998 }
5999
6000 if (hoursDifference > 0) {
6001 result += hoursDifference + 'h ';
6002 }
6003
6004 if (minutesDifference > 0) {
6005 result += minutesDifference + 'm ';
6006 }
6007
6008 if (secondsDifference > 0) {
6009 result += secondsDifference + 's ';
6010 }
6011
6012 result += difference + 'ms';
6013
6014 return result;
6015};
6016
6017/**
6018 * Convert '\n' to '<br />' in string
6019 * @param {String} string
6020 * @return {String}
6021 */
6022SaraUtils.nl2br = function (string) {
6023 string = string || '';
6024
6025 return string.replace(/\n/g, '<br />');
6026};
6027
6028/**
6029 * Clean all data of SNSC
6030 */
6031SaraUtils.cleanup = function (filter) {
6032 if (!gs.hasRole(SaraCommon.ROLES.ADMIN)) {
6033 var message = 'You dont\'t have sufficient permission to do this action. Allowed role: ' + SaraCommon.ROLES.ADMIN;
6034 throw new Error(message);
6035 }
6036
6037 var glideHelper = new SaraGlideHelper();
6038 var LOGGER = new SaraLog('SaraUtils');
6039 var catItemIds = [];
6040 var varSetIds = [];
6041 var catCateIds = [];
6042 var targetCateIds = [];
6043
6044 filter = filter || {};
6045
6046 // Get list of catalog item from SaraCommon.TABLE_NAME.SARA_DEFINITION table
6047 var saraItems = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, filter, true);
6048
6049 if (saraItems.length > 0) {
6050 LOGGER.info('Found {0} item(s) in "{1}"', saraItems.length, SaraCommon.TABLE_NAME.SARA_DEFINITION);
6051
6052 for (var i = 0, saraItem; saraItem = saraItems[i]; i++) {
6053 if (saraItem['u_sc_item']) {
6054 catItemIds.push(saraItem['u_sc_item']);
6055 }
6056
6057 if (saraItem['u_var_set']) {
6058 varSetIds.push(saraItem['u_var_set']);
6059 }
6060
6061 if (saraItem['u_service_catalog_category']) {
6062 catCateIds.push(saraItem['u_service_catalog_category']);
6063 }
6064
6065 if (saraItem['u_type'] === 'category') {
6066 targetCateIds.push(saraItem['u_parent']);
6067 }
6068 }
6069
6070 var message = 'There are :';
6071 message += SaraUtils.formatString('\n - {0} catalog item(s)', catItemIds.length);
6072 message += SaraUtils.formatString('\n - {0} variable set(s)', varSetIds.length);
6073 message += SaraUtils.formatString('\n - {0} category(s)', catCateIds.length);
6074 message += SaraUtils.formatString('\n - {0} target category(s)', targetCateIds.length);
6075 LOGGER.info(message);
6076
6077 if (varSetIds.length > 0) {
6078 LOGGER.info('Removing {0} variable set(s)...', varSetIds.length);
6079
6080 for (var i = 0, varSetId; varSetId = varSetIds[i]; i++) {
6081 // Remove all variables belong to above variable sets
6082 LOGGER.info('Removing variables from variable set {0}...', varSetId);
6083 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_VARIABLE, {
6084 'variable_set': varSetId
6085 }, true);
6086
6087 // Remove all variable sets
6088 LOGGER.info('Removing variable set (sys_id = {0})...', varSetId);
6089 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_VARIABLE_SET, {
6090 'sys_id': varSetId
6091 }, true);
6092 }
6093 }
6094
6095 // Cleanup service catalog items
6096 if (catItemIds.length > 0) {
6097 LOGGER.info('Removing {0} catalog item(s)...', catItemIds.length);
6098
6099 for (var i = 0, catItemId; catItemId = catItemIds[i]; i++) {
6100 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_CAT_ITEM, {
6101 'sys_id': catItemId
6102 });
6103 }
6104 }
6105
6106 // Cleanup catalog categories
6107 if (catCateIds.length > 0) {
6108 LOGGER.info('Removing {0} catalog category(s)...', catCateIds.length);
6109
6110 for (var i = 0, catCateId; catCateId = catCateIds[i]; i++) {
6111 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_CATEGORY, {
6112 'sys_id': catCateId
6113 });
6114 }
6115 }
6116
6117 // Refresh target categories
6118 if (targetCateIds.length > 0) {
6119 LOGGER.info('Refreshing {0} target category(s)...', catCateIds.length);
6120
6121 for (var i = 0, targetCateId; targetCateId = targetCateIds[i]; i++) {
6122 glideHelper.updateData(SaraCommon.TABLE_NAME.SN_CATEGORY, {
6123 'sys_id': targetCateId
6124 }, {
6125 'active': false
6126 });
6127
6128 glideHelper.updateData(SaraCommon.TABLE_NAME.SN_CATEGORY, {
6129 'sys_id': targetCateId
6130 }, {
6131 'active': true
6132 });
6133
6134 LOGGER.info('Target category (sys_id = {0}) is refreshed.', targetCateId);
6135 }
6136 }
6137
6138 LOGGER.info('Cleaning up {0} table ...', SaraCommon.TABLE_NAME.SARA_DEFINITION);
6139 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {}, true);
6140
6141 LOGGER.info('Cleaning up {0} table ...', SaraCommon.TABLE_NAME.SARA_VARIABLE);
6142 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_VARIABLE, {}, true);
6143 } else {
6144 LOGGER.warn('There is no items in "{0}". Skip cleanup!', SaraCommon.TABLE_NAME.SARA_DEFINITION);
6145 }
6146};
6147
6148/**
6149 * Create catalog variable from field information
6150 * @param {Object} field
6151 * @return {SaraModel.CatalogVariable}
6152 */
6153SaraUtils.createCatalogVariable = function (field) {
6154 var defaultValue = '';
6155 var varType;
6156 var isLookupControl = false;
6157 var LOGGER = new SaraLog('SaraUtils');
6158
6159 if (field['default'] && field['default'].length > 0) {
6160 defaultValue = field['default'];
6161 }
6162
6163 switch (field.type) {
6164 case 'Label':
6165 varType = SaraCommon.VAR_TYPE.LABEL;
6166 break;
6167 case 'Number':
6168 // SN only have NUM_SCALE variable type but not suitable, just use string
6169 varType = SaraCommon.VAR_TYPE.SINGLE_LINE_TEXT;
6170 break;
6171 case 'String':
6172 varType = SaraCommon.VAR_TYPE.SINGLE_LINE_TEXT;
6173 break;
6174 case 'List':
6175 varType = field.multiSelect ? SaraCommon.VAR_TYPE.LIST_COLLECTOR : SaraCommon.VAR_TYPE.LOOKUP_SELECT_BOX;
6176 isLookupControl = true;
6177 break;
6178 case 'Time':
6179 varType = SaraCommon.VAR_TYPE.SINGLE_LINE_TEXT;
6180 break;
6181 case 'Date':
6182 varType = SaraCommon.VAR_TYPE.DATE;
6183 break;
6184 case 'Timestamp':
6185 varType = SaraCommon.VAR_TYPE.DATE_TIME;
6186 break;
6187 default:
6188 break;
6189 }
6190
6191 var catalogVariable = new SaraModel.CatalogVariable();
6192 catalogVariable.setName(this.legitVarName(field.name));
6193 catalogVariable.setType(varType);
6194 catalogVariable.setLabel(field.caption);
6195 catalogVariable.setDefaultValue(defaultValue);
6196 catalogVariable.setDescription(field.description);
6197 catalogVariable.setRange([]);
6198 catalogVariable.setAsLookup(isLookupControl);
6199
6200 if(field.order != null && field.order != undefined) {
6201 catalogVariable.setOrder(field.order);
6202 }
6203
6204 if (field.maskAsPassword) {
6205 catalogVariable.setAsPassword(field.maskAsPassword);
6206 }
6207
6208 if (field.range && field.range[0].values) {
6209 var rangeValue = field.range[0].values;
6210 catalogVariable.setRange(rangeValue);
6211
6212 // Generate range hash for variable
6213 var hash = SaraUtils.md5(SaraJSON.stringify(rangeValue));
6214 catalogVariable.setHash(hash);
6215 }
6216
6217 if (field.name) {
6218 catalogVariable.setActualName(field.name);
6219 }
6220
6221 if (field.required) {
6222 catalogVariable.setRequired(field.required);
6223 }
6224
6225 if (field.multiSelect) {
6226 catalogVariable.setMultiSelect(field.multiSelect);
6227 }
6228
6229 return catalogVariable;
6230};
6231
6232/**
6233 * Legitimates variable name that is not qualified business rule validate_variable_name
6234 * @param {String} varName
6235 * @return {String}
6236 */
6237SaraUtils.legitVarName = function (varName) {
6238 var firstLegal = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
6239 var firstLetter = varName.charAt(0);
6240 if (firstLegal.indexOf(firstLetter) == -1) {
6241 varName = 'v_' + varName;
6242 }
6243
6244 var legal = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789';
6245 for (var i = 0; i < varName.length; i++) {
6246 var letter = varName.charAt(i);
6247 if (legal.indexOf(letter) == -1) {
6248 // replace illegal char with _
6249 varName = varName.substr(0, i) + '_' + varName.substr(i + 1);
6250 }
6251 }
6252
6253 return varName;
6254};
6255
6256SaraUtils.getImportTargetCatRefQual = function(){
6257 var gh = new SaraGlideHelper();
6258
6259 var catalogs = gh.getData('sc_catalog', {}, true);
6260 var catalogIds = [];
6261 for(var i = 0; i < catalogs.length; i++) {
6262 catalogIds.push(catalogs[i].sys_id);
6263 }
6264
6265 var catalogFilter = ['IN', catalogIds.join(',')];
6266 gs.info('catalogFilter = ' + catalogFilter);
6267
6268 var result = 'sys_idIN';
6269 var cats = gh.getData('sc_category', {sc_catalog: catalogFilter}, true);
6270 var categoryIds = [];
6271
6272 for(i = 0;i < cats.length; i++) {
6273 var cat = cats[i];
6274 gs.info(SaraJSON.stringify(cat));
6275 categoryIds.push(cat.sys_id);
6276 }
6277 result += categoryIds.join(',');
6278
6279 return result;
6280};
6281
6282/**
6283 * Build url
6284 * @param {String} url
6285 * @return {String}
6286 */
6287SaraUtils.buildUrl = function (url) {
6288 if (!url) {
6289 url = '';
6290 }
6291
6292 var scheme;
6293 var pattern = /^https?:\/\//i;
6294 if (pattern.test(url)) {
6295 scheme = 'absolute';
6296 } else {
6297 scheme = 'relative';
6298 }
6299
6300 if (scheme === 'relative') {
6301 var basePath = new SaraConfig().getBasePath();
6302 if (basePath.charAt(basePath.length - 1) == '/' && url.substring(0, 1) == '/') {
6303 return basePath + url.substring(1);
6304 }
6305
6306 if (basePath.charAt(basePath.length - 1) != '/' && url.substring(0, 1) != '/') {
6307 return basePath + '/' + url;
6308 }
6309
6310 return basePath + url;
6311 }
6312
6313 if (url == '/') {
6314 return new SaraConfig().getBasePath();
6315 }
6316
6317 return url;
6318};
6319
6320/**
6321 * Gets index of item in array
6322 * @param {Array} array
6323 * @param {*} item
6324 * @return {Number}
6325 */
6326SaraUtils.indexOf = function (array, item) {
6327 for (var i = 0; i < array.length; ++i) {
6328 if (array[i] === item) {
6329 return i;
6330 }
6331 }
6332
6333 return -1;
6334};
6335
6336/**
6337 * Detects the array item is in array or not
6338 * @param {Array} array
6339 * @param {*} item
6340 * @return {Boolean}
6341 */
6342SaraUtils.inArray = function (array, item) {
6343 return SaraUtils.indexOf(array, item) !== -1;
6344};
6345
6346/**
6347 * Get redirection endpoint of current instance
6348 * @return {String} The redirection endpoint
6349 */
6350SaraUtils.getRedirectionUrl = function () {
6351 return gs.getProperty('glide.servlet.uri') + SaraCommon.SCOPED_APP + '_sara_oauth_callback.do';
6352};
6353
6354SaraUtils.guardNotNullOrEmpty = function(param, msg) {
6355 if(!param || param === null || param === "") {
6356 throw msg;
6357 }
6358};
6359
6360SaraUtils.isNullOrEmpty = function(param) {
6361 if(!param || param === null || param === "") {
6362 return true;
6363 }
6364 return false;
6365};
6366
6367SaraUtils.md5 = function (string, key, raw) {
6368 /*
6369 * JavaScript MD5 1.0.1
6370 * https://github.com/blueimp/JavaScript-MD5
6371 *
6372 * Copyright 2011, Sebastian Tschan
6373 * https://blueimp.net
6374 *
6375 * Licensed under the MIT license:
6376 * http://www.opensource.org/licenses/MIT
6377 *
6378 * Based on
6379 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
6380 * Digest Algorithm, as defined in RFC 1321.
6381 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
6382 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
6383 * Distributed under the BSD License
6384 * See http://pajhome.org.uk/crypt/md5 for more info.
6385 */
6386 /*jslint bitwise: true */
6387 /*global unescape, define */
6388
6389 'use strict';
6390 /*
6391 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
6392 * to work around bugs in some JS interpreters.
6393 */
6394 function safe_add(x, y) {
6395 var lsw = (x & 0xFFFF) + (y & 0xFFFF),
6396 msw = (x >> 16) + (y >> 16) + (lsw >> 16);
6397 return (msw << 16) | (lsw & 0xFFFF);
6398 }
6399 /*
6400 * Bitwise rotate a 32-bit number to the left.
6401 */
6402 function bit_rol(num, cnt) {
6403 return (num << cnt) | (num >>> (32 - cnt));
6404 }
6405 /*
6406 * These functions implement the four basic operations the algorithm uses.
6407 */
6408 function md5_cmn(q, a, b, x, s, t) {
6409 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
6410 }
6411
6412 function md5_ff(a, b, c, d, x, s, t) {
6413 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
6414 }
6415
6416 function md5_gg(a, b, c, d, x, s, t) {
6417 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
6418 }
6419
6420 function md5_hh(a, b, c, d, x, s, t) {
6421 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
6422 }
6423
6424 function md5_ii(a, b, c, d, x, s, t) {
6425 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
6426 }
6427 /*
6428 * Calculate the MD5 of an array of little-endian words, and a bit length.
6429 */
6430 function binl_md5(x, len) {
6431 /* append padding */
6432 x[len >> 5] |= 0x80 << (len % 32);
6433 x[(((len + 64) >>> 9) << 4) + 14] = len;
6434 var i, olda, oldb, oldc, oldd,
6435 a = 1732584193,
6436 b = -271733879,
6437 c = -1732584194,
6438 d = 271733878;
6439 for (i = 0; i < x.length; i += 16) {
6440 olda = a;
6441 oldb = b;
6442 oldc = c;
6443 oldd = d;
6444 a = md5_ff(a, b, c, d, x[i], 7, -680876936);
6445 d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
6446 c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
6447 b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
6448 a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
6449 d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
6450 c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
6451 b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
6452 a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
6453 d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
6454 c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
6455 b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
6456 a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
6457 d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
6458 c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
6459 b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
6460 a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
6461 d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
6462 c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
6463 b = md5_gg(b, c, d, a, x[i], 20, -373897302);
6464 a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
6465 d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
6466 c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
6467 b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
6468 a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
6469 d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
6470 c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
6471 b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
6472 a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
6473 d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
6474 c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
6475 b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
6476 a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
6477 d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
6478 c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
6479 b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
6480 a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
6481 d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
6482 c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
6483 b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
6484 a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
6485 d = md5_hh(d, a, b, c, x[i], 11, -358537222);
6486 c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
6487 b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
6488 a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
6489 d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
6490 c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
6491 b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
6492 a = md5_ii(a, b, c, d, x[i], 6, -198630844);
6493 d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
6494 c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
6495 b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
6496 a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
6497 d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
6498 c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
6499 b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
6500 a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
6501 d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
6502 c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
6503 b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
6504 a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
6505 d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
6506 c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
6507 b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
6508 a = safe_add(a, olda);
6509 b = safe_add(b, oldb);
6510 c = safe_add(c, oldc);
6511 d = safe_add(d, oldd);
6512 }
6513 return [a, b, c, d];
6514 }
6515 /*
6516 * Convert an array of little-endian words to a string
6517 */
6518 function binl2rstr(input) {
6519 var i,
6520 output = '';
6521 for (i = 0; i < input.length * 32; i += 8) {
6522 output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
6523 }
6524 return output;
6525 }
6526 /*
6527 * Convert a raw string to an array of little-endian words
6528 * Characters >255 have their high-byte silently ignored.
6529 */
6530 function rstr2binl(input) {
6531 var i,
6532 output = [];
6533 output[(input.length >> 2) - 1] = undefined;
6534 for (i = 0; i < output.length; i += 1) {
6535 output[i] = 0;
6536 }
6537 for (i = 0; i < input.length * 8; i += 8) {
6538 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
6539 }
6540 return output;
6541 }
6542 /*
6543 * Calculate the MD5 of a raw string
6544 */
6545 function rstr_md5(s) {
6546 return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
6547 }
6548 /*
6549 * Calculate the HMAC-MD5, of a key and some data (raw strings)
6550 */
6551 function rstr_hmac_md5(key, data) {
6552 var i,
6553 bkey = rstr2binl(key),
6554 ipad = [],
6555 opad = [],
6556 hash;
6557 ipad[15] = opad[15] = undefined;
6558 if (bkey.length > 16) {
6559 bkey = binl_md5(bkey, key.length * 8);
6560 }
6561 for (i = 0; i < 16; i += 1) {
6562 ipad[i] = bkey[i] ^ 0x36363636;
6563 opad[i] = bkey[i] ^ 0x5C5C5C5C;
6564 }
6565 hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
6566 return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
6567 }
6568 /*
6569 * Convert a raw string to a hex string
6570 */
6571 function rstr2hex(input) {
6572 var hex_tab = '0123456789abcdef',
6573 output = '',
6574 x,
6575 i;
6576 for (i = 0; i < input.length; i += 1) {
6577 x = input.charCodeAt(i);
6578 output += hex_tab.charAt((x >>> 4) & 0x0F) +
6579 hex_tab.charAt(x & 0x0F);
6580 }
6581 return output;
6582 }
6583 /*
6584 * Encode a string as utf-8
6585 */
6586 function str2rstr_utf8(input) {
6587 return unescape(encodeURIComponent(input));
6588 }
6589 /*
6590 * Take string arguments and return either raw or hex encoded strings
6591 */
6592 function raw_md5(s) {
6593 return rstr_md5(str2rstr_utf8(s));
6594 }
6595
6596 function hex_md5(s) {
6597 return rstr2hex(raw_md5(s));
6598 }
6599
6600 function raw_hmac_md5(k, d) {
6601 return rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d));
6602 }
6603
6604 function hex_hmac_md5(k, d) {
6605 return rstr2hex(raw_hmac_md5(k, d));
6606 }
6607
6608 if (!key) {
6609 if (!raw) {
6610 return hex_md5(string);
6611 }
6612 return raw_md5(string);
6613 }
6614 if (!raw) {
6615 return hex_hmac_md5(key, string);
6616 }
6617
6618 return raw_hmac_md5(key, string);
6619};
6620]]></script>
6621 <description>Sara Utilities</description>
6622 <active>true</active>
6623 <client_callable>false</client_callable>
6624 <access>public</access>
6625 </script_include>
6626
6627 <script_include>
6628 <name>SaraTestBench</name>
6629 <script><![CDATA[/*
6630Test bench for Sara Scripts
6631Create manually in scope of Automic SNSC
6632Use background script to execute:
6633
6634var test = new SaraTestBench();
6635test.execute();
6636 */
6637var SaraTestBench = Class.create();
6638SaraTestBench.prototype = {
6639 initialize: function () {
6640 },
6641
6642 execute: function(){
6643 SaraTest.resetSummary();
6644
6645 SaraTransformMapTest.execute();
6646
6647 SaraConsumerDALTest.execute();
6648
6649 SaraConsumerImportTest.execute();
6650
6651 gs.info("=======================================================================================");
6652 gs.info("SUMMARY");
6653 gs.info("=======================================================================================");
6654 var summary = SaraTest.getSummary();
6655 gs.info("------ TOTAL: " + summary.total);
6656 gs.info("------ PASS: " + summary.pass);
6657 gs.info("------ FAIL: " + summary.fail);
6658 gs.info("------ IGNORE: " + summary.ignore);
6659 }
6660};
6661
6662var SaraConsumerDALTest = (function() {
6663 var gh = new SaraGlideHelper();
6664 var dal = new SaraConsumerDAL();
6665 return {
6666 execute: function() {
6667 gs.info("----------------------------------------------------------------------------");
6668 gs.info("Test SaraConsumerDAL");
6669 gs.info("----------------------------------------------------------------------------");
6670
6671 this.testGetCatalog();
6672 this.testSaveOrUpdateCatalog();
6673 this.testSaveOrUpdateCategory();
6674 this.testGetDefaultCategoryId();
6675 this.testSaveCategoryToSaraDefinition();
6676 this.testDeactivateSaraDefinition();
6677 },
6678
6679 testGetCatalog: function() {
6680 SaraTest.test("get catalog id by title", function() {
6681 var cat = dal.getCatalog("Service Catalog");
6682 SaraTest.assert(cat !== undefined, "catalog is get correctly");
6683 SaraTest.assert(cat.title === "Service Catalog", "title is get correctly");
6684 gs.info(SaraJSON.stringify(cat));
6685 });
6686 },
6687
6688 testSaveOrUpdateCatalog: function() {
6689 SaraTest.test("save or update catalog", function() {
6690 var catName = "snsc dal cat 1" + SaraUtils.getRandom();
6691 var desc = "test description";
6692
6693 var catId = dal.saveOrUpdateCatalog({
6694 title: catName,
6695 description: desc,
6696 active: true
6697 }).sys_id;
6698 SaraTest.assert(catId !== null, "catalog is persisted correctly");
6699
6700 var cat = gh.getData("sc_catalog", {sys_id: catId});
6701 gs.info(SaraJSON.stringify(cat));
6702 SaraTest.assert(cat !== null, "catalog is get correctly");
6703 SaraTest.assert(cat.title === catName, "title is set correctly");
6704 SaraTest.assert(cat.description === desc, "description is set correctly");
6705 SaraTest.assert(cat.active == "true", "active is set correctly");
6706
6707 gh.deleteData("sc_category", {sc_catalog: catId}, true);
6708 gh.deleteData("sc_catalog", {sys_id: catId}, true);
6709 });
6710 },
6711
6712 testSaveOrUpdateCategory: function() {
6713 SaraTest.test("save or update category", function() {
6714 var catName = "snsc dal cat 2" + SaraUtils.getRandom();
6715 var desc = "test description";
6716 var categoryName = "snsc dal category 2" + SaraUtils.getRandom();
6717 var categoryDescription = "category description";
6718 var categoryNewDescription = "category description new";
6719
6720 var catId = dal.saveOrUpdateCatalog({
6721 title: catName,
6722 description: desc,
6723 active: true
6724 }).sys_id;
6725
6726 var cat = {
6727 sc_catalog: catId,
6728 title: categoryName,
6729 description: categoryDescription,
6730 active: true};
6731 cat.description = categoryDescription;
6732 var category = dal.saveOrUpdateCategory(cat);
6733 gs.info("category: " + SaraJSON.stringify(category));
6734 SaraTest.assert(category !== null, "category is get correctly");
6735 SaraTest.assert(category.title === categoryName, "title is set correctly");
6736 SaraTest.assert(category.description === categoryDescription, "description is set correctly");
6737 SaraTest.assert(category.active == "true", "active is set correctly");
6738
6739 category.description = categoryNewDescription;
6740 category.active = false;
6741 dal.saveOrUpdateCategory(category);
6742
6743 var result = gh.getData("sc_category", {sys_id: category.sys_id});
6744 gs.info("result: " + SaraJSON.stringify(result));
6745
6746 SaraTest.assert(result.description === categoryNewDescription, "description is updated correctly");
6747 SaraTest.assert(result.active == "false", "active is updated correctly");
6748
6749 gh.deleteData("sc_category", {sc_catalog: catId}, true);
6750 gh.deleteData("sc_catalog", {sys_id: catId}, true);
6751 });
6752 },
6753
6754 testGetDefaultCategoryId: function() {
6755 SaraTest.test("get default category", function () {
6756 var catId = dal.getDefaultCategoryId();
6757 var category = gh.getData("sc_category", {sys_id: catId});
6758
6759 SaraTest.assert(category !== null, "getDetaultCategoryId return valid category id");
6760 gs.info(SaraJSON.stringify(category));
6761 });
6762 },
6763
6764 testSaveCategoryToSaraDefinition: function() {
6765 SaraTest.test("save category to sara definition", function() {
6766 var catName = "snsc dal cat 3" + SaraUtils.getRandom();
6767 var desc = "test description";
6768
6769 var categoryName = "snsc dal category 3" + SaraUtils.getRandom();
6770 var categoryDescription = "category description";
6771
6772 var catId = dal.saveOrUpdateCatalog({
6773 title: catName,
6774 description: desc,
6775 active: true
6776 }).sys_id;
6777
6778 var category = dal.saveOrUpdateCategory({
6779 sc_catalog: catId,
6780 title: categoryName,
6781 description: categoryDescription,
6782 active: true
6783 });
6784
6785 var definitionId = dal.saveRootImportCategoryToSaraDefinition(category.sys_id).sys_id;
6786 var definition = gh.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: definitionId});
6787 gs.info(SaraJSON.stringify(definition));
6788
6789 SaraTest.assert(definition !== null, "definition is saved correctly");
6790 SaraTest.assert(definition.u_name === categoryName, "u_name is saved correctly");
6791 SaraTest.assert(definition.u_parent === category.sys_id, "u_parent is saved correctly");
6792 SaraTest.assert(definition.u_type === 'category', "u_type is saved correctly");
6793 SaraTest.assert(definition.u_active == 'true', "active is saved correctly");
6794
6795 gh.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: definitionId}, true);
6796 gh.deleteData("sc_category", {sc_catalog: catId}, true);
6797 gh.deleteData("sc_catalog", {sys_id: catId}, true);
6798 });
6799 },
6800
6801 testDeactivateSaraDefinition: function() {
6802 SaraTest.test("deactivate sara definition", function() {
6803 var catName = "snsc dal cat 6" + SaraUtils.getRandom();
6804 var desc = "test description";
6805 var categoryName = "snsc dal category 6" + SaraUtils.getRandom();
6806 var categoryDescription = "category description";
6807 var catalogItemName = "snsc dal catalog item 6";
6808
6809 var parentDefinitionName = "snsc definition 6 parent" + SaraUtils.getRandom();
6810 var definitionName = "snsc definition 6" + SaraUtils.getRandom();
6811
6812 var catId = dal.saveOrUpdateCatalog({
6813 title: catName,
6814 description: desc,
6815 active: true
6816 }).sys_id;
6817 var category = dal.saveOrUpdateCategory({
6818 title: categoryName,
6819 description: categoryDescription,
6820 sc_catalog: catId
6821 });
6822 var catalogItem = dal.saveOrUpdateCatalogItem({
6823 category: category.sys_id,
6824 name: catalogItemName,
6825 active: true
6826 });
6827
6828 var parentDefinition = dal.saveOrUpdateSaraDefinition({
6829 u_name: parentDefinitionName,
6830 u_active: true,
6831 u_consume_url: "http://testurl.com",
6832 u_parent: category.sys_id,
6833 u_type: 'catalog'
6834 });
6835
6836 var definition = dal.saveOrUpdateSaraDefinition({
6837 u_name: definitionName,
6838 u_active: true,
6839 u_consume_url: "http://testurl.com",
6840 u_parent: category.sys_id,
6841 u_type: 'service',
6842 u_sc_item: catalogItem.sys_id,
6843 u_hash: '123'
6844 });
6845
6846 SaraTest.assert(parentDefinition.u_active == 'true', "parent definition is active");
6847 SaraTest.assert(definition.u_active == 'true', "definition is active");
6848
6849 gs.info("parent definition: " + SaraJSON.stringify(parentDefinition));
6850 gs.info("definition: " + SaraJSON.stringify(definition));
6851
6852 dal.deactivateSaraDefinition(parentDefinition);
6853
6854 definition = gh.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: definition.sys_id});
6855 parentDefinition = gh.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: parentDefinition.sys_id});
6856
6857 category = gh.getData("sc_category", {sys_id: category.sys_id});
6858 gs.info("category: " + SaraJSON.stringify(category));
6859
6860 catalogItem = gh.getData("sc_cat_item", {sys_id: catalogItem.sys_id});
6861 gs.info("catalogItem: " + SaraJSON.stringify(catalogItem));
6862
6863 SaraTest.assert(catalogItem.name === catalogItemName,"get correct catalog item");
6864 SaraTest.assert(catalogItem.active == 'false',"catalog item is deactivated");
6865 SaraTest.assert(definition.u_name === definitionName,"get correct definition");
6866 SaraTest.assert(definition.u_active == 'false',"definition is deactivated");
6867 SaraTest.assert(parentDefinition.u_name === parentDefinitionName,"get correct parent definition");
6868 SaraTest.assert(parentDefinition.u_active == 'false',"parent definition is deactivated");
6869
6870
6871 gh.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: definition.sys_id}, true);
6872 gh.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: parentDefinition.sys_id}, true);
6873 //gh.deleteData("sc_cat_item", {category: category.sys_id}, true);
6874 gh.deleteData("sc_category", {sc_catalog: catId}, true);
6875 gh.deleteData("sc_catalog", {sys_id: catId}, true);
6876 });
6877 }
6878 };
6879})();
6880
6881var SaraConsumerImportTest = (function() {
6882 var logger = new SaraLog("SaraGlideHelperTest");
6883 var glideHelper = new SaraGlideHelper();
6884 var categoryName = "snsc test import " + SaraUtils.getRandom();
6885 var consumer = new SaraConsumerImportSet();
6886 var categoryId = null;
6887 var catalogId;
6888 var category;
6889 var dal = new SaraConsumerDAL();
6890 var catItem1 = null;
6891
6892 return {
6893 execute: function() {
6894 gs.info("----------------------------------------------------------------------------");
6895 gs.info("Test SaraConsumerImportSet");
6896 gs.info("----------------------------------------------------------------------------");
6897
6898 this.initialize();
6899
6900 this.testImportCategory();
6901
6902 this.testImportItem();
6903
6904 this.testSyncLookup();
6905
6906 this.tearDown();
6907 },
6908
6909 initialize: function() {
6910 catalogId = glideHelper.getData("sc_catalog", { title: "Service Catalog" }).sys_id;
6911
6912 category = dal.saveOrUpdateCategory({
6913 title: categoryName,
6914 description: "test",
6915 sc_catalog: catalogId,
6916 active: true
6917 });
6918 gs.info("created category: " + category);
6919
6920 gs.info("category to be imported: " + categoryName);
6921
6922 categoryId = category.sys_id;
6923 },
6924
6925 getMockCatalogData: function() {
6926 var catalogsData = {
6927 "DEMO":{
6928 "title":"Automic Demo Services",
6929 "active":true,
6930 "description":"Automic Demo Services",
6931 "parent":"",
6932 "name":"DEMO"},
6933 "DEMO2":{
6934 "title":"DEMO2",
6935 "active":true,
6936 "description":"",
6937 "parent":"",
6938 "name":"DEMO2"}};
6939
6940 //mock catalog data for testing
6941 for(var ctgName in catalogsData) {
6942 this.wrapCategoryData(catalogsData[ctgName]);
6943 }
6944
6945 return catalogsData;
6946 },
6947
6948 getMockupServicesData: function() {
6949 var servicesData = {
6950 "DEMO": {
6951 "PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.ACTIVATE_SNSC_SERVICE.NEW.1":
6952 {
6953 "variables": [
6954 { "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#" },
6955 { "description": "", "label": "Previous Month(s) included", "defaultValue": ["3"], "type": 6, "required": true, "range": [], "asLookup": false, "name": "EOM_MONTHBACK_", "actualName": "EOM_MONTHBACK#" },
6956 { "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#" },
6957 { "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#" },
6958 { "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#" }
6959 ], "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" },
6960 "PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.DEACTIVATE_SNSC_SERVICE.NEW.1":
6961 {
6962 "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" }
6963 },
6964 "DEMO2": {
6965 "PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.DEMO_SERVICE.NEW.1": {
6966 "variables": [
6967 { "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#" },
6968 { "description": "", "label": "Previous Month(s) included", "defaultValue": ["3"], "type": 6, "required": true, "range": [], "asLookup": false, "name": "EOM_MONTHBACK_", "actualName": "EOM_MONTHBACK#" },
6969 { "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#" },
6970 { "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#" },
6971 { "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#" }
6972 ], "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" }
6973 }};
6974
6975 //mock service data for testing
6976 for (var catalogName in servicesData) {
6977 var catalog = servicesData[catalogName];
6978 for(var serviceName in catalog) {
6979 this.wrapServiceData(catalog[serviceName]);
6980 }
6981 }
6982
6983 return servicesData;
6984 },
6985
6986 wrapCategoryData: function(dataObj) {
6987 dataObj.__proto__ = new SaraModel.CatalogCategory();
6988 },
6989
6990 wrapServiceData: function(dataObj) {
6991 dataObj.__proto__ = new SaraModel.CatalogItem();
6992 if(dataObj.variables && dataObj.variables instanceof Array) {
6993 for(var i = 0; i < dataObj.variables.length; i ++) {
6994 dataObj.variables[i].__proto__ = new SaraModel.CatalogVariable();
6995 }
6996 }
6997 },
6998
6999 testImportCategory: function () {
7000 consumer.catalogsData = this.getMockCatalogData();
7001 SaraTest.test("test import categories, de-activate definition removed from AE, update existing definition and create new definition", function () {
7002 var categoryName2 = "snsc test import " + SaraUtils.getRandom();
7003 var categoryName3 = "snsc test import " + SaraUtils.getRandom();
7004
7005 var definitionName = "snsc test import " + SaraUtils.getRandom();
7006 var categoryDescription = "testImportCategory category description";
7007
7008 var category2 = dal.saveOrUpdateCategory({
7009 title: categoryName2,
7010 description: categoryDescription,
7011 sc_catalog: catalogId,
7012 active: true
7013 });
7014
7015
7016 var definition = dal.saveOrUpdateSaraDefinition({
7017 u_name: definitionName,
7018 u_active: true,
7019 u_consume_url: "http://testurl.com",
7020 u_parent: category.sys_id,
7021 u_type: 'catalog',
7022 u_service_catalog_category: category2.sys_id
7023 });
7024
7025 var category3 = dal.saveOrUpdateCategory({
7026 title: categoryName3,
7027 description: categoryDescription,
7028 sc_catalog: catalogId,
7029 active: true
7030 });
7031
7032 var demoDefinition = dal.saveOrUpdateSaraDefinition({
7033 u_name: "DEMO",
7034 u_active: true,
7035 u_consume_url: "oldurl",
7036 u_parent: category.sys_id,
7037 u_type: 'catalog',
7038 u_service_catalog_category: category3.sys_id
7039 });
7040
7041 gs.info("done prepare test data");
7042 //create new definition and make sure that it will be de-activate during synchronization
7043 consumer.importCategory(categoryId);
7044
7045 var resultDefinition = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, { u_name: definitionName, u_parent: category.sys_id });
7046 SaraTest.assert(resultDefinition.u_active == "false", "Definition does not exist in AE should be de-activated");
7047
7048 category2 = glideHelper.getData(SaraCommon.TABLE_NAME.SN_CATEGORY, { sys_id: category2.sys_id });
7049 SaraTest.assert(category2.active == "false", "Category linked to definition does not exist in AE should be de-activated");
7050
7051 category3 = glideHelper.getData(SaraCommon.TABLE_NAME.SN_CATEGORY, { sys_id: category3.sys_id });
7052 SaraTest.assert(category3.parent == category.sys_id, "parent of category linked to definition exist is updated");
7053 SaraTest.assert(category3.title == "Automic Demo Services", "title of category linked to definition exist is updated");
7054 SaraTest.assert(category3.description == "Automic Demo Services", "description of category linked to definition exist is updated");
7055 });
7056 },
7057
7058 testImportItem: function() {
7059 consumer.servicesData = this.getMockupServicesData();
7060
7061 SaraTest.test("test import items", function() {
7062 consumer.importItem();
7063
7064 gs.info("get sub category of " + categoryId);
7065 //get catalog items under import category
7066 var subCategories = glideHelper.getData("sc_category", {parent: categoryId, active: true}, true);
7067 gs.info("sub categories: " + SaraJSON.stringify(subCategories));
7068 SaraTest.assertEqual(subCategories.length, 2, "2 categories are created");
7069 var category1 = subCategories[0].title === "DEMO2" ? subCategories[1] : subCategories[0];
7070 var catItemsOfCategory1 = glideHelper.getData("sc_cat_item", {category: category1.sys_id}, true);
7071
7072 SaraTest.assertEqual(catItemsOfCategory1.length, 2, "2 catalog item under category " + category1.title);
7073
7074 gs.info("catItemsOfCategory1: " + SaraJSON.stringify(catItemsOfCategory1));
7075 catItem1 = catItemsOfCategory1[0].name === "Activate SNSC Service" ? catItemsOfCategory1[0] : catItemsOfCategory1[1];
7076 var itemVarSet = glideHelper.getData("io_set_item", {sc_cat_item: catItem1.sys_id});
7077 var varSet = glideHelper.getData("item_option_new_set", {sys_id: itemVarSet.variable_set});
7078 gs.info(" varSet of the item: " + SaraJSON.stringify(varSet));
7079 var variables = glideHelper.getData("x_ausgh_snsc_sara_variable", {variable_set: varSet.sys_id}, true);
7080 gs.info(" variables of the item: " + SaraJSON.stringify(variables));
7081 SaraTest.assert(variables.length == 7, "5 + 2 variables are created");
7082 });
7083 },
7084
7085 testSyncLookup: function() {
7086 var newSapiService = {
7087 "variables": [
7088 { "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#" },
7089 { "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#" },
7090 { "description": "", "label": "Previous Month(s) included", "defaultValue": ["3"], "type": 6, "required": true, "range": [], "asLookup": false, "name": "EOM_MONTHBACK_", "actualName": "EOM_MONTHBACK#" },
7091 { "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#" },
7092 { "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#" },
7093 { "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#" }
7094 ], "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" };
7095 this.wrapServiceData(newSapiService);
7096
7097 SaraTest.test("test sync lookup", function() {
7098 var saraSync = new SaraSync();
7099 gs.info("catItem1: " + SaraJSON.stringify(catItem1));
7100 var definition = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {u_sc_item:catItem1.sys_id });
7101 gs.info("newSapiService: " + SaraJSON.stringify(newSapiService));
7102 saraSync.syncLookup(definition, newSapiService);
7103 });
7104 },
7105
7106 tearDown: function() {
7107 SaraUtils.cleanup( { u_parent: category.sys_id });
7108 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, { u_parent: category.sys_id }, true);
7109 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_CATEGORY, { parent: categoryId }, true);
7110 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_CATEGORY, { title: ["CONTAINS", "snsc test import"] }, true);
7111 }
7112 };
7113})();
7114
7115var SaraTransformMapTest = (function(){
7116 var logger = new SaraLog("SaraGlideHelperTest");
7117 var glideHelper = new SaraGlideHelper();
7118
7119 var catalogId = glideHelper.getSysId("sc_catalog", {title: "Service Catalog"});
7120 gs.info("catelog id: " + catalogId);
7121
7122 var getCategory = function(title) {
7123 return glideHelper.getData("sc_category", {title: title });
7124 };
7125
7126 var deleteCategory = function(title, deleteAll) {
7127 glideHelper.deleteData("sc_category", {title: title },deleteAll);
7128 glideHelper.deleteData("x_ausgh_snsc_sc_category_ist", {title: title },deleteAll);
7129 };
7130
7131 var createCategory = function(title, active, description, parent) {
7132 glideHelper.persistData("x_ausgh_snsc_sc_category_ist", {
7133 title: title,
7134 active: active,
7135 description: description,
7136 parent: parent,
7137 sc_catalog: catalogId
7138 });
7139 };
7140
7141 return {
7142 execute: function() {
7143 gs.info("----------------------------------------------------------------------------");
7144 gs.info("Test transform map definitions");
7145 gs.info("----------------------------------------------------------------------------");
7146
7147 this.testPersistCatalog();
7148 this.testPersistCategory();
7149 this.testPersistCatalogItem();
7150 this.testPersistVariableSet();
7151 this.testPersistCatelogVariableSet();
7152 this.testPersistSaraDefinition();
7153 },
7154
7155 testPersistCatalog: function() {
7156 var catalogName = "snsc test catalog";
7157 glideHelper.deleteData("sc_catalog", {"title": catalogName});
7158
7159 SaraTest.test("Persist catalog via Importset", function() {
7160 glideHelper.persistData("x_ausgh_snsc_sc_catalog_ist", {
7161 title: catalogName,
7162 description: "test description",
7163 active: "true"
7164 });
7165
7166 var catalog = glideHelper.getData("sc_catalog", {"title": catalogName});
7167
7168 SaraTest.assert(catalog !== null, "catalog is transformed correctly");
7169 SaraTest.assert(catalog.title === catalogName, "catalog title is transformed correctly");
7170 SaraTest.assert(catalog.description === "test description", "catalog description is transformed correctly");
7171 gs.info("active: " + catalog.active);
7172 SaraTest.assert(catalog.active, "catalog active is transformed correctly");
7173 });
7174
7175 SaraTest.test("Update catalog via Importset", function() {
7176 var catalog = glideHelper.getData("sc_catalog", {title: catalogName});
7177 var data = {
7178 id: catalog.sys_id,
7179 description: "new description 2",
7180 active: false
7181 };
7182 glideHelper.persistData("x_ausgh_snsc_sc_catalog_ist", data);
7183
7184 var newCatalog = glideHelper.getData("sc_catalog", {"title": catalogName});
7185 gs.info("new catalog: " + SaraJSON.stringify(newCatalog));
7186 SaraTest.assert(newCatalog !== null, "catalog is transformed correctly, title is not overrided");
7187 SaraTest.assert(newCatalog.description === "new description 2", "catalog description is updated correctly");
7188 gs.info("active: " + newCatalog.active);
7189 SaraTest.assert(newCatalog.active == "false", "catalog active is updated correctly");
7190 });
7191 },
7192
7193 testPersistCategory: function() {
7194 var categoryName1 = "snsc test catagory";
7195 var categoryName2 = "snsc test sub catagory";
7196 deleteCategory(categoryName1, true);
7197 deleteCategory(categoryName2, true);
7198
7199 SaraTest.test("Persist category via Importset", function() {
7200 var category = getCategory(categoryName1);
7201 SaraTest.assert(category === null, "category must not exists");
7202 var category2 = getCategory(categoryName2);
7203 SaraTest.assert(category2 === null, "sub category must not exists");
7204
7205 createCategory(categoryName1,true,"test description", null);
7206 category = getCategory(categoryName1);
7207 gs.info(SaraJSON.stringify(category));
7208 SaraTest.assert(category !== null, "Category ImportSet should be transform to category table");
7209 SaraTest.assert(category.title === categoryName1, "Assert title transform correctly");
7210
7211 //create via importset table
7212 createCategory(categoryName2,true,"test sub description", category.sys_id);
7213 //get real data
7214 category2 = getCategory(categoryName2);
7215 SaraTest.assert(category2 !== null, "Sub category ImportSet should be transform to category table");
7216 SaraTest.assert(category2.title === categoryName2, "Assert title transform correctly");
7217
7218 var parent = glideHelper.getData("sc_category", {sys_id:category2.parent});
7219 SaraTest.assert(parent !== null, "Assert parent transform correctly");
7220 SaraTest.assert(parent.title === categoryName1, "Assert parent transform correctly");
7221 });
7222
7223 SaraTest.test("Save category with same name but different parent should create new category", function() {
7224 //create another category with different parent and assert that new item is
7225 //inserted to target table
7226 gs.info("create another record with name " + categoryName2);
7227 createCategory(categoryName2,true,"test description 2");
7228 var records = glideHelper.getData("sc_category", {title:categoryName2}, true);
7229 SaraTest.assert(records.length === 2, "new category is created");
7230 });
7231 },
7232
7233 testPersistCatalogItem: function() {
7234 var gh = glideHelper;
7235 var name = "snsc sample catelog item" + SaraUtils.getRandom();
7236 gs.info("catelog item name: " + name);
7237 var description = "whatever";
7238 var short_description = "short descriprion";
7239 var categoryName = "snsc item category";
7240 var category = null;
7241
7242 SaraTest.test("Persist catalog item via Importset", function(){
7243 //prepare data
7244 deleteCategory(categoryName, true);
7245 createCategory(categoryName, true, "");
7246 category = getCategory(categoryName);
7247 gs.info("category id: " + category.sys_id);
7248 SaraTest.assert(category !== null, "category is created successfully");
7249
7250 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7251 name: name,
7252 description: description,
7253 short_description: short_description,
7254 use_sc_layout: true,
7255 no_quantity: true,
7256 category: category.sys_id,
7257 active: true
7258 });
7259 var item = gh.getData("sc_cat_item", {name: name});
7260 SaraTest.assert(item.name === name, "item is transformed correctly");
7261 SaraTest.assert(item.description === description, "description is transformed correctly");
7262 SaraTest.assert(item.short_description === short_description, "short_description is transformed correctly");
7263 SaraTest.assert(item.use_sc_layout == "true", "use_sc_layout is transformed correctly");
7264 SaraTest.assert(item.no_quantity == "true", "no_quantity is transformed correctly");
7265 SaraTest.assert(item.active == "true", "active is transformed correctly");
7266 SaraTest.assert(item.category === category.sys_id, "category is transformed correctly");
7267 });
7268
7269 SaraTest.test("Catalog item same name different category should create new", function() {
7270 var newCategoryName = categoryName + SaraUtils.getRandom();
7271 createCategory(newCategoryName, true, "");
7272 var newCat = getCategory(newCategoryName);
7273 gs.info("new category id: " + newCat.sys_id);
7274 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7275 name: name,
7276 description: "new description",
7277 short_description: "new short description",
7278 use_sc_layout: false,
7279 no_quantity: false,
7280 category: newCat.sys_id,
7281 active: false
7282 });
7283
7284 var records = gh.getData("sc_cat_item", {name: name}, true);
7285 SaraTest.assert(records.length === 2, "new item is created");
7286 });
7287
7288 SaraTest.test("Update catalog item via Importset", function(){
7289 var existingItem = gh.getData("sc_cat_item", {
7290 name: name,
7291 category: category.sys_id
7292 });
7293
7294 SaraTest.assert(existingItem !== undefined, "existing item is get correctly");
7295
7296 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7297 id: existingItem.sys_id,
7298 name: name,
7299 description: "new description",
7300 short_description: "new short description",
7301 use_sc_layout: false,
7302 no_quantity: false,
7303 category: category.sys_id,
7304 active: false
7305 });
7306 var items = gh.getData("sc_cat_item", {name: name, category: category.sys_id}, true);
7307 SaraTest.assert(items.length === 1, "no new item is created");
7308
7309 var item = items[0];
7310 SaraTest.assert(item.name === name, "item is transformed correctly");
7311 SaraTest.assert(item.description === "new description", "description is transformed correctly");
7312 SaraTest.assert(item.short_description === "new short description", "short_description is transformed correctly");
7313 SaraTest.assert(item.use_sc_layout == "false", "use_sc_layout is transformed correctly");
7314 SaraTest.assert(item.no_quantity == "false", "no_quantity is transformed correctly");
7315 SaraTest.assert(item.active == "false", "active is transformed correctly");
7316 SaraTest.assert(item.category === category.sys_id, "category is transformed correctly");
7317 });
7318 },
7319
7320 testPersistVariableSet: function() {
7321 var varSetName = "snsc test variable set " + SaraUtils.getRandom();
7322 var varSetTitle = "title";
7323 var varSetDescription = "test description";
7324 var varSetDisplayName = "display name";
7325
7326 var varSetTitleNew = "title new";
7327 var varSetDescriptionNew = "test description new";
7328 var varSetDisplayNameNew = "display name new";
7329
7330 glideHelper.deleteData("item_option_new_set", {"name": ["CONTAINS", "snsc test"]}, true);
7331
7332 SaraTest.test("Persist variable set via Importset", function() {
7333 glideHelper.persistData("x_ausgh_snsc_item_option_new_set_ist", {
7334 name: varSetName,
7335 title: varSetTitle,
7336 description: varSetDescription,
7337 sys_name: varSetDisplayName
7338 });
7339
7340 var varSet = glideHelper.getData("item_option_new_set", {"name": varSetName});
7341
7342 SaraTest.assert(varSet !== null, "varSet is transformed correctly");
7343 SaraTest.assert(varSet.name === varSetName, "var set name is transformed correctly");
7344 SaraTest.assert(varSet.title === varSetTitle, "var set title is transformed correctly");
7345 SaraTest.assert(varSet.description === varSetDescription, "var set description is transformed correctly");
7346 SaraTest.assert(varSet.sys_name === varSetDisplayName, "var set display name is transformed correctly");
7347 });
7348
7349 SaraTest.test("Update var set via Importset", function() {
7350 var existingVarSet = glideHelper.getData("item_option_new_set", {name: varSetName});
7351 SaraTest.assert(existingVarSet !== undefined, "var set is get correctly");
7352
7353 glideHelper.persistData("x_ausgh_snsc_item_option_new_set_ist", {
7354 id: existingVarSet.sys_id,
7355 name: varSetName,
7356 title: varSetTitleNew,
7357 description: varSetDescriptionNew
7358 });
7359
7360 var varSets = glideHelper.getData("item_option_new_set", {"name": varSetName}, true);
7361
7362 SaraTest.assert(varSets.length === 1, "no new item is get correctly");
7363 var varSet = varSets[0];
7364 SaraTest.assert(varSet !== null, "varSet is transformed correctly");
7365 SaraTest.assert(varSet.name === varSetName, "var set name is transformed correctly");
7366 SaraTest.assert(varSet.title === varSetTitleNew, "var set title is updated correctly");
7367 SaraTest.assert(varSet.description === varSetDescriptionNew, "var set description is updated correctly");
7368 });
7369 },
7370
7371 testPersistCatelogVariableSet : function() {
7372 var varSetName = "snsc test variable set " + SaraUtils.getRandom();
7373 var varSetTitle = "title";
7374 var varSetDescription = "test description";
7375 var varSetDisplayName = "display name";
7376
7377 var newCategoryName = "snsc category " + SaraUtils.getRandom();
7378
7379 var catItemName = "snsc cat item " + SaraUtils.getRandom();
7380
7381 var gh = glideHelper;
7382
7383 gh.deleteData("item_option_new_set", {"name": ["CONTAINS", "snsc test"]}, true);
7384
7385 SaraTest.test("Persist catalog variable set via Importset", function() {
7386 gh.persistData("x_ausgh_snsc_item_option_new_set_ist", {
7387 name: varSetName,
7388 title: varSetTitle,
7389 description: varSetDescription,
7390 display_name: varSetDisplayName
7391 });
7392
7393 var varSet = glideHelper.getData("item_option_new_set", {"name": varSetName});
7394
7395 SaraTest.assert(varSet !== null, "varSet is transformed correctly");
7396
7397 createCategory(newCategoryName);
7398 var newCat = getCategory(newCategoryName);
7399
7400 gs.info("new category id: " + newCat.sys_id);
7401
7402 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7403 name: catItemName,
7404 description: "new description",
7405 short_description: "new short description",
7406 use_sc_layout: true,
7407 no_quantity: true,
7408 category: newCat.sys_id,
7409 active: true
7410 });
7411
7412 var catItem = gh.getData("sc_cat_item", {name: catItemName, category: newCat.sys_id});
7413 SaraTest.assert(catItem !== undefined, "cat item is transformed successfully");
7414
7415 //link item and varset via import set
7416 gh.persistData("x_ausgh_snsc_io_set_item_ist", {sc_cat_item: catItem.sys_id, variable_set: varSet.sys_id});
7417 //get real
7418 var catVarSet = gh.getData("io_set_item", {sc_cat_item: catItem.sys_id, variable_set: varSet.sys_id});
7419
7420 SaraTest.assert(catVarSet !== null, "catalog item variable is transformed correctly");
7421 SaraTest.assert(catVarSet.sc_cat_item === catItem.sys_id, "cat item is set correctly");
7422 SaraTest.assert(catVarSet.variable_set === varSet.sys_id, "var set is set correctly");
7423 });
7424 },
7425
7426 testPersistSaraDefinition : function() {
7427 var newCategoryName = "snsc test category " + SaraUtils.getRandom();
7428 var parentCategoryName = "snsc test parent category " + SaraUtils.getRandom();
7429
7430 var varSetName = "snsc test var set" + SaraUtils.getRandom();
7431
7432 var definitionName1 = "snsc test" + SaraUtils.getRandom();
7433 var definitionName2 = "snsc test" + SaraUtils.getRandom();
7434 var definitionName3 = "snsc test" + SaraUtils.getRandom();
7435
7436 var catItemName1 = "snsc test cat item" + SaraUtils.getRandom();
7437
7438 var consume_url1 = "http://automictest.com";
7439 var consume_url2 = "http://automictest2.com";
7440 var hash1 = "FDSGHERGGGGFGFGDGFS";
7441 var hash2 = "FDSFFSDHASAFGFGDGFS";
7442
7443 var gh = glideHelper;
7444
7445 gh.deleteData("x_ausgh_snsc_sara_definition", {"name": ["CONTAINS", "snsc test"]}, true);
7446
7447 SaraTest.test("Persist sara definition for catalog item via Importset", function() {
7448 createCategory(parentCategoryName);
7449 var parentCat = getCategory(parentCategoryName);
7450 SaraTest.assert(parentCat !== null, "parentCat is transformed correctly");
7451
7452 createCategory(newCategoryName);
7453 var newCat = getCategory(newCategoryName);
7454 SaraTest.assert(newCat !== null, "newCat is transformed correctly");
7455
7456 //create var set
7457 gh.persistData("x_ausgh_snsc_item_option_new_set_ist", {
7458 name: varSetName,
7459 title: "title",
7460 description: "description",
7461 display_name: "whatever"
7462 });
7463
7464 var varSet = gh.getData("item_option_new_set", {"name": varSetName});
7465 SaraTest.assert(varSet !== null, "varSet is transformed correctly");
7466
7467 //create catalog item
7468 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7469 name: catItemName1,
7470 description: "new description",
7471 short_description: "new short description",
7472 use_sc_layout: true,
7473 no_quantity: true,
7474 category: newCat.sys_id,
7475 active: true
7476 });
7477
7478 var catItem = gh.getData("sc_cat_item", {name: catItemName1, category: newCat.sys_id});
7479 SaraTest.assert(catItem !== null, "catItem is transformed correctly");
7480
7481 gh.persistData("x_ausgh_snsc_sara_definition_ist", {
7482 u_name: definitionName1,
7483 u_consume_url: consume_url1,
7484 u_sc_item: catItem.sys_id,
7485 u_service_catalog_category: newCat.sys_id,
7486 u_var_set: varSet.sys_id,
7487 u_parent: parentCat.sys_id,
7488 u_type: "service",
7489 u_hash: hash1
7490 });
7491 var saraDefinition = gh.getData("x_ausgh_snsc_sara_definition_ist", {u_name: definitionName1, u_parent: parentCat.sys_id});
7492
7493 SaraTest.assert(saraDefinition !== null, "saraDefinition is transformed correctly");
7494 gs.info("saraDefinition: " + SaraJSON.stringify(saraDefinition));
7495 SaraTest.assert(saraDefinition.u_name === definitionName1, "u_name is transformed correctly");
7496 SaraTest.assert(saraDefinition.u_consume_url === consume_url1, "consume_url is transformed correctly");
7497 SaraTest.assert(saraDefinition.u_sc_item === catItem.sys_id, "u_sc_item is transformed correctly");
7498 SaraTest.assert(saraDefinition.u_service_catalog_category === newCat.sys_id, "u_service_catalog_category is transformed correctly");
7499 SaraTest.assert(saraDefinition.u_var_set === varSet.sys_id, "u_var_set is transformed correctly");
7500 SaraTest.assert(saraDefinition.u_parent === parentCat.sys_id, "u_parent is transformed correctly");
7501 SaraTest.assert(saraDefinition.u_type === "service", "u_type is transformed correctly");
7502 SaraTest.assert(saraDefinition.u_hash === hash1, "u_hash is transformed correctly");
7503 });
7504 }
7505 };
7506})();
7507
7508var SaraTest = (function() {
7509 var indent = "";
7510 var logger = new SaraLog("SaraTest");
7511 var pass = 0;
7512 var fail = 0;
7513 var isIgnore = false;
7514 var ignored = 0;
7515 var continueOnError = true;
7516
7517 var log = function() {
7518 logger.info.apply(logger,arguments);
7519 };
7520
7521 return {
7522 resetSummary: function() {
7523 pass = 0;
7524 fail = 0;
7525 ignored = 0;
7526 },
7527
7528 disableContinueOnError:function() {
7529 continueOnError = false;
7530 },
7531
7532 getSummary: function() {
7533 return {
7534 pass: pass,
7535 fail: fail,
7536 ignore: ignored,
7537 total: pass + fail + ignored
7538 };
7539 },
7540
7541 ignore: function() {
7542 isIgnore = true;
7543 },
7544
7545 assert: function(value, desc) {
7546 var prefix = ">>>PASS: ";
7547 if(!value) {
7548 prefix = "<<<FAIL: ";
7549 }
7550 logger.info("{0}{1}{2}", indent, prefix, desc);
7551 if(!value) {
7552 var exceptionMsg = prefix + desc;
7553 throw new Error(exceptionMsg);
7554 }
7555 },
7556 assertEqual: function(actual, expected, desc) {
7557 var failed = false;
7558 var prefix = ">>>PASS: ";
7559 if(actual != expected) {
7560 prefix = "<<<FAIL: ";
7561 failed = true;
7562 }
7563 logger.info("{0}{1}{2}", indent, prefix, desc);
7564 if(failed) {
7565 logger.info("Expected: {0}; Actual: {1}", expected, actual);
7566 }
7567 if(failed) {
7568 var exceptionMsg = prefix + desc + "; Expected:" + expected + "; Actual: " + actual
7569
7570 throw new Error(exceptionMsg);
7571 }
7572 },
7573 test: function(name, fn) {
7574 indent = "";
7575 logger.info("********************************");
7576 if(isIgnore) {
7577 logger.info("[IGNORE] {0}", name);
7578 isIgnore = false;
7579 ignored++;
7580 return;
7581 }
7582 logger.info("[TEST CASE] {0}", name);
7583 indent = " ";
7584
7585 if(continueOnError) {
7586 try {
7587 fn();
7588 pass++;
7589 }
7590 catch(err) {
7591 gs.error(err);
7592 fail++;
7593 }
7594 }
7595 else {
7596 fn();
7597 pass++;
7598 }
7599
7600 indent = "";
7601 },
7602 type: "SaraTest"
7603 };
7604})();
7605]]></script>
7606 <description>Sara Test Bench</description>
7607 <active>true</active>
7608 <client_callable>false</client_callable>
7609 <access>public</access>
7610 </script_include>
7611</script_includes>
7612
7613
7614 <ui_scripts>
7615 <ui_script>
7616 <script_name>SaraVarSet</script_name>
7617 <script><![CDATA[/**
7618 * Catalog client script for SaraVariableSet
7619 */
7620var x_ausgh_snsc = x_ausgh_snsc || {};
7621x_ausgh_snsc.SaraVarSet = x_ausgh_snsc.SaraVarSet || {};
7622
7623(function (SaraVarSet) {
7624 'use strict';
7625
7626 /**
7627 * OnLoad event handler for Sara variable set
7628 */
7629 SaraVarSet.onLoad = function () {
7630 SaraVarSet.initListCollector();
7631 SaraVarSet.setSelectBoxWidth();
7632 };
7633
7634 /**
7635 * Init collector filter
7636 */
7637 SaraVarSet.initListCollector = function () {
7638 x_ausgh_snsc.log('Start: SaraVarSet.initListCollector');
7639 var messageTables = $$('[id$=_select_0_add_remove_message_table]');
7640 var listWrappers = $$('.list_name');
7641
7642 for (var i = 0, table; table = messageTables[i]; i++) {
7643 var name = table.id.replace('_select_0_add_remove_message_table', '');
7644 var wrapper = listWrappers[i];
7645 var target;
7646 var id;
7647
7648 if (wrapper) {
7649 target = wrapper;
7650 } else {
7651 target = table;
7652 }
7653
7654 id = target.nextSibling.id.replace('IO:', '');
7655
7656 SaraVarSet.getListCollectorData(id, name);
7657 }
7658
7659 x_ausgh_snsc.log('End: SaraVarSet.initListCollector');
7660 };
7661
7662 /**
7663 * Get list collector data from lookup table
7664 * @param {String} id The sys_id of list collector
7665 * @param {String} name The name of list collector
7666 */
7667 SaraVarSet.getListCollectorData = function (id, name) {
7668 var filterFn = name + 'g_filter';
7669 var acRequestFn = name + 'acRequest';
7670
7671 if (window[filterFn] === undefined || window[acRequestFn] === undefined) {
7672 setTimeout(function () {
7673 SaraVarSet.getListCollectorData(id, name);
7674 }, 100);
7675 return;
7676 }
7677
7678 window[filterFn].reset();
7679 window[filterFn].setQuery('u_control_id=' + id);
7680 window[acRequestFn](null);
7681 };
7682
7683 /**
7684 * Make all selecbox's width is 250px for preventing the broken of layout when value of option is too long
7685 */
7686 SaraVarSet.setSelectBoxWidth = function () {
7687 x_ausgh_snsc.log('Start: SaraVarSet.setSelectBoxWidth');
7688 var selectboxes = $$('select.cat_item_option');
7689
7690 for (var i = 0, selectbox; selectbox = selectboxes[i]; i++) {
7691 selectbox.style.width = '250px';
7692 }
7693
7694 x_ausgh_snsc.log('End: SaraVarSet.setSelectBoxWidth');
7695 };
7696
7697})(x_ausgh_snsc.SaraVarSet);
7698]]></script>
7699 <description>Catalog client script for SaraVariableSet</description>
7700 <active>true</active>
7701 <global>false</global>
7702 </ui_script>
7703 <ui_script>
7704 <script_name>SaraCommon</script_name>
7705 <script><![CDATA[/**
7706 * Common client properties for Sara
7707 */
7708var SaraCommon = SaraCommon || {};
7709
7710var x_ausgh_snsc = x_ausgh_snsc || {};
7711x_ausgh_snsc.SaraCommon = x_ausgh_snsc.SaraCommon || {};
7712
7713x_ausgh_snsc.log = function () {
7714 if (typeof (console) !== 'undefined') {
7715 if (navigator.appName === 'Microsoft Internet Explorer') {
7716 if (arguments.length == 1) {
7717 console.log('[SARA]', arguments[0]);
7718 } else if (arguments.length === 2) {
7719 console.log('[SARA]', arguments[0], arguments[1]);
7720 } else if (arguments.length > 2) {
7721 console.log('[SARA]', arguments[0], arguments[1], arguments[2]);
7722 }
7723 } else {
7724 console.log('[SARA]', arguments);
7725 }
7726 }
7727};
7728
7729x_ausgh_snsc.config = x_ausgh_snsc.config || {};
7730
7731(function (SaraCommon) {
7732 'use strict';
7733
7734 SaraCommon.SCOPED_APP = 'x_ausgh_snsc';
7735
7736 SaraCommon.CONFIG_NAME = {
7737 CLIENT_ID: 'client_id',
7738 CLIENT_SECRET: 'client_secret',
7739 TECHNICAL_USER: 'technical_user',
7740 SAPI_ENDPOINT: 'sapi_endpoint',
7741 TOKEN_ENDPOINT: 'token_endpoint',
7742 AUTH_ENDPOINT: 'auth_endpoint'
7743 };
7744
7745 SaraCommon.CONTROL_NAME = {
7746 CLIENT_SCRIPTS: 'sara_client_scripts',
7747 HIDDEN_CONTROL: 'sara_hidden_control'
7748 };
7749
7750})(x_ausgh_snsc.SaraCommon);
7751]]></script>
7752 <description>Common client properties for Sara</description>
7753 <active>true</active>
7754 <global>false</global>
7755 </ui_script>
7756 <ui_script>
7757 <script_name>SaraOAuth</script_name>
7758 <script><![CDATA[/**
7759 * Client script for OAuth integration
7760 */
7761var x_ausgh_snsc = x_ausgh_snsc || {};
7762x_ausgh_snsc.SaraOAuth = x_ausgh_snsc.SaraOAuth || {};
7763
7764(function (SaraOAuth) {
7765 'use strict';
7766
7767 /**
7768 * Login to OAuth server for authentication
7769 * @param {String} clientId The client ID of OAuth Server
7770 * @param {String} technicalUser The tecnical user who owns the tokens
7771 * @param {String} authEndpoint The authorization endpoint of OAuth Server
7772 * @param {Object} callback The callback object contains onSuccess and onFail handler
7773 */
7774 SaraOAuth.login = function (clientId, technicalUser, authEndpoint, callback) {
7775 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?')) {
7776 SaraOAuth.processSuccess = null;
7777 SaraOAuth.processFail = null;
7778
7779 if (SaraOAuth.win) {
7780 SaraOAuth.win.close();
7781 }
7782 SaraOAuth.win = null;
7783
7784 var ga = new x_ausgh_snsc.SaraGlideAjax('SaraOAuthAjax', 'Getting OAuth url...');
7785 ga.addParam('sysparm_name', 'getOAuthUrl');
7786 ga.addParam('sysparm_client_id', clientId);
7787 ga.addParam('sysparm_technical_user', technicalUser);
7788 ga.addParam('sysparm_auth_endpoint', authEndpoint);
7789 ga.getXML(function (response) {
7790 if (callback && callback.onSuccess && typeof (callback.onSuccess) == 'function') {
7791 SaraOAuth.processSuccess = callback.onSuccess;
7792 }
7793
7794 if (callback && callback.onFail && typeof (callback.onFail) == 'function') {
7795 SaraOAuth.processFail = callback.onFail;
7796 }
7797
7798 var w = 500;
7799 var h = 600;
7800
7801 var left = (screen.width / 2) - (w / 2);
7802 var top = (screen.height / 2) - (h / 2);
7803
7804 var url = response.responseXML.documentElement.getAttribute('answer');
7805 SaraOAuth.win = window.open(url, 'aelogin', 'width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
7806 });
7807 }
7808 };
7809
7810 /**
7811 * Process response from OAuth server. If is 'ok', will call SaraOAuth.processSuccess callback.
7812 * If is not 'ok', will log the answer and alert message.
7813 * @param {*} response The response
7814 */
7815 SaraOAuth.processResponse = function (response) {
7816 if (SaraOAuth.win) {
7817 SaraOAuth.win.close();
7818 }
7819
7820 x_ausgh_snsc.log('Callback response is: ' + response);
7821
7822 if (response === 'ok') {
7823 if (SaraOAuth.processSuccess && typeof (SaraOAuth.processSuccess) == 'function') {
7824 SaraOAuth.processSuccess();
7825 }
7826 } else {
7827 var msg;
7828
7829 if (typeof (response) == 'string' && response.match('^function') != 'function') {
7830 msg = x_ausgh_snsc.SaraUtils.formatString('Token request finished unsuccessfully{0}. Please try again later or contact administrators.', response ? (', error: ' + response) : '');
7831 } else {
7832 msg = 'Token request finished unsuccessfully! Please try again later or contact administrators.';
7833 }
7834
7835 alert(msg);
7836
7837 if (SaraOAuth.processFail && typeof (SaraOAuth.processFail) == 'function') {
7838 SaraOAuth.processFail();
7839 }
7840
7841 x_ausgh_snsc.log(msg);
7842 }
7843 };
7844
7845 /**
7846 * Get configuration
7847 * @param {Function} callback The callback will be called when getting configuration
7848 * successfully with parametter is object with same keys with x_ausgh_snsc.SaraCommon.CONFIG_NAME
7849 */
7850 SaraOAuth.getConfig = function (callback) {
7851 var configData = {};
7852 var ga = new x_ausgh_snsc.SaraGlideAjax('SaraOAuthAjax', 'Getting OAuth configuration...');
7853 ga.addParam('sysparm_name', 'getConfig');
7854
7855 ga.getXML(function (resp) {
7856 var config = resp.responseXML.getElementsByTagName('config')[0];
7857
7858 for (var key in x_ausgh_snsc.SaraCommon.CONFIG_NAME) {
7859 var name = x_ausgh_snsc.SaraCommon.CONFIG_NAME[key];
7860
7861 configData[name] = config.getAttribute(name);
7862 }
7863
7864 callback.call(this, configData);
7865 });
7866 };
7867
7868 /**
7869 * Check OAuth Token of current technical user is invalid, expired or empty
7870 * @param {String} technicalUser The tecnical user who owns the tokens
7871 * @param {String} sapiEndpoint The SAPI endpoint
7872 * @param {Boolean} hideWizardSubmit Hide submit button of wizard or not when token is empty, expired
7873 * or invalid
7874 * @param {Object<String, Function>} callback The callback object contains callbacks when valid,
7875 * invalid, error:
7876 * - onValid(); // Will be called when tokens are existed and valid.
7877 * - onInvalid(); // Will be called when tokens are existed but invalid.
7878 * - onError(errorMessage); // Will be called when have any error. 'errorMessage' is error message
7879 * - onExisted(); // Will be called if current technical user has tokens but not validate the token yet.
7880 * SaraCommon.TABLE_NAME.SARA_OAUTH table
7881 */
7882 SaraOAuth.checkOAuthToken = function (technicalUser, sapiEndpoint, hideWizardSubmit, callback) {
7883 x_ausgh_snsc.log('checkOAuthToken', technicalUser, sapiEndpoint, hideWizardSubmit, callback);
7884
7885 var ga = new x_ausgh_snsc.SaraGlideAjax('SaraOAuthAjax', 'Validating token...');
7886 ga.addParam('sysparm_name', 'validateToken');
7887 ga.addParam('sysparm_technical_user', technicalUser);
7888 ga.addParam('sysparm_sapi_endpoint', sapiEndpoint);
7889
7890 ga.getXML(function (resp) {
7891 var result = resp.responseXML.getElementsByTagName('result')[0];
7892
7893 if (result) {
7894 var isValid = result.getAttribute('isValid');
7895
7896 // Valid
7897 if (isValid === 'true') {
7898 if (hideWizardSubmit) {
7899 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(true);
7900 }
7901
7902 x_ausgh_snsc.log('Access token is valid');
7903
7904 if (typeof callback.onValid === 'function') {
7905 callback.onValid.call(this);
7906 }
7907
7908 // Invalid
7909 } else if (isValid === 'false') {
7910 if (hideWizardSubmit) {
7911 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(false);
7912 }
7913
7914 x_ausgh_snsc.log('Access token is invalid');
7915
7916 if (typeof callback.onInvalid === 'function') {
7917 callback.onInvalid.call(this);
7918 }
7919
7920 // Error
7921 } else {
7922 var errorMessage = result.getAttribute('message');
7923 x_ausgh_snsc.log(errorMessage);
7924
7925
7926 if (typeof callback.onError === 'function') {
7927 callback.onError.call(this, errorMessage);
7928 }
7929 }
7930 } else {
7931 var error = resp.responseXML.getElementsByTagName('error')[0];
7932 var errorMessage;
7933
7934 if (error) {
7935 errorMessage = error.getAttribute('message');
7936 }
7937
7938 if (typeof callback.onError === 'function') {
7939 callback.onError.call(this, errorMessage);
7940 }
7941 }
7942 });
7943 };
7944
7945})(x_ausgh_snsc.SaraOAuth);
7946]]></script>
7947 <description>Client script for OAuth integration</description>
7948 <active>true</active>
7949 <global>false</global>
7950 </ui_script>
7951 <ui_script>
7952 <script_name>SaraUtils</script_name>
7953 <script><![CDATA[/**
7954 * Sara Utilities
7955 */
7956var x_ausgh_snsc = x_ausgh_snsc || {};
7957x_ausgh_snsc.SaraUtils = x_ausgh_snsc.SaraUtils || {};
7958
7959(function (SaraUtils) {
7960 'use strict';
7961
7962 /**
7963 * Format strings
7964 * @method format
7965 * @param {String} string The template string
7966 * @param {String[]} args Zero or more objects to format, supplied either in a comma-delimited list or as an array
7967 */
7968 SaraUtils.formatString = function (string) {
7969 var args = Array.prototype.slice.call(arguments, 1);
7970
7971 return string.replace(/{(\d+)}/g, function (match, number) {
7972 return typeof args[number] != 'undefined' ? args[number] : match;
7973 });
7974 };
7975
7976 /**
7977 * Get parameter value in current URL
7978 * @param {String} name The name of parameter
7979 * @return {String}
7980 */
7981 SaraUtils.getParmVal = function (name) {
7982 name = name.replace(/[\[]/, '\\\[').replace(/[\]]/, '\\\]');
7983 var regexS = '[\\?&]' + name + '=([^&#]*)';
7984 var regex = new RegExp(regexS);
7985 var results = regex.exec(window.location.href);
7986
7987 if (results == null) {
7988 return '';
7989 } else {
7990 return unescape(results[1]);
7991 }
7992 };
7993
7994 /**
7995 * Hide/show submit button of wizard
7996 * @param {Boolean} isVisible Submit button is visible or not
7997 */
7998 SaraUtils.setWizardSubmitVisible = function (isVisible) {
7999 document.getElementById('expert_next').style.display = isVisible ? '' : 'none';
8000 };
8001
8002 /**
8003 * Set visible of a form control
8004 * @param {String} name Name of control
8005 * @param {Boolean} isVisible Control is hidden or visible
8006 */
8007 SaraUtils.setFormControlVisible = function (name, isVisible) {
8008 if (g_form) {
8009 g_form.setDisplay(name, isVisible);
8010 }
8011 }
8012
8013})(x_ausgh_snsc.SaraUtils);
8014]]></script>
8015 <description>Sara Utilities</description>
8016 <active>true</active>
8017 <global>false</global>
8018 </ui_script>
8019 <ui_script>
8020 <script_name>SaraGlideAjax</script_name>
8021 <script><![CDATA[/**
8022 * Helper class wraps GlideAjax class of ServiceNow and provide Loading Dialog with custom title
8023 */
8024var x_ausgh_snsc = x_ausgh_snsc || {};
8025x_ausgh_snsc.SaraGlideAjax = x_ausgh_snsc.SaraGlideAjax || Class.create();
8026
8027(function (SaraGlideAjax) {
8028 'use strict';
8029
8030 SaraGlideAjax.prototype = {
8031 /**
8032 * Initialize SaraGlideAjax
8033 * @param {String} className The class name of callable Script Include
8034 * @param {String} title The title of loading dialog
8035 */
8036 initialize: function (className, title) {
8037 this.title = title;
8038 this.ga = new GlideAjax(className);
8039 this.ga.addParam('sysparm_scope', x_ausgh_snsc.SaraCommon.SCOPED_APP);
8040 this.className = className;
8041 },
8042
8043 /**
8044 * Add parameter for GlideAjax
8045 * @param {String} key The key of parameter
8046 * @param {String} value The value of parameter
8047 */
8048 addParam: function (key, value) {
8049 this.ga.addParam(key, value);
8050 },
8051
8052 /**
8053 * Get XML response from server
8054 * @param {Function} callback The callback will be call after getting response from server
8055 */
8056 getXML: function (callback) {
8057 var loadingDialog = new GlideDialogWindow('hierarchical_progress_viewer');
8058 loadingDialog.hideCloseButton();
8059 loadingDialog.setTitle(this.title);
8060
8061 var className = this.className;
8062 x_ausgh_snsc.log('Sending request to ' + className + '...');
8063
8064 this.ga.getXML(function (response) {
8065 loadingDialog.destroy();
8066 x_ausgh_snsc.log('Got response from ' + className, response);
8067
8068 if (typeof callback === 'function') {
8069 callback.apply(this, arguments);
8070 }
8071 });
8072 },
8073
8074 type: 'SaraGlideAjax'
8075 };
8076
8077})(x_ausgh_snsc.SaraGlideAjax);
8078]]></script>
8079 <description>Helper class wraps GlideAjax class of ServiceNow and provide Loading Dialog with custom title</description>
8080 <active>true</active>
8081 <global>false</global>
8082 </ui_script>
8083</ui_scripts>
8084
8085
8086 <ui_pages>
8087 <ui_page>
8088 <name>sara_oauth_callback</name>
8089 <description>OAuth Redirection Endpoint</description>
8090 <category>general</category>
8091 <html><![CDATA[<?xml version="1.0" encoding="utf-8" ?>
8092<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
8093 <g:requires name="x_ausgh_snsc.SaraCommon.jsdbx" params="cache=$[jvar_stamp]" />
8094 <g:requires name="x_ausgh_snsc.SaraGlideHelper.jsdbx" params="cache=$[jvar_stamp]" />
8095 <g:requires name="x_ausgh_snsc.SaraGlideAjax.jsdbx" params="cache=$[jvar_stamp]" />
8096 <g:requires name="x_ausgh_snsc.SaraOAuth.jsdbx" params="cache=$[jvar_stamp]" />
8097 <g:requires name="x_ausgh_snsc.SaraUtils.jsdbx" params="cache=$[jvar_stamp]" />
8098 <g:requires name="x_ausgh_snsc.SaraVarSet.jsdbx" params="cache=$[jvar_stamp]" />
8099
8100 <g:ui_form>
8101 <p>
8102 <label>Please wait, processing...</label>
8103 </p>
8104 </g:ui_form>
8105</j:jelly>
8106]]></html>
8107 <client_script><![CDATA[var parentWin = (window.opener && window.opener.x_ausgh_snsc.SaraOAuth) ? window.opener : window.parent;
8108
8109if (!parentWin || !parentWin.x_ausgh_snsc || !parentWin.x_ausgh_snsc.SaraOAuth || !parentWin.x_ausgh_snsc.SaraOAuth.processResponse || typeof(parentWin.x_ausgh_snsc.SaraOAuth.processResponse) !== 'function') {
8110 window.location.href = '/home.do';
8111} else {
8112 var code = x_ausgh_snsc.SaraUtils.getParmVal('code');
8113 x_ausgh_snsc.log('Code: ' + code);
8114
8115 if (code) {
8116 var clientId = parentWin.x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_ID];
8117 var clientSecret = parentWin.x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_SECRET];
8118 var technicalUser = parentWin.x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER];
8119 var tokenEndpoint = parentWin.x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT];
8120
8121 x_ausgh_snsc.log('Client ID: ' + clientId, 'Client Secret: ' + clientSecret, 'Token Endpoint: ' + tokenEndpoint)
8122
8123 // Invoke x_ausgh_snsc.SaraOAuthAjax to exchange code for tokens
8124 x_ausgh_snsc.log('Init GlideAjax for requesting token by code...');
8125 var ga = new x_ausgh_snsc.SaraGlideAjax('SaraOAuthAjax', 'Requesting token by code...');
8126 ga.addParam('sysparm_name', 'requestTokenByCode');
8127 ga.addParam('sysparm_code', code);
8128 ga.addParam('sysparm_client_id', clientId);
8129 ga.addParam('sysparm_client_secret', clientSecret);
8130 ga.addParam('sysparm_technical_user', technicalUser);
8131 ga.addParam('sysparm_token_endpoint', tokenEndpoint);
8132
8133 ga.getXML(function (response) {
8134 var answer = response.responseXML.documentElement.getAttribute('answer');
8135 parentWin.x_ausgh_snsc.SaraOAuth.processResponse(answer);
8136 });
8137 } else {
8138 x_ausgh_snsc.log('Code is empty!');
8139 parentWin.x_ausgh_snsc.SaraOAuth.processResponse();
8140 }
8141}
8142]]></client_script>
8143 <processing_script/>
8144 </ui_page>
8145</ui_pages>
8146
8147
8148 <ui_macros>
8149 <ui_macro>
8150 <name>sara_hidden_control</name>
8151 <description>UI Marco for Sara Hidden Control</description>
8152 <category>catalog</category>
8153 <active>true</active>
8154 <media_type/>
8155 <xml><![CDATA[<?xml version="1.0" encoding="utf-8" ?>
8156<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
8157 <script type="text/javascript">
8158 $j(function () {
8159 x_ausgh_snsc.SaraUtils.setFormControlVisible(x_ausgh_snsc.SaraCommon.CONTROL_NAME.HIDDEN_CONTROL, false);
8160 x_ausgh_snsc.SaraVarSet.onLoad();
8161 });
8162 </script>
8163</j:jelly>
8164]]></xml>
8165 </ui_macro>
8166 <ui_macro>
8167 <name>sara_client_scripts</name>
8168 <description/>
8169 <category>catalog</category>
8170 <active>true</active>
8171 <media_type/>
8172 <xml><![CDATA[<?xml version="1.0" encoding="utf-8" ?>
8173<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
8174 <g:requires name="x_ausgh_snsc.SaraCommon.jsdbx" params="cache=$[jvar_stamp]" />
8175 <g:requires name="x_ausgh_snsc.SaraGlideAjax.jsdbx" params="cache=$[jvar_stamp]" />
8176 <g:requires name="x_ausgh_snsc.SaraOAuth.jsdbx" params="cache=$[jvar_stamp]" />
8177 <g:requires name="x_ausgh_snsc.SaraUtils.jsdbx" params="cache=$[jvar_stamp]" />
8178 <g:requires name="x_ausgh_snsc.SaraVarSet.jsdbx" params="cache=$[jvar_stamp]" />
8179
8180 <script type="text/javascript">
8181 $j(function () {
8182 x_ausgh_snsc.SaraUtils.setFormControlVisible(x_ausgh_snsc.SaraCommon.CONTROL_NAME.CLIENT_SCRIPTS, false);
8183 });
8184 </script>
8185</j:jelly>
8186]]></xml>
8187 </ui_macro>
8188</ui_macros>
8189
8190
8191 <workflows>
8192 <workflow>
8193 <name>Sara Service</name>
8194 <description>Sara Service workflow</description>
8195 <start>begin</start>
8196 <table>sc_req_item</table>
8197 <active>true</active>
8198 <published>true</published>
8199 <max_activity_count>100000</max_activity_count>
8200
8201
8202 <stages>
8203 <stage>
8204 <name>Initializing</name>
8205 <order>100</order>
8206 <value>initializing</value>
8207 <ola/>
8208 </stage>
8209 <stage>
8210 <name>Transferring</name>
8211 <order>200</order>
8212 <value>transferring</value>
8213 <ola/>
8214 </stage>
8215 <stage>
8216 <name>Transferred</name>
8217 <order>300</order>
8218 <value>transferred</value>
8219 <ola/>
8220 </stage>
8221 <stage>
8222 <name>Transfer Failed</name>
8223 <order>300</order>
8224 <value>transfer_failed</value>
8225 <ola/>
8226 </stage>
8227 <stage>
8228 <name>Consume Failed</name>
8229 <order>400</order>
8230 <value>consume_failed</value>
8231 <ola/>
8232 </stage>
8233 <stage>
8234 <name>Running</name>
8235 <order>500</order>
8236 <value>running</value>
8237 <ola/>
8238 </stage>
8239 <stage>
8240 <name>Ended OK</name>
8241 <order>900</order>
8242 <value>ended_ok</value>
8243 <ola/>
8244 </stage>
8245 <stage>
8246 <name>Ended Failed</name>
8247 <order>900</order>
8248 <value>ended_failed</value>
8249 <ola/>
8250 </stage>
8251 <stage>
8252 <name>Completed</name>
8253 <order>1000</order>
8254 <value>completed</value>
8255 <ola/>
8256 </stage>
8257</stages>
8258
8259
8260
8261 <activities>
8262 <activity>
8263 <name>Begin</name>
8264 <activity_definition>Begin</activity_definition>
8265 <stage/>
8266 <width/>
8267 <height/>
8268 <x>1</x>
8269 <y>1</y>
8270 <snsc_name>begin</snsc_name>
8271 </activity>
8272
8273 <activity>
8274 <name>Check item's price is 0 or not?</name>
8275 <activity_definition>If</activity_definition>
8276 <stage/>
8277 <width/>
8278 <height/>
8279 <x>1</x>
8280 <y>2</y>
8281 <snsc_name>check_price</snsc_name>
8282 <variables>
8283 <variable>
8284 <name>script</name>
8285 <value><![CDATA[function ifScript() {
8286 var item = (new x_ausgh_snsc.SaraGlideHelper()).getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SN_CATALOG_ITEM, {
8287 'sys_id': current.cat_item.sys_id
8288 });
8289
8290 if ((item.price.toString()) === '0') {
8291 return 'yes';
8292 }
8293
8294 return 'no';
8295}
8296
8297answer = ifScript();
8298]]></value>
8299 </variable>
8300 <variable>
8301 <name>advanced</name>
8302 <value>1</value>
8303 </variable>
8304 </variables>
8305 </activity>
8306
8307 <activity>
8308 <name>Waiting for approval</name>
8309 <activity_definition>Approval - Group</activity_definition>
8310 <stage/>
8311 <width/>
8312 <height/>
8313 <x>1</x>
8314 <y>3</y>
8315 <snsc_name>waiting_for_approval</snsc_name>
8316 <variables>
8317 <variable>
8318 <name>wait_for</name>
8319 <value>first_any</value>
8320 </variable>
8321 <variable>
8322 <name>reject_handling</name>
8323 <value>reject</value>
8324 </variable>
8325 </variables>
8326 </activity>
8327
8328 <activity>
8329 <name>Approved</name>
8330 <activity_definition>Approval Action</activity_definition>
8331 <stage/>
8332 <width/>
8333 <height/>
8334 <x>2</x>
8335 <y>3</y>
8336 <snsc_name>approved</snsc_name>
8337 <variables>
8338 <variable>
8339 <name>action</name>
8340 <value>approved</value>
8341 </variable>
8342 </variables>
8343 </activity>
8344
8345 <activity>
8346 <name>Rejected</name>
8347 <activity_definition>Approval Action</activity_definition>
8348 <stage/>
8349 <width/>
8350 <height/>
8351 <x>1</x>
8352 <y>4</y>
8353 <snsc_name>rejected</snsc_name>
8354 <variables>
8355 <variable>
8356 <name>action</name>
8357 <value>rejected</value>
8358 </variable>
8359 </variables>
8360 </activity>
8361
8362 <activity>
8363 <name>Initializing</name>
8364 <activity_definition>Timer</activity_definition>
8365 <stage>initializing</stage>
8366 <width/>
8367 <height/>
8368 <x>3</x>
8369 <y>3</y>
8370 <snsc_name>initializing</snsc_name>
8371 <variables>
8372 <variable>
8373 <name>timer_type</name>
8374 <value>script</value>
8375 </variable>
8376 <variable>
8377 <name>script</name>
8378 <value><![CDATA[workflow.info('Initializing ...');
8379var currentUser = current.opened_by.user_name.toString();
8380workflow.info('Workflow started by {0}', currentUser);
8381workflow.scratchpad.openedBy = currentUser;
8382
8383var technicalUser = new x_ausgh_snsc.SaraConfig().getTechnicalUser();
8384workflow.info('Technical user: {0}', technicalUser);
8385workflow.scratchpad.technicalUser = technicalUser;
8386
8387// Set 'answer' to the number of seconds this timer should wait
8388answer = 2;
8389]]></value>
8390 </variable>
8391 </variables>
8392 </activity>
8393
8394 <activity>
8395 <name>Invoke Consume URL</name>
8396 <activity_definition>Run Script</activity_definition>
8397 <stage>transferring</stage>
8398 <width/>
8399 <height/>
8400 <x>4</x>
8401 <y>3</y>
8402 <snsc_name>invoke_consume</snsc_name>
8403 <variables>
8404 <variable>
8405 <name>script</name>
8406 <value><![CDATA[var restClient = new x_ausgh_snsc.SaraRESTClient();
8407restClient.setMIDServer(x_ausgh_snsc.SaraUtils.getMIDServer());
8408var oauthClient = new x_ausgh_snsc.SaraOAuthClient(restClient);
8409var glideHelper = new x_ausgh_snsc.SaraGlideHelper();
8410
8411// Get tokens, store tokens in workflow scratchpad
8412var tokens = oauthClient.getUserTokens(workflow.scratchpad.technicalUser);
8413
8414if (!tokens) {
8415 workflow.info('Cannot find access tokens for this user "{0}". Order will be skipped', workflow.scratchpad.technicalUser);
8416} else {
8417 workflow.scratchpad.executionHref = null;
8418 workflow.scratchpad.isTransfered = false;
8419
8420 // get service name & consume URL
8421 var serviceName, consumeUrl, varSetId;
8422 var catId = current.cat_item.sys_id;
8423 var saraItem = glideHelper.getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SARA_DEFINITION, {
8424 'u_sc_item': catId
8425 });
8426
8427 if (saraItem) {
8428 serviceName = saraItem['u_name'];
8429 consumeUrl = saraItem['u_consume_url'];
8430 varSetId = saraItem['u_var_set'];
8431
8432 consumeUrl = x_ausgh_snsc.SaraUtils.buildUrl(consumeUrl);
8433
8434 workflow.info('Service name = {0}', serviceName);
8435 workflow.info('Consume URL = {0}', consumeUrl);
8436 workflow.info('Cat item = {0}', current.cat_item.name);
8437
8438 var payload = {};
8439 var payloadFields = {};
8440 payload.fieldvalues = payloadFields;
8441
8442 if (varSetId) {
8443 var saraVariables = glideHelper.getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SARA_VARIABLE, {
8444 'variable_set': varSetId
8445 }, true);
8446
8447 for (var i = 0, variable; variable = saraVariables[i]; i++) {
8448 var variableName = variable['name'];
8449
8450 if (variableName !== x_ausgh_snsc.SaraCommon.CONTROL_NAME.CLIENT_SCRIPTS
8451 && variableName !== x_ausgh_snsc.SaraCommon.CONTROL_NAME.HIDDEN_CONTROL
8452 && variable['u_name']) {
8453
8454 var currentVariable = current.variables[variableName];
8455 var currentValue;
8456
8457 if (variable['type'] === x_ausgh_snsc.SaraCommon.VAR_TYPE.LIST_COLLECTOR.toString()) {
8458 var values = currentVariable.toString().split(',');
8459 currentValue = [];
8460
8461 for (var j = 0, value; value = values[j]; j++) {
8462 var realValue = glideHelper.getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SARA_LOOKUP, {
8463 'sys_id': value
8464 });
8465
8466 currentValue.push(realValue['u_display_name']);
8467 }
8468 } else {
8469 currentValue = [currentVariable.getDisplayValue()];
8470 }
8471
8472 payloadFields[variable['u_name']] = currentValue;
8473 }
8474 }
8475 } else {
8476 workflow.info('There is no variables in catalog item (sys_id = {0})', catId);
8477 }
8478
8479 //---------------- audit information ---------------
8480 workflow.info('Add audit information');
8481
8482 var payloadParams = {};
8483 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.ORDER_ID] = current.request.number.toString();
8484 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.ORDER_TIMESTAMP] = current.sys_created_on.toString();
8485 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.ORDER_NAME] = current.sys_created_by.toString();
8486
8487 var approvalHistory = '<<Auto Approval>>';
8488
8489 if(current.approval_history != null) {
8490 var journal = glideHelper.getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SN_JOURNAL_FIELD, {
8491 'element_id' : current.sys_id
8492 });
8493 if(journal != null) {
8494 approvalHistory = journal.value.toString();
8495 }
8496 }
8497
8498 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.APPROVAL_HISTORY] = approvalHistory;
8499 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.APPROVAL_TIMESTAMP] = current.approval_set.toString();
8500
8501 payload.parametervalues = payloadParams;
8502 //--------------- /audit information ---------------
8503
8504 var payloadStr = x_ausgh_snsc.SaraJSON.stringify(payload);
8505 workflow.info(payloadStr);
8506
8507 // Make request
8508 if (serviceName) {
8509 workflow.info('Invoking consume URL...');
8510
8511 var request = restClient.newSAPIRequest('post', consumeUrl);
8512 request.setContent('${payload}');
8513 request.addHeader('content-type', 'application/json;charset=UTF-8');
8514 request.setStringParameterNoEscape('payload', payloadStr);
8515
8516 // Add Authorization header
8517 request.addHeader('Authorization', tokens[3] + ' ' + tokens[0]);
8518
8519 var response = restClient.executeWithRefreshToken(request);
8520 var responseObject = response.getResponseObject();
8521
8522 if (response.haveError()) {
8523 workflow.info('Order process FAILED.');
8524 } else {
8525 workflow.info('Successfully transfered.');
8526 workflow.info('Response: {0}', response.getBody());
8527 var resObj = x_ausgh_snsc.SaraJSON.parse(response.getBody());
8528 var runId = resObj['runID'];
8529
8530 workflow.scratchpad.isTransfered = true;
8531
8532 if (runId !== undefined) {
8533 var executionHref = resObj['_links']['self']['href'];
8534 workflow.info('Got runId: {0}', runId.toString());
8535 workflow.info('Got execution href: {0}', executionHref);
8536 workflow.scratchpad.runId = runId;
8537 workflow.scratchpad.executionHref = executionHref;
8538
8539 // save runId to the 'correlation_id' column of current record in 'sc_req_item' table
8540 current['correlation_id'] = '' + runId;
8541 current.update();
8542 } else {
8543 workflow.info(resObj.message);
8544 }
8545 }
8546
8547 } else {
8548 workflow.info('Failed to make consume request as no service definition was defined.');
8549 }
8550 } else {
8551 workflow.info('Catalog item (sys_id = {0}) doesn\'t existed any more in {1}!', [catId, x_ausgh_snsc.SaraCommon.TABLE_NAME.SARA_DEFINITION]);
8552 }
8553}
8554]]></value>
8555 </variable>
8556 </variables>
8557 </activity>
8558
8559 <activity>
8560 <name>Check transfer result</name>
8561 <activity_definition>If</activity_definition>
8562 <stage>transferred</stage>
8563 <width/>
8564 <height/>
8565 <x>5</x>
8566 <y>3</y>
8567 <snsc_name>check_transfer</snsc_name>
8568 <variables>
8569 <variable>
8570 <name>script</name>
8571 <value><![CDATA[// This script needs to set answer to 'yes' or 'no' to indicate the state of the activity.
8572//
8573// For example,
8574//
8575answer = ifScript();
8576
8577function ifScript() {
8578 return (workflow.scratchpad.isTransfered == true ? 'yes' : 'no');
8579}
8580]]></value>
8581 </variable>
8582 <variable>
8583 <name>advanced</name>
8584 <value>1</value>
8585 </variable>
8586 </variables>
8587 </activity>
8588
8589 <activity>
8590 <name>Transfer Request Failed</name>
8591 <activity_definition>Log Message</activity_definition>
8592 <stage>transfer_failed</stage>
8593 <width/>
8594 <height/>
8595 <x>5</x>
8596 <y>4</y>
8597 <snsc_name>transfer_failed</snsc_name>
8598 <variables>
8599 <variable>
8600 <name>message</name>
8601 <value>Transfer request failed, order skipped.</value>
8602 </variable>
8603 </variables>
8604 </activity>
8605
8606 <activity>
8607 <name>Check consume result</name>
8608 <activity_definition>If</activity_definition>
8609 <stage>transferred</stage>
8610 <width/>
8611 <height/>
8612 <x>6</x>
8613 <y>4</y>
8614 <snsc_name>check_consume</snsc_name>
8615 <variables>
8616 <variable>
8617 <name>script</name>
8618 <value><![CDATA[// This script needs to set answer to 'yes' or 'no' to indicate the state of the activity.
8619//
8620// For example,
8621//
8622answer = ifScript();
8623
8624function ifScript() {
8625 return (workflow.scratchpad.executionHref != null ? 'yes' : 'no');
8626}
8627]]></value>
8628 </variable>
8629 <variable>
8630 <name>advanced</name>
8631 <value>1</value>
8632 </variable>
8633 </variables>
8634 </activity>
8635
8636 <activity>
8637 <name>Consume Request Failed</name>
8638 <activity_definition>Log Message</activity_definition>
8639 <stage>consume_failed</stage>
8640 <width/>
8641 <height/>
8642 <x>6</x>
8643 <y>5</y>
8644 <snsc_name>consume_failed</snsc_name>
8645 <variables>
8646 <variable>
8647 <name>message</name>
8648 <value>Consume request failed, order skipped.</value>
8649 </variable>
8650 </variables>
8651 </activity>
8652
8653 <activity>
8654 <name>Workflow Timer</name>
8655 <activity_definition>Timer</activity_definition>
8656 <stage>running</stage>
8657 <width/>
8658 <height/>
8659 <x>7</x>
8660 <y>5</y>
8661 <snsc_name>workflow_timer</snsc_name>
8662 <variables>
8663 <variable>
8664 <name>timer_type</name>
8665 <value>script</value>
8666 </variable>
8667 <variable>
8668 <name>script</name>
8669 <value><![CDATA[if (workflow.scratchpad.delay === undefined) {
8670 var delay = +x_ausgh_snsc.SaraUtils.getSaraProperty(SaraCommon.SYSTEM_PROPERTY_NAME.WORKFLOW_DELAY);
8671 var timeout = +x_ausgh_snsc.SaraUtils.getSaraProperty(SaraCommon.SYSTEM_PROPERTY_NAME.WORKFLOW_TIMEOUT);
8672
8673 // If delay time in config is equal or lesser than 0, let make it '60'
8674 if (delay <= 0) {
8675 delay = 60;
8676 }
8677
8678 // Make sure that timeout minimum always be '0'
8679 if (timeout < 0) {
8680 timeout = 0;
8681 }
8682
8683 workflow.scratchpad.counter = 1;
8684 workflow.scratchpad.maxCount = (timeout / delay) + 1;
8685 workflow.scratchpad.delay = delay;
8686 workflow.scratchpad.timeout = timeout;
8687}
8688
8689answer = workflow.scratchpad.delay;
8690]]></value>
8691 </variable>
8692 </variables>
8693 </activity>
8694
8695 <activity>
8696 <name>Retrieve Execution Status</name>
8697 <activity_definition>Run Script</activity_definition>
8698 <stage>running</stage>
8699 <width/>
8700 <height/>
8701 <x>8</x>
8702 <y>5</y>
8703 <snsc_name>retrieve_status</snsc_name>
8704 <variables>
8705 <variable>
8706 <name>script</name>
8707 <value><![CDATA[var restClient = new x_ausgh_snsc.SaraRESTClient();
8708restClient.setMIDServer(x_ausgh_snsc.SaraUtils.getMIDServer());
8709var oauthClient = new x_ausgh_snsc.SaraOAuthClient(restClient);
8710var executionHref = x_ausgh_snsc.SaraUtils.buildUrl(workflow.scratchpad.executionHref);
8711
8712workflow.scratchpad.ended = 'unknown';
8713
8714// Get tokens, store tokens in workflow scratchpad
8715var tokens = oauthClient.getUserTokens(workflow.scratchpad.technicalUser);
8716var request = restClient.newSAPIRequest('get', executionHref);
8717request.addHeader('Authorization', tokens[3] + ' ' + tokens[0]);
8718
8719workflow.info('[{0}] Waiting for execution checking response ...', workflow.scratchpad.counter);
8720var response = restClient.executeWithRefreshToken(request);
8721var responseObject = response.getResponseObject();
8722
8723if (response.haveError()) {
8724 workflow.warn('Status code: {0}, error message: {1}', [responseObject.statusCode, responseObject.errorMessage]);
8725
8726 workflow.info('Stop retrieving execution status now.');
8727} else {
8728 workflow.info('Response received: {0}', response.getBody());
8729 var resObj = responseObject.bodyObject;
8730 var statusCode = resObj.statusCode;
8731 workflow.info('Status code: {0}, statusText: {1}', [statusCode.toString(), resObj.statusText]);
8732
8733 if (statusCode >= 1800) {
8734 if (statusCode === x_ausgh_snsc.SaraCommon.WORKFLOW_STATUS_CODE.ENDED_OK) {
8735 workflow.info('Execution finished successfully!');
8736 workflow.scratchpad.ended = 'ENDED_OK';
8737 } else {
8738 workflow.scratchpad.ended = statusCode + ' - ' + resObj.statusText;
8739 }
8740 }
8741}
8742
8743workflow.scratchpad.counter++;
8744]]></value>
8745 </variable>
8746 </variables>
8747 </activity>
8748
8749 <activity>
8750 <name>Check Timeout</name>
8751 <activity_definition>If</activity_definition>
8752 <stage>running</stage>
8753 <width/>
8754 <height/>
8755 <x>9</x>
8756 <y>5</y>
8757 <snsc_name>check_timeout</snsc_name>
8758 <variables>
8759 <variable>
8760 <name>script</name>
8761 <value><![CDATA[function ifScript() {
8762 var counter = workflow.scratchpad.counter;
8763 var maxCount = workflow.scratchpad.maxCount;
8764 var timeout = workflow.scratchpad.timeout;
8765
8766 if (timeout === 0) {
8767 if (workflow.scratchpad.ended !== 'unknown') {
8768 return 'yes';
8769 }
8770 } else {
8771 if (counter <= maxCount) {
8772 if (workflow.scratchpad.ended !== 'unknown') {
8773 return 'yes';
8774 }
8775 } else {
8776 return 'yes';
8777 }
8778 }
8779
8780 return 'no';
8781}
8782
8783answer = ifScript();
8784]]></value>
8785 </variable>
8786 <variable>
8787 <name>advanced</name>
8788 <value>1</value>
8789 </variable>
8790 </variables>
8791 </activity>
8792
8793 <activity>
8794 <name>Check Execution Result</name>
8795 <activity_definition>If</activity_definition>
8796 <stage>running</stage>
8797 <width/>
8798 <height/>
8799 <x>10</x>
8800 <y>6</y>
8801 <snsc_name>check_result</snsc_name>
8802 <variables>
8803 <variable>
8804 <name>script</name>
8805 <value><![CDATA[// This script needs to set answer to 'yes' or 'no' to indicate the state of the activity.
8806
8807answer = ifScript();
8808
8809function ifScript() {
8810 return (workflow.scratchpad.ended == 'ENDED_OK' ? 'yes' : 'no');
8811}
8812]]></value>
8813 </variable>
8814 <variable>
8815 <name>advanced</name>
8816 <value>1</value>
8817 </variable>
8818 </variables>
8819 </activity>
8820
8821 <activity>
8822 <name>Ended Failed</name>
8823 <activity_definition>Log Message</activity_definition>
8824 <stage>ended_failed</stage>
8825 <width/>
8826 <height/>
8827 <x>10</x>
8828 <y>7</y>
8829 <snsc_name>ended_failed</snsc_name>
8830 <variables>
8831 <variable>
8832 <name>message</name>
8833 <value>Workflow finished NOT OK.</value>
8834 </variable>
8835 </variables>
8836 </activity>
8837
8838 <activity>
8839 <name>Ended OK</name>
8840 <activity_definition>Log Message</activity_definition>
8841 <stage>ended_ok</stage>
8842 <width/>
8843 <height/>
8844 <x>11</x>
8845 <y>7</y>
8846 <snsc_name>ended_ok</snsc_name>
8847 <variables>
8848 <variable>
8849 <name>message</name>
8850 <value>Workflow finished successfully.</value>
8851 </variable>
8852 </variables>
8853 </activity>
8854
8855 <activity>
8856 <name>End</name>
8857 <activity_definition>End</activity_definition>
8858 <stage>completed</stage>
8859 <width/>
8860 <height/>
8861 <x>2</x>
8862 <y>8</y>
8863 <snsc_name>end</snsc_name>
8864 </activity>
8865</activities>
8866
8867
8868
8869 <transitions>
8870
8871 <transition>
8872 <from>begin</from>
8873 <to>check_price</to>
8874 <condition>
8875 <name>Always</name>
8876 <condition>true</condition>
8877 <order>1</order>
8878 <description/>
8879 </condition>
8880 </transition>
8881
8882
8883 <transition>
8884 <from>check_price</from>
8885 <to>waiting_for_approval</to>
8886 <condition>
8887 <name>No</name>
8888 <condition>activity.result == 'no'</condition>
8889 <order>1</order>
8890 <description/>
8891 </condition>
8892 </transition>
8893
8894
8895 <transition>
8896 <from>check_price</from>
8897 <to>approved</to>
8898 <condition>
8899 <name>Yes</name>
8900 <condition>activity.result == 'yes'</condition>
8901 <order>1</order>
8902 <description/>
8903 </condition>
8904 </transition>
8905
8906
8907 <transition>
8908 <from>waiting_for_approval</from>
8909 <to>rejected</to>
8910 <condition>
8911 <name>Rejected</name>
8912 <condition>activity.result == 'rejected'</condition>
8913 <order>1</order>
8914 <description/>
8915 </condition>
8916 </transition>
8917
8918
8919 <transition>
8920 <from>rejected</from>
8921 <to>end</to>
8922 <condition>
8923 <name>Always</name>
8924 <condition>true</condition>
8925 <order>1</order>
8926 <description/>
8927 </condition>
8928 </transition>
8929
8930
8931 <transition>
8932 <from>waiting_for_approval</from>
8933 <to>approved</to>
8934 <condition>
8935 <name>Approved</name>
8936 <condition>activity.result == 'approved' || activity.result == 'skipped'</condition>
8937 <order>1</order>
8938 <description/>
8939 </condition>
8940 </transition>
8941
8942
8943 <transition>
8944 <from>approved</from>
8945 <to>initializing</to>
8946 <condition>
8947 <name>Always</name>
8948 <condition>true</condition>
8949 <order>1</order>
8950 <description/>
8951 </condition>
8952 </transition>
8953
8954
8955 <transition>
8956 <from>initializing</from>
8957 <to>invoke_consume</to>
8958 <condition>
8959 <name>Always</name>
8960 <condition>true</condition>
8961 <order>1</order>
8962 <description/>
8963 </condition>
8964 </transition>
8965
8966
8967 <transition>
8968 <from>invoke_consume</from>
8969 <to>check_transfer</to>
8970 <condition>
8971 <name>Always</name>
8972 <condition>true</condition>
8973 <order>1</order>
8974 <description/>
8975 </condition>
8976 </transition>
8977
8978
8979 <transition>
8980 <from>check_transfer</from>
8981 <to>transfer_failed</to>
8982 <condition>
8983 <name>No</name>
8984 <condition>activity.result == 'no'</condition>
8985 <order>1</order>
8986 <description/>
8987 </condition>
8988 </transition>
8989
8990
8991 <transition>
8992 <from>transfer_failed</from>
8993 <to>end</to>
8994 <condition>
8995 <name>Always</name>
8996 <condition>true</condition>
8997 <order>1</order>
8998 <description/>
8999 </condition>
9000 </transition>
9001
9002
9003 <transition>
9004 <from>check_transfer</from>
9005 <to>check_consume</to>
9006 <condition>
9007 <name>Yes</name>
9008 <condition>activity.result == 'yes'</condition>
9009 <order>1</order>
9010 <description/>
9011 </condition>
9012 </transition>
9013
9014
9015 <transition>
9016 <from>check_consume</from>
9017 <to>consume_failed</to>
9018 <condition>
9019 <name>No</name>
9020 <condition>activity.result == 'no'</condition>
9021 <order>1</order>
9022 <description/>
9023 </condition>
9024 </transition>
9025
9026
9027 <transition>
9028 <from>consume_failed</from>
9029 <to>end</to>
9030 <condition>
9031 <name>Always</name>
9032 <condition>true</condition>
9033 <order>1</order>
9034 <description/>
9035 </condition>
9036 </transition>
9037
9038
9039 <transition>
9040 <from>check_consume</from>
9041 <to>workflow_timer</to>
9042 <condition>
9043 <name>Yes</name>
9044 <condition>activity.result == 'yes'</condition>
9045 <order>1</order>
9046 <description/>
9047 </condition>
9048 </transition>
9049
9050
9051 <transition>
9052 <from>workflow_timer</from>
9053 <to>retrieve_status</to>
9054 <condition>
9055 <name>Always</name>
9056 <condition>true</condition>
9057 <order>1</order>
9058 <description/>
9059 </condition>
9060 </transition>
9061
9062
9063 <transition>
9064 <from>retrieve_status</from>
9065 <to>check_timeout</to>
9066 <condition>
9067 <name>Always</name>
9068 <condition>true</condition>
9069 <order>1</order>
9070 <description/>
9071 </condition>
9072 </transition>
9073
9074
9075 <transition>
9076 <from>check_timeout</from>
9077 <to>workflow_timer</to>
9078 <condition>
9079 <name>No</name>
9080 <condition>activity.result == 'no'</condition>
9081 <order>2</order>
9082 <description/>
9083 </condition>
9084 </transition>
9085
9086
9087 <transition>
9088 <from>check_timeout</from>
9089 <to>check_result</to>
9090 <condition>
9091 <name>Yes</name>
9092 <condition>activity.result == 'yes'</condition>
9093 <order>1</order>
9094 <description/>
9095 </condition>
9096 </transition>
9097
9098
9099 <transition>
9100 <from>check_result</from>
9101 <to>ended_failed</to>
9102 <condition>
9103 <name>No</name>
9104 <condition>activity.result == 'no'</condition>
9105 <order>2</order>
9106 <description/>
9107 </condition>
9108 </transition>
9109
9110
9111 <transition>
9112 <from>ended_failed</from>
9113 <to>end</to>
9114 <condition>
9115 <name>Always</name>
9116 <condition>true</condition>
9117 <order>1</order>
9118 <description/>
9119 </condition>
9120 </transition>
9121
9122
9123 <transition>
9124 <from>check_result</from>
9125 <to>ended_ok</to>
9126 <condition>
9127 <name>Yes</name>
9128 <condition>activity.result == 'yes'</condition>
9129 <order>1</order>
9130 <description/>
9131 </condition>
9132 </transition>
9133
9134
9135 <transition>
9136 <from>ended_ok</from>
9137 <to>end</to>
9138 <condition>
9139 <name>Always</name>
9140 <condition>true</condition>
9141 <order>1</order>
9142 <description/>
9143 </condition>
9144 </transition>
9145</transitions>
9146
9147 </workflow>
9148</workflows>
9149
9150
9151 <fix_scripts>
9152 <fix_script>
9153 <name>Sara - Create Scheduler for auto-sync</name>
9154 <description>Create Scheduler for auto-sync service and lookup value</description>
9155 <active>true</active>
9156 <run_once>true</run_once>
9157 <script><![CDATA[var glideHelper = new x_ausgh_snsc.SaraGlideHelper();
9158
9159glideHelper.persistData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SN_AUTO_SCRIPT, {
9160 'name': 'SaraAutoSync',
9161 'script': 'new x_ausgh_snsc.SaraSync().syncServices();',
9162 'active': true,
9163 'run_type': 'periodically',
9164 'run_period': '02:00:00',
9165 'sys_class_name': 'sysauto_script',
9166 'run_dayofweek': 1
9167});
9168]]></script>
9169 </fix_script>
9170 <fix_script>
9171 <name>Sara - Remove Scheduler for auto-sync</name>
9172 <description>Remove Scheduler for auto-sync service and lookup value</description>
9173 <active>true</active>
9174 <run_once>true</run_once>
9175 <script><![CDATA[var glideHelper = new x_ausgh_snsc.SaraGlideHelper();
9176
9177glideHelper.deleteData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SN_AUTO_SCRIPT, {
9178 'name': 'SaraAutoSync'
9179}, true);
9180]]></script>
9181 </fix_script>
9182</fix_scripts>
9183
9184
9185 <schedulers>
9186 <scheduler>
9187 <name>SaraAutoSync</name>
9188 <active>false</active>
9189 <run_type>periodically</run_type>
9190 <run_period>02:00:00</run_period>
9191 <sys_class_name>sysauto_script</sys_class_name>
9192 <run_dayofweek>1</run_dayofweek>
9193 <script>new x_ausgh_snsc.SaraSync().syncServices();</script>
9194 </scheduler>
9195</schedulers>
9196
9197
9198 <wizards>
9199 <wizard>
9200 <name>Automic OAuth Configuration</name>
9201 <type>expert</type>
9202 <banner_type>fixed</banner_type>
9203 <roles>x_ausgh_snsc.admin</roles>
9204 <first_panel>OAuth Client</first_panel>
9205 <variables>
9206 <variable>
9207 <name>sara_client_scripts</name>
9208 <type>14</type>
9209 <class>expert_variable</class>
9210 <question>Sara Client Scripts</question>
9211 <order>0</order>
9212 <mandatory>false</mandatory>
9213 <active>true</active>
9214 <panel>Config OAuth Client</panel>
9215 <macro>sara_client_scripts</macro>
9216 </variable>
9217 <variable>
9218 <name>client_id</name>
9219 <type>6</type>
9220 <class>expert_variable</class>
9221 <question>Client ID</question>
9222 <order>100</order>
9223 <mandatory>true</mandatory>
9224 <active>true</active>
9225 <panel>Config OAuth Client</panel>
9226 <show_help>true</show_help>
9227 <help_tag>More information</help_tag>
9228 <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>
9229 </variable>
9230 <variable>
9231 <name>client_secret</name>
9232 <type>6</type>
9233 <class>expert_variable</class>
9234 <question>Client Secret</question>
9235 <order>200</order>
9236 <mandatory>true</mandatory>
9237 <active>true</active>
9238 <panel>Config OAuth Client</panel>
9239 <show_help>true</show_help>
9240 <help_tag>More information</help_tag>
9241 <help_text>Secret phrase of OAuth client user. Example: AES_12345, the value will be encrypted in ServiceNow.</help_text>
9242 </variable>
9243 <variable>
9244 <name>technical_user</name>
9245 <type>6</type>
9246 <class>expert_variable</class>
9247 <question>Technical User</question>
9248 <order>300</order>
9249 <mandatory>true</mandatory>
9250 <active>true</active>
9251 <panel>Config OAuth Client</panel>
9252 <show_help>true</show_help>
9253 <help_tag>More information</help_tag>
9254 <help_text>User Name/Department. Example: TECHSYNC/AUTOMIC</help_text>
9255 </variable>
9256 <variable>
9257 <name>sapi_endpoint</name>
9258 <type>6</type>
9259 <class>expert_variable</class>
9260 <question>SAPI Endpoint</question>
9261 <order>400</order>
9262 <mandatory>true</mandatory>
9263 <active>true</active>
9264 <panel>Config OAuth Client</panel>
9265 <show_help>true</show_help>
9266 <help_tag>More information</help_tag>
9267 <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>
9268 </variable>
9269 <variable>
9270 <name>token_endpoint</name>
9271 <type>6</type>
9272 <class>expert_variable</class>
9273 <question>Token Endpoint</question>
9274 <order>500</order>
9275 <mandatory>true</mandatory>
9276 <active>true</active>
9277 <panel>Config OAuth Client</panel>
9278 <show_help>true</show_help>
9279 <help_tag>More information</help_tag>
9280 <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>
9281 </variable>
9282 <variable>
9283 <name>auth_endpoint</name>
9284 <type>6</type>
9285 <class>expert_variable</class>
9286 <question>Authorization Endpoint</question>
9287 <order>600</order>
9288 <mandatory>true</mandatory>
9289 <active>true</active>
9290 <panel>Config OAuth Client</panel>
9291 <show_help>true</show_help>
9292 <help_tag>More information</help_tag>
9293 <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>
9294 </variable>
9295 </variables>
9296
9297 <panels>
9298 <panel>
9299 <name>Config OAuth Client</name>
9300 <title>Config OAuth Client</title>
9301 <class>expert_panel</class>
9302 <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>
9303 <previous_message>Previous</previous_message>
9304 <next_message>Store OAuth Client Settings</next_message>
9305 <complete_message>Done</complete_message>
9306 <client_script>
9307 <name>SARA OAuth Client OnLoad</name>
9308 <active>true</active>
9309 <type>onLoad</type>
9310 <script><![CDATA[function onLoad() {
9311 g_form.getControl(x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_SECRET).type = 'password';
9312 x_ausgh_snsc.oldConfig = {};
9313
9314 x_ausgh_snsc.SaraOAuth.getConfig(function (configData) {
9315 for (var name in configData) {
9316 var value = configData[name];
9317
9318 g_form.setValue(name, value);
9319 x_ausgh_snsc.oldConfig[name] = value;
9320 }
9321 });
9322}
9323]]></script>
9324 </client_script>
9325 <client_script>
9326 <name>SARA OAuth Client OnSubmit</name>
9327 <active>true</active>
9328 <type>onSubmit</type>
9329 <script><![CDATA[function onSubmit() {
9330 if (x_ausgh_snsc.isTokenValid) {
9331 return true;
9332 } else {
9333 var isChange = false;
9334 for (var name in x_ausgh_snsc.oldConfig) {
9335 if (x_ausgh_snsc.oldConfig[name] !== g_form.getValue(name).toString() && name !== x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT) {
9336 isChange = true;
9337 break;
9338 }
9339 }
9340
9341 if (isChange && !x_ausgh_snsc.notChange) {
9342 getToken();
9343 } else {
9344 // Clean all existing messages
9345 g_form.clearMessages();
9346
9347 // Check if Sara tokens exist for Technical User
9348 var technicalUser = g_form.getValue(x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER).toString();
9349 var sapiEndpoint = g_form.getValue(x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT).toString();
9350 x_ausgh_snsc.SaraOAuth.checkOAuthToken(technicalUser, sapiEndpoint, false, {
9351 onValid: function () {
9352 x_ausgh_snsc.isTokenValid = true;
9353 g_expert.next();
9354 },
9355 onInvalid: function () {
9356 x_ausgh_snsc.isTokenValid = false;
9357 getToken();
9358 },
9359 onError: function (errorMessage) {
9360 x_ausgh_snsc.isTokenValid = false;
9361 g_form.addErrorMessage(errorMessage);
9362 }
9363 });
9364 }
9365 }
9366
9367 return false;
9368}
9369
9370function getToken() {
9371 x_ausgh_snsc.log('Preparing for openning OAuth login popup...');
9372
9373 for (var key in x_ausgh_snsc.SaraCommon.CONFIG_NAME) {
9374 var name = x_ausgh_snsc.SaraCommon.CONFIG_NAME[key];
9375
9376 x_ausgh_snsc.config[name] = g_form.getValue(name).toString();
9377 }
9378
9379 x_ausgh_snsc.SaraOAuth.login(
9380 x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_ID],
9381 x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER],
9382 x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.AUTH_ENDPOINT], {
9383 onSuccess: function () {
9384 x_ausgh_snsc.notChange = true;
9385 g_expert.next();
9386 }
9387 }
9388 );
9389}
9390]]></script>
9391 </client_script>
9392 </panel>
9393 <panel>
9394 <name>Config OAuth Client Completed</name>
9395 <title>Config OAuth Client Completed</title>
9396 <class>expert_panel</class>
9397 <description/>
9398 <previous_message>Previous</previous_message>
9399 <next_message>Next</next_message>
9400 <complete_message>Done</complete_message>
9401 </panel>
9402 </panels>
9403
9404 <transitions>
9405 <transition>
9406 <from>Config OAuth Client</from>
9407 <to>Config OAuth Client Completed</to>
9408 <order>100</order>
9409 <condition/>
9410 <transition_script><![CDATA[var LOGGER = new x_ausgh_snsc.SaraLog('sara_oauth_client_transition');
9411
9412gs.addInfoMessage('Client ID = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_ID]
9413 + ', Client Secret = ***'
9414 + ', Technical User = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER]
9415 + ', SAPI Endpoint = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT]
9416 + ', Token Endpoint = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT]
9417 + ', Authorization Endpoint = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.AUTH_ENDPOINT]);
9418
9419var saraConfig = new x_ausgh_snsc.SaraConfig();
9420try {
9421 var configData = {};
9422 for (var key in x_ausgh_snsc.SaraCommon.CONFIG_NAME) {
9423 var name = x_ausgh_snsc.SaraCommon.CONFIG_NAME[key];
9424
9425 configData[name] = wizard[name];
9426 }
9427
9428 saraConfig.storeClientConfig(configData);
9429 LOGGER.info('OAuth Configuration updated:\n'
9430 + ' - Client ID = {0}, \n'
9431 + ' - Client Secret = ***, \n'
9432 + ' - Technical User = {1} \n'
9433 + ' - SAPI Endpoint = {2}, \n'
9434 + ' - Token Endpoint = {3}, \n'
9435 + ' - Authorization Endpoint = {4}',
9436 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_ID],
9437 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER],
9438 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT],
9439 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT],
9440 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.AUTH_ENDPOINT]
9441 );
9442
9443 gs.addInfoMessage('Successfully update Automic OAuth client settings');
9444} catch (err) {
9445 LOGGER.info('Error on update Automic OAuth client settings: {0}', err);
9446
9447 gs.addInfoMessage('Failed to update Automic OAuth client settings');
9448}
9449]]></transition_script>
9450 </transition>
9451 </transitions>
9452 </wizard>
9453
9454 <wizard>
9455 <name>Automic Import Services</name>
9456 <type>expert</type>
9457 <banner_type>fixed</banner_type>
9458 <roles>x_ausgh_snsc.admin</roles>
9459 <first_panel>Import Services</first_panel>
9460 <variables>
9461 <variable>
9462 <name>sara_client_scripts</name>
9463 <type>14</type>
9464 <class>expert_variable</class>
9465 <question>Sara Client Scripts</question>
9466 <order>0</order>
9467 <mandatory>false</mandatory>
9468 <active>true</active>
9469 <panel>Import Services</panel>
9470 <macro>sara_client_scripts</macro>
9471 </variable>
9472 <variable>
9473 <name>sara_message</name>
9474 <type>6</type>
9475 <class>expert_variable</class>
9476 <question>Sara Message</question>
9477 <order>100</order>
9478 <mandatory>false</mandatory>
9479 <active>true</active>
9480 <panel>Import Services</panel>
9481 </variable>
9482 <variable>
9483 <name>sara_target_category</name>
9484 <type>18</type>
9485 <class>expert_variable</class>
9486 <question>Select Target Category</question>
9487 <order>200</order>
9488 <mandatory>true</mandatory>
9489 <active>true</active>
9490 <lookup_table>sc_category</lookup_table>
9491 <lookup_value>sys_id</lookup_value>
9492 <lookup_label>title</lookup_label>
9493 <panel>Import Services</panel>
9494 <reference_qual>javascript:x_ausgh_snsc.SaraUtils.getImportTargetCatRefQual()</reference_qual>
9495 </variable>
9496 </variables>
9497
9498 <panels>
9499 <panel>
9500 <name>Import Services</name>
9501 <title>Import Services</title>
9502 <class>expert_panel</class>
9503 <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>
9504 <previous_message>Previous</previous_message>
9505 <next_message>Import Services</next_message>
9506 <complete_message>Done</complete_message>
9507 <client_script>
9508 <name>Import Services OnLoad</name>
9509 <active>true</active>
9510 <type>onLoad</type>
9511 <script><![CDATA[function onLoad() {
9512 x_ausgh_snsc.SaraUtils.setFormControlVisible('sara_message', false);
9513 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(false);
9514
9515 x_ausgh_snsc.SaraOAuth.getConfig(function (configData) {
9516 for (var key in configData) {
9517 var value = configData[key];
9518
9519 x_ausgh_snsc.config[key] = value;
9520
9521 if (!value) {
9522 g_form.addErrorMessage('OAuth Configuration "' + key + '" is empty. Please check the current OAuth configuration.');
9523 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(false);
9524 break;
9525 }
9526 }
9527
9528 setTimeout(function () {
9529 checkToken();
9530 }, 100);
9531 });
9532}
9533
9534function checkToken() {
9535 var technicalUser = x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER];
9536 var sapiEndpoint = x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT];
9537 x_ausgh_snsc.SaraOAuth.checkOAuthToken(technicalUser, sapiEndpoint, true, {
9538 onValid: function () {
9539 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(true);
9540 },
9541 onInvalid: function () {
9542 g_form.addErrorMessage('Tokens are empty, invalid or expired! Please contact your administrator for resolving this problem.');
9543 },
9544 onError: function (errorMessage) {
9545 g_form.addErrorMessage(errorMessage);
9546 }
9547 });
9548}
9549]]></script>
9550 </client_script>
9551 <client_script>
9552 <name>Import Services OnSubmit</name>
9553 <active>true</active>
9554 <type>onSubmit</type>
9555 <script><![CDATA[function onSubmit() {
9556 if (x_ausgh_snsc.isOk) {
9557 return true;
9558 }
9559
9560 var importDialog = new GlideDialogWindow('hierarchical_progress_viewer');
9561 importDialog.setPreference('sysparm_ajax_processor', 'x_ausgh_snsc.SaraConsumerRunner');
9562 importDialog.setPreference('sysparm_catid', g_form.getValue('sara_target_category').toString());
9563 importDialog.setSize(400, 300);
9564 importDialog.setTitle('Importing service...');
9565
9566 importDialog.on('executionComplete', function (trackerObj) {
9567 x_ausgh_snsc.log('executionComplete', trackerObj);
9568 if (trackerObj.result && trackerObj.result.info) {
9569 importDialog.setTitle(trackerObj.result.msg);
9570 g_form.setValue('sara_message', trackerObj.result.info);
9571
9572 x_ausgh_snsc.isOk = true;
9573 x_ausgh_snsc.log('Go to next panel', x_ausgh_snsc.isOk);
9574 g_expert.next();
9575
9576
9577 x_ausgh_snsc.log('Destroy diablog', importDialog);
9578 importDialog.destroy();
9579 }
9580 });
9581
9582 importDialog.on("renderStatus", function (trackerObj) {
9583 x_ausgh_snsc.log('renderStatus', trackerObj);
9584
9585 if (trackerObj && trackerObj.result && trackerObj.result.msg) {
9586 importDialog.setTitle(trackerObj.result.msg);
9587 }
9588 });
9589
9590 // Render the viewer
9591 importDialog.render();
9592
9593 return false;
9594}
9595]]></script>
9596 </client_script>
9597 </panel>
9598 <panel>
9599 <name>Import Services Completed</name>
9600 <title>Import Services Completed</title>
9601 <class>expert_panel</class>
9602 <description/>
9603 <previous_message>Previous</previous_message>
9604 <next_message>Next</next_message>
9605 <complete_message>Done</complete_message>
9606 </panel>
9607 </panels>
9608
9609 <transitions>
9610 <transition>
9611 <from>Import Services</from>
9612 <to>Import Services Completed</to>
9613 <order>100</order>
9614 <condition>[sara_target_category]!=^EQ</condition>
9615 <transition_script><![CDATA[gs.addInfoMessage(wizard.sara_message.toString());
9616]]></transition_script>
9617 </transition>
9618 </transitions>
9619 </wizard>
9620
9621 <wizard>
9622 <name>Automic Clean-up</name>
9623 <type>expert</type>
9624 <banner_type>fixed</banner_type>
9625 <roles>x_ausgh_snsc.admin</roles>
9626 <first_panel>Automic Cleanup</first_panel>
9627 <variables>
9628 <variable/>
9629 </variables>
9630
9631 <panels>
9632 <panel>
9633 <name>Cleanup Catalog Items</name>
9634 <title>Cleanup Catalog Items</title>
9635 <class>expert_panel</class>
9636 <description>Cleanup all Automic SARA stuffs. This will delete all subcategories and service items.</description>
9637 <previous_message>Previous</previous_message>
9638 <next_message>Cleanup</next_message>
9639 <complete_message>Done</complete_message>
9640 </panel>
9641 <panel>
9642 <name>Cleanup Catalog Items Completed</name>
9643 <title>Cleanup Catalog Items Completed</title>
9644 <class>expert_panel</class>
9645 <description>Cleanup successfully!</description>
9646 <previous_message>Previous</previous_message>
9647 <next_message>Next</next_message>
9648 <complete_message>Done</complete_message>
9649 </panel>
9650 </panels>
9651
9652 <transitions>
9653 <transition>
9654 <from>Cleanup Catalog Items</from>
9655 <to>Cleanup Catalog Items Completed</to>
9656 <order>100</order>
9657 <condition/>
9658 <transition_script>
9659 <![CDATA[x_ausgh_snsc.SaraUtils.cleanup();]]>
9660 </transition_script>
9661 </transition>
9662 </transitions>
9663 </wizard>
9664</wizards>
9665
9666
9667 <processors>
9668 <processor>
9669 <name>SaraUpdateStatus</name>
9670 <type>script</type>
9671 <active>true</active>
9672 <description>Sara REST api for updating status of worflow remotely</description>
9673 <path>sara_update_status</path>
9674 <script><![CDATA[var LOGGER = new x_ausgh_snsc.SaraLog('SaraUpdateStatus');
9675var runId = g_request.getParameter('runId');
9676var status = g_request.getParameter('status');
9677var error = 0;
9678var result = {};
9679
9680LOGGER.info('SaraUpdateStatus: RunId = {0}, Status = {1}', runId, status);
9681LOGGER.info('SaraUpdateStatus: Request user = ' + gs.getUserName());
9682
9683if (!runId) {
9684 error += 1;
9685}
9686
9687if (!status) {
9688 error += 1;
9689}
9690
9691if (error === 0) {
9692 runId = +runId;
9693
9694 if (isNaN(runId)) {
9695 result = {
9696 code: 99,
9697 message: 'The runId must be digits!'
9698 };
9699 } else {
9700 var glideHelper = new x_ausgh_snsc.SaraGlideHelper();
9701 var reqItem = glideHelper.getData('sc_req_item', {
9702 'correlation_id': runId.toString()
9703 });
9704
9705 if (reqItem) {
9706 LOGGER.info('Found current request item (correlation_id = {0}, sys_id = {1})', runId, reqItem['sys_id']);
9707
9708 try {
9709 glideHelper.updateData('sc_req_item', {
9710 'sys_id': reqItem['sys_id']
9711 }, {
9712 'comments': status,
9713 'display_state': status
9714 });
9715
9716 result = {
9717 code: 200,
9718 message: 'Update OK!',
9719 sysId: reqItem['sys_id']
9720 };
9721 } catch (e) {
9722 result = {
9723 code: 99,
9724 message: err
9725 };
9726 }
9727 } else {
9728 var message = x_ausgh_snsc.SaraUtils.formatString('No request item (correlation_id = {0}) found! Update status failed.', runId);
9729 LOGGER.info(message);
9730
9731 result = {
9732 code: 99,
9733 message: message
9734 };
9735 }
9736 }
9737} else {
9738 result = {
9739 code: 99,
9740 message: 'The runId and status must be not null!'
9741 }
9742}
9743
9744var response = x_ausgh_snsc.SaraJSON.stringify(result);
9745
9746LOGGER.debug('SaraUpdateStatus: {0}', response);
9747
9748g_processor.writeOutput('application/json', response);
9749]]></script>
9750 </processor>
9751</processors>
9752
9753
9754 <snsc_application>
9755 <application>
9756 <name>Automic SNSC</name>
9757 <short_description>Automic ServiceNow Service Connector Application</short_description>
9758 <active>true</active>
9759 <user_role>x_ausgh_snsc.user</user_role>
9760 <version>1.0.2</version>
9761 <menu>u_ausgh_snsc_menu</menu>
9762 <scope>x_ausgh_snsc</scope>
9763 </application>
9764 <application_menu>
9765 <name>u_ausgh_snsc_menu</name>
9766 <active>true</active>
9767 <category>Custom Applications</category>
9768 <title>Automic SNSC</title>
9769 <roles>x_ausgh_snsc.user,x_ausgh_snsc.admin</roles>
9770 <hint>Automic ServiceNow Service Connector Application</hint>
9771 </application_menu>
9772 <user_roles>
9773 <user_role>
9774 <name>x_ausgh_snsc.user</name>
9775 <description>User role for SNSC application</description>
9776 </user_role>
9777 <user_role>
9778 <name>x_ausgh_snsc.admin</name>
9779 <description>Admin role for SNSC application</description>
9780 <includes_roles>x_ausgh_snsc.user</includes_roles>
9781 </user_role>
9782 </user_roles>
9783</snsc_application>
9784
9785
9786 <modules>
9787 <module>
9788 <title>Automic Configuration</title>
9789 <order>0</order>
9790 <active>true</active>
9791 <link_type>SEPARATOR</link_type>
9792 <roles>x_ausgh_snsc.admin</roles>
9793 </module>
9794 <module>
9795 <title>Automic Clean-up</title>
9796 <reference>wizard</reference>
9797 <reference_name>Automic Clean-up</reference_name>
9798 <order>10</order>
9799 <active>true</active>
9800 <link_type>DIRECT</link_type>
9801 <query>/expert_shell.do?sysparm_sys_id=@{sys_id}&sysparm_initial=true</query>
9802 <roles>x_ausgh_snsc.admin</roles>
9803 </module>
9804 <module>
9805 <title>Automic Import Services</title>
9806 <reference>wizard</reference>
9807 <reference_name>Automic Import Services</reference_name>
9808 <order>20</order>
9809 <active>true</active>
9810 <link_type>DIRECT</link_type>
9811 <query>/expert_shell.do?sysparm_sys_id=@{sys_id}&sysparm_initial=true</query>
9812 <roles>x_ausgh_snsc.admin</roles>
9813 </module>
9814 <module>
9815 <title>Automic OAuth Configuration</title>
9816 <reference>wizard</reference>
9817 <reference_name>Automic OAuth Configuration</reference_name>
9818 <order>30</order>
9819 <active>true</active>
9820 <link_type>DIRECT</link_type>
9821 <query>/expert_shell.do?sysparm_sys_id=@{sys_id}&sysparm_initial=true</query>
9822 <roles>x_ausgh_snsc.admin</roles>
9823 </module>
9824 <module>
9825 <title>Automic SNSC Components</title>
9826 <order>100</order>
9827 <active>true</active>
9828 <link_type>SEPARATOR</link_type>
9829 </module>
9830 <module>
9831 <title>Sara Tables</title>
9832 <order>110</order>
9833 <active>true</active>
9834 <link_type>LIST</link_type>
9835 <table_name>sys_db_object</table_name>
9836 <filter>nameSTARTSWITHx_ausgh_snsc_</filter>
9837 </module>
9838 <module>
9839 <title>Sara Transform Maps</title>
9840 <order>115</order>
9841 <active>true</active>
9842 <link_type>LIST</link_type>
9843 <table_name>sys_transform_map</table_name>
9844 <filter>nameSTARTSWITHx_ausgh_snsc_</filter>
9845 </module>
9846 <module>
9847 <title>Sara System Properties</title>
9848 <reference>system_property</reference>
9849 <reference_name>Automic</reference_name>
9850 <order>120</order>
9851 <active>true</active>
9852 <link_type>DIRECT</link_type>
9853 <query>/sys_properties_category.do?sys_id=@{sys_id}</query>
9854 </module>
9855 <module>
9856 <title>Sara Script Includes</title>
9857 <order>130</order>
9858 <active>true</active>
9859 <link_type>LIST</link_type>
9860 <table_name>sys_script_include</table_name>
9861 <filter>nameSTARTSWITHSara</filter>
9862 </module>
9863 <module>
9864 <title>Sara UI Scripts</title>
9865 <order>140</order>
9866 <active>true</active>
9867 <link_type>LIST</link_type>
9868 <table_name>sys_ui_script</table_name>
9869 <filter>nameSTARTSWITHx_ausgh_snsc.Sara</filter>
9870 </module>
9871 <module>
9872 <title>Sara UI Pages</title>
9873 <order>150</order>
9874 <active>true</active>
9875 <link_type>LIST</link_type>
9876 <table_name>sys_ui_page</table_name>
9877 <filter>nameSTARTSWITHsara_</filter>
9878 </module>
9879 <module>
9880 <title>Sara UI Macros</title>
9881 <order>160</order>
9882 <active>true</active>
9883 <link_type>LIST</link_type>
9884 <table_name>sys_ui_macro</table_name>
9885 <filter>nameSTARTSWITHsara_</filter>
9886 </module>
9887 <module>
9888 <title>Sara Processors</title>
9889 <order>170</order>
9890 <active>true</active>
9891 <link_type>LIST</link_type>
9892 <table_name>sys_processor</table_name>
9893 <filter>nameSTARTSWITHSara</filter>
9894 </module>
9895 <module>
9896 <title>Sara Wizards</title>
9897 <order>180</order>
9898 <active>true</active>
9899 <link_type>LIST</link_type>
9900 <table_name>expert</table_name>
9901 <filter>nameSTARTSWITHAutomic</filter>
9902 </module>
9903 <module>
9904 <title>Sara Schedulers</title>
9905 <order>190</order>
9906 <active>true</active>
9907 <link_type>LIST</link_type>
9908 <table_name>sysauto</table_name>
9909 <filter>nameSTARTSWITHSara</filter>
9910 </module>
9911 <module>
9912 <title>Sara REST Messages</title>
9913 <order>200</order>
9914 <active>true</active>
9915 <link_type>LIST</link_type>
9916 <table_name>sys_rest_message</table_name>
9917 <filter>nameSTARTSWITHSara</filter>
9918 </module>
9919 <module>
9920 <title>Support</title>
9921 <order>900</order>
9922 <active>true</active>
9923 <link_type>SEPARATOR</link_type>
9924 </module>
9925 <module>
9926 <title>Used ServiceNow's Tables</title>
9927 <order>910</order>
9928 <active>true</active>
9929 <link_type>LIST</link_type>
9930 <table_name>sys_db_object</table_name>
9931 <query>name=sc_category^ORname=item_option_new_set^ORname=io_set_item^ORname=sysauto_script^ORname=item_option_new</query>
9932 </module>
9933 <module>
9934 <title>Sara Transform History</title>
9935 <order>915</order>
9936 <active>true</active>
9937 <link_type>LIST</link_type>
9938 <table_name>sys_import_set_run</table_name>
9939 <query>sys_transform_mapSTARTSWITHx_ausgh_snsc</query>
9940 </module>
9941 <module>
9942 <title>Contact Us</title>
9943 <order>920</order>
9944 <active>true</active>
9945 <link_type>DIRECT</link_type>
9946 <query>https://automic.com/contact-us</query>
9947 </module>
9948 <module>
9949 <title>Support</title>
9950 <order>930</order>
9951 <active>true</active>
9952 <link_type>DIRECT</link_type>
9953 <query>https://automic.force.com/support</query>
9954 </module>
9955</modules>
9956
9957
9958 <rest_messages>
9959 <rest_message>
9960 <name>Sara - SAPI Services</name>
9961 <description>Sara Outbound Web Service for SAPI</description>
9962 <rest_endpoint>${sapiEndpoint}</rest_endpoint>
9963 <methods>
9964 <method>
9965 <function_name>GET</function_name>
9966 <http_method>GET</http_method>
9967 </method>
9968 <method>
9969 <function_name>POST</function_name>
9970 <http_method>POST</http_method>
9971 </method>
9972 <method>
9973 <function_name>PUT</function_name>
9974 <http_method>PUT</http_method>
9975 </method>
9976 <method>
9977 <function_name>DELETE</function_name>
9978 <http_method>DELETE</http_method>
9979 </method>
9980 </methods>
9981 </rest_message>
9982 <rest_message>
9983 <name>Sara - OAuth Services</name>
9984 <description>Sara Outbound Web Service for OAuth</description>
9985 <rest_endpoint>${oauthEndpoint}</rest_endpoint>
9986 <methods>
9987 <method>
9988 <function_name>GET</function_name>
9989 <http_method>GET</http_method>
9990 </method>
9991 <method>
9992 <function_name>POST</function_name>
9993 <http_method>POST</http_method>
9994 </method>
9995 <method>
9996 <function_name>PUT</function_name>
9997 <http_method>PUT</http_method>
9998 </method>
9999 <method>
10000 <function_name>DELETE</function_name>
10001 <http_method>DELETE</http_method>
10002 </method>
10003 </methods>
10004 </rest_message>
10005</rest_messages>
10006
10007 </package>
10008</sara>