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