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