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