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