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