· 8 years ago · Nov 06, 2017, 08:56 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 "{0}" does not have tokens', technicalUser);
4763
4764 this.addItem('result', {
4765 isValid: false
4766 });
4767 }
4768
4769 } catch (e) {
4770 this.logError(e);
4771 }
4772
4773 return;
4774 },
4775
4776 /**
4777 * Log error
4778 * @param {Error} error
4779 * @param {SaraLog} LOGGER
4780 */
4781 logError: function (error, LOGGER) {
4782 LOGGER.error('{0}', error);
4783
4784 this.addItem('error', {
4785 message: error
4786 });
4787 },
4788
4789 /**
4790 * Add item in response
4791 * @param {String} itemName The name of item
4792 * @param {Object<String, String>} attributes The object contains item's attributes
4793 */
4794 addItem: function (itemName, attributes) {
4795 var item = this.newItem(itemName);
4796
4797 for (var name in attributes) {
4798 var value = attributes[name];
4799
4800 item.setAttribute(name, value);
4801 }
4802 },
4803
4804 type: 'SaraOAuthAjax'
4805});
4806]]></script>
4807 <description>AJAX facade for SaraOAuthClient</description>
4808 <active>true</active>
4809 <client_callable>true</client_callable>
4810 <access>package_private</access>
4811 </script_include>
4812
4813 <script_include>
4814 <name>SaraOAuthClient</name>
4815 <script><![CDATA[/**
4816 * This class contains all OAuth-relaled functions
4817 */
4818var SaraOAuthClient = Class.create();
4819SaraOAuthClient.prototype = {
4820 /**
4821 * Init new OAuth Client from SaraRESTClient object
4822 * @param {SaraRestCLient} restClient
4823 */
4824 initialize: function (restClient) {
4825 this.glideHelper = new SaraGlideHelper();
4826 this.saraConfig = new SaraConfig();
4827 this.LOGGER = new SaraLog(this);
4828
4829 if (!restClient) {
4830 this.restClient = new SaraRESTClient();
4831 this.restClient.setMIDServer(SaraUtils.getMIDServer());
4832 } else {
4833 this.restClient = restClient;
4834 }
4835 },
4836
4837 /**
4838 * Store user tokens into 'SaraCommon.TABLE_NAME.SARA_OAUTH' table
4839 * @param {String} username The username which owns tokens
4840 * @param {String} accessToken The access token of user
4841 * @param {String} refreshToken The refresh token of user
4842 * @param {String} tokenExpiry The expiry of token
4843 * @param {String} tokenType The type of token
4844 * @return {String} The sys_id of user tokens record
4845 */
4846 storeUserTokens: function (username, accessToken, refreshToken, tokenExpiry, tokenType) {
4847 var LOGGER = this.LOGGER;
4848
4849 if (!username) {
4850 LOGGER.info('Store user token: Username must not be empty!');
4851 return;
4852 }
4853
4854 if (!accessToken) {
4855 LOGGER.info('Error: Access token must be non-empty!');
4856 return;
4857 }
4858
4859 LOGGER.info('Preparing for storing user tokens...');
4860
4861 // Request tokens of user in 'SaraCommon.TABLE_NAME.SARA_OAUTH' table
4862 var saraOAuth = this.glideHelper.getData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4863 'u_user': username
4864 });
4865
4866 // If user's tokens are existed
4867 if (saraOAuth) {
4868 LOGGER.info('User\'s tokens are existed. Updating tokens...');
4869
4870 this.glideHelper.updateData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4871 'sys_id': saraOAuth['sys_id']
4872 }, {
4873 'u_access_token': accessToken,
4874 'u_refresh_token': refreshToken,
4875 'u_token_expiry': tokenExpiry,
4876 'u_token_type': tokenType
4877 });
4878
4879 return saraOAuth['sys_id'];
4880 } else {
4881 LOGGER.info('Storing user\'s tokens...');
4882
4883 return this.glideHelper.persistData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4884 'u_user': username,
4885 'u_access_token': accessToken,
4886 'u_refresh_token': refreshToken,
4887 'u_token_expiry': tokenExpiry,
4888 'u_token_type': tokenType
4889 });
4890 }
4891 },
4892
4893 /**
4894 * Get user tokens by username. The result will be [accessToken, refreshToken, tokenExpiry, tokenType, { createdAt, createdBy, updateAt, updateBy }]
4895 * @param {String} username
4896 * @return {Array<String|Object>}
4897 */
4898 getUserTokens: function (username) {
4899 var LOGGER = this.LOGGER;
4900
4901 if (!username) {
4902 return null;
4903 }
4904
4905 var saraOAuth = this.glideHelper.getData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4906 'u_user': username
4907 });
4908
4909 if (saraOAuth) {
4910 return [
4911 saraOAuth['u_access_token'],
4912 saraOAuth['u_refresh_token'],
4913 saraOAuth['u_token_expiry'],
4914 saraOAuth['u_token_type'], {
4915 'createdAt': saraOAuth['sys_created_on'],
4916 'createdBy': saraOAuth['sys_created_by'],
4917 'updatedAt': saraOAuth['sys_updated_on'],
4918 'updatedBy': saraOAuth['sys_updated_by']
4919 }
4920 ];
4921 } else {
4922 LOGGER.info('Tokens of "{0}" do not exist!', username);
4923 return null;
4924 }
4925 },
4926
4927 /**
4928 * Remove user tokens by username
4929 * @param {String} username
4930 * @return {String} The sys_id of deleted record
4931 */
4932 removeUserToken: function (username) {
4933 var LOGGER = this.LOGGER;
4934
4935 if (!username) {
4936 return null;
4937 }
4938
4939 var saraOAuth = this.glideHelper.getData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4940 'u_user': username
4941 });
4942
4943 if (saraOAuth) {
4944 saraOAuth = this.glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_OAUTH, {
4945 'sys_id': saraOAuth['sys_id']
4946 });
4947
4948 return saraOAuth['sys_id'];
4949 } else {
4950 LOGGER.info('No token found for user "{0}"', username);
4951 return null;
4952 }
4953 },
4954
4955 /**
4956 * Requests user tokens, the request must use client_id/client_secret to authenticate (BASICally) against SARA server,
4957 * LDAP username/password and grant_type will be embedded in request's body
4958 * @param {String} username
4959 * @param {String} password
4960 * @return {Object} Object contains access token, refresh token, token expiry and token type
4961 */
4962 requestToken: function (username, password) {
4963 var LOGGER = this.LOGGER;
4964
4965 LOGGER.debug('Preparing for requesting tokens for SARA user {0}...', username);
4966
4967 var clientInfo = this.saraConfig.getClientConfig();
4968 var clientId = clientInfo[SaraCommon.CONFIG_NAME.CLIENT_ID];
4969 var clientSecret = clientInfo[SaraCommon.CONFIG_NAME.CLIENT_SECERT];
4970 var tokenEndpoint = clientInfo[SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT];
4971
4972 var request = this.restClient.newOAuthRequest('post', tokenEndpoint);
4973 request.setBasicAuth(clientId, clientSecret);
4974
4975 // Add POST body, set Content-Type header
4976 request.setContentType('application/x-www-form-urlencoded');
4977 var formEntity = {
4978 'grant_type': 'password',
4979 'username': username,
4980 'password': password
4981 };
4982 request.setFormContent(formEntity);
4983
4984 LOGGER.info('Requesting tokens for SARA user {0}...', username);
4985 var response = this.restClient.execute(request);
4986 var responseObject = response.getResponseObject();
4987
4988 if (response.haveError()) {
4989 LOGGER.info('Failed to request token for user {0}', username);
4990
4991 return {
4992 'error': responseObject.errorMessage,
4993 'error_description': responseObject.errorDescription
4994 }
4995 }
4996
4997 LOGGER.info('Successfully obtain token for user {0}', username);
4998 return responseObject.bodyObject;
4999 },
5000
5001 /**
5002 * Requests user tokens, the request must use client_id/client_secret to authenticate (BASICally) against SARA server,
5003 * LDAP redirect_uri/authorization_code and grant_type will be embedded in request's body
5004 * @param {String} code The authorization code which get from OAuth after logged-in successfully in Auth Endpoint
5005 * @param {Object} config The config of OAuth Server
5006 * @return {Object} Object contains access token, refresh token, token expiry and token type
5007 */
5008 requestTokenByCode: function (code, config) {
5009 var LOGGER = this.LOGGER;
5010
5011 LOGGER.debug('Preparing for requesting tokens by code "{0}"...', code);
5012
5013 var clientId = config[SaraCommon.CONFIG_NAME.CLIENT_ID];
5014 var clientSecret = config[SaraCommon.CONFIG_NAME.CLIENT_SECERT];
5015 var tokenEndpoint = config[SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT];
5016 var redirectionEndpoint = SaraUtils.getRedirectionUrl();
5017
5018 var request = this.restClient.newOAuthRequest('post', tokenEndpoint);
5019 request.setBasicAuth(clientId, clientSecret);
5020
5021 // Add POST body, set Content-Type header
5022 request.setContentType('application/x-www-form-urlencoded');
5023 var formEntity = {
5024 'grant_type': 'authorization_code',
5025 'redirect_uri': redirectionEndpoint,
5026 'code': code
5027 };
5028 request.setFormContent(formEntity);
5029
5030 LOGGER.info('Requesting tokens by code...');
5031 var response = this.restClient.execute(request);
5032 var responseObject = response.getResponseObject();
5033
5034 if (response.haveError()) {
5035 LOGGER.info('Failed to request token by code');
5036
5037 return {
5038 'error': responseObject.errorMessage,
5039 'error_description': responseObject.errorDescription
5040 }
5041 }
5042
5043 LOGGER.info('Successfully obtain token for user by code "{0}"', code);
5044 return responseObject.bodyObject;
5045 },
5046
5047 /**
5048 * Refresh user tokens
5049 * @param {String} username
5050 * @return {Object}
5051 */
5052 refreshToken: function (username) {
5053 var LOGGER = this.LOGGER;
5054
5055 // Get refresh tokens for this user from 'SaraCommon.TABLE_NAME.SARA_OAUTH' table
5056 var tokens = this.getUserTokens(username);
5057 if (!tokens || tokens.length < 1) {
5058 LOGGER.info('Tokens not found for user {0}', username);
5059 return null;
5060 }
5061
5062 LOGGER.info('Preparing for refreshing tokens for user {0}...', username);
5063
5064 // Use that refesh token to retrieve new tokens
5065 var clientInfo = this.saraConfig.getClientConfig();
5066 var clientId = clientInfo[SaraCommon.CONFIG_NAME.CLIENT_ID];
5067 var clientSecret = clientInfo[SaraCommon.CONFIG_NAME.CLIENT_SECRET];
5068 var tokenEndpoint = clientInfo[SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT];
5069 var request = this.restClient.newOAuthRequest('post', tokenEndpoint);
5070 request.setBasicAuth(clientId, clientSecret);
5071
5072 // Add POST body, set Content-Type header
5073 request.setContentType('application/x-www-form-urlencoded');
5074 request.setFormContent({
5075 'grant_type': 'refresh_token',
5076 'refresh_token': tokens[1]
5077 });
5078
5079 LOGGER.info('Refreshing tokens for user {0}...', username);
5080 var response = this.restClient.execute(request);
5081 var responseObject = response.getResponseObject();
5082
5083 if (response.haveError()) {
5084 LOGGER.info('Failed to refresh token for code');
5085
5086 return {
5087 'error': responseObject.errorMessage,
5088 'error_description': responseObject.errorDescription
5089 }
5090 }
5091
5092 LOGGER.info('Successfully refresh token for user {0}', username);
5093 return responseObject.bodyObject;
5094 },
5095
5096 /**
5097 * Validate access token key of user is invalid or expired
5098 * @param {String} token The access token key of user
5099 * @param {String} sapiEndpoint The SAPI endpoint
5100 * @return {Boolean|String}
5101 */
5102 validateToken: function (token, sapiEndpoint) {
5103 var LOGGER = this.LOGGER;
5104
5105 LOGGER.info('Preparing for validating token "{0}"...', token.toString());
5106
5107 var configData = this.saraConfig.getClientConfig();
5108 var response = this.executeGetRequest(token, sapiEndpoint);
5109 var responseObject = response.getResponseObject();
5110
5111 if (response.haveError()) {
5112 if (responseObject.statusCode !== 401) {
5113 var message = SaraUtils.formatString('Error when validating token! Error code: {0} - Error message: {1}', responseObject.statusCode, responseObject.errorMessage);
5114 LOGGER.error(message);
5115 return message;
5116 } else {
5117 var username = this.saraConfig.getTechnicalUser();
5118 this.removeUserToken(username);
5119 return false;
5120 }
5121 } else {
5122 LOGGER.info('Preparing for validating services endpoint ...');
5123 response = this.executeGetRequest(token, SaraUtils.buildUrl('services', sapiEndpoint));
5124 LOGGER.debug('Response of validating services endpoint {0} ...', responseObject);
5125 responseObject = response.getResponseObject();
5126 if(responseObject.statusCode === 200) {
5127 return true;
5128 }
5129 LOGGER.error(responseObject.errorMessage);
5130 return SaraUtils.formatString('Error when validating SAPI get services endpoint! Error code: {0} - Error message: {1}', responseObject.statusCode, responseObject.errorMessage);
5131 }
5132 },
5133
5134 /**
5135 * Execute get request
5136 * @param {String} token The access token key of user
5137 * @param {String} sapiEndpoint The SAPI endpoint
5138 * @return {SaraRESTResponse}
5139 */
5140 executeGetRequest: function (token, sapiEndpoint) {
5141 var request = this.restClient.newSAPIRequest('get', sapiEndpoint);
5142 request.addHeader('Authorization', 'bearer ' + token);
5143 return this.restClient.executeWithRefreshToken(request);
5144 },
5145
5146 type: 'SaraOAuthClient'
5147};
5148]]></script>
5149 <description>This class contains all OAuth-relaled functions</description>
5150 <active>true</active>
5151 <client_callable>false</client_callable>
5152 <access>public</access>
5153 </script_include>
5154
5155 <script_include>
5156 <name>SaraRESTClient</name>
5157 <script><![CDATA[/**
5158 * Wraps Service Now RESTMessage in a class to provide convenient methods interacting with SARA REST
5159 */
5160var SaraRESTClient = Class.create();
5161SaraRESTClient.prototype = {
5162 initialize: function () {
5163 this.LOGGER = new SaraLog(this);
5164 },
5165
5166 /**
5167 * Init new service request from SaraRESTMessage class
5168 * @param {String} name The name of the REST message record
5169 * @param {String} method The name of the HTTP method to use, such as GET or PUT
5170 * @param {String} endpoint The endpoint for the REST message
5171 * @param {Array<String>} basicAuthCreds The basic authentication headers for the REST message
5172 * @param {Array<Object>} headers The object contains headers for the REST message
5173 * @param {Array<Object>} stringParameters The object contains string parameters for the REST message
5174 * @param {Array<Object>} stringParametersNoEscape The object contains string parameters which will be not escaped for the REST message
5175 * @return {SaraRESTMessage}
5176 */
5177 newServiceRequest: function (name, method, endpoint, basicAuthCreds, headers, stringParameters, stringParametersNoEscape) {
5178 var restMsg = new SaraRESTMessage(name, method);
5179
5180 if (endpoint) {
5181 restMsg.setEndpoint(endpoint);
5182 }
5183
5184 if (this.midServer) {
5185 restMsg.setMIDServer(this.midServer);
5186 }
5187
5188 if (basicAuthCreds && basicAuthCreds.length > 1) {
5189 restMsg.setBasicAuth(basicAuthCreds[0], basicAuthCreds[1]);
5190 }
5191
5192 if (headers) {
5193 for (var i = 0, header; header = headers[i]; i++) {
5194 if (header['name']) {
5195 restMsg.addHeader(header['name'], header['value']);
5196 }
5197 }
5198 }
5199
5200 if (stringParameters) {
5201 for (var i = 0, stringParameter; stringParameter = stringParameters[i]; i++) {
5202 if (stringParameter['name']) {
5203 restMsg.setStringParameter(stringParameter['name'], stringParameter['value']);
5204 }
5205 }
5206 }
5207
5208 if (stringParametersNoEscape) {
5209 for (var i = 0, stringParameter; stringParameter = stringParametersNoEscape[i]; i++) {
5210 if (stringParameter['name']) {
5211 restMsg.setStringParameterNoEscape(stringParameter['name'], stringParameter['value']);
5212 }
5213 }
5214 }
5215
5216 return restMsg;
5217 },
5218
5219 /**
5220 * Init new SAPI service request from SaraRESTMessage class
5221 * @param {String} method The name of the HTTP method to use, such as GET or PUT
5222 * @param {String} endpoint The endpoint for the REST message
5223 * @param {Array<String>} basicAuthCreds The basic authentication headers for the REST message
5224 * @param {Array<Object>} headers The object contains headers for the REST message
5225 * @param {Array<Object>} stringParameters The object contains string parameters for the REST message
5226 * @param {Array<Object>} stringParametersNoEscape The object contains string parameters which will be not escaped for the REST message
5227 * @return {SaraRESTMessage}
5228 */
5229 newSAPIRequest: function (method, endpoint, basicAuthCreds, headers, stringParameters, stringParametersNoEscape) {
5230 return this.newServiceRequest(SaraCommon.REST_NAME.SAPI, method, endpoint, basicAuthCreds, headers)
5231 },
5232
5233 /**
5234 * Init new OAuth service request from SaraRESTMessage class
5235 * @param {String} method The name of the HTTP method to use, such as GET or PUT
5236 * @param {String} endpoint The endpoint for the REST message
5237 * @param {Array<String>} basicAuthCreds The basic authentication headers for the REST message
5238 * @param {Array<Object>} headers The object contains headers for the REST message
5239 * @param {Array<Object>} stringParameters The object contains string parameters for the REST message
5240 * @param {Array<Object>} stringParametersNoEscape The object contains string parameters which will be not escaped for the REST message
5241 * @return {SaraRESTMessage}
5242 */
5243 newOAuthRequest: function (method, endpoint, basicAuthCreds, headers, stringParameters, stringParametersNoEscape) {
5244 return this.newServiceRequest(SaraCommon.REST_NAME.OAUTH, method, endpoint, basicAuthCreds, headers)
5245 },
5246
5247 /**
5248 * Execute REST Message request
5249 * @param {SaraRESTMessage} saraRest Sara REST Message object
5250 * @return {SaraRESTResponse}
5251 */
5252 execute: function (saraRest) {
5253 var LOGGER = this.LOGGER;
5254
5255 LOGGER.info('Making {0} request to {1}...', saraRest.getMethod(), saraRest.getEndpoint());
5256 LOGGER.debug(saraRest.dump());
5257
5258 var response;
5259 if (this.midServer) {
5260 response = saraRest.executeViaMIDServer(this.midServer);
5261 } else {
5262 response = saraRest.execute();
5263 }
5264
5265 return response;
5266 },
5267
5268 /**
5269 * Execute REST Message request with automatically get new token if token is expired
5270 * @param {SaraRESTMessage} saraRest Sara REST Message object
5271 * @return {SaraRESTResponse}
5272 */
5273 executeWithRefreshToken: function (saraRest) {
5274 var LOGGER = this.LOGGER;
5275
5276 // First time request
5277 var response = this.execute(saraRest);
5278 var responseObject = response.getResponseObject();
5279
5280 if (response.haveError()) {
5281 if (responseObject.statusCode === 401) {
5282 LOGGER.info('Access token of user is invalid or expired');
5283
5284 var oauthClient = new SaraOAuthClient(this);
5285 var username = new SaraConfig().getTechnicalUser();
5286
5287 LOGGER.info('Trying to refresh token for user "{0}"...', username);
5288 var tokens = oauthClient.refreshToken(username);
5289
5290 if (tokens && !tokens.error) {
5291 LOGGER.info('Refresh token finished successfully.');
5292 oauthClient.storeUserTokens(username, tokens['access_token'], tokens['refresh_token'], tokens['expires_in'], tokens['token_type']);
5293
5294 // Request again with new token
5295 saraRest.addHeader('Authorization', 'bearer ' + tokens['access_token']);
5296 response = this.execute(saraRest);
5297 } else {
5298 LOGGER.error('Error when refreshing token');
5299
5300 if (!tokens) {
5301 LOGGER.info('Error: {0} - Error description: {1}', tokens.error, tokens.errorDescription);
5302 oauthClient.removeUserToken(username);
5303 }
5304 }
5305 }
5306 }
5307
5308 return response;
5309 },
5310
5311 /**
5312 * Set MID Server
5313 * @param {String} midServer The MID Server name
5314 */
5315 setMIDServer: function (midServer) {
5316 this.midServer = midServer;
5317 },
5318
5319 type: 'SaraRESTClient'
5320};
5321]]></script>
5322 <description>Wraps Service Now RESTMessage in a class to provide convenient methods interacting with SARA REST</description>
5323 <active>true</active>
5324 <client_callable>false</client_callable>
5325 <access>public</access>
5326 </script_include>
5327
5328 <script_include>
5329 <name>SaraRESTMessage</name>
5330 <script><![CDATA[/**
5331 * Wrap original ServiceNow's RESTMessageV2 class to make HTTP request
5332 */
5333var SaraRESTMessage = Class.create();
5334SaraRESTMessage.prototype = {
5335 /**
5336 * Init Sara REST Message object
5337 * @param {String} name Name of REST message record
5338 * @param {String} method The name of the HTTP method to use, such as GET or PUT
5339 */
5340 initialize: function (name, method) {
5341 method = method.toLowerCase();
5342 this.restMsg = new sn_ws.RESTMessageV2(name, method);
5343 this.restMsg.setEccParameter('skip_sensor', true);
5344 this.name = name;
5345 this.method = method;
5346
5347 this.LOGGER = new SaraLog(this);
5348 },
5349
5350 /**
5351 * Set the content of the REST message body
5352 * @param {String} content The content of REST Message
5353 */
5354 setContent: function (content) {
5355 this.restMsg.setRequestBody(content);
5356 },
5357
5358 /**
5359 * Set form content for REST Message
5360 * @param {Object} formData The object contains form data
5361 */
5362 setFormContent: function (formData) {
5363 if (!formData) {
5364 return;
5365 }
5366
5367 var content = '';
5368
5369 for (var propName in formData) {
5370 var value = formData[propName];
5371
5372 if (value instanceof Array) {
5373 for (var i = 0; i < value.length; i++) {
5374 var _value = value[i];
5375
5376 content += (encodeURIComponent(propName) + '=' + encodeURIComponent(_value) + '&');
5377 }
5378 } else {
5379 content += (encodeURIComponent(propName) + '=' + encodeURIComponent(value) + '&');
5380 }
5381 }
5382
5383 if (content.length > 0) {
5384 content = content.substring(0, content.length - 1);
5385 this.setContent(content);
5386 }
5387 },
5388
5389 /**
5390 * Get the content of the REST message body
5391 * @return {String}
5392 */
5393 getContent: function () {
5394 return this.restMsg.getRequestBody();
5395 },
5396
5397 /**
5398 * Add headers for REST Message
5399 * @param {String} key The key of header
5400 * @param {*} value The value of header
5401 */
5402 addHeader: function (key, value) {
5403 var LOGGER = this.LOGGER;
5404
5405 LOGGER.debug('addHeader: key = "{0}" and value = "{1}"', key, value);
5406
5407 this.restMsg.setRequestHeader(key, value);
5408 },
5409
5410 /**
5411 * Add type for header named 'content-type'
5412 * @param {String} type The content type of REST Message
5413 */
5414 setContentType: function (type) {
5415 var LOGGER = this.LOGGER;
5416
5417 LOGGER.debug('setContentType: type = "{0}"', type);
5418
5419 this.addHeader('content-type', type);
5420 },
5421
5422 /**
5423 * Set basic authentication headers for the REST message
5424 * @param {String} usename
5425 * @param {String} password
5426 */
5427 setBasicAuth: function (username, password) {
5428 var LOGGER = this.LOGGER;
5429
5430 LOGGER.debug('setBasicAuth: username = "{0}" and password = "{1}"', username, password);
5431
5432 this.restMsg.setBasicAuth(username, password);
5433 },
5434
5435 /**
5436 * Set a REST message function variable to the specified value
5437 * @param {String} name The name of parameter
5438 * @param {String} value The value of parameter
5439 */
5440 setStringParameter: function (name, value) {
5441 var LOGGER = this.LOGGER;
5442
5443 LOGGER.debug('setStringParameter: name = "{0}" and value = "{1}"', name, value);
5444
5445 this.restMsg.setStringParameter(name, value);
5446 },
5447
5448 /**
5449 * Set a REST message function variable to the specified value without escaping XML reserved characters
5450 * @param {String} name The name of parameter
5451 * @param {String} value The value of parameter
5452 */
5453 setStringParameterNoEscape: function (name, value) {
5454 var LOGGER = this.LOGGER;
5455
5456 LOGGER.debug('setStringParameterNoEscape: name = "{0}" and value = "{1}"', name, value);
5457
5458 this.restMsg.setStringParameterNoEscape(name, value);
5459 },
5460
5461 /**
5462 * Set the endpoint for the REST message
5463 * @param {String} endpoint
5464 */
5465 setEndpoint: function (endpoint) {
5466 var LOGGER = this.LOGGER;
5467
5468 LOGGER.debug('setEndpoint: endpoint = "{0}"', endpoint);
5469
5470 this.restMsg.setEndpoint(endpoint);
5471 },
5472
5473 /**
5474 * Get the URL of the endpoint for the REST message.
5475 * @return {String}
5476 */
5477 getEndpoint: function () {
5478 return this.restMsg.getEndpoint();
5479 },
5480
5481 /**
5482 * Configure the REST message to communicate through a MID Server.
5483 * @param {String} midServer The name of MID Server
5484 */
5485 setMIDServer: function (midServer) {
5486 var LOGGER = this.LOGGER;
5487
5488 LOGGER.debug('setMIDServer: midServer = "{0}"', midServer);
5489
5490 this.restMsg.setMIDServer(midServer);
5491 },
5492
5493 /**
5494 * Send REST Message to endpoint
5495 * @return {}
5496 */
5497 execute: function () {
5498 return new SaraRESTResponse(this.restMsg.execute());
5499 },
5500
5501 /**
5502 * Execute REST request via MID Server
5503 * @param {String} midServer The name of MID Server
5504 */
5505 executeViaMIDServer: function (midServer) {
5506 var LOGGER = this.LOGGER;
5507
5508 if (midServer) {
5509 this.restMsg.setMIDServer(midServer);
5510 this.midServer = midServer;
5511 LOGGER.info('Using MID Server {0}', this.midServer);
5512 }
5513
5514 if (!this.midServer) {
5515 LOGGER.info('No MID Server defined for the request. Request is aborted!');
5516 return null;
5517 }
5518
5519 return new SaraRESTResponse(this.restMsg.execute(), true);
5520 },
5521
5522 /**
5523 * Get method name of this REST Message
5524 * @return {String}
5525 */
5526 getMethod: function () {
5527 return this.method.toUpperCase();
5528 },
5529
5530 /**
5531 * Dump information of REST Message
5532 */
5533 dump: function () {
5534 var LOGGER = this.LOGGER;
5535
5536 try {
5537 var str = this.getMethod() + ' ' + this.getEndpoint() + ' HTTP/1.1';
5538
5539 var headers = this.restMsg.getRequestHeaders();
5540 if (headers) {
5541 for (key in headers) {
5542 var value = headers[key];
5543
5544 if (!gs.nil(value)) {
5545 if (key === 'Authorization') {
5546 value = '**********************';
5547 }
5548
5549 str += SaraUtils.formatString('\n {0}: {1}', key, value);
5550 }
5551 }
5552 }
5553
5554 var content = this.getContent();
5555
5556 if (!gs.nil(content) && content !== 'undefined' && content) {
5557 str += SaraUtils.formatString('\n\n', content);
5558 }
5559
5560 return str;
5561 } catch (error) {
5562 LOGGER.info('Error in SaraRESTMessage.dump(): ' + error);
5563 }
5564 },
5565
5566 type: 'SaraRESTMessage'
5567};
5568]]></script>
5569 <description>Class extend from original ServiceNow's RESTMessage class to make HTTP request</description>
5570 <active>true</active>
5571 <client_callable>false</client_callable>
5572 <access>package_private</access>
5573 </script_include>
5574
5575 <script_include>
5576 <name>SaraRESTResponse</name>
5577 <script><![CDATA[/**
5578 * Wrap original ServiceNow's RESTResponseV2 class to handle response of RESTMessageV2
5579 */
5580var SaraRESTResponse = Class.create();
5581SaraRESTResponse.prototype = {
5582 /**
5583 * Init Sara REST Response object
5584 * @param {sn_ws.RESTResponseV2} response The response object of RESTResponseV2
5585 * @param {Boolean} useMIDServer Get response via MID Server or not
5586 */
5587 initialize: function (response, useMIDServer) {
5588 this.response = response;
5589
5590 var LOGGER = this.LOGGER = new SaraLog(this);
5591
5592 if (useMIDServer) {
5593 var timeout = SaraUtils.getSaraProperty(SaraCommon.SYSTEM_PROPERTY_NAME.REST_REQUEST_TIMEOUT);
5594 LOGGER.debug('Timeout for REST Message: {0}s', timeout);
5595 response.waitForResponse(timeout);
5596 }
5597
5598 if (response.haveError()) {
5599 LOGGER.info('Error when requesting REST Message: {0} - {1}', response.getErrorCode(), response.getErrorMessage());
5600 } else {
5601 LOGGER.info('Status code: {0}', response.getStatusCode());
5602 }
5603
5604 LOGGER.debug('Response body: {0}', response.getBody());
5605 },
5606
5607 /**
5608 * Set the amount of time the instance waits for the response
5609 * @param {Number} timeoutSecs The amount of time, in seconds, to wait for this response.
5610 */
5611 waitForResponse: function (timeoutSecs) {
5612 this.response.waitForResponse(timeoutSecs);
5613 },
5614
5615 /**
5616 * Get the numeric HTTP status code returned by the REST provider
5617 * @return {Number}
5618 */
5619 getStatusCode: function () {
5620 return this.response.getStatusCode();
5621 },
5622
5623 /**
5624 * Get the value for a specified header
5625 * @param {Number} timeoutSecs The name of the header that you want the value for, such as Set-Cookie.
5626 * @return {String}
5627 */
5628 getHeader: function (name) {
5629 return this.response.getHeader(name);
5630 },
5631
5632 /**
5633 * Get all headers returned in the REST response and the associated values
5634 * @return {Object}
5635 */
5636 getHeaders: function () {
5637 return this.response.getHeaders();
5638 },
5639
5640 /**
5641 * Get the content of the REST response body
5642 * @return {String}
5643 */
5644 getBody: function () {
5645 return this.response.getBody();
5646 },
5647
5648 /**
5649 * Indicate if there was an error during the REST transaction
5650 * @return {Boolean}
5651 */
5652 haveError: function () {
5653 return this.response.haveError();
5654 },
5655
5656 /**
5657 * Get the numeric error code if there was an error during the REST transaction. This error code is
5658 * specific to the ServiceNow platform, it is not an HTTP error code. Provide this error code if you
5659 * require assistance from ServiceNow Customer Support
5660 * @return {Number}
5661 */
5662 getErrorCode: function () {
5663 return this.response.getErrorCode();
5664 },
5665
5666 /**
5667 * Get the error message if there was an error during the REST transaction
5668 * @return {String}
5669 */
5670 getErrorMessage: function () {
5671 return this.response.getErrorMessage();
5672 },
5673
5674 /**
5675 * Get the fully-resolved query sent to the REST endpoint. This query contains the endpoint URL as well
5676 * as any values assigned to variables in the REST message
5677 */
5678 getQueryString: function () {
5679 return this, response.getQueryString();
5680 },
5681
5682 /**
5683 * Get response body with format is Object
5684 * @return {Object|Null}
5685 */
5686 getBodyObject: function () {
5687 var LOGGER = this.LOGGER;
5688
5689 var body = this.getBody();
5690 if (body) {
5691 try {
5692 body = SaraJSON.parse(body);
5693 } catch (ex) {
5694 LOGGER.error('Error when parsing response body to Object: {0}', ex);
5695 }
5696 }
5697
5698 return body;
5699 },
5700
5701 /**
5702 * Get response with format is Object. This response contains body object, status code, error message and
5703 * error description
5704 * @return {Object}
5705 */
5706 getResponseObject: function () {
5707 var bodyObject = this.getBodyObject();
5708 var statusCode = this.getStatusCode();
5709 var errorMessage = this.getErrorMessage();
5710 var errorDescription = this.getErrorMessage();
5711
5712 if (bodyObject) {
5713 if (bodyObject['error']) {
5714 errorMessage = bodyObject['error'];
5715 }
5716
5717 if (bodyObject['error_description']) {
5718 errorDescription = bodyObject['error_description'];
5719 }
5720 }
5721
5722 return {
5723 bodyObject: bodyObject,
5724 statusCode: statusCode,
5725 errorMessage: errorMessage,
5726 errorDescription: errorDescription
5727 }
5728 },
5729
5730 type: 'SaraRESTResponse'
5731};
5732]]></script>
5733 <description>Wrap original ServiceNow's RESTResponseV2 class to handle RESTMessageV2 response</description>
5734 <active>true</active>
5735 <client_callable>false</client_callable>
5736 <access>package_private</access>
5737 </script_include>
5738
5739 <script_include>
5740 <name>SaraSync</name>
5741 <script><![CDATA[/**
5742 * Sara Sync Utilities
5743 */
5744var SaraSync = Class.create();
5745SaraSync.prototype = {
5746 initialize: function () {
5747 this.glideHelper = new SaraGlideHelper();
5748 this.LOGGER = new SaraLog(this);
5749 this.dal = new SaraConsumerDAL();
5750 },
5751
5752 /**
5753 * Sync services and catalogs of all category which was imported services
5754 */
5755 syncServices: function () {
5756 var glideHelper = this.glideHelper;
5757 var LOGGER = this.LOGGER;
5758
5759 var importedCategories = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {
5760 'u_type': 'category'
5761 }, true);
5762
5763 if (importedCategories.length > 0) {
5764 LOGGER.info('There are {0} target category(s) which were imported services\n', importedCategories.length);
5765
5766 var consumer = new SaraConsumerImportSet();
5767 var response = consumer.discover();
5768
5769 if (response.error) {
5770 LOGGER.error('Discover data from SAPI not successfully. Syncing services is aborted!');
5771 return;
5772 } else {
5773 for (var i = 0; i < importedCategories.length; i++) {
5774 var importedCategory = importedCategories[i];
5775 LOGGER.info('Syncing target category (name = {0}, sys_id = {1})', importedCategory.u_name, importedCategory.u_parent);
5776
5777 consumer.doImport(importedCategory.u_parent);
5778 consumer.refreshImportedData();
5779
5780 LOGGER.info('Target category (name = {0}, sys_id = {1}) is synced!', importedCategory.u_name, importedCategory.u_parent);
5781 }
5782 }
5783 } else {
5784 LOGGER.warn('No target category found. Skip syncServices!');
5785 }
5786 },
5787
5788 /**
5789 * Sync all lookup values of catalog item
5790 * @param {String} saraItem The catalog item in SaraCommon.TABLE_NAME.SARA_DEFINITION
5791 * @param {SaraModel.CatalogItem} catalogItem
5792 */
5793 //saraCatalogItem, catalogItem
5794 syncLookup: function (existDefinition, sapiService) {
5795 var glideHelper = this.glideHelper;
5796 var LOGGER = this.LOGGER;
5797
5798 LOGGER.info('Starting syncLookup... definition: {0}; sapiService: {1}',
5799 SaraJSON.stringify(existDefinition), SaraJSON.stringify(sapiService));
5800
5801 if (sapiService.getVariables()) {
5802 // Get variable set of catalog item
5803 var varSetId = existDefinition.u_var_set;
5804 LOGGER.info('Found sys_id of variable set of {0} is: {1}', existDefinition.u_name, varSetId);
5805
5806 // Get lookup variables of variable set
5807 var saraLookupVariables = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_VARIABLE, {
5808 'variable_set': varSetId,
5809 'u_is_lookup': true
5810 }, true);
5811
5812 if (saraLookupVariables.length > 0) {
5813 LOGGER.info('Found {0} lookup variable(s) in variable set (sys_id = {1})', saraLookupVariables.length, varSetId);
5814
5815 for (var i = 0; i < saraLookupVariables.length; i++) {
5816 var saraVariable = saraLookupVariables[i];
5817 LOGGER.info("Processing variable: " + saraVariable.name);
5818 var variable = this.getVariable(sapiService, saraVariable.name);
5819 if(variable !== null) {
5820 this.updateLookupVariable(saraVariable, variable);
5821 }
5822 }
5823 } else {
5824 LOGGER.warn('No lookup variable found in variable set (sys_id = {0}). Skip syncLookup!', varSetId);
5825 }
5826 } else {
5827 LOGGER.warn('There\' no variable found in catalog (item name = {0}). Skip syncLookup!', existDefinition.u_name);
5828 }
5829
5830 LOGGER.info('Ended syncLookup!');
5831 },
5832
5833 /**
5834 * Get variable from instance of SaraModel.CatalogItem
5835 * @param {SaraModel.CatalogItem} catalogItem
5836 * @param {String} saraVariableName
5837 * @return {SaraModel.CatalogVariable||Null}
5838 */
5839 getVariable: function (sapiService, saraVariableName) {
5840 for (var i = 0; i < sapiService.variables.length; i++) {
5841 if (sapiService.variables[i].name === saraVariableName) {
5842 return sapiService.variables[i];
5843 }
5844 }
5845
5846 return null;
5847 },
5848
5849 /**
5850 * Update lookup variable
5851 * @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'
5852 * @param {SaraModel.CatalogVariable} variable
5853 */
5854 updateLookupVariable: function (saraVariable, variable) {
5855 var glideHelper = this.glideHelper;
5856 var LOGGER = this.LOGGER;
5857
5858 LOGGER.info('New and old hash of variable "{0}": {1} - {2}', saraVariable.name, variable.getHash(), saraVariable.u_hash);
5859
5860 if (variable.getHash() === saraVariable.u_hash) {
5861 LOGGER.info('Lookup value of variable "{0}" is not changed!', saraVariable.name);
5862 } else {
5863 LOGGER.info('Lookup value of variable "{0}" is changed!', saraVariable.name);
5864
5865 this.deactivateOldLookupValues(saraVariable);
5866
5867 var newDefaultValues = [];
5868 var ranges = variable.getRange();
5869
5870 // Insert new range values
5871 for (var i = 0; i < ranges.length; i++) {
5872 var range = ranges[i];
5873 var rangeId = this.dal.saveOrUpdateSaraLookup({
5874 'u_key': range.Value,
5875 'u_display_name': range.Key,
5876 'u_control_id': saraVariable.sys_id
5877 }).sys_id;
5878
5879 if (SaraUtils.inArray(variable.getDefaultValue(), range.Key)) {
5880 if(variable.getType() === SaraCommon.VAR_TYPE.LIST_COLLECTOR) {
5881 newDefaultValues.push(rangeId);
5882 }
5883 else {
5884 newDefaultValues.push(range.Key);
5885 }
5886 }
5887 }
5888 LOGGER.info('Inserted new data of {0} in {1}!', saraVariable.name, SaraCommon.TABLE_NAME.SARA_LOOKUP);
5889
5890 if (saraVariable.default_value) {
5891 newDefaultValues = newDefaultValues.join(',');
5892
5893 saraVariable.default_value = newDefaultValues;
5894 saraVariable.u_hash = variable.getHash();
5895 this.dal.saveOrUpdateVariable(saraVariable);
5896
5897 LOGGER.info('Updated default value for variable (name = {0}, sys_id = {1}) with new default_value = {2}',
5898 saraVariable.name, saraVariable.sys_id, newDefaultValues);
5899 }
5900 }
5901 },
5902
5903 deactivateOldLookupValues: function(saraVariable) {
5904 var glideHelper = this.glideHelper;
5905 var LOGGER = this.LOGGER;
5906 // Remove the old data of lookup table
5907 var lookups = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_LOOKUP, {
5908 'u_control_id': saraVariable.sys_id
5909 }, true);
5910
5911 for(var i = 0; i < lookups.length; i++) {
5912 var lookup = lookups[i];
5913 lookup.u_control_id = "";
5914 this.dal.saveOrUpdateSaraLookup(lookup);
5915 }
5916
5917 LOGGER.info('Deactivated old data of {0} in {1}!', saraVariable.name, SaraCommon.TABLE_NAME.SARA_LOOKUP);
5918 },
5919
5920 type: 'SaraSync'
5921};
5922]]></script>
5923 <description>Sara Sync Utilities</description>
5924 <active>true</active>
5925 <client_callable>false</client_callable>
5926 <access>public</access>
5927 </script_include>
5928
5929 <script_include>
5930 <name>SaraUtils</name>
5931 <script><![CDATA[/**
5932 * Sara Utilities
5933 */
5934var SaraUtils = Class.create();
5935SaraUtils.prototype = {
5936 initialize: function () {},
5937
5938 type: 'SaraUtils'
5939};
5940
5941/**
5942 * Format strings
5943 * @param {String} string The template string
5944 * @param {String[]} args Zero or more objects to format, supplied either in a comma-delimited list or as an array
5945 */
5946SaraUtils.formatString = function (string) {
5947 if(!string) {
5948 return "";
5949 }
5950 var args = Array.prototype.slice.call(arguments, 1);
5951
5952 return string.replace(/\{(\d+)\}/g, function (match, number) {
5953 return typeof args[number] != 'undefined' ? args[number] : match;
5954 });
5955};
5956
5957/**
5958 * Get Sara property
5959 * @param {String} name Name of sara property
5960 * @return {String}
5961 */
5962SaraUtils.getSaraProperty = function (name) {
5963 var property = gs.getProperty(SaraCommon.PROP_PREFIX + '.' + name);
5964 if(property == null) {
5965 property = gs.getProperty(name);
5966 }
5967
5968 return property;
5969};
5970
5971/**
5972 * Get mid servcer
5973 * @return {String}
5974 */
5975SaraUtils.getMIDServer = function () {
5976 return SaraUtils.getSaraProperty(SaraCommon.SYSTEM_PROPERTY_NAME.MID_SERVER);
5977};
5978
5979/**
5980 * Get timestamp of current
5981 * @return {String}
5982 */
5983SaraUtils.getTimeStamp = function () {
5984 return new Date().valueOf();
5985};
5986
5987/**
5988 * Get random number
5989 * @return {String}
5990 */
5991SaraUtils.getRandom = function () {
5992 return Math.round(Math.random() * 987654321);
5993};
5994
5995/**
5996 * Diff time and return 'h, m, s'
5997 * @param {Number} time1 The first timestamp
5998 * @param {Number} time2 The second timestamp
5999 * @return {String}
6000 */
6001SaraUtils.diffTime = function (time1, time2) {
6002 var difference = time2 - time1;
6003
6004 var daysDifference = Math.floor(difference / 1000 / 60 / 60 / 24);
6005 difference -= daysDifference * 1000 * 60 * 60 * 24;
6006
6007 var hoursDifference = Math.floor(difference / 1000 / 60 / 60);
6008 difference -= hoursDifference * 1000 * 60 * 60;
6009
6010 var minutesDifference = Math.floor(difference / 1000 / 60);
6011 difference -= minutesDifference * 1000 * 60;
6012
6013 var secondsDifference = Math.floor(difference / 1000);
6014 difference -= secondsDifference * 1000;
6015
6016 var result = '';
6017
6018 if (daysDifference > 0) {
6019 result += daysDifference + 'd ';
6020 }
6021
6022 if (hoursDifference > 0) {
6023 result += hoursDifference + 'h ';
6024 }
6025
6026 if (minutesDifference > 0) {
6027 result += minutesDifference + 'm ';
6028 }
6029
6030 if (secondsDifference > 0) {
6031 result += secondsDifference + 's ';
6032 }
6033
6034 result += difference + 'ms';
6035
6036 return result;
6037};
6038
6039/**
6040 * Convert '\n' to '<br />' in string
6041 * @param {String} string
6042 * @return {String}
6043 */
6044SaraUtils.nl2br = function (string) {
6045 string = string || '';
6046
6047 return string.replace(/\n/g, '<br />');
6048};
6049
6050/**
6051 * Clean all data of SNSC
6052 */
6053SaraUtils.cleanup = function (filter) {
6054 if (!gs.hasRole(SaraCommon.ROLES.ADMIN)) {
6055 var message = 'You dont\'t have sufficient permission to do this action. Allowed role: ' + SaraCommon.ROLES.ADMIN;
6056 throw new Error(message);
6057 }
6058
6059 var glideHelper = new SaraGlideHelper();
6060 var LOGGER = new SaraLog('SaraUtils');
6061 var catItemIds = [];
6062 var varSetIds = [];
6063 var catCateIds = [];
6064 var targetCateIds = [];
6065
6066 filter = filter || {};
6067
6068 // Get list of catalog item from SaraCommon.TABLE_NAME.SARA_DEFINITION table
6069 var saraItems = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, filter, true);
6070
6071 if (saraItems.length > 0) {
6072 LOGGER.info('Found {0} item(s) in "{1}"', saraItems.length, SaraCommon.TABLE_NAME.SARA_DEFINITION);
6073
6074 for (var i = 0, saraItem; saraItem = saraItems[i]; i++) {
6075 if (saraItem['u_sc_item']) {
6076 catItemIds.push(saraItem['u_sc_item']);
6077 }
6078
6079 if (saraItem['u_var_set']) {
6080 varSetIds.push(saraItem['u_var_set']);
6081 }
6082
6083 if (saraItem['u_service_catalog_category']) {
6084 catCateIds.push(saraItem['u_service_catalog_category']);
6085 }
6086
6087 if (saraItem['u_type'] === 'category') {
6088 targetCateIds.push(saraItem['u_parent']);
6089 }
6090 }
6091
6092 var message = 'There are :';
6093 message += SaraUtils.formatString('\n - {0} catalog item(s)', catItemIds.length);
6094 message += SaraUtils.formatString('\n - {0} variable set(s)', varSetIds.length);
6095 message += SaraUtils.formatString('\n - {0} category(s)', catCateIds.length);
6096 message += SaraUtils.formatString('\n - {0} target category(s)', targetCateIds.length);
6097 LOGGER.info(message);
6098
6099 if (varSetIds.length > 0) {
6100 LOGGER.info('Removing {0} variable set(s)...', varSetIds.length);
6101
6102 for (var i = 0, varSetId; varSetId = varSetIds[i]; i++) {
6103 // Remove all variables belong to above variable sets
6104 LOGGER.info('Removing variables from variable set {0}...', varSetId);
6105 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_VARIABLE, {
6106 'variable_set': varSetId
6107 }, true);
6108
6109 // Remove all variable sets
6110 LOGGER.info('Removing variable set (sys_id = {0})...', varSetId);
6111 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_VARIABLE_SET, {
6112 'sys_id': varSetId
6113 }, true);
6114 }
6115 }
6116
6117 // Cleanup service catalog items
6118 if (catItemIds.length > 0) {
6119 LOGGER.info('Removing {0} catalog item(s)...', catItemIds.length);
6120
6121 for (var i = 0, catItemId; catItemId = catItemIds[i]; i++) {
6122 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_CAT_ITEM, {
6123 'sys_id': catItemId
6124 });
6125 }
6126 }
6127
6128 // Cleanup catalog categories
6129 if (catCateIds.length > 0) {
6130 LOGGER.info('Removing {0} catalog category(s)...', catCateIds.length);
6131
6132 for (var i = 0, catCateId; catCateId = catCateIds[i]; i++) {
6133 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_CATEGORY, {
6134 'sys_id': catCateId
6135 });
6136 }
6137 }
6138
6139 // Refresh target categories
6140 if (targetCateIds.length > 0) {
6141 LOGGER.info('Refreshing {0} target category(s)...', catCateIds.length);
6142
6143 for (var i = 0, targetCateId; targetCateId = targetCateIds[i]; i++) {
6144 glideHelper.updateData(SaraCommon.TABLE_NAME.SN_CATEGORY, {
6145 'sys_id': targetCateId
6146 }, {
6147 'active': false
6148 });
6149
6150 glideHelper.updateData(SaraCommon.TABLE_NAME.SN_CATEGORY, {
6151 'sys_id': targetCateId
6152 }, {
6153 'active': true
6154 });
6155
6156 LOGGER.info('Target category (sys_id = {0}) is refreshed.', targetCateId);
6157 }
6158 }
6159
6160 LOGGER.info('Cleaning up {0} table ...', SaraCommon.TABLE_NAME.SARA_DEFINITION);
6161 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {}, true);
6162
6163 LOGGER.info('Cleaning up {0} table ...', SaraCommon.TABLE_NAME.SARA_VARIABLE);
6164 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_VARIABLE, {}, true);
6165 } else {
6166 LOGGER.warn('There is no items in "{0}". Skip cleanup!', SaraCommon.TABLE_NAME.SARA_DEFINITION);
6167 }
6168};
6169
6170/**
6171 * Create catalog variable from field information
6172 * @param {Object} field
6173 * @return {SaraModel.CatalogVariable}
6174 */
6175SaraUtils.createCatalogVariable = function (field) {
6176 var defaultValue = '';
6177 var varType;
6178 var isLookupControl = false;
6179 var LOGGER = new SaraLog('SaraUtils');
6180
6181 if (field['default'] && field['default'].length > 0) {
6182 defaultValue = field['default'];
6183 }
6184
6185 switch (field.type) {
6186 case 'Label':
6187 varType = SaraCommon.VAR_TYPE.LABEL;
6188 break;
6189 case 'Number':
6190 // SN only have NUM_SCALE variable type but not suitable, just use string
6191 varType = SaraCommon.VAR_TYPE.SINGLE_LINE_TEXT;
6192 break;
6193 case 'String':
6194 varType = SaraCommon.VAR_TYPE.SINGLE_LINE_TEXT;
6195 break;
6196 case 'List':
6197 varType = field.multiSelect ? SaraCommon.VAR_TYPE.LIST_COLLECTOR : SaraCommon.VAR_TYPE.LOOKUP_SELECT_BOX;
6198 isLookupControl = true;
6199 break;
6200 case 'Time':
6201 varType = SaraCommon.VAR_TYPE.SINGLE_LINE_TEXT;
6202 break;
6203 case 'Date':
6204 varType = SaraCommon.VAR_TYPE.DATE;
6205 break;
6206 case 'Timestamp':
6207 varType = SaraCommon.VAR_TYPE.DATE_TIME;
6208 break;
6209 default:
6210 break;
6211 }
6212
6213 var catalogVariable = new SaraModel.CatalogVariable();
6214 catalogVariable.setName(this.legitVarName(field.name));
6215 catalogVariable.setType(varType);
6216 catalogVariable.setLabel(field.caption);
6217 catalogVariable.setDefaultValue(defaultValue);
6218 catalogVariable.setDescription(field.description);
6219 catalogVariable.setRange([]);
6220 catalogVariable.setAsLookup(isLookupControl);
6221
6222 if(field.order != null && field.order != undefined) {
6223 catalogVariable.setOrder(field.order);
6224 }
6225
6226 if (field.maskAsPassword) {
6227 catalogVariable.setAsPassword(field.maskAsPassword);
6228 }
6229
6230 if (field.range && field.range[0].values) {
6231 var rangeValue = field.range[0].values;
6232 catalogVariable.setRange(rangeValue);
6233
6234 // Generate range hash for variable
6235 var hash = SaraUtils.md5(SaraJSON.stringify(rangeValue));
6236 catalogVariable.setHash(hash);
6237 }
6238
6239 if (field.name) {
6240 catalogVariable.setActualName(field.name);
6241 }
6242
6243 if (field.required) {
6244 catalogVariable.setRequired(field.required);
6245 }
6246
6247 if (field.multiSelect) {
6248 catalogVariable.setMultiSelect(field.multiSelect);
6249 }
6250
6251 return catalogVariable;
6252};
6253
6254/**
6255 * Legitimates variable name that is not qualified business rule validate_variable_name
6256 * @param {String} varName
6257 * @return {String}
6258 */
6259SaraUtils.legitVarName = function (varName) {
6260 var firstLegal = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
6261 var firstLetter = varName.charAt(0);
6262 if (firstLegal.indexOf(firstLetter) == -1) {
6263 varName = 'v_' + varName;
6264 }
6265
6266 var legal = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789';
6267 for (var i = 0; i < varName.length; i++) {
6268 var letter = varName.charAt(i);
6269 if (legal.indexOf(letter) == -1) {
6270 // replace illegal char with _
6271 varName = varName.substr(0, i) + '_' + varName.substr(i + 1);
6272 }
6273 }
6274
6275 return varName;
6276};
6277
6278SaraUtils.getImportTargetCatRefQual = function(){
6279 var gh = new SaraGlideHelper();
6280
6281 var catalogs = gh.getData('sc_catalog', {}, true);
6282 var catalogIds = [];
6283 for(var i = 0; i < catalogs.length; i++) {
6284 catalogIds.push(catalogs[i].sys_id);
6285 }
6286
6287 var catalogFilter = ['IN', catalogIds.join(',')];
6288 gs.info('catalogFilter = ' + catalogFilter);
6289
6290 var result = 'sys_idIN';
6291 var cats = gh.getData('sc_category', {sc_catalog: catalogFilter}, true);
6292 var categoryIds = [];
6293
6294 for(i = 0;i < cats.length; i++) {
6295 var cat = cats[i];
6296 gs.info(SaraJSON.stringify(cat));
6297 categoryIds.push(cat.sys_id);
6298 }
6299 result += categoryIds.join(',');
6300
6301 return result;
6302};
6303
6304/**
6305 * Build url
6306 * @param {String} url
6307 * @param {String} baseUrl
6308 * @return {String}
6309 */
6310SaraUtils.buildUrl = function (url, baseUrl) {
6311 var LOGGER = new SaraLog('SaraUtils');
6312
6313 if (!url) {
6314 url = '';
6315 }
6316
6317 var scheme;
6318 var pattern = /^https?:\/\//i;
6319 if (pattern.test(url)) {
6320 scheme = 'absolute';
6321 } else {
6322 scheme = 'relative';
6323 }
6324
6325 if (scheme === 'relative') {
6326 var basePath = new SaraConfig().getBasePath();
6327 if(baseUrl) {
6328 LOGGER.debug('Found baseUrl type {0} - value {1}', typeof baseUrl, baseUrl);
6329 basePath = baseUrl;
6330 if(typeof baseUrl === 'object') {
6331 basePath = JSON.stringify(baseUrl).replace(/"/g, '');
6332 }
6333 LOGGER.debug('basePath: {0}', basePath);
6334 }
6335
6336 if (basePath.charAt(basePath.length - 1) == '/' && url.substring(0, 1) == '/') {
6337 return basePath + url.substring(1);
6338 }
6339
6340 if (basePath.charAt(basePath.length - 1) != '/' && url.substring(0, 1) != '/') {
6341 return basePath + '/' + url;
6342 }
6343
6344 return basePath + url;
6345 }
6346
6347 if (url == '/') {
6348 return new SaraConfig().getBasePath();
6349 }
6350
6351 return url;
6352};
6353
6354/**
6355 * Gets index of item in array
6356 * @param {Array} array
6357 * @param {*} item
6358 * @return {Number}
6359 */
6360SaraUtils.indexOf = function (array, item) {
6361 for (var i = 0; i < array.length; ++i) {
6362 if (array[i] === item) {
6363 return i;
6364 }
6365 }
6366
6367 return -1;
6368};
6369
6370/**
6371 * Detects the array item is in array or not
6372 * @param {Array} array
6373 * @param {*} item
6374 * @return {Boolean}
6375 */
6376SaraUtils.inArray = function (array, item) {
6377 return SaraUtils.indexOf(array, item) !== -1;
6378};
6379
6380/**
6381 * Get redirection endpoint of current instance
6382 * @return {String} The redirection endpoint
6383 */
6384SaraUtils.getRedirectionUrl = function () {
6385 return gs.getProperty('glide.servlet.uri') + SaraCommon.SCOPED_APP + '_sara_oauth_callback.do';
6386};
6387
6388SaraUtils.guardNotNullOrEmpty = function(param, msg) {
6389 if(!param || param === null || param === "") {
6390 throw msg;
6391 }
6392};
6393
6394SaraUtils.isNullOrEmpty = function(param) {
6395 if(!param || param === null || param === "") {
6396 return true;
6397 }
6398 return false;
6399};
6400
6401SaraUtils.md5 = function (string, key, raw) {
6402 /*
6403 * JavaScript MD5 1.0.1
6404 * https://github.com/blueimp/JavaScript-MD5
6405 *
6406 * Copyright 2011, Sebastian Tschan
6407 * https://blueimp.net
6408 *
6409 * Licensed under the MIT license:
6410 * http://www.opensource.org/licenses/MIT
6411 *
6412 * Based on
6413 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
6414 * Digest Algorithm, as defined in RFC 1321.
6415 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
6416 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
6417 * Distributed under the BSD License
6418 * See http://pajhome.org.uk/crypt/md5 for more info.
6419 */
6420 /*jslint bitwise: true */
6421 /*global unescape, define */
6422
6423 'use strict';
6424 /*
6425 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
6426 * to work around bugs in some JS interpreters.
6427 */
6428 function safe_add(x, y) {
6429 var lsw = (x & 0xFFFF) + (y & 0xFFFF),
6430 msw = (x >> 16) + (y >> 16) + (lsw >> 16);
6431 return (msw << 16) | (lsw & 0xFFFF);
6432 }
6433 /*
6434 * Bitwise rotate a 32-bit number to the left.
6435 */
6436 function bit_rol(num, cnt) {
6437 return (num << cnt) | (num >>> (32 - cnt));
6438 }
6439 /*
6440 * These functions implement the four basic operations the algorithm uses.
6441 */
6442 function md5_cmn(q, a, b, x, s, t) {
6443 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
6444 }
6445
6446 function md5_ff(a, b, c, d, x, s, t) {
6447 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
6448 }
6449
6450 function md5_gg(a, b, c, d, x, s, t) {
6451 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
6452 }
6453
6454 function md5_hh(a, b, c, d, x, s, t) {
6455 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
6456 }
6457
6458 function md5_ii(a, b, c, d, x, s, t) {
6459 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
6460 }
6461 /*
6462 * Calculate the MD5 of an array of little-endian words, and a bit length.
6463 */
6464 function binl_md5(x, len) {
6465 /* append padding */
6466 x[len >> 5] |= 0x80 << (len % 32);
6467 x[(((len + 64) >>> 9) << 4) + 14] = len;
6468 var i, olda, oldb, oldc, oldd,
6469 a = 1732584193,
6470 b = -271733879,
6471 c = -1732584194,
6472 d = 271733878;
6473 for (i = 0; i < x.length; i += 16) {
6474 olda = a;
6475 oldb = b;
6476 oldc = c;
6477 oldd = d;
6478 a = md5_ff(a, b, c, d, x[i], 7, -680876936);
6479 d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
6480 c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
6481 b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
6482 a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
6483 d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
6484 c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
6485 b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
6486 a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
6487 d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
6488 c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
6489 b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
6490 a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
6491 d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
6492 c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
6493 b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
6494 a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
6495 d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
6496 c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
6497 b = md5_gg(b, c, d, a, x[i], 20, -373897302);
6498 a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
6499 d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
6500 c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
6501 b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
6502 a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
6503 d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
6504 c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
6505 b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
6506 a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
6507 d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
6508 c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
6509 b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
6510 a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
6511 d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
6512 c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
6513 b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
6514 a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
6515 d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
6516 c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
6517 b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
6518 a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
6519 d = md5_hh(d, a, b, c, x[i], 11, -358537222);
6520 c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
6521 b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
6522 a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
6523 d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
6524 c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
6525 b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
6526 a = md5_ii(a, b, c, d, x[i], 6, -198630844);
6527 d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
6528 c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
6529 b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
6530 a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
6531 d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
6532 c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
6533 b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
6534 a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
6535 d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
6536 c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
6537 b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
6538 a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
6539 d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
6540 c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
6541 b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
6542 a = safe_add(a, olda);
6543 b = safe_add(b, oldb);
6544 c = safe_add(c, oldc);
6545 d = safe_add(d, oldd);
6546 }
6547 return [a, b, c, d];
6548 }
6549 /*
6550 * Convert an array of little-endian words to a string
6551 */
6552 function binl2rstr(input) {
6553 var i,
6554 output = '';
6555 for (i = 0; i < input.length * 32; i += 8) {
6556 output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
6557 }
6558 return output;
6559 }
6560 /*
6561 * Convert a raw string to an array of little-endian words
6562 * Characters >255 have their high-byte silently ignored.
6563 */
6564 function rstr2binl(input) {
6565 var i,
6566 output = [];
6567 output[(input.length >> 2) - 1] = undefined;
6568 for (i = 0; i < output.length; i += 1) {
6569 output[i] = 0;
6570 }
6571 for (i = 0; i < input.length * 8; i += 8) {
6572 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
6573 }
6574 return output;
6575 }
6576 /*
6577 * Calculate the MD5 of a raw string
6578 */
6579 function rstr_md5(s) {
6580 return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
6581 }
6582 /*
6583 * Calculate the HMAC-MD5, of a key and some data (raw strings)
6584 */
6585 function rstr_hmac_md5(key, data) {
6586 var i,
6587 bkey = rstr2binl(key),
6588 ipad = [],
6589 opad = [],
6590 hash;
6591 ipad[15] = opad[15] = undefined;
6592 if (bkey.length > 16) {
6593 bkey = binl_md5(bkey, key.length * 8);
6594 }
6595 for (i = 0; i < 16; i += 1) {
6596 ipad[i] = bkey[i] ^ 0x36363636;
6597 opad[i] = bkey[i] ^ 0x5C5C5C5C;
6598 }
6599 hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
6600 return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
6601 }
6602 /*
6603 * Convert a raw string to a hex string
6604 */
6605 function rstr2hex(input) {
6606 var hex_tab = '0123456789abcdef',
6607 output = '',
6608 x,
6609 i;
6610 for (i = 0; i < input.length; i += 1) {
6611 x = input.charCodeAt(i);
6612 output += hex_tab.charAt((x >>> 4) & 0x0F) +
6613 hex_tab.charAt(x & 0x0F);
6614 }
6615 return output;
6616 }
6617 /*
6618 * Encode a string as utf-8
6619 */
6620 function str2rstr_utf8(input) {
6621 return unescape(encodeURIComponent(input));
6622 }
6623 /*
6624 * Take string arguments and return either raw or hex encoded strings
6625 */
6626 function raw_md5(s) {
6627 return rstr_md5(str2rstr_utf8(s));
6628 }
6629
6630 function hex_md5(s) {
6631 return rstr2hex(raw_md5(s));
6632 }
6633
6634 function raw_hmac_md5(k, d) {
6635 return rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d));
6636 }
6637
6638 function hex_hmac_md5(k, d) {
6639 return rstr2hex(raw_hmac_md5(k, d));
6640 }
6641
6642 if (!key) {
6643 if (!raw) {
6644 return hex_md5(string);
6645 }
6646 return raw_md5(string);
6647 }
6648 if (!raw) {
6649 return hex_hmac_md5(key, string);
6650 }
6651
6652 return raw_hmac_md5(key, string);
6653};
6654]]></script>
6655 <description>Sara Utilities</description>
6656 <active>true</active>
6657 <client_callable>false</client_callable>
6658 <access>public</access>
6659 </script_include>
6660
6661 <script_include>
6662 <name>SaraTestBench</name>
6663 <script><![CDATA[/*
6664Test bench for Sara Scripts
6665Create manually in scope of Automic SNSC
6666Use background script to execute:
6667
6668var test = new SaraTestBench();
6669test.execute();
6670 */
6671var SaraTestBench = Class.create();
6672SaraTestBench.prototype = {
6673 initialize: function () {
6674 },
6675
6676 execute: function(){
6677 SaraTest.resetSummary();
6678
6679 SaraTransformMapTest.execute();
6680
6681 SaraConsumerDALTest.execute();
6682
6683 SaraConsumerImportTest.execute();
6684
6685 gs.info("=======================================================================================");
6686 gs.info("SUMMARY");
6687 gs.info("=======================================================================================");
6688 var summary = SaraTest.getSummary();
6689 gs.info("------ TOTAL: " + summary.total);
6690 gs.info("------ PASS: " + summary.pass);
6691 gs.info("------ FAIL: " + summary.fail);
6692 gs.info("------ IGNORE: " + summary.ignore);
6693 }
6694};
6695
6696var SaraConsumerDALTest = (function() {
6697 var gh = new SaraGlideHelper();
6698 var dal = new SaraConsumerDAL();
6699 return {
6700 execute: function() {
6701 gs.info("----------------------------------------------------------------------------");
6702 gs.info("Test SaraConsumerDAL");
6703 gs.info("----------------------------------------------------------------------------");
6704
6705 this.testGetCatalog();
6706 this.testSaveOrUpdateCatalog();
6707 this.testSaveOrUpdateCategory();
6708 this.testGetDefaultCategoryId();
6709 this.testSaveCategoryToSaraDefinition();
6710 this.testDeactivateSaraDefinition();
6711 },
6712
6713 testGetCatalog: function() {
6714 SaraTest.test("get catalog id by title", function() {
6715 var cat = dal.getCatalog("Service Catalog");
6716 SaraTest.assert(cat !== undefined, "catalog is get correctly");
6717 SaraTest.assert(cat.title === "Service Catalog", "title is get correctly");
6718 gs.info(SaraJSON.stringify(cat));
6719 });
6720 },
6721
6722 testSaveOrUpdateCatalog: function() {
6723 SaraTest.test("save or update catalog", function() {
6724 var catName = "snsc dal cat 1" + SaraUtils.getRandom();
6725 var desc = "test description";
6726
6727 var catId = dal.saveOrUpdateCatalog({
6728 title: catName,
6729 description: desc,
6730 active: true
6731 }).sys_id;
6732 SaraTest.assert(catId !== null, "catalog is persisted correctly");
6733
6734 var cat = gh.getData("sc_catalog", {sys_id: catId});
6735 gs.info(SaraJSON.stringify(cat));
6736 SaraTest.assert(cat !== null, "catalog is get correctly");
6737 SaraTest.assert(cat.title === catName, "title is set correctly");
6738 SaraTest.assert(cat.description === desc, "description is set correctly");
6739 SaraTest.assert(cat.active == "true", "active is set correctly");
6740
6741 gh.deleteData("sc_category", {sc_catalog: catId}, true);
6742 gh.deleteData("sc_catalog", {sys_id: catId}, true);
6743 });
6744 },
6745
6746 testSaveOrUpdateCategory: function() {
6747 SaraTest.test("save or update category", function() {
6748 var catName = "snsc dal cat 2" + SaraUtils.getRandom();
6749 var desc = "test description";
6750 var categoryName = "snsc dal category 2" + SaraUtils.getRandom();
6751 var categoryDescription = "category description";
6752 var categoryNewDescription = "category description new";
6753
6754 var catId = dal.saveOrUpdateCatalog({
6755 title: catName,
6756 description: desc,
6757 active: true
6758 }).sys_id;
6759
6760 var cat = {
6761 sc_catalog: catId,
6762 title: categoryName,
6763 description: categoryDescription,
6764 active: true};
6765 cat.description = categoryDescription;
6766 var category = dal.saveOrUpdateCategory(cat);
6767 gs.info("category: " + SaraJSON.stringify(category));
6768 SaraTest.assert(category !== null, "category is get correctly");
6769 SaraTest.assert(category.title === categoryName, "title is set correctly");
6770 SaraTest.assert(category.description === categoryDescription, "description is set correctly");
6771 SaraTest.assert(category.active == "true", "active is set correctly");
6772
6773 category.description = categoryNewDescription;
6774 category.active = false;
6775 dal.saveOrUpdateCategory(category);
6776
6777 var result = gh.getData("sc_category", {sys_id: category.sys_id});
6778 gs.info("result: " + SaraJSON.stringify(result));
6779
6780 SaraTest.assert(result.description === categoryNewDescription, "description is updated correctly");
6781 SaraTest.assert(result.active == "false", "active is updated correctly");
6782
6783 gh.deleteData("sc_category", {sc_catalog: catId}, true);
6784 gh.deleteData("sc_catalog", {sys_id: catId}, true);
6785 });
6786 },
6787
6788 testGetDefaultCategoryId: function() {
6789 SaraTest.test("get default category", function () {
6790 var catId = dal.getDefaultCategoryId();
6791 var category = gh.getData("sc_category", {sys_id: catId});
6792
6793 SaraTest.assert(category !== null, "getDetaultCategoryId return valid category id");
6794 gs.info(SaraJSON.stringify(category));
6795 });
6796 },
6797
6798 testSaveCategoryToSaraDefinition: function() {
6799 SaraTest.test("save category to sara definition", function() {
6800 var catName = "snsc dal cat 3" + SaraUtils.getRandom();
6801 var desc = "test description";
6802
6803 var categoryName = "snsc dal category 3" + SaraUtils.getRandom();
6804 var categoryDescription = "category description";
6805
6806 var catId = dal.saveOrUpdateCatalog({
6807 title: catName,
6808 description: desc,
6809 active: true
6810 }).sys_id;
6811
6812 var category = dal.saveOrUpdateCategory({
6813 sc_catalog: catId,
6814 title: categoryName,
6815 description: categoryDescription,
6816 active: true
6817 });
6818
6819 var definitionId = dal.saveRootImportCategoryToSaraDefinition(category.sys_id).sys_id;
6820 var definition = gh.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: definitionId});
6821 gs.info(SaraJSON.stringify(definition));
6822
6823 SaraTest.assert(definition !== null, "definition is saved correctly");
6824 SaraTest.assert(definition.u_name === categoryName, "u_name is saved correctly");
6825 SaraTest.assert(definition.u_parent === category.sys_id, "u_parent is saved correctly");
6826 SaraTest.assert(definition.u_type === 'category', "u_type is saved correctly");
6827 SaraTest.assert(definition.u_active == 'true', "active is saved correctly");
6828
6829 gh.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: definitionId}, true);
6830 gh.deleteData("sc_category", {sc_catalog: catId}, true);
6831 gh.deleteData("sc_catalog", {sys_id: catId}, true);
6832 });
6833 },
6834
6835 testDeactivateSaraDefinition: function() {
6836 SaraTest.test("deactivate sara definition", function() {
6837 var catName = "snsc dal cat 6" + SaraUtils.getRandom();
6838 var desc = "test description";
6839 var categoryName = "snsc dal category 6" + SaraUtils.getRandom();
6840 var categoryDescription = "category description";
6841 var catalogItemName = "snsc dal catalog item 6";
6842
6843 var parentDefinitionName = "snsc definition 6 parent" + SaraUtils.getRandom();
6844 var definitionName = "snsc definition 6" + SaraUtils.getRandom();
6845
6846 var catId = dal.saveOrUpdateCatalog({
6847 title: catName,
6848 description: desc,
6849 active: true
6850 }).sys_id;
6851 var category = dal.saveOrUpdateCategory({
6852 title: categoryName,
6853 description: categoryDescription,
6854 sc_catalog: catId
6855 });
6856 var catalogItem = dal.saveOrUpdateCatalogItem({
6857 category: category.sys_id,
6858 name: catalogItemName,
6859 active: true
6860 });
6861
6862 var parentDefinition = dal.saveOrUpdateSaraDefinition({
6863 u_name: parentDefinitionName,
6864 u_active: true,
6865 u_consume_url: "http://testurl.com",
6866 u_parent: category.sys_id,
6867 u_type: 'catalog'
6868 });
6869
6870 var definition = dal.saveOrUpdateSaraDefinition({
6871 u_name: definitionName,
6872 u_active: true,
6873 u_consume_url: "http://testurl.com",
6874 u_parent: category.sys_id,
6875 u_type: 'service',
6876 u_sc_item: catalogItem.sys_id,
6877 u_hash: '123'
6878 });
6879
6880 SaraTest.assert(parentDefinition.u_active == 'true', "parent definition is active");
6881 SaraTest.assert(definition.u_active == 'true', "definition is active");
6882
6883 gs.info("parent definition: " + SaraJSON.stringify(parentDefinition));
6884 gs.info("definition: " + SaraJSON.stringify(definition));
6885
6886 dal.deactivateSaraDefinition(parentDefinition);
6887
6888 definition = gh.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: definition.sys_id});
6889 parentDefinition = gh.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: parentDefinition.sys_id});
6890
6891 category = gh.getData("sc_category", {sys_id: category.sys_id});
6892 gs.info("category: " + SaraJSON.stringify(category));
6893
6894 catalogItem = gh.getData("sc_cat_item", {sys_id: catalogItem.sys_id});
6895 gs.info("catalogItem: " + SaraJSON.stringify(catalogItem));
6896
6897 SaraTest.assert(catalogItem.name === catalogItemName,"get correct catalog item");
6898 SaraTest.assert(catalogItem.active == 'false',"catalog item is deactivated");
6899 SaraTest.assert(definition.u_name === definitionName,"get correct definition");
6900 SaraTest.assert(definition.u_active == 'false',"definition is deactivated");
6901 SaraTest.assert(parentDefinition.u_name === parentDefinitionName,"get correct parent definition");
6902 SaraTest.assert(parentDefinition.u_active == 'false',"parent definition is deactivated");
6903
6904
6905 gh.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: definition.sys_id}, true);
6906 gh.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {sys_id: parentDefinition.sys_id}, true);
6907 //gh.deleteData("sc_cat_item", {category: category.sys_id}, true);
6908 gh.deleteData("sc_category", {sc_catalog: catId}, true);
6909 gh.deleteData("sc_catalog", {sys_id: catId}, true);
6910 });
6911 }
6912 };
6913})();
6914
6915var SaraConsumerImportTest = (function() {
6916 var logger = new SaraLog("SaraGlideHelperTest");
6917 var glideHelper = new SaraGlideHelper();
6918 var categoryName = "snsc test import " + SaraUtils.getRandom();
6919 var consumer = new SaraConsumerImportSet();
6920 var categoryId = null;
6921 var catalogId;
6922 var category;
6923 var dal = new SaraConsumerDAL();
6924 var catItem1 = null;
6925
6926 return {
6927 execute: function() {
6928 gs.info("----------------------------------------------------------------------------");
6929 gs.info("Test SaraConsumerImportSet");
6930 gs.info("----------------------------------------------------------------------------");
6931
6932 this.initialize();
6933
6934 this.testImportCategory();
6935
6936 this.testImportItem();
6937
6938 this.testSyncLookup();
6939
6940 this.tearDown();
6941 },
6942
6943 initialize: function() {
6944 catalogId = glideHelper.getData("sc_catalog", { title: "Service Catalog" }).sys_id;
6945
6946 category = dal.saveOrUpdateCategory({
6947 title: categoryName,
6948 description: "test",
6949 sc_catalog: catalogId,
6950 active: true
6951 });
6952 gs.info("created category: " + category);
6953
6954 gs.info("category to be imported: " + categoryName);
6955
6956 categoryId = category.sys_id;
6957 },
6958
6959 getMockCatalogData: function() {
6960 var catalogsData = {
6961 "DEMO":{
6962 "title":"Automic Demo Services",
6963 "active":true,
6964 "description":"Automic Demo Services",
6965 "parent":"",
6966 "name":"DEMO"},
6967 "DEMO2":{
6968 "title":"DEMO2",
6969 "active":true,
6970 "description":"",
6971 "parent":"",
6972 "name":"DEMO2"}};
6973
6974 //mock catalog data for testing
6975 for(var ctgName in catalogsData) {
6976 this.wrapCategoryData(catalogsData[ctgName]);
6977 }
6978
6979 return catalogsData;
6980 },
6981
6982 getMockupServicesData: function() {
6983 var servicesData = {
6984 "DEMO": {
6985 "PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.ACTIVATE_SNSC_SERVICE.NEW.1":
6986 {
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": "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" },
6994 "PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.DEACTIVATE_SNSC_SERVICE.NEW.1":
6995 {
6996 "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" }
6997 },
6998 "DEMO2": {
6999 "PCK.AUTOMIC_SNSC_CERTIFICATION.PUB.ACTION.DEMO_SERVICE.NEW.1": {
7000 "variables": [
7001 { "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#" },
7002 { "description": "", "label": "Previous Month(s) included", "defaultValue": ["3"], "type": 6, "required": true, "range": [], "asLookup": false, "name": "EOM_MONTHBACK_", "actualName": "EOM_MONTHBACK#" },
7003 { "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#" },
7004 { "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#" },
7005 { "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#" }
7006 ], "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" }
7007 }};
7008
7009 //mock service data for testing
7010 for (var catalogName in servicesData) {
7011 var catalog = servicesData[catalogName];
7012 for(var serviceName in catalog) {
7013 this.wrapServiceData(catalog[serviceName]);
7014 }
7015 }
7016
7017 return servicesData;
7018 },
7019
7020 wrapCategoryData: function(dataObj) {
7021 dataObj.__proto__ = new SaraModel.CatalogCategory();
7022 },
7023
7024 wrapServiceData: function(dataObj) {
7025 dataObj.__proto__ = new SaraModel.CatalogItem();
7026 if(dataObj.variables && dataObj.variables instanceof Array) {
7027 for(var i = 0; i < dataObj.variables.length; i ++) {
7028 dataObj.variables[i].__proto__ = new SaraModel.CatalogVariable();
7029 }
7030 }
7031 },
7032
7033 testImportCategory: function () {
7034 consumer.catalogsData = this.getMockCatalogData();
7035 SaraTest.test("test import categories, de-activate definition removed from AE, update existing definition and create new definition", function () {
7036 var categoryName2 = "snsc test import " + SaraUtils.getRandom();
7037 var categoryName3 = "snsc test import " + SaraUtils.getRandom();
7038
7039 var definitionName = "snsc test import " + SaraUtils.getRandom();
7040 var categoryDescription = "testImportCategory category description";
7041
7042 var category2 = dal.saveOrUpdateCategory({
7043 title: categoryName2,
7044 description: categoryDescription,
7045 sc_catalog: catalogId,
7046 active: true
7047 });
7048
7049
7050 var definition = dal.saveOrUpdateSaraDefinition({
7051 u_name: definitionName,
7052 u_active: true,
7053 u_consume_url: "http://testurl.com",
7054 u_parent: category.sys_id,
7055 u_type: 'catalog',
7056 u_service_catalog_category: category2.sys_id
7057 });
7058
7059 var category3 = dal.saveOrUpdateCategory({
7060 title: categoryName3,
7061 description: categoryDescription,
7062 sc_catalog: catalogId,
7063 active: true
7064 });
7065
7066 var demoDefinition = dal.saveOrUpdateSaraDefinition({
7067 u_name: "DEMO",
7068 u_active: true,
7069 u_consume_url: "oldurl",
7070 u_parent: category.sys_id,
7071 u_type: 'catalog',
7072 u_service_catalog_category: category3.sys_id
7073 });
7074
7075 gs.info("done prepare test data");
7076 //create new definition and make sure that it will be de-activate during synchronization
7077 consumer.importCategory(categoryId);
7078
7079 var resultDefinition = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, { u_name: definitionName, u_parent: category.sys_id });
7080 SaraTest.assert(resultDefinition.u_active == "false", "Definition does not exist in AE should be de-activated");
7081
7082 category2 = glideHelper.getData(SaraCommon.TABLE_NAME.SN_CATEGORY, { sys_id: category2.sys_id });
7083 SaraTest.assert(category2.active == "false", "Category linked to definition does not exist in AE should be de-activated");
7084
7085 category3 = glideHelper.getData(SaraCommon.TABLE_NAME.SN_CATEGORY, { sys_id: category3.sys_id });
7086 SaraTest.assert(category3.parent == category.sys_id, "parent of category linked to definition exist is updated");
7087 SaraTest.assert(category3.title == "Automic Demo Services", "title of category linked to definition exist is updated");
7088 SaraTest.assert(category3.description == "Automic Demo Services", "description of category linked to definition exist is updated");
7089 });
7090 },
7091
7092 testImportItem: function() {
7093 consumer.servicesData = this.getMockupServicesData();
7094
7095 SaraTest.test("test import items", function() {
7096 consumer.importItem();
7097
7098 gs.info("get sub category of " + categoryId);
7099 //get catalog items under import category
7100 var subCategories = glideHelper.getData("sc_category", {parent: categoryId, active: true}, true);
7101 gs.info("sub categories: " + SaraJSON.stringify(subCategories));
7102 SaraTest.assertEqual(subCategories.length, 2, "2 categories are created");
7103 var category1 = subCategories[0].title === "DEMO2" ? subCategories[1] : subCategories[0];
7104 var catItemsOfCategory1 = glideHelper.getData("sc_cat_item", {category: category1.sys_id}, true);
7105
7106 SaraTest.assertEqual(catItemsOfCategory1.length, 2, "2 catalog item under category " + category1.title);
7107
7108 gs.info("catItemsOfCategory1: " + SaraJSON.stringify(catItemsOfCategory1));
7109 catItem1 = catItemsOfCategory1[0].name === "Activate SNSC Service" ? catItemsOfCategory1[0] : catItemsOfCategory1[1];
7110 var itemVarSet = glideHelper.getData("io_set_item", {sc_cat_item: catItem1.sys_id});
7111 var varSet = glideHelper.getData("item_option_new_set", {sys_id: itemVarSet.variable_set});
7112 gs.info(" varSet of the item: " + SaraJSON.stringify(varSet));
7113 var variables = glideHelper.getData("x_ausgh_snsc_sara_variable", {variable_set: varSet.sys_id}, true);
7114 gs.info(" variables of the item: " + SaraJSON.stringify(variables));
7115 SaraTest.assert(variables.length == 7, "5 + 2 variables are created");
7116 });
7117 },
7118
7119 testSyncLookup: function() {
7120 var newSapiService = {
7121 "variables": [
7122 { "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#" },
7123 { "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#" },
7124 { "description": "", "label": "Previous Month(s) included", "defaultValue": ["3"], "type": 6, "required": true, "range": [], "asLookup": false, "name": "EOM_MONTHBACK_", "actualName": "EOM_MONTHBACK#" },
7125 { "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#" },
7126 { "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#" },
7127 { "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#" }
7128 ], "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" };
7129 this.wrapServiceData(newSapiService);
7130
7131 SaraTest.test("test sync lookup", function() {
7132 var saraSync = new SaraSync();
7133 gs.info("catItem1: " + SaraJSON.stringify(catItem1));
7134 var definition = glideHelper.getData(SaraCommon.TABLE_NAME.SARA_DEFINITION, {u_sc_item:catItem1.sys_id });
7135 gs.info("newSapiService: " + SaraJSON.stringify(newSapiService));
7136 saraSync.syncLookup(definition, newSapiService);
7137 });
7138 },
7139
7140 tearDown: function() {
7141 SaraUtils.cleanup( { u_parent: category.sys_id });
7142 glideHelper.deleteData(SaraCommon.TABLE_NAME.SARA_DEFINITION, { u_parent: category.sys_id }, true);
7143 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_CATEGORY, { parent: categoryId }, true);
7144 glideHelper.deleteData(SaraCommon.TABLE_NAME.SN_CATEGORY, { title: ["CONTAINS", "snsc test import"] }, true);
7145 }
7146 };
7147})();
7148
7149var SaraTransformMapTest = (function(){
7150 var logger = new SaraLog("SaraGlideHelperTest");
7151 var glideHelper = new SaraGlideHelper();
7152
7153 var catalogId = glideHelper.getSysId("sc_catalog", {title: "Service Catalog"});
7154 gs.info("catelog id: " + catalogId);
7155
7156 var getCategory = function(title) {
7157 return glideHelper.getData("sc_category", {title: title });
7158 };
7159
7160 var deleteCategory = function(title, deleteAll) {
7161 glideHelper.deleteData("sc_category", {title: title },deleteAll);
7162 glideHelper.deleteData("x_ausgh_snsc_sc_category_ist", {title: title },deleteAll);
7163 };
7164
7165 var createCategory = function(title, active, description, parent) {
7166 glideHelper.persistData("x_ausgh_snsc_sc_category_ist", {
7167 title: title,
7168 active: active,
7169 description: description,
7170 parent: parent,
7171 sc_catalog: catalogId
7172 });
7173 };
7174
7175 return {
7176 execute: function() {
7177 gs.info("----------------------------------------------------------------------------");
7178 gs.info("Test transform map definitions");
7179 gs.info("----------------------------------------------------------------------------");
7180
7181 this.testPersistCatalog();
7182 this.testPersistCategory();
7183 this.testPersistCatalogItem();
7184 this.testPersistVariableSet();
7185 this.testPersistCatelogVariableSet();
7186 this.testPersistSaraDefinition();
7187 },
7188
7189 testPersistCatalog: function() {
7190 var catalogName = "snsc test catalog";
7191 glideHelper.deleteData("sc_catalog", {"title": catalogName});
7192
7193 SaraTest.test("Persist catalog via Importset", function() {
7194 glideHelper.persistData("x_ausgh_snsc_sc_catalog_ist", {
7195 title: catalogName,
7196 description: "test description",
7197 active: "true"
7198 });
7199
7200 var catalog = glideHelper.getData("sc_catalog", {"title": catalogName});
7201
7202 SaraTest.assert(catalog !== null, "catalog is transformed correctly");
7203 SaraTest.assert(catalog.title === catalogName, "catalog title is transformed correctly");
7204 SaraTest.assert(catalog.description === "test description", "catalog description is transformed correctly");
7205 gs.info("active: " + catalog.active);
7206 SaraTest.assert(catalog.active, "catalog active is transformed correctly");
7207 });
7208
7209 SaraTest.test("Update catalog via Importset", function() {
7210 var catalog = glideHelper.getData("sc_catalog", {title: catalogName});
7211 var data = {
7212 id: catalog.sys_id,
7213 description: "new description 2",
7214 active: false
7215 };
7216 glideHelper.persistData("x_ausgh_snsc_sc_catalog_ist", data);
7217
7218 var newCatalog = glideHelper.getData("sc_catalog", {"title": catalogName});
7219 gs.info("new catalog: " + SaraJSON.stringify(newCatalog));
7220 SaraTest.assert(newCatalog !== null, "catalog is transformed correctly, title is not overrided");
7221 SaraTest.assert(newCatalog.description === "new description 2", "catalog description is updated correctly");
7222 gs.info("active: " + newCatalog.active);
7223 SaraTest.assert(newCatalog.active == "false", "catalog active is updated correctly");
7224 });
7225 },
7226
7227 testPersistCategory: function() {
7228 var categoryName1 = "snsc test catagory";
7229 var categoryName2 = "snsc test sub catagory";
7230 deleteCategory(categoryName1, true);
7231 deleteCategory(categoryName2, true);
7232
7233 SaraTest.test("Persist category via Importset", function() {
7234 var category = getCategory(categoryName1);
7235 SaraTest.assert(category === null, "category must not exists");
7236 var category2 = getCategory(categoryName2);
7237 SaraTest.assert(category2 === null, "sub category must not exists");
7238
7239 createCategory(categoryName1,true,"test description", null);
7240 category = getCategory(categoryName1);
7241 gs.info(SaraJSON.stringify(category));
7242 SaraTest.assert(category !== null, "Category ImportSet should be transform to category table");
7243 SaraTest.assert(category.title === categoryName1, "Assert title transform correctly");
7244
7245 //create via importset table
7246 createCategory(categoryName2,true,"test sub description", category.sys_id);
7247 //get real data
7248 category2 = getCategory(categoryName2);
7249 SaraTest.assert(category2 !== null, "Sub category ImportSet should be transform to category table");
7250 SaraTest.assert(category2.title === categoryName2, "Assert title transform correctly");
7251
7252 var parent = glideHelper.getData("sc_category", {sys_id:category2.parent});
7253 SaraTest.assert(parent !== null, "Assert parent transform correctly");
7254 SaraTest.assert(parent.title === categoryName1, "Assert parent transform correctly");
7255 });
7256
7257 SaraTest.test("Save category with same name but different parent should create new category", function() {
7258 //create another category with different parent and assert that new item is
7259 //inserted to target table
7260 gs.info("create another record with name " + categoryName2);
7261 createCategory(categoryName2,true,"test description 2");
7262 var records = glideHelper.getData("sc_category", {title:categoryName2}, true);
7263 SaraTest.assert(records.length === 2, "new category is created");
7264 });
7265 },
7266
7267 testPersistCatalogItem: function() {
7268 var gh = glideHelper;
7269 var name = "snsc sample catelog item" + SaraUtils.getRandom();
7270 gs.info("catelog item name: " + name);
7271 var description = "whatever";
7272 var short_description = "short descriprion";
7273 var categoryName = "snsc item category";
7274 var category = null;
7275
7276 SaraTest.test("Persist catalog item via Importset", function(){
7277 //prepare data
7278 deleteCategory(categoryName, true);
7279 createCategory(categoryName, true, "");
7280 category = getCategory(categoryName);
7281 gs.info("category id: " + category.sys_id);
7282 SaraTest.assert(category !== null, "category is created successfully");
7283
7284 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7285 name: name,
7286 description: description,
7287 short_description: short_description,
7288 use_sc_layout: true,
7289 no_quantity: true,
7290 category: category.sys_id,
7291 active: true
7292 });
7293 var item = gh.getData("sc_cat_item", {name: name});
7294 SaraTest.assert(item.name === name, "item is transformed correctly");
7295 SaraTest.assert(item.description === description, "description is transformed correctly");
7296 SaraTest.assert(item.short_description === short_description, "short_description is transformed correctly");
7297 SaraTest.assert(item.use_sc_layout == "true", "use_sc_layout is transformed correctly");
7298 SaraTest.assert(item.no_quantity == "true", "no_quantity is transformed correctly");
7299 SaraTest.assert(item.active == "true", "active is transformed correctly");
7300 SaraTest.assert(item.category === category.sys_id, "category is transformed correctly");
7301 });
7302
7303 SaraTest.test("Catalog item same name different category should create new", function() {
7304 var newCategoryName = categoryName + SaraUtils.getRandom();
7305 createCategory(newCategoryName, true, "");
7306 var newCat = getCategory(newCategoryName);
7307 gs.info("new category id: " + newCat.sys_id);
7308 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7309 name: name,
7310 description: "new description",
7311 short_description: "new short description",
7312 use_sc_layout: false,
7313 no_quantity: false,
7314 category: newCat.sys_id,
7315 active: false
7316 });
7317
7318 var records = gh.getData("sc_cat_item", {name: name}, true);
7319 SaraTest.assert(records.length === 2, "new item is created");
7320 });
7321
7322 SaraTest.test("Update catalog item via Importset", function(){
7323 var existingItem = gh.getData("sc_cat_item", {
7324 name: name,
7325 category: category.sys_id
7326 });
7327
7328 SaraTest.assert(existingItem !== undefined, "existing item is get correctly");
7329
7330 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7331 id: existingItem.sys_id,
7332 name: name,
7333 description: "new description",
7334 short_description: "new short description",
7335 use_sc_layout: false,
7336 no_quantity: false,
7337 category: category.sys_id,
7338 active: false
7339 });
7340 var items = gh.getData("sc_cat_item", {name: name, category: category.sys_id}, true);
7341 SaraTest.assert(items.length === 1, "no new item is created");
7342
7343 var item = items[0];
7344 SaraTest.assert(item.name === name, "item is transformed correctly");
7345 SaraTest.assert(item.description === "new description", "description is transformed correctly");
7346 SaraTest.assert(item.short_description === "new short description", "short_description is transformed correctly");
7347 SaraTest.assert(item.use_sc_layout == "false", "use_sc_layout is transformed correctly");
7348 SaraTest.assert(item.no_quantity == "false", "no_quantity is transformed correctly");
7349 SaraTest.assert(item.active == "false", "active is transformed correctly");
7350 SaraTest.assert(item.category === category.sys_id, "category is transformed correctly");
7351 });
7352 },
7353
7354 testPersistVariableSet: function() {
7355 var varSetName = "snsc test variable set " + SaraUtils.getRandom();
7356 var varSetTitle = "title";
7357 var varSetDescription = "test description";
7358 var varSetDisplayName = "display name";
7359
7360 var varSetTitleNew = "title new";
7361 var varSetDescriptionNew = "test description new";
7362 var varSetDisplayNameNew = "display name new";
7363
7364 glideHelper.deleteData("item_option_new_set", {"name": ["CONTAINS", "snsc test"]}, true);
7365
7366 SaraTest.test("Persist variable set via Importset", function() {
7367 glideHelper.persistData("x_ausgh_snsc_item_option_new_set_ist", {
7368 name: varSetName,
7369 title: varSetTitle,
7370 description: varSetDescription,
7371 sys_name: varSetDisplayName
7372 });
7373
7374 var varSet = glideHelper.getData("item_option_new_set", {"name": varSetName});
7375
7376 SaraTest.assert(varSet !== null, "varSet is transformed correctly");
7377 SaraTest.assert(varSet.name === varSetName, "var set name is transformed correctly");
7378 SaraTest.assert(varSet.title === varSetTitle, "var set title is transformed correctly");
7379 SaraTest.assert(varSet.description === varSetDescription, "var set description is transformed correctly");
7380 SaraTest.assert(varSet.sys_name === varSetDisplayName, "var set display name is transformed correctly");
7381 });
7382
7383 SaraTest.test("Update var set via Importset", function() {
7384 var existingVarSet = glideHelper.getData("item_option_new_set", {name: varSetName});
7385 SaraTest.assert(existingVarSet !== undefined, "var set is get correctly");
7386
7387 glideHelper.persistData("x_ausgh_snsc_item_option_new_set_ist", {
7388 id: existingVarSet.sys_id,
7389 name: varSetName,
7390 title: varSetTitleNew,
7391 description: varSetDescriptionNew
7392 });
7393
7394 var varSets = glideHelper.getData("item_option_new_set", {"name": varSetName}, true);
7395
7396 SaraTest.assert(varSets.length === 1, "no new item is get correctly");
7397 var varSet = varSets[0];
7398 SaraTest.assert(varSet !== null, "varSet is transformed correctly");
7399 SaraTest.assert(varSet.name === varSetName, "var set name is transformed correctly");
7400 SaraTest.assert(varSet.title === varSetTitleNew, "var set title is updated correctly");
7401 SaraTest.assert(varSet.description === varSetDescriptionNew, "var set description is updated correctly");
7402 });
7403 },
7404
7405 testPersistCatelogVariableSet : function() {
7406 var varSetName = "snsc test variable set " + SaraUtils.getRandom();
7407 var varSetTitle = "title";
7408 var varSetDescription = "test description";
7409 var varSetDisplayName = "display name";
7410
7411 var newCategoryName = "snsc category " + SaraUtils.getRandom();
7412
7413 var catItemName = "snsc cat item " + SaraUtils.getRandom();
7414
7415 var gh = glideHelper;
7416
7417 gh.deleteData("item_option_new_set", {"name": ["CONTAINS", "snsc test"]}, true);
7418
7419 SaraTest.test("Persist catalog variable set via Importset", function() {
7420 gh.persistData("x_ausgh_snsc_item_option_new_set_ist", {
7421 name: varSetName,
7422 title: varSetTitle,
7423 description: varSetDescription,
7424 display_name: varSetDisplayName
7425 });
7426
7427 var varSet = glideHelper.getData("item_option_new_set", {"name": varSetName});
7428
7429 SaraTest.assert(varSet !== null, "varSet is transformed correctly");
7430
7431 createCategory(newCategoryName);
7432 var newCat = getCategory(newCategoryName);
7433
7434 gs.info("new category id: " + newCat.sys_id);
7435
7436 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7437 name: catItemName,
7438 description: "new description",
7439 short_description: "new short description",
7440 use_sc_layout: true,
7441 no_quantity: true,
7442 category: newCat.sys_id,
7443 active: true
7444 });
7445
7446 var catItem = gh.getData("sc_cat_item", {name: catItemName, category: newCat.sys_id});
7447 SaraTest.assert(catItem !== undefined, "cat item is transformed successfully");
7448
7449 //link item and varset via import set
7450 gh.persistData("x_ausgh_snsc_io_set_item_ist", {sc_cat_item: catItem.sys_id, variable_set: varSet.sys_id});
7451 //get real
7452 var catVarSet = gh.getData("io_set_item", {sc_cat_item: catItem.sys_id, variable_set: varSet.sys_id});
7453
7454 SaraTest.assert(catVarSet !== null, "catalog item variable is transformed correctly");
7455 SaraTest.assert(catVarSet.sc_cat_item === catItem.sys_id, "cat item is set correctly");
7456 SaraTest.assert(catVarSet.variable_set === varSet.sys_id, "var set is set correctly");
7457 });
7458 },
7459
7460 testPersistSaraDefinition : function() {
7461 var newCategoryName = "snsc test category " + SaraUtils.getRandom();
7462 var parentCategoryName = "snsc test parent category " + SaraUtils.getRandom();
7463
7464 var varSetName = "snsc test var set" + SaraUtils.getRandom();
7465
7466 var definitionName1 = "snsc test" + SaraUtils.getRandom();
7467 var definitionName2 = "snsc test" + SaraUtils.getRandom();
7468 var definitionName3 = "snsc test" + SaraUtils.getRandom();
7469
7470 var catItemName1 = "snsc test cat item" + SaraUtils.getRandom();
7471
7472 var consume_url1 = "http://automictest.com";
7473 var consume_url2 = "http://automictest2.com";
7474 var hash1 = "FDSGHERGGGGFGFGDGFS";
7475 var hash2 = "FDSFFSDHASAFGFGDGFS";
7476
7477 var gh = glideHelper;
7478
7479 gh.deleteData("x_ausgh_snsc_sara_definition", {"name": ["CONTAINS", "snsc test"]}, true);
7480
7481 SaraTest.test("Persist sara definition for catalog item via Importset", function() {
7482 createCategory(parentCategoryName);
7483 var parentCat = getCategory(parentCategoryName);
7484 SaraTest.assert(parentCat !== null, "parentCat is transformed correctly");
7485
7486 createCategory(newCategoryName);
7487 var newCat = getCategory(newCategoryName);
7488 SaraTest.assert(newCat !== null, "newCat is transformed correctly");
7489
7490 //create var set
7491 gh.persistData("x_ausgh_snsc_item_option_new_set_ist", {
7492 name: varSetName,
7493 title: "title",
7494 description: "description",
7495 display_name: "whatever"
7496 });
7497
7498 var varSet = gh.getData("item_option_new_set", {"name": varSetName});
7499 SaraTest.assert(varSet !== null, "varSet is transformed correctly");
7500
7501 //create catalog item
7502 gh.persistData("x_ausgh_snsc_sara_cat_item_ist", {
7503 name: catItemName1,
7504 description: "new description",
7505 short_description: "new short description",
7506 use_sc_layout: true,
7507 no_quantity: true,
7508 category: newCat.sys_id,
7509 active: true
7510 });
7511
7512 var catItem = gh.getData("sc_cat_item", {name: catItemName1, category: newCat.sys_id});
7513 SaraTest.assert(catItem !== null, "catItem is transformed correctly");
7514
7515 gh.persistData("x_ausgh_snsc_sara_definition_ist", {
7516 u_name: definitionName1,
7517 u_consume_url: consume_url1,
7518 u_sc_item: catItem.sys_id,
7519 u_service_catalog_category: newCat.sys_id,
7520 u_var_set: varSet.sys_id,
7521 u_parent: parentCat.sys_id,
7522 u_type: "service",
7523 u_hash: hash1
7524 });
7525 var saraDefinition = gh.getData("x_ausgh_snsc_sara_definition_ist", {u_name: definitionName1, u_parent: parentCat.sys_id});
7526
7527 SaraTest.assert(saraDefinition !== null, "saraDefinition is transformed correctly");
7528 gs.info("saraDefinition: " + SaraJSON.stringify(saraDefinition));
7529 SaraTest.assert(saraDefinition.u_name === definitionName1, "u_name is transformed correctly");
7530 SaraTest.assert(saraDefinition.u_consume_url === consume_url1, "consume_url is transformed correctly");
7531 SaraTest.assert(saraDefinition.u_sc_item === catItem.sys_id, "u_sc_item is transformed correctly");
7532 SaraTest.assert(saraDefinition.u_service_catalog_category === newCat.sys_id, "u_service_catalog_category is transformed correctly");
7533 SaraTest.assert(saraDefinition.u_var_set === varSet.sys_id, "u_var_set is transformed correctly");
7534 SaraTest.assert(saraDefinition.u_parent === parentCat.sys_id, "u_parent is transformed correctly");
7535 SaraTest.assert(saraDefinition.u_type === "service", "u_type is transformed correctly");
7536 SaraTest.assert(saraDefinition.u_hash === hash1, "u_hash is transformed correctly");
7537 });
7538 }
7539 };
7540})();
7541
7542var SaraTest = (function() {
7543 var indent = "";
7544 var logger = new SaraLog("SaraTest");
7545 var pass = 0;
7546 var fail = 0;
7547 var isIgnore = false;
7548 var ignored = 0;
7549 var continueOnError = true;
7550
7551 var log = function() {
7552 logger.info.apply(logger,arguments);
7553 };
7554
7555 return {
7556 resetSummary: function() {
7557 pass = 0;
7558 fail = 0;
7559 ignored = 0;
7560 },
7561
7562 disableContinueOnError:function() {
7563 continueOnError = false;
7564 },
7565
7566 getSummary: function() {
7567 return {
7568 pass: pass,
7569 fail: fail,
7570 ignore: ignored,
7571 total: pass + fail + ignored
7572 };
7573 },
7574
7575 ignore: function() {
7576 isIgnore = true;
7577 },
7578
7579 assert: function(value, desc) {
7580 var prefix = ">>>PASS: ";
7581 if(!value) {
7582 prefix = "<<<FAIL: ";
7583 }
7584 logger.info("{0}{1}{2}", indent, prefix, desc);
7585 if(!value) {
7586 var exceptionMsg = prefix + desc;
7587 throw new Error(exceptionMsg);
7588 }
7589 },
7590 assertEqual: function(actual, expected, desc) {
7591 var failed = false;
7592 var prefix = ">>>PASS: ";
7593 if(actual != expected) {
7594 prefix = "<<<FAIL: ";
7595 failed = true;
7596 }
7597 logger.info("{0}{1}{2}", indent, prefix, desc);
7598 if(failed) {
7599 logger.info("Expected: {0}; Actual: {1}", expected, actual);
7600 }
7601 if(failed) {
7602 var exceptionMsg = prefix + desc + "; Expected:" + expected + "; Actual: " + actual
7603
7604 throw new Error(exceptionMsg);
7605 }
7606 },
7607 test: function(name, fn) {
7608 indent = "";
7609 logger.info("********************************");
7610 if(isIgnore) {
7611 logger.info("[IGNORE] {0}", name);
7612 isIgnore = false;
7613 ignored++;
7614 return;
7615 }
7616 logger.info("[TEST CASE] {0}", name);
7617 indent = " ";
7618
7619 if(continueOnError) {
7620 try {
7621 fn();
7622 pass++;
7623 }
7624 catch(err) {
7625 gs.error(err);
7626 fail++;
7627 }
7628 }
7629 else {
7630 fn();
7631 pass++;
7632 }
7633
7634 indent = "";
7635 },
7636 type: "SaraTest"
7637 };
7638})();
7639]]></script>
7640 <description>Sara Test Bench</description>
7641 <active>true</active>
7642 <client_callable>false</client_callable>
7643 <access>public</access>
7644 </script_include>
7645</script_includes>
7646
7647
7648 <ui_scripts>
7649 <ui_script>
7650 <script_name>SaraVarSet</script_name>
7651 <script><![CDATA[/**
7652 * Catalog client script for SaraVariableSet
7653 */
7654var x_ausgh_snsc = x_ausgh_snsc || {};
7655x_ausgh_snsc.SaraVarSet = x_ausgh_snsc.SaraVarSet || {};
7656
7657(function (SaraVarSet) {
7658 'use strict';
7659
7660 /**
7661 * OnLoad event handler for Sara variable set
7662 */
7663 SaraVarSet.onLoad = function () {
7664 SaraVarSet.initListCollector();
7665 SaraVarSet.setSelectBoxWidth();
7666 };
7667
7668 /**
7669 * Init collector filter
7670 */
7671 SaraVarSet.initListCollector = function () {
7672 x_ausgh_snsc.log('Start: SaraVarSet.initListCollector');
7673 var messageTables = $$('[id$=_select_0_add_remove_message_table]');
7674 var listWrappers = $$('.list_name');
7675
7676 for (var i = 0, table; table = messageTables[i]; i++) {
7677 var name = table.id.replace('_select_0_add_remove_message_table', '');
7678 var wrapper = listWrappers[i];
7679 var target;
7680 var id;
7681
7682 if (wrapper) {
7683 target = wrapper;
7684 } else {
7685 target = table;
7686 }
7687
7688 id = target.nextSibling.id.replace('IO:', '');
7689
7690 SaraVarSet.getListCollectorData(id, name);
7691 }
7692
7693 x_ausgh_snsc.log('End: SaraVarSet.initListCollector');
7694 };
7695
7696 /**
7697 * Get list collector data from lookup table
7698 * @param {String} id The sys_id of list collector
7699 * @param {String} name The name of list collector
7700 */
7701 SaraVarSet.getListCollectorData = function (id, name) {
7702 var filterFn = name + 'g_filter';
7703 var acRequestFn = name + 'acRequest';
7704
7705 if (window[filterFn] === undefined || window[acRequestFn] === undefined) {
7706 setTimeout(function () {
7707 SaraVarSet.getListCollectorData(id, name);
7708 }, 100);
7709 return;
7710 }
7711
7712 window[filterFn].reset();
7713 window[filterFn].setQuery('u_control_id=' + id);
7714 window[acRequestFn](null);
7715 };
7716
7717 /**
7718 * Make all selecbox's width is 250px for preventing the broken of layout when value of option is too long
7719 */
7720 SaraVarSet.setSelectBoxWidth = function () {
7721 x_ausgh_snsc.log('Start: SaraVarSet.setSelectBoxWidth');
7722 var selectboxes = $$('select.cat_item_option');
7723
7724 for (var i = 0, selectbox; selectbox = selectboxes[i]; i++) {
7725 selectbox.style.width = '250px';
7726 }
7727
7728 x_ausgh_snsc.log('End: SaraVarSet.setSelectBoxWidth');
7729 };
7730
7731})(x_ausgh_snsc.SaraVarSet);
7732]]></script>
7733 <description>Catalog client script for SaraVariableSet</description>
7734 <active>true</active>
7735 <global>false</global>
7736 </ui_script>
7737 <ui_script>
7738 <script_name>SaraCommon</script_name>
7739 <script><![CDATA[/**
7740 * Common client properties for Sara
7741 */
7742var SaraCommon = SaraCommon || {};
7743
7744var x_ausgh_snsc = x_ausgh_snsc || {};
7745x_ausgh_snsc.SaraCommon = x_ausgh_snsc.SaraCommon || {};
7746
7747x_ausgh_snsc.log = function () {
7748 if (typeof (console) !== 'undefined') {
7749 if (navigator.appName === 'Microsoft Internet Explorer') {
7750 if (arguments.length == 1) {
7751 console.log('[SARA]', arguments[0]);
7752 } else if (arguments.length === 2) {
7753 console.log('[SARA]', arguments[0], arguments[1]);
7754 } else if (arguments.length > 2) {
7755 console.log('[SARA]', arguments[0], arguments[1], arguments[2]);
7756 }
7757 } else {
7758 console.log('[SARA]', arguments);
7759 }
7760 }
7761};
7762
7763x_ausgh_snsc.config = x_ausgh_snsc.config || {};
7764
7765(function (SaraCommon) {
7766 'use strict';
7767
7768 SaraCommon.SCOPED_APP = 'x_ausgh_snsc';
7769
7770 SaraCommon.CONFIG_NAME = {
7771 CLIENT_ID: 'client_id',
7772 CLIENT_SECRET: 'client_secret',
7773 TECHNICAL_USER: 'technical_user',
7774 SAPI_ENDPOINT: 'sapi_endpoint',
7775 TOKEN_ENDPOINT: 'token_endpoint',
7776 AUTH_ENDPOINT: 'auth_endpoint'
7777 };
7778
7779 SaraCommon.CONTROL_NAME = {
7780 CLIENT_SCRIPTS: 'sara_client_scripts',
7781 HIDDEN_CONTROL: 'sara_hidden_control'
7782 };
7783
7784})(x_ausgh_snsc.SaraCommon);
7785]]></script>
7786 <description>Common client properties for Sara</description>
7787 <active>true</active>
7788 <global>false</global>
7789 </ui_script>
7790 <ui_script>
7791 <script_name>SaraOAuth</script_name>
7792 <script><![CDATA[/**
7793 * Client script for OAuth integration
7794 */
7795var x_ausgh_snsc = x_ausgh_snsc || {};
7796x_ausgh_snsc.SaraOAuth = x_ausgh_snsc.SaraOAuth || {};
7797
7798(function (SaraOAuth) {
7799 'use strict';
7800
7801 /**
7802 * Login to OAuth server for authentication
7803 * @param {String} clientId The client ID of OAuth Server
7804 * @param {String} technicalUser The tecnical user who owns the tokens
7805 * @param {String} authEndpoint The authorization endpoint of OAuth Server
7806 * @param {Object} callback The callback object contains onSuccess and onFail handler
7807 */
7808 SaraOAuth.login = function (clientId, technicalUser, authEndpoint, callback) {
7809 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?')) {
7810 SaraOAuth.processSuccess = null;
7811 SaraOAuth.processFail = null;
7812
7813 if (SaraOAuth.win) {
7814 SaraOAuth.win.close();
7815 }
7816 SaraOAuth.win = null;
7817
7818 var ga = new x_ausgh_snsc.SaraGlideAjax('SaraOAuthAjax', 'Getting OAuth url...');
7819 ga.addParam('sysparm_name', 'getOAuthUrl');
7820 ga.addParam('sysparm_client_id', clientId);
7821 ga.addParam('sysparm_technical_user', technicalUser);
7822 ga.addParam('sysparm_auth_endpoint', authEndpoint);
7823 ga.getXML(function (response) {
7824 if (callback && callback.onSuccess && typeof (callback.onSuccess) == 'function') {
7825 SaraOAuth.processSuccess = callback.onSuccess;
7826 }
7827
7828 if (callback && callback.onFail && typeof (callback.onFail) == 'function') {
7829 SaraOAuth.processFail = callback.onFail;
7830 }
7831
7832 var w = 500;
7833 var h = 600;
7834
7835 var left = (screen.width / 2) - (w / 2);
7836 var top = (screen.height / 2) - (h / 2);
7837
7838 var url = response.responseXML.documentElement.getAttribute('answer');
7839 SaraOAuth.win = window.open(url, 'aelogin', 'width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
7840 });
7841 }
7842 };
7843
7844 /**
7845 * Process response from OAuth server. If is 'ok', will call SaraOAuth.processSuccess callback.
7846 * If is not 'ok', will log the answer and alert message.
7847 * @param {*} response The response
7848 */
7849 SaraOAuth.processResponse = function (response) {
7850 if (SaraOAuth.win) {
7851 SaraOAuth.win.close();
7852 }
7853
7854 x_ausgh_snsc.log('Callback response is: ' + response);
7855
7856 if (response === 'ok') {
7857 if (SaraOAuth.processSuccess && typeof (SaraOAuth.processSuccess) == 'function') {
7858 SaraOAuth.processSuccess();
7859 }
7860 } else {
7861 var msg;
7862
7863 if (typeof (response) == 'string' && response.match('^function') != 'function') {
7864 msg = x_ausgh_snsc.SaraUtils.formatString('Token request finished unsuccessfully{0}. Please try again later or contact administrators.', response ? (', error: ' + response) : '');
7865 } else {
7866 msg = 'Token request finished unsuccessfully! Please try again later or contact administrators.';
7867 }
7868
7869 alert(msg);
7870
7871 if (SaraOAuth.processFail && typeof (SaraOAuth.processFail) == 'function') {
7872 SaraOAuth.processFail();
7873 }
7874
7875 x_ausgh_snsc.log(msg);
7876 }
7877 };
7878
7879 /**
7880 * Get configuration
7881 * @param {Function} callback The callback will be called when getting configuration
7882 * successfully with parametter is object with same keys with x_ausgh_snsc.SaraCommon.CONFIG_NAME
7883 */
7884 SaraOAuth.getConfig = function (callback) {
7885 var configData = {};
7886 var ga = new x_ausgh_snsc.SaraGlideAjax('SaraOAuthAjax', 'Getting OAuth configuration...');
7887 ga.addParam('sysparm_name', 'getConfig');
7888
7889 ga.getXML(function (resp) {
7890 var config = resp.responseXML.getElementsByTagName('config')[0];
7891
7892 for (var key in x_ausgh_snsc.SaraCommon.CONFIG_NAME) {
7893 var name = x_ausgh_snsc.SaraCommon.CONFIG_NAME[key];
7894
7895 configData[name] = config.getAttribute(name);
7896 }
7897
7898 callback.call(this, configData);
7899 });
7900 };
7901
7902 /**
7903 * Check OAuth Token of current technical user is invalid, expired or empty
7904 * @param {String} technicalUser The tecnical user who owns the tokens
7905 * @param {String} sapiEndpoint The SAPI endpoint
7906 * @param {Boolean} hideWizardSubmit Hide submit button of wizard or not when token is empty, expired
7907 * or invalid
7908 * @param {Object<String, Function>} callback The callback object contains callbacks when valid,
7909 * invalid, error:
7910 * - onValid(); // Will be called when tokens are existed and valid.
7911 * - onInvalid(); // Will be called when tokens are existed but invalid.
7912 * - onError(errorMessage); // Will be called when have any error. 'errorMessage' is error message
7913 * - onExisted(); // Will be called if current technical user has tokens but not validate the token yet.
7914 * SaraCommon.TABLE_NAME.SARA_OAUTH table
7915 */
7916 SaraOAuth.checkOAuthToken = function (technicalUser, sapiEndpoint, hideWizardSubmit, callback) {
7917 x_ausgh_snsc.log('checkOAuthToken', technicalUser, sapiEndpoint, hideWizardSubmit, callback);
7918
7919 var ga = new x_ausgh_snsc.SaraGlideAjax('SaraOAuthAjax', 'Validating token...');
7920 ga.addParam('sysparm_name', 'validateToken');
7921 ga.addParam('sysparm_technical_user', technicalUser);
7922 ga.addParam('sysparm_sapi_endpoint', sapiEndpoint);
7923
7924 ga.getXML(function (resp) {
7925 var result = resp.responseXML.getElementsByTagName('result')[0];
7926
7927 if (result) {
7928 var isValid = result.getAttribute('isValid');
7929
7930 // Valid
7931 if (isValid === 'true') {
7932 if (hideWizardSubmit) {
7933 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(true);
7934 }
7935
7936 x_ausgh_snsc.log('Access token is valid');
7937
7938 if (typeof callback.onValid === 'function') {
7939 callback.onValid.call(this);
7940 }
7941
7942 // Invalid
7943 } else if (isValid === 'false') {
7944 if (hideWizardSubmit) {
7945 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(false);
7946 }
7947
7948 x_ausgh_snsc.log('Access token is invalid');
7949
7950 if (typeof callback.onInvalid === 'function') {
7951 callback.onInvalid.call(this);
7952 }
7953
7954 // Error
7955 } else {
7956 var errorMessage = result.getAttribute('message');
7957 x_ausgh_snsc.log(errorMessage);
7958
7959
7960 if (typeof callback.onError === 'function') {
7961 callback.onError.call(this, errorMessage);
7962 }
7963 }
7964 } else {
7965 var error = resp.responseXML.getElementsByTagName('error')[0];
7966 var errorMessage;
7967
7968 if (error) {
7969 errorMessage = error.getAttribute('message');
7970 }
7971
7972 if (typeof callback.onError === 'function') {
7973 callback.onError.call(this, errorMessage);
7974 }
7975 }
7976 });
7977 };
7978
7979})(x_ausgh_snsc.SaraOAuth);
7980]]></script>
7981 <description>Client script for OAuth integration</description>
7982 <active>true</active>
7983 <global>false</global>
7984 </ui_script>
7985 <ui_script>
7986 <script_name>SaraUtils</script_name>
7987 <script><![CDATA[/**
7988 * Sara Utilities
7989 */
7990var x_ausgh_snsc = x_ausgh_snsc || {};
7991x_ausgh_snsc.SaraUtils = x_ausgh_snsc.SaraUtils || {};
7992
7993(function (SaraUtils) {
7994 'use strict';
7995
7996 /**
7997 * Format strings
7998 * @method format
7999 * @param {String} string The template string
8000 * @param {String[]} args Zero or more objects to format, supplied either in a comma-delimited list or as an array
8001 */
8002 SaraUtils.formatString = function (string) {
8003 var args = Array.prototype.slice.call(arguments, 1);
8004
8005 return string.replace(/{(\d+)}/g, function (match, number) {
8006 return typeof args[number] != 'undefined' ? args[number] : match;
8007 });
8008 };
8009
8010 /**
8011 * Get parameter value in current URL
8012 * @param {String} name The name of parameter
8013 * @return {String}
8014 */
8015 SaraUtils.getParmVal = function (name) {
8016 name = name.replace(/[\[]/, '\\\[').replace(/[\]]/, '\\\]');
8017 var regexS = '[\\?&]' + name + '=([^&#]*)';
8018 var regex = new RegExp(regexS);
8019 var results = regex.exec(window.location.href);
8020
8021 if (results == null) {
8022 return '';
8023 } else {
8024 return unescape(results[1]);
8025 }
8026 };
8027
8028 /**
8029 * Hide/show submit button of wizard
8030 * @param {Boolean} isVisible Submit button is visible or not
8031 */
8032 SaraUtils.setWizardSubmitVisible = function (isVisible) {
8033 document.getElementById('expert_next').style.display = isVisible ? '' : 'none';
8034 };
8035
8036 /**
8037 * Set visible of a form control
8038 * @param {String} name Name of control
8039 * @param {Boolean} isVisible Control is hidden or visible
8040 */
8041 SaraUtils.setFormControlVisible = function (name, isVisible) {
8042 if (g_form) {
8043 g_form.setDisplay(name, isVisible);
8044 }
8045 }
8046
8047})(x_ausgh_snsc.SaraUtils);
8048]]></script>
8049 <description>Sara Utilities</description>
8050 <active>true</active>
8051 <global>false</global>
8052 </ui_script>
8053 <ui_script>
8054 <script_name>SaraGlideAjax</script_name>
8055 <script><![CDATA[/**
8056 * Helper class wraps GlideAjax class of ServiceNow and provide Loading Dialog with custom title
8057 */
8058var x_ausgh_snsc = x_ausgh_snsc || {};
8059x_ausgh_snsc.SaraGlideAjax = x_ausgh_snsc.SaraGlideAjax || Class.create();
8060
8061(function (SaraGlideAjax) {
8062 'use strict';
8063
8064 SaraGlideAjax.prototype = {
8065 /**
8066 * Initialize SaraGlideAjax
8067 * @param {String} className The class name of callable Script Include
8068 * @param {String} title The title of loading dialog
8069 */
8070 initialize: function (className, title) {
8071 this.title = title;
8072 this.ga = new GlideAjax(className);
8073 this.ga.addParam('sysparm_scope', x_ausgh_snsc.SaraCommon.SCOPED_APP);
8074 this.className = className;
8075 },
8076
8077 /**
8078 * Add parameter for GlideAjax
8079 * @param {String} key The key of parameter
8080 * @param {String} value The value of parameter
8081 */
8082 addParam: function (key, value) {
8083 this.ga.addParam(key, value);
8084 },
8085
8086 /**
8087 * Get XML response from server
8088 * @param {Function} callback The callback will be call after getting response from server
8089 */
8090 getXML: function (callback) {
8091 var loadingDialog = new GlideDialogWindow('hierarchical_progress_viewer');
8092 loadingDialog.hideCloseButton();
8093 loadingDialog.setTitle(this.title);
8094
8095 var className = this.className;
8096 x_ausgh_snsc.log('Sending request to ' + className + '...');
8097
8098 this.ga.getXML(function (response) {
8099 loadingDialog.destroy();
8100 x_ausgh_snsc.log('Got response from ' + className, response);
8101
8102 if (typeof callback === 'function') {
8103 callback.apply(this, arguments);
8104 }
8105 });
8106 },
8107
8108 type: 'SaraGlideAjax'
8109 };
8110
8111})(x_ausgh_snsc.SaraGlideAjax);
8112]]></script>
8113 <description>Helper class wraps GlideAjax class of ServiceNow and provide Loading Dialog with custom title</description>
8114 <active>true</active>
8115 <global>false</global>
8116 </ui_script>
8117</ui_scripts>
8118
8119
8120 <ui_pages>
8121 <ui_page>
8122 <name>sara_oauth_callback</name>
8123 <description>OAuth Redirection Endpoint</description>
8124 <category>general</category>
8125 <html><![CDATA[<?xml version="1.0" encoding="utf-8" ?>
8126<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
8127 <g:requires name="x_ausgh_snsc.SaraCommon.jsdbx" params="cache=$[jvar_stamp]" />
8128 <g:requires name="x_ausgh_snsc.SaraGlideHelper.jsdbx" params="cache=$[jvar_stamp]" />
8129 <g:requires name="x_ausgh_snsc.SaraGlideAjax.jsdbx" params="cache=$[jvar_stamp]" />
8130 <g:requires name="x_ausgh_snsc.SaraOAuth.jsdbx" params="cache=$[jvar_stamp]" />
8131 <g:requires name="x_ausgh_snsc.SaraUtils.jsdbx" params="cache=$[jvar_stamp]" />
8132 <g:requires name="x_ausgh_snsc.SaraVarSet.jsdbx" params="cache=$[jvar_stamp]" />
8133
8134 <g:ui_form>
8135 <p>
8136 <label>Please wait, processing...</label>
8137 </p>
8138 </g:ui_form>
8139</j:jelly>
8140]]></html>
8141 <client_script><![CDATA[var parentWin = (window.opener && window.opener.x_ausgh_snsc.SaraOAuth) ? window.opener : window.parent;
8142
8143if (!parentWin || !parentWin.x_ausgh_snsc || !parentWin.x_ausgh_snsc.SaraOAuth || !parentWin.x_ausgh_snsc.SaraOAuth.processResponse || typeof(parentWin.x_ausgh_snsc.SaraOAuth.processResponse) !== 'function') {
8144 window.location.href = '/home.do';
8145} else {
8146 var code = x_ausgh_snsc.SaraUtils.getParmVal('code');
8147 x_ausgh_snsc.log('Code: ' + code);
8148
8149 if (code) {
8150 var clientId = parentWin.x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_ID];
8151 var clientSecret = parentWin.x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_SECRET];
8152 var technicalUser = parentWin.x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER];
8153 var tokenEndpoint = parentWin.x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT];
8154
8155 x_ausgh_snsc.log('Client ID: ' + clientId, 'Client Secret: ' + clientSecret, 'Token Endpoint: ' + tokenEndpoint)
8156
8157 // Invoke x_ausgh_snsc.SaraOAuthAjax to exchange code for tokens
8158 x_ausgh_snsc.log('Init GlideAjax for requesting token by code...');
8159 var ga = new x_ausgh_snsc.SaraGlideAjax('SaraOAuthAjax', 'Requesting token by code...');
8160 ga.addParam('sysparm_name', 'requestTokenByCode');
8161 ga.addParam('sysparm_code', code);
8162 ga.addParam('sysparm_client_id', clientId);
8163 ga.addParam('sysparm_client_secret', clientSecret);
8164 ga.addParam('sysparm_technical_user', technicalUser);
8165 ga.addParam('sysparm_token_endpoint', tokenEndpoint);
8166
8167 ga.getXML(function (response) {
8168 var answer = response.responseXML.documentElement.getAttribute('answer');
8169 parentWin.x_ausgh_snsc.SaraOAuth.processResponse(answer);
8170 });
8171 } else {
8172 x_ausgh_snsc.log('Code is empty!');
8173 parentWin.x_ausgh_snsc.SaraOAuth.processResponse();
8174 }
8175}
8176]]></client_script>
8177 <processing_script/>
8178 </ui_page>
8179</ui_pages>
8180
8181
8182 <ui_macros>
8183 <ui_macro>
8184 <name>sara_hidden_control</name>
8185 <description>UI Marco for Sara Hidden Control</description>
8186 <category>catalog</category>
8187 <active>true</active>
8188 <media_type/>
8189 <xml><![CDATA[<?xml version="1.0" encoding="utf-8" ?>
8190<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
8191 <script type="text/javascript">
8192 $j(function () {
8193 x_ausgh_snsc.SaraUtils.setFormControlVisible(x_ausgh_snsc.SaraCommon.CONTROL_NAME.HIDDEN_CONTROL, false);
8194 x_ausgh_snsc.SaraVarSet.onLoad();
8195 });
8196 </script>
8197</j:jelly>
8198]]></xml>
8199 </ui_macro>
8200 <ui_macro>
8201 <name>sara_client_scripts</name>
8202 <description/>
8203 <category>catalog</category>
8204 <active>true</active>
8205 <media_type/>
8206 <xml><![CDATA[<?xml version="1.0" encoding="utf-8" ?>
8207<j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
8208 <g:requires name="x_ausgh_snsc.SaraCommon.jsdbx" params="cache=$[jvar_stamp]" />
8209 <g:requires name="x_ausgh_snsc.SaraGlideAjax.jsdbx" params="cache=$[jvar_stamp]" />
8210 <g:requires name="x_ausgh_snsc.SaraOAuth.jsdbx" params="cache=$[jvar_stamp]" />
8211 <g:requires name="x_ausgh_snsc.SaraUtils.jsdbx" params="cache=$[jvar_stamp]" />
8212 <g:requires name="x_ausgh_snsc.SaraVarSet.jsdbx" params="cache=$[jvar_stamp]" />
8213
8214 <script type="text/javascript">
8215 $j(function () {
8216 x_ausgh_snsc.SaraUtils.setFormControlVisible(x_ausgh_snsc.SaraCommon.CONTROL_NAME.CLIENT_SCRIPTS, false);
8217 });
8218 </script>
8219</j:jelly>
8220]]></xml>
8221 </ui_macro>
8222</ui_macros>
8223
8224
8225 <workflows>
8226 <workflow>
8227 <name>Sara Service</name>
8228 <description>Sara Service workflow</description>
8229 <start>begin</start>
8230 <table>sc_req_item</table>
8231 <active>true</active>
8232 <published>true</published>
8233 <max_activity_count>1000000</max_activity_count>
8234
8235
8236 <stages>
8237 <stage>
8238 <name>Initializing</name>
8239 <order>100</order>
8240 <value>initializing</value>
8241 <ola/>
8242 </stage>
8243 <stage>
8244 <name>Transferring</name>
8245 <order>200</order>
8246 <value>transferring</value>
8247 <ola/>
8248 </stage>
8249 <stage>
8250 <name>Transferred</name>
8251 <order>300</order>
8252 <value>transferred</value>
8253 <ola/>
8254 </stage>
8255 <stage>
8256 <name>Transfer Failed</name>
8257 <order>300</order>
8258 <value>transfer_failed</value>
8259 <ola/>
8260 </stage>
8261 <stage>
8262 <name>Consume Failed</name>
8263 <order>400</order>
8264 <value>consume_failed</value>
8265 <ola/>
8266 </stage>
8267 <stage>
8268 <name>Running</name>
8269 <order>500</order>
8270 <value>running</value>
8271 <ola/>
8272 </stage>
8273 <stage>
8274 <name>Ended OK</name>
8275 <order>900</order>
8276 <value>ended_ok</value>
8277 <ola/>
8278 </stage>
8279 <stage>
8280 <name>Ended Failed</name>
8281 <order>900</order>
8282 <value>ended_failed</value>
8283 <ola/>
8284 </stage>
8285 <stage>
8286 <name>Completed</name>
8287 <order>1000</order>
8288 <value>completed</value>
8289 <ola/>
8290 </stage>
8291</stages>
8292
8293
8294
8295 <activities>
8296 <activity>
8297 <name>Begin</name>
8298 <activity_definition>Begin</activity_definition>
8299 <stage/>
8300 <width/>
8301 <height/>
8302 <x>1</x>
8303 <y>1</y>
8304 <snsc_name>begin</snsc_name>
8305 </activity>
8306
8307 <activity>
8308 <name>Check item's price is 0 or not?</name>
8309 <activity_definition>If</activity_definition>
8310 <stage/>
8311 <width/>
8312 <height/>
8313 <x>1</x>
8314 <y>2</y>
8315 <snsc_name>check_price</snsc_name>
8316 <variables>
8317 <variable>
8318 <name>script</name>
8319 <value><![CDATA[function ifScript() {
8320 var item = (new x_ausgh_snsc.SaraGlideHelper()).getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SN_CATALOG_ITEM, {
8321 'sys_id': current.cat_item.sys_id
8322 });
8323
8324 if ((item.price.toString()) === '0') {
8325 return 'yes';
8326 }
8327
8328 return 'no';
8329}
8330
8331answer = ifScript();
8332]]></value>
8333 </variable>
8334 <variable>
8335 <name>advanced</name>
8336 <value>1</value>
8337 </variable>
8338 </variables>
8339 </activity>
8340
8341 <activity>
8342 <name>Waiting for approval</name>
8343 <activity_definition>Approval - Group</activity_definition>
8344 <stage/>
8345 <width/>
8346 <height/>
8347 <x>1</x>
8348 <y>3</y>
8349 <snsc_name>waiting_for_approval</snsc_name>
8350 <variables>
8351 <variable>
8352 <name>wait_for</name>
8353 <value>first_any</value>
8354 </variable>
8355 <variable>
8356 <name>reject_handling</name>
8357 <value>reject</value>
8358 </variable>
8359 </variables>
8360 </activity>
8361
8362 <activity>
8363 <name>Approved</name>
8364 <activity_definition>Approval Action</activity_definition>
8365 <stage/>
8366 <width/>
8367 <height/>
8368 <x>2</x>
8369 <y>3</y>
8370 <snsc_name>approved</snsc_name>
8371 <variables>
8372 <variable>
8373 <name>action</name>
8374 <value>approved</value>
8375 </variable>
8376 </variables>
8377 </activity>
8378
8379 <activity>
8380 <name>Rejected</name>
8381 <activity_definition>Approval Action</activity_definition>
8382 <stage/>
8383 <width/>
8384 <height/>
8385 <x>1</x>
8386 <y>4</y>
8387 <snsc_name>rejected</snsc_name>
8388 <variables>
8389 <variable>
8390 <name>action</name>
8391 <value>rejected</value>
8392 </variable>
8393 </variables>
8394 </activity>
8395
8396 <activity>
8397 <name>Initializing</name>
8398 <activity_definition>Timer</activity_definition>
8399 <stage>initializing</stage>
8400 <width/>
8401 <height/>
8402 <x>3</x>
8403 <y>3</y>
8404 <snsc_name>initializing</snsc_name>
8405 <variables>
8406 <variable>
8407 <name>timer_type</name>
8408 <value>script</value>
8409 </variable>
8410 <variable>
8411 <name>script</name>
8412 <value><![CDATA[workflow.info('Initializing ...');
8413var currentUser = current.opened_by.user_name.toString();
8414workflow.info('Workflow started by {0}', currentUser);
8415workflow.scratchpad.openedBy = currentUser;
8416
8417var technicalUser = new x_ausgh_snsc.SaraConfig().getTechnicalUser();
8418workflow.info('Technical user: {0}', technicalUser);
8419workflow.scratchpad.technicalUser = technicalUser;
8420
8421// Set 'answer' to the number of seconds this timer should wait
8422answer = 2;
8423]]></value>
8424 </variable>
8425 </variables>
8426 </activity>
8427
8428 <activity>
8429 <name>Invoke Consume URL</name>
8430 <activity_definition>Run Script</activity_definition>
8431 <stage>transferring</stage>
8432 <width/>
8433 <height/>
8434 <x>4</x>
8435 <y>3</y>
8436 <snsc_name>invoke_consume</snsc_name>
8437 <variables>
8438 <variable>
8439 <name>script</name>
8440 <value><![CDATA[var restClient = new x_ausgh_snsc.SaraRESTClient();
8441restClient.setMIDServer(x_ausgh_snsc.SaraUtils.getMIDServer());
8442var oauthClient = new x_ausgh_snsc.SaraOAuthClient(restClient);
8443var glideHelper = new x_ausgh_snsc.SaraGlideHelper();
8444
8445// Get tokens, store tokens in workflow scratchpad
8446var tokens = oauthClient.getUserTokens(workflow.scratchpad.technicalUser);
8447
8448if (!tokens) {
8449 workflow.info('Cannot find access tokens for this user "{0}". Order will be skipped', workflow.scratchpad.technicalUser);
8450} else {
8451 workflow.scratchpad.executionHref = null;
8452 workflow.scratchpad.isTransfered = false;
8453
8454 // get service name & consume URL
8455 var serviceName, consumeUrl, varSetId;
8456 var catId = current.cat_item.sys_id;
8457 var saraItem = glideHelper.getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SARA_DEFINITION, {
8458 'u_sc_item': catId
8459 });
8460
8461 if (saraItem) {
8462 serviceName = saraItem['u_name'];
8463 consumeUrl = saraItem['u_consume_url'];
8464 varSetId = saraItem['u_var_set'];
8465
8466 consumeUrl = x_ausgh_snsc.SaraUtils.buildUrl(consumeUrl);
8467
8468 workflow.info('Service name = {0}', serviceName);
8469 workflow.info('Consume URL = {0}', consumeUrl);
8470 workflow.info('Cat item = {0}', current.cat_item.name);
8471
8472 var payload = {};
8473 var payloadFields = {};
8474 payload.fieldvalues = payloadFields;
8475
8476 if (varSetId) {
8477 var saraVariables = glideHelper.getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SARA_VARIABLE, {
8478 'variable_set': varSetId
8479 }, true);
8480
8481 for (var i = 0, variable; variable = saraVariables[i]; i++) {
8482 var variableName = variable['name'];
8483
8484 if (variableName !== x_ausgh_snsc.SaraCommon.CONTROL_NAME.CLIENT_SCRIPTS
8485 && variableName !== x_ausgh_snsc.SaraCommon.CONTROL_NAME.HIDDEN_CONTROL
8486 && variable['u_name']) {
8487
8488 var currentVariable = current.variables[variableName];
8489 var currentValue;
8490
8491 if (variable['type'] === x_ausgh_snsc.SaraCommon.VAR_TYPE.LIST_COLLECTOR.toString()) {
8492 var values = currentVariable.toString().split(',');
8493 currentValue = [];
8494
8495 for (var j = 0, value; value = values[j]; j++) {
8496 var realValue = glideHelper.getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SARA_LOOKUP, {
8497 'sys_id': value
8498 });
8499
8500 currentValue.push(realValue['u_display_name']);
8501 }
8502 } else {
8503 currentValue = [currentVariable.getDisplayValue()];
8504 }
8505
8506 payloadFields[variable['u_name']] = currentValue;
8507 }
8508 }
8509 } else {
8510 workflow.info('There is no variables in catalog item (sys_id = {0})', catId);
8511 }
8512
8513 //---------------- audit information ---------------
8514 workflow.info('Add audit information');
8515
8516 var payloadParams = {};
8517 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.ORDER_ID] = current.request.number.toString();
8518 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.ORDER_TIMESTAMP] = current.sys_created_on.toString();
8519 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.ORDER_NAME] = current.sys_created_by.toString();
8520
8521 var approvalHistory = '<<Auto Approval>>';
8522
8523 if(current.approval_history != null) {
8524 var journal = glideHelper.getData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SN_JOURNAL_FIELD, {
8525 'element_id' : current.sys_id
8526 });
8527 if(journal != null) {
8528 approvalHistory = journal.value.toString();
8529 }
8530 }
8531
8532 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.APPROVAL_HISTORY] = approvalHistory;
8533 payloadParams[x_ausgh_snsc.SaraCommon.AUDIT.APPROVAL_TIMESTAMP] = current.approval_set.toString();
8534
8535 payload.parametervalues = payloadParams;
8536 //--------------- /audit information ---------------
8537
8538 var payloadStr = x_ausgh_snsc.SaraJSON.stringify(payload);
8539 workflow.info(payloadStr);
8540
8541 // Make request
8542 if (serviceName) {
8543 workflow.info('Invoking consume URL...');
8544
8545 var request = restClient.newSAPIRequest('post', consumeUrl);
8546 request.setContent('${payload}');
8547 request.addHeader('content-type', 'application/json;charset=UTF-8');
8548 request.setStringParameterNoEscape('payload', payloadStr);
8549
8550 // Add Authorization header
8551 request.addHeader('Authorization', tokens[3] + ' ' + tokens[0]);
8552
8553 var response = restClient.executeWithRefreshToken(request);
8554 var responseObject = response.getResponseObject();
8555
8556 if (response.haveError()) {
8557 workflow.info('Order process FAILED.');
8558 } else {
8559 workflow.info('Successfully transfered.');
8560 workflow.info('Response: {0}', response.getBody());
8561 var resObj = x_ausgh_snsc.SaraJSON.parse(response.getBody());
8562 var runId = resObj['runID'];
8563
8564 workflow.scratchpad.isTransfered = true;
8565
8566 if (runId !== undefined) {
8567 var executionHref = resObj['_links']['self']['href'];
8568 workflow.info('Got runId: {0}', runId.toString());
8569 workflow.info('Got execution href: {0}', executionHref);
8570 workflow.scratchpad.runId = runId;
8571 workflow.scratchpad.executionHref = executionHref;
8572
8573 // save runId to the 'correlation_id' column of current record in 'sc_req_item' table
8574 current['correlation_id'] = '' + runId;
8575 current.update();
8576 } else {
8577 workflow.info(resObj.message);
8578 }
8579 }
8580
8581 } else {
8582 workflow.info('Failed to make consume request as no service definition was defined.');
8583 }
8584 } else {
8585 workflow.info('Catalog item (sys_id = {0}) doesn\'t existed any more in {1}!', [catId, x_ausgh_snsc.SaraCommon.TABLE_NAME.SARA_DEFINITION]);
8586 }
8587}
8588]]></value>
8589 </variable>
8590 </variables>
8591 </activity>
8592
8593 <activity>
8594 <name>Check transfer result</name>
8595 <activity_definition>If</activity_definition>
8596 <stage>transferred</stage>
8597 <width/>
8598 <height/>
8599 <x>5</x>
8600 <y>3</y>
8601 <snsc_name>check_transfer</snsc_name>
8602 <variables>
8603 <variable>
8604 <name>script</name>
8605 <value><![CDATA[// This script needs to set answer to 'yes' or 'no' to indicate the state of the activity.
8606//
8607// For example,
8608//
8609answer = ifScript();
8610
8611function ifScript() {
8612 return (workflow.scratchpad.isTransfered == true ? 'yes' : 'no');
8613}
8614]]></value>
8615 </variable>
8616 <variable>
8617 <name>advanced</name>
8618 <value>1</value>
8619 </variable>
8620 </variables>
8621 </activity>
8622
8623 <activity>
8624 <name>Transfer Request Failed</name>
8625 <activity_definition>Log Message</activity_definition>
8626 <stage>transfer_failed</stage>
8627 <width/>
8628 <height/>
8629 <x>5</x>
8630 <y>4</y>
8631 <snsc_name>transfer_failed</snsc_name>
8632 <variables>
8633 <variable>
8634 <name>message</name>
8635 <value>Transfer request failed, order skipped.</value>
8636 </variable>
8637 </variables>
8638 </activity>
8639
8640 <activity>
8641 <name>Check consume result</name>
8642 <activity_definition>If</activity_definition>
8643 <stage>transferred</stage>
8644 <width/>
8645 <height/>
8646 <x>6</x>
8647 <y>4</y>
8648 <snsc_name>check_consume</snsc_name>
8649 <variables>
8650 <variable>
8651 <name>script</name>
8652 <value><![CDATA[// This script needs to set answer to 'yes' or 'no' to indicate the state of the activity.
8653//
8654// For example,
8655//
8656answer = ifScript();
8657
8658function ifScript() {
8659 return (workflow.scratchpad.executionHref != null ? 'yes' : 'no');
8660}
8661]]></value>
8662 </variable>
8663 <variable>
8664 <name>advanced</name>
8665 <value>1</value>
8666 </variable>
8667 </variables>
8668 </activity>
8669
8670 <activity>
8671 <name>Consume Request Failed</name>
8672 <activity_definition>Log Message</activity_definition>
8673 <stage>consume_failed</stage>
8674 <width/>
8675 <height/>
8676 <x>6</x>
8677 <y>5</y>
8678 <snsc_name>consume_failed</snsc_name>
8679 <variables>
8680 <variable>
8681 <name>message</name>
8682 <value>Consume request failed, order skipped.</value>
8683 </variable>
8684 </variables>
8685 </activity>
8686
8687 <activity>
8688 <name>Workflow Timer</name>
8689 <activity_definition>Timer</activity_definition>
8690 <stage>running</stage>
8691 <width/>
8692 <height/>
8693 <x>7</x>
8694 <y>5</y>
8695 <snsc_name>workflow_timer</snsc_name>
8696 <variables>
8697 <variable>
8698 <name>timer_type</name>
8699 <value>script</value>
8700 </variable>
8701 <variable>
8702 <name>script</name>
8703 <value><![CDATA[if (workflow.scratchpad.delay === undefined) {
8704 var delay = +x_ausgh_snsc.SaraUtils.getSaraProperty(SaraCommon.SYSTEM_PROPERTY_NAME.WORKFLOW_DELAY);
8705 var timeout = +x_ausgh_snsc.SaraUtils.getSaraProperty(SaraCommon.SYSTEM_PROPERTY_NAME.WORKFLOW_TIMEOUT);
8706
8707 // If delay time in config is equal or lesser than 0, let make it '60'
8708 if (delay <= 0) {
8709 delay = 60;
8710 }
8711
8712 // Make sure that timeout minimum always be '0'
8713 if (timeout < 0) {
8714 timeout = 0;
8715 }
8716
8717 workflow.scratchpad.counter = 1;
8718 workflow.scratchpad.maxCount = (timeout / delay) + 1;
8719 workflow.scratchpad.delay = delay;
8720 workflow.scratchpad.timeout = timeout;
8721}
8722
8723answer = workflow.scratchpad.delay;
8724]]></value>
8725 </variable>
8726 </variables>
8727 </activity>
8728
8729 <activity>
8730 <name>Retrieve Execution Status</name>
8731 <activity_definition>Run Script</activity_definition>
8732 <stage>running</stage>
8733 <width/>
8734 <height/>
8735 <x>8</x>
8736 <y>5</y>
8737 <snsc_name>retrieve_status</snsc_name>
8738 <variables>
8739 <variable>
8740 <name>script</name>
8741 <value><![CDATA[var restClient = new x_ausgh_snsc.SaraRESTClient();
8742restClient.setMIDServer(x_ausgh_snsc.SaraUtils.getMIDServer());
8743var oauthClient = new x_ausgh_snsc.SaraOAuthClient(restClient);
8744var executionHref = x_ausgh_snsc.SaraUtils.buildUrl(workflow.scratchpad.executionHref);
8745
8746workflow.scratchpad.ended = 'unknown';
8747
8748// Get tokens, store tokens in workflow scratchpad
8749var tokens = oauthClient.getUserTokens(workflow.scratchpad.technicalUser);
8750var request = restClient.newSAPIRequest('get', executionHref);
8751request.addHeader('Authorization', tokens[3] + ' ' + tokens[0]);
8752
8753workflow.info('[{0}] Waiting for execution checking response ...', workflow.scratchpad.counter);
8754var response = restClient.executeWithRefreshToken(request);
8755var responseObject = response.getResponseObject();
8756
8757if (response.haveError()) {
8758 workflow.warn('Status code: {0}, error message: {1}', [responseObject.statusCode, responseObject.errorMessage]);
8759
8760 workflow.info('Stop retrieving execution status now.');
8761} else {
8762 workflow.info('Response received: {0}', response.getBody());
8763 var resObj = responseObject.bodyObject;
8764 var statusCode = resObj.statusCode;
8765 workflow.info('Status code: {0}, statusText: {1}', [statusCode.toString(), resObj.statusText]);
8766
8767 if (statusCode >= 1800) {
8768 if (statusCode === x_ausgh_snsc.SaraCommon.WORKFLOW_STATUS_CODE.ENDED_OK) {
8769 workflow.info('Execution finished successfully!');
8770 workflow.scratchpad.ended = 'ENDED_OK';
8771 } else {
8772 workflow.scratchpad.ended = statusCode + ' - ' + resObj.statusText;
8773 }
8774 }
8775}
8776
8777workflow.scratchpad.counter++;
8778]]></value>
8779 </variable>
8780 </variables>
8781 </activity>
8782
8783 <activity>
8784 <name>Check Timeout</name>
8785 <activity_definition>If</activity_definition>
8786 <stage>running</stage>
8787 <width/>
8788 <height/>
8789 <x>9</x>
8790 <y>5</y>
8791 <snsc_name>check_timeout</snsc_name>
8792 <variables>
8793 <variable>
8794 <name>script</name>
8795 <value><![CDATA[function ifScript() {
8796 var counter = workflow.scratchpad.counter;
8797 var maxCount = workflow.scratchpad.maxCount;
8798 var timeout = workflow.scratchpad.timeout;
8799
8800 if (timeout === 0) {
8801 if (workflow.scratchpad.ended !== 'unknown') {
8802 return 'yes';
8803 }
8804 } else {
8805 if (counter <= maxCount) {
8806 if (workflow.scratchpad.ended !== 'unknown') {
8807 return 'yes';
8808 }
8809 } else {
8810 return 'yes';
8811 }
8812 }
8813
8814 return 'no';
8815}
8816
8817answer = ifScript();
8818]]></value>
8819 </variable>
8820 <variable>
8821 <name>advanced</name>
8822 <value>1</value>
8823 </variable>
8824 </variables>
8825 </activity>
8826
8827 <activity>
8828 <name>Check Execution Result</name>
8829 <activity_definition>If</activity_definition>
8830 <stage>running</stage>
8831 <width/>
8832 <height/>
8833 <x>10</x>
8834 <y>6</y>
8835 <snsc_name>check_result</snsc_name>
8836 <variables>
8837 <variable>
8838 <name>script</name>
8839 <value><![CDATA[// This script needs to set answer to 'yes' or 'no' to indicate the state of the activity.
8840
8841answer = ifScript();
8842
8843function ifScript() {
8844 return (workflow.scratchpad.ended == 'ENDED_OK' ? 'yes' : 'no');
8845}
8846]]></value>
8847 </variable>
8848 <variable>
8849 <name>advanced</name>
8850 <value>1</value>
8851 </variable>
8852 </variables>
8853 </activity>
8854
8855 <activity>
8856 <name>Ended Failed</name>
8857 <activity_definition>Log Message</activity_definition>
8858 <stage>ended_failed</stage>
8859 <width/>
8860 <height/>
8861 <x>10</x>
8862 <y>7</y>
8863 <snsc_name>ended_failed</snsc_name>
8864 <variables>
8865 <variable>
8866 <name>message</name>
8867 <value>Workflow finished NOT OK.</value>
8868 </variable>
8869 </variables>
8870 </activity>
8871
8872 <activity>
8873 <name>Ended OK</name>
8874 <activity_definition>Log Message</activity_definition>
8875 <stage>ended_ok</stage>
8876 <width/>
8877 <height/>
8878 <x>11</x>
8879 <y>7</y>
8880 <snsc_name>ended_ok</snsc_name>
8881 <variables>
8882 <variable>
8883 <name>message</name>
8884 <value>Workflow finished successfully.</value>
8885 </variable>
8886 </variables>
8887 </activity>
8888
8889 <activity>
8890 <name>End</name>
8891 <activity_definition>End</activity_definition>
8892 <stage>completed</stage>
8893 <width/>
8894 <height/>
8895 <x>2</x>
8896 <y>8</y>
8897 <snsc_name>end</snsc_name>
8898 </activity>
8899</activities>
8900
8901
8902
8903 <transitions>
8904
8905 <transition>
8906 <from>begin</from>
8907 <to>check_price</to>
8908 <condition>
8909 <name>Always</name>
8910 <condition>true</condition>
8911 <order>1</order>
8912 <description/>
8913 </condition>
8914 </transition>
8915
8916
8917 <transition>
8918 <from>check_price</from>
8919 <to>waiting_for_approval</to>
8920 <condition>
8921 <name>No</name>
8922 <condition>activity.result == 'no'</condition>
8923 <order>1</order>
8924 <description/>
8925 </condition>
8926 </transition>
8927
8928
8929 <transition>
8930 <from>check_price</from>
8931 <to>approved</to>
8932 <condition>
8933 <name>Yes</name>
8934 <condition>activity.result == 'yes'</condition>
8935 <order>1</order>
8936 <description/>
8937 </condition>
8938 </transition>
8939
8940
8941 <transition>
8942 <from>waiting_for_approval</from>
8943 <to>rejected</to>
8944 <condition>
8945 <name>Rejected</name>
8946 <condition>activity.result == 'rejected'</condition>
8947 <order>1</order>
8948 <description/>
8949 </condition>
8950 </transition>
8951
8952
8953 <transition>
8954 <from>rejected</from>
8955 <to>end</to>
8956 <condition>
8957 <name>Always</name>
8958 <condition>true</condition>
8959 <order>1</order>
8960 <description/>
8961 </condition>
8962 </transition>
8963
8964
8965 <transition>
8966 <from>waiting_for_approval</from>
8967 <to>approved</to>
8968 <condition>
8969 <name>Approved</name>
8970 <condition>activity.result == 'approved' || activity.result == 'skipped'</condition>
8971 <order>1</order>
8972 <description/>
8973 </condition>
8974 </transition>
8975
8976
8977 <transition>
8978 <from>approved</from>
8979 <to>initializing</to>
8980 <condition>
8981 <name>Always</name>
8982 <condition>true</condition>
8983 <order>1</order>
8984 <description/>
8985 </condition>
8986 </transition>
8987
8988
8989 <transition>
8990 <from>initializing</from>
8991 <to>invoke_consume</to>
8992 <condition>
8993 <name>Always</name>
8994 <condition>true</condition>
8995 <order>1</order>
8996 <description/>
8997 </condition>
8998 </transition>
8999
9000
9001 <transition>
9002 <from>invoke_consume</from>
9003 <to>check_transfer</to>
9004 <condition>
9005 <name>Always</name>
9006 <condition>true</condition>
9007 <order>1</order>
9008 <description/>
9009 </condition>
9010 </transition>
9011
9012
9013 <transition>
9014 <from>check_transfer</from>
9015 <to>transfer_failed</to>
9016 <condition>
9017 <name>No</name>
9018 <condition>activity.result == 'no'</condition>
9019 <order>1</order>
9020 <description/>
9021 </condition>
9022 </transition>
9023
9024
9025 <transition>
9026 <from>transfer_failed</from>
9027 <to>end</to>
9028 <condition>
9029 <name>Always</name>
9030 <condition>true</condition>
9031 <order>1</order>
9032 <description/>
9033 </condition>
9034 </transition>
9035
9036
9037 <transition>
9038 <from>check_transfer</from>
9039 <to>check_consume</to>
9040 <condition>
9041 <name>Yes</name>
9042 <condition>activity.result == 'yes'</condition>
9043 <order>1</order>
9044 <description/>
9045 </condition>
9046 </transition>
9047
9048
9049 <transition>
9050 <from>check_consume</from>
9051 <to>consume_failed</to>
9052 <condition>
9053 <name>No</name>
9054 <condition>activity.result == 'no'</condition>
9055 <order>1</order>
9056 <description/>
9057 </condition>
9058 </transition>
9059
9060
9061 <transition>
9062 <from>consume_failed</from>
9063 <to>end</to>
9064 <condition>
9065 <name>Always</name>
9066 <condition>true</condition>
9067 <order>1</order>
9068 <description/>
9069 </condition>
9070 </transition>
9071
9072
9073 <transition>
9074 <from>check_consume</from>
9075 <to>workflow_timer</to>
9076 <condition>
9077 <name>Yes</name>
9078 <condition>activity.result == 'yes'</condition>
9079 <order>1</order>
9080 <description/>
9081 </condition>
9082 </transition>
9083
9084
9085 <transition>
9086 <from>workflow_timer</from>
9087 <to>retrieve_status</to>
9088 <condition>
9089 <name>Always</name>
9090 <condition>true</condition>
9091 <order>1</order>
9092 <description/>
9093 </condition>
9094 </transition>
9095
9096
9097 <transition>
9098 <from>retrieve_status</from>
9099 <to>check_timeout</to>
9100 <condition>
9101 <name>Always</name>
9102 <condition>true</condition>
9103 <order>1</order>
9104 <description/>
9105 </condition>
9106 </transition>
9107
9108
9109 <transition>
9110 <from>check_timeout</from>
9111 <to>workflow_timer</to>
9112 <condition>
9113 <name>No</name>
9114 <condition>activity.result == 'no'</condition>
9115 <order>2</order>
9116 <description/>
9117 </condition>
9118 </transition>
9119
9120
9121 <transition>
9122 <from>check_timeout</from>
9123 <to>check_result</to>
9124 <condition>
9125 <name>Yes</name>
9126 <condition>activity.result == 'yes'</condition>
9127 <order>1</order>
9128 <description/>
9129 </condition>
9130 </transition>
9131
9132
9133 <transition>
9134 <from>check_result</from>
9135 <to>ended_failed</to>
9136 <condition>
9137 <name>No</name>
9138 <condition>activity.result == 'no'</condition>
9139 <order>2</order>
9140 <description/>
9141 </condition>
9142 </transition>
9143
9144
9145 <transition>
9146 <from>ended_failed</from>
9147 <to>end</to>
9148 <condition>
9149 <name>Always</name>
9150 <condition>true</condition>
9151 <order>1</order>
9152 <description/>
9153 </condition>
9154 </transition>
9155
9156
9157 <transition>
9158 <from>check_result</from>
9159 <to>ended_ok</to>
9160 <condition>
9161 <name>Yes</name>
9162 <condition>activity.result == 'yes'</condition>
9163 <order>1</order>
9164 <description/>
9165 </condition>
9166 </transition>
9167
9168
9169 <transition>
9170 <from>ended_ok</from>
9171 <to>end</to>
9172 <condition>
9173 <name>Always</name>
9174 <condition>true</condition>
9175 <order>1</order>
9176 <description/>
9177 </condition>
9178 </transition>
9179</transitions>
9180
9181 </workflow>
9182</workflows>
9183
9184
9185 <fix_scripts>
9186 <fix_script>
9187 <name>Sara - Create Scheduler for auto-sync</name>
9188 <description>Create Scheduler for auto-sync service and lookup value</description>
9189 <active>true</active>
9190 <run_once>true</run_once>
9191 <script><![CDATA[var glideHelper = new x_ausgh_snsc.SaraGlideHelper();
9192
9193glideHelper.persistData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SN_AUTO_SCRIPT, {
9194 'name': 'SaraAutoSync',
9195 'script': 'new x_ausgh_snsc.SaraSync().syncServices();',
9196 'active': true,
9197 'run_type': 'periodically',
9198 'run_period': '02:00:00',
9199 'sys_class_name': 'sysauto_script',
9200 'run_dayofweek': 1
9201});
9202]]></script>
9203 </fix_script>
9204 <fix_script>
9205 <name>Sara - Remove Scheduler for auto-sync</name>
9206 <description>Remove Scheduler for auto-sync service and lookup value</description>
9207 <active>true</active>
9208 <run_once>true</run_once>
9209 <script><![CDATA[var glideHelper = new x_ausgh_snsc.SaraGlideHelper();
9210
9211glideHelper.deleteData(x_ausgh_snsc.SaraCommon.TABLE_NAME.SN_AUTO_SCRIPT, {
9212 'name': 'SaraAutoSync'
9213}, true);
9214]]></script>
9215 </fix_script>
9216</fix_scripts>
9217
9218
9219 <schedulers>
9220 <scheduler>
9221 <name>SaraAutoSync</name>
9222 <active>false</active>
9223 <run_type>periodically</run_type>
9224 <run_period>02:00:00</run_period>
9225 <sys_class_name>sysauto_script</sys_class_name>
9226 <run_dayofweek>1</run_dayofweek>
9227 <script>new x_ausgh_snsc.SaraSync().syncServices();</script>
9228 </scheduler>
9229</schedulers>
9230
9231
9232 <wizards>
9233 <wizard>
9234 <name>Automic OAuth Configuration</name>
9235 <type>expert</type>
9236 <banner_type>fixed</banner_type>
9237 <roles>x_ausgh_snsc.admin</roles>
9238 <first_panel>OAuth Client</first_panel>
9239 <variables>
9240 <variable>
9241 <name>sara_client_scripts</name>
9242 <type>14</type>
9243 <class>expert_variable</class>
9244 <question>Sara Client Scripts</question>
9245 <order>0</order>
9246 <mandatory>false</mandatory>
9247 <active>true</active>
9248 <panel>Config OAuth Client</panel>
9249 <macro>sara_client_scripts</macro>
9250 </variable>
9251 <variable>
9252 <name>client_id</name>
9253 <type>6</type>
9254 <class>expert_variable</class>
9255 <question>Client ID</question>
9256 <order>100</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>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>
9263 </variable>
9264 <variable>
9265 <name>client_secret</name>
9266 <type>6</type>
9267 <class>expert_variable</class>
9268 <question>Client Secret</question>
9269 <order>200</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>Secret phrase of OAuth client user. Example: AES_12345, the value will be encrypted in ServiceNow.</help_text>
9276 </variable>
9277 <variable>
9278 <name>technical_user</name>
9279 <type>6</type>
9280 <class>expert_variable</class>
9281 <question>Technical User</question>
9282 <order>300</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>User Name/Department. Example: TECHSYNC/AUTOMIC</help_text>
9289 </variable>
9290 <variable>
9291 <name>sapi_endpoint</name>
9292 <type>6</type>
9293 <class>expert_variable</class>
9294 <question>SAPI Endpoint</question>
9295 <order>400</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>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>
9302 </variable>
9303 <variable>
9304 <name>token_endpoint</name>
9305 <type>6</type>
9306 <class>expert_variable</class>
9307 <question>Token Endpoint</question>
9308 <order>500</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>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>
9315 </variable>
9316 <variable>
9317 <name>auth_endpoint</name>
9318 <type>6</type>
9319 <class>expert_variable</class>
9320 <question>Authorization Endpoint</question>
9321 <order>600</order>
9322 <mandatory>true</mandatory>
9323 <active>true</active>
9324 <panel>Config OAuth Client</panel>
9325 <show_help>true</show_help>
9326 <help_tag>More information</help_tag>
9327 <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>
9328 </variable>
9329 </variables>
9330
9331 <panels>
9332 <panel>
9333 <name>Config OAuth Client</name>
9334 <title>Config OAuth Client</title>
9335 <class>expert_panel</class>
9336 <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>
9337 <previous_message>Previous</previous_message>
9338 <next_message>Store OAuth Client Settings</next_message>
9339 <complete_message>Done</complete_message>
9340 <client_script>
9341 <name>SARA OAuth Client OnLoad</name>
9342 <active>true</active>
9343 <type>onLoad</type>
9344 <script><![CDATA[function onLoad() {
9345 g_form.getControl(x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_SECRET).type = 'password';
9346 x_ausgh_snsc.oldConfig = {};
9347
9348 x_ausgh_snsc.SaraOAuth.getConfig(function (configData) {
9349 for (var name in configData) {
9350 var value = configData[name];
9351
9352 g_form.setValue(name, value);
9353 x_ausgh_snsc.oldConfig[name] = value;
9354 }
9355 });
9356}
9357]]></script>
9358 </client_script>
9359 <client_script>
9360 <name>SARA OAuth Client OnSubmit</name>
9361 <active>true</active>
9362 <type>onSubmit</type>
9363 <script><![CDATA[function onSubmit() {
9364 if (x_ausgh_snsc.isTokenValid) {
9365 return true;
9366 } else {
9367 var isChange = false;
9368 for (var name in x_ausgh_snsc.oldConfig) {
9369 if (x_ausgh_snsc.oldConfig[name] !== g_form.getValue(name).toString() && name !== x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT) {
9370 isChange = true;
9371 break;
9372 }
9373 }
9374
9375 if (isChange && !x_ausgh_snsc.notChange) {
9376 getToken();
9377 } else {
9378 // Clean all existing messages
9379 g_form.clearMessages();
9380
9381 // Check if Sara tokens exist for Technical User
9382 var technicalUser = g_form.getValue(x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER).toString();
9383 var sapiEndpoint = g_form.getValue(x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT).toString();
9384 x_ausgh_snsc.SaraOAuth.checkOAuthToken(technicalUser, sapiEndpoint, false, {
9385 onValid: function () {
9386 x_ausgh_snsc.isTokenValid = true;
9387 g_expert.next();
9388 },
9389 onInvalid: function () {
9390 x_ausgh_snsc.isTokenValid = false;
9391 getToken();
9392 },
9393 onError: function (errorMessage) {
9394 x_ausgh_snsc.isTokenValid = false;
9395 if(errorMessage) {
9396 g_form.addErrorMessage(errorMessage);
9397 }
9398 }
9399 });
9400 }
9401 }
9402
9403 return false;
9404}
9405
9406function getToken() {
9407 x_ausgh_snsc.log('Preparing for openning OAuth login popup...');
9408
9409 for (var key in x_ausgh_snsc.SaraCommon.CONFIG_NAME) {
9410 var name = x_ausgh_snsc.SaraCommon.CONFIG_NAME[key];
9411
9412 x_ausgh_snsc.config[name] = g_form.getValue(name).toString();
9413 }
9414
9415 x_ausgh_snsc.SaraOAuth.login(
9416 x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_ID],
9417 x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER],
9418 x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.AUTH_ENDPOINT], {
9419 onSuccess: function () {
9420 x_ausgh_snsc.notChange = true;
9421 g_expert.next();
9422 }
9423 }
9424 );
9425}
9426]]></script>
9427 </client_script>
9428 </panel>
9429 <panel>
9430 <name>Config OAuth Client Completed</name>
9431 <title>Config OAuth Client Completed</title>
9432 <class>expert_panel</class>
9433 <description/>
9434 <previous_message>Previous</previous_message>
9435 <next_message>Next</next_message>
9436 <complete_message>Done</complete_message>
9437 </panel>
9438 </panels>
9439
9440 <transitions>
9441 <transition>
9442 <from>Config OAuth Client</from>
9443 <to>Config OAuth Client Completed</to>
9444 <order>100</order>
9445 <condition/>
9446 <transition_script><![CDATA[var LOGGER = new x_ausgh_snsc.SaraLog('sara_oauth_client_transition');
9447
9448gs.addInfoMessage('Client ID = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_ID]
9449 + ', Client Secret = ***'
9450 + ', Technical User = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER]
9451 + ', SAPI Endpoint = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT]
9452 + ', Token Endpoint = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT]
9453 + ', Authorization Endpoint = ' + wizard[x_ausgh_snsc.SaraCommon.CONFIG_NAME.AUTH_ENDPOINT]);
9454
9455var saraConfig = new x_ausgh_snsc.SaraConfig();
9456try {
9457 var configData = {};
9458 for (var key in x_ausgh_snsc.SaraCommon.CONFIG_NAME) {
9459 var name = x_ausgh_snsc.SaraCommon.CONFIG_NAME[key];
9460
9461 configData[name] = wizard[name];
9462 }
9463
9464 saraConfig.storeClientConfig(configData);
9465 LOGGER.info('OAuth Configuration updated:\n'
9466 + ' - Client ID = {0}, \n'
9467 + ' - Client Secret = ***, \n'
9468 + ' - Technical User = {1} \n'
9469 + ' - SAPI Endpoint = {2}, \n'
9470 + ' - Token Endpoint = {3}, \n'
9471 + ' - Authorization Endpoint = {4}',
9472 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.CLIENT_ID],
9473 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER],
9474 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT],
9475 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TOKEN_ENDPOINT],
9476 configData[x_ausgh_snsc.SaraCommon.CONFIG_NAME.AUTH_ENDPOINT]
9477 );
9478
9479 gs.addInfoMessage('Successfully update Automic OAuth client settings');
9480} catch (err) {
9481 LOGGER.info('Error on update Automic OAuth client settings: {0}', err);
9482
9483 gs.addInfoMessage('Failed to update Automic OAuth client settings');
9484}
9485]]></transition_script>
9486 </transition>
9487 </transitions>
9488 </wizard>
9489
9490 <wizard>
9491 <name>Automic Import Services</name>
9492 <type>expert</type>
9493 <banner_type>fixed</banner_type>
9494 <roles>x_ausgh_snsc.admin</roles>
9495 <first_panel>Import Services</first_panel>
9496 <variables>
9497 <variable>
9498 <name>sara_client_scripts</name>
9499 <type>14</type>
9500 <class>expert_variable</class>
9501 <question>Sara Client Scripts</question>
9502 <order>0</order>
9503 <mandatory>false</mandatory>
9504 <active>true</active>
9505 <panel>Import Services</panel>
9506 <macro>sara_client_scripts</macro>
9507 </variable>
9508 <variable>
9509 <name>sara_message</name>
9510 <type>6</type>
9511 <class>expert_variable</class>
9512 <question>Sara Message</question>
9513 <order>100</order>
9514 <mandatory>false</mandatory>
9515 <active>true</active>
9516 <panel>Import Services</panel>
9517 </variable>
9518 <variable>
9519 <name>sara_target_category</name>
9520 <type>18</type>
9521 <class>expert_variable</class>
9522 <question>Select Target Category</question>
9523 <order>200</order>
9524 <mandatory>true</mandatory>
9525 <active>true</active>
9526 <lookup_table>sc_category</lookup_table>
9527 <lookup_value>sys_id</lookup_value>
9528 <lookup_label>title</lookup_label>
9529 <panel>Import Services</panel>
9530 <reference_qual>javascript:x_ausgh_snsc.SaraUtils.getImportTargetCatRefQual()</reference_qual>
9531 </variable>
9532 </variables>
9533
9534 <panels>
9535 <panel>
9536 <name>Import Services</name>
9537 <title>Import Services</title>
9538 <class>expert_panel</class>
9539 <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>
9540 <previous_message>Previous</previous_message>
9541 <next_message>Import Services</next_message>
9542 <complete_message>Done</complete_message>
9543 <client_script>
9544 <name>Import Services OnLoad</name>
9545 <active>true</active>
9546 <type>onLoad</type>
9547 <script><![CDATA[function onLoad() {
9548 x_ausgh_snsc.SaraUtils.setFormControlVisible('sara_message', false);
9549 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(false);
9550
9551 x_ausgh_snsc.SaraOAuth.getConfig(function (configData) {
9552 for (var key in configData) {
9553 var value = configData[key];
9554
9555 x_ausgh_snsc.config[key] = value;
9556
9557 if (!value) {
9558 g_form.addErrorMessage('OAuth Configuration "' + key + '" is empty. Please check the current OAuth configuration.');
9559 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(false);
9560 break;
9561 }
9562 }
9563
9564 setTimeout(function () {
9565 checkToken();
9566 }, 100);
9567 });
9568}
9569
9570function checkToken() {
9571 var technicalUser = x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.TECHNICAL_USER];
9572 var sapiEndpoint = x_ausgh_snsc.config[x_ausgh_snsc.SaraCommon.CONFIG_NAME.SAPI_ENDPOINT];
9573 x_ausgh_snsc.SaraOAuth.checkOAuthToken(technicalUser, sapiEndpoint, true, {
9574 onValid: function () {
9575 x_ausgh_snsc.SaraUtils.setWizardSubmitVisible(true);
9576 },
9577 onInvalid: function () {
9578 g_form.addErrorMessage('Tokens are empty, invalid or expired! Please contact your administrator for resolving this problem.');
9579 },
9580 onError: function (errorMessage) {
9581 if(errorMessage) {
9582 g_form.addErrorMessage(errorMessage);
9583 }
9584 }
9585 });
9586}
9587]]></script>
9588 </client_script>
9589 <client_script>
9590 <name>Import Services OnSubmit</name>
9591 <active>true</active>
9592 <type>onSubmit</type>
9593 <script><![CDATA[function onSubmit() {
9594 if (x_ausgh_snsc.isOk) {
9595 return true;
9596 }
9597
9598 var importDialog = new GlideDialogWindow('hierarchical_progress_viewer');
9599 importDialog.setPreference('sysparm_ajax_processor', 'x_ausgh_snsc.SaraConsumerRunner');
9600 importDialog.setPreference('sysparm_catid', g_form.getValue('sara_target_category').toString());
9601 importDialog.setSize(400, 300);
9602 importDialog.setTitle('Importing service...');
9603
9604 importDialog.on('executionComplete', function (trackerObj) {
9605 x_ausgh_snsc.log('executionComplete', trackerObj);
9606 if (trackerObj.result && trackerObj.result.info) {
9607 importDialog.setTitle(trackerObj.result.msg);
9608 g_form.setValue('sara_message', trackerObj.result.info);
9609
9610 x_ausgh_snsc.isOk = true;
9611 x_ausgh_snsc.log('Go to next panel', x_ausgh_snsc.isOk);
9612 g_expert.next();
9613
9614
9615 x_ausgh_snsc.log('Destroy diablog', importDialog);
9616 importDialog.destroy();
9617 }
9618 });
9619
9620 importDialog.on("renderStatus", function (trackerObj) {
9621 x_ausgh_snsc.log('renderStatus', trackerObj);
9622
9623 if (trackerObj && trackerObj.result && trackerObj.result.msg) {
9624 importDialog.setTitle(trackerObj.result.msg);
9625 }
9626 });
9627
9628 // Render the viewer
9629 importDialog.render();
9630
9631 return false;
9632}
9633]]></script>
9634 </client_script>
9635 </panel>
9636 <panel>
9637 <name>Import Services Completed</name>
9638 <title>Import Services Completed</title>
9639 <class>expert_panel</class>
9640 <description/>
9641 <previous_message>Previous</previous_message>
9642 <next_message>Next</next_message>
9643 <complete_message>Done</complete_message>
9644 </panel>
9645 </panels>
9646
9647 <transitions>
9648 <transition>
9649 <from>Import Services</from>
9650 <to>Import Services Completed</to>
9651 <order>100</order>
9652 <condition>[sara_target_category]!=^EQ</condition>
9653 <transition_script><![CDATA[gs.addInfoMessage(wizard.sara_message.toString());
9654]]></transition_script>
9655 </transition>
9656 </transitions>
9657 </wizard>
9658
9659 <wizard>
9660 <name>Automic Clean-up</name>
9661 <type>expert</type>
9662 <banner_type>fixed</banner_type>
9663 <roles>x_ausgh_snsc.admin</roles>
9664 <first_panel>Automic Cleanup</first_panel>
9665 <variables>
9666 <variable/>
9667 </variables>
9668
9669 <panels>
9670 <panel>
9671 <name>Cleanup Catalog Items</name>
9672 <title>Cleanup Catalog Items</title>
9673 <class>expert_panel</class>
9674 <description>Cleanup all Automic SARA stuffs. This will delete all subcategories and service items.</description>
9675 <previous_message>Previous</previous_message>
9676 <next_message>Cleanup</next_message>
9677 <complete_message>Done</complete_message>
9678 </panel>
9679 <panel>
9680 <name>Cleanup Catalog Items Completed</name>
9681 <title>Cleanup Catalog Items Completed</title>
9682 <class>expert_panel</class>
9683 <description>Cleanup successfully!</description>
9684 <previous_message>Previous</previous_message>
9685 <next_message>Next</next_message>
9686 <complete_message>Done</complete_message>
9687 </panel>
9688 </panels>
9689
9690 <transitions>
9691 <transition>
9692 <from>Cleanup Catalog Items</from>
9693 <to>Cleanup Catalog Items Completed</to>
9694 <order>100</order>
9695 <condition/>
9696 <transition_script>
9697 <![CDATA[x_ausgh_snsc.SaraUtils.cleanup();]]>
9698 </transition_script>
9699 </transition>
9700 </transitions>
9701 </wizard>
9702</wizards>
9703
9704
9705 <processors>
9706 <processor>
9707 <name>SaraUpdateStatus</name>
9708 <type>script</type>
9709 <active>true</active>
9710 <description>Sara REST api for updating status of worflow remotely</description>
9711 <path>sara_update_status</path>
9712 <script><![CDATA[var LOGGER = new x_ausgh_snsc.SaraLog('SaraUpdateStatus');
9713var runId = g_request.getParameter('runId');
9714var status = g_request.getParameter('status');
9715var error = 0;
9716var result = {};
9717
9718LOGGER.info('SaraUpdateStatus: RunId = {0}, Status = {1}', runId, status);
9719LOGGER.info('SaraUpdateStatus: Request user = ' + gs.getUserName());
9720
9721if (!runId) {
9722 error += 1;
9723}
9724
9725if (!status) {
9726 error += 1;
9727}
9728
9729if (error === 0) {
9730 runId = +runId;
9731
9732 if (isNaN(runId)) {
9733 result = {
9734 code: 99,
9735 message: 'The runId must be digits!'
9736 };
9737 } else {
9738 var glideHelper = new x_ausgh_snsc.SaraGlideHelper();
9739 var reqItem = glideHelper.getData('sc_req_item', {
9740 'correlation_id': runId.toString()
9741 });
9742
9743 if (reqItem) {
9744 LOGGER.info('Found current request item (correlation_id = {0}, sys_id = {1})', runId, reqItem['sys_id']);
9745
9746 try {
9747 glideHelper.updateData('sc_req_item', {
9748 'sys_id': reqItem['sys_id']
9749 }, {
9750 'comments': status,
9751 'display_state': status
9752 });
9753
9754 result = {
9755 code: 200,
9756 message: 'Update OK!',
9757 sysId: reqItem['sys_id']
9758 };
9759 } catch (e) {
9760 result = {
9761 code: 99,
9762 message: err
9763 };
9764 }
9765 } else {
9766 var message = x_ausgh_snsc.SaraUtils.formatString('No request item (correlation_id = {0}) found! Update status failed.', runId);
9767 LOGGER.info(message);
9768
9769 result = {
9770 code: 99,
9771 message: message
9772 };
9773 }
9774 }
9775} else {
9776 result = {
9777 code: 99,
9778 message: 'The runId and status must be not null!'
9779 }
9780}
9781
9782var response = x_ausgh_snsc.SaraJSON.stringify(result);
9783
9784LOGGER.debug('SaraUpdateStatus: {0}', response);
9785
9786g_processor.writeOutput('application/json', response);
9787]]></script>
9788 </processor>
9789</processors>
9790
9791
9792 <snsc_application>
9793 <application>
9794 <name>Automic SNSC</name>
9795 <short_description>Automic ServiceNow Service Connector Application</short_description>
9796 <active>true</active>
9797 <user_role>x_ausgh_snsc.user</user_role>
9798 <version>1.0.2</version>
9799 <menu>u_ausgh_snsc_menu</menu>
9800 <scope>x_ausgh_snsc</scope>
9801 </application>
9802 <application_menu>
9803 <name>u_ausgh_snsc_menu</name>
9804 <active>true</active>
9805 <category>Custom Applications</category>
9806 <title>Automic SNSC</title>
9807 <roles>x_ausgh_snsc.user,x_ausgh_snsc.admin</roles>
9808 <hint>Automic ServiceNow Service Connector Application</hint>
9809 </application_menu>
9810 <user_roles>
9811 <user_role>
9812 <name>x_ausgh_snsc.user</name>
9813 <description>User role for SNSC application</description>
9814 </user_role>
9815 <user_role>
9816 <name>x_ausgh_snsc.admin</name>
9817 <description>Admin role for SNSC application</description>
9818 <includes_roles>x_ausgh_snsc.user</includes_roles>
9819 </user_role>
9820 </user_roles>
9821</snsc_application>
9822
9823
9824 <modules>
9825 <module>
9826 <title>Automic Configuration</title>
9827 <order>0</order>
9828 <active>true</active>
9829 <link_type>SEPARATOR</link_type>
9830 <roles>x_ausgh_snsc.admin</roles>
9831 </module>
9832 <module>
9833 <title>Automic Clean-up</title>
9834 <reference>wizard</reference>
9835 <reference_name>Automic Clean-up</reference_name>
9836 <order>10</order>
9837 <active>true</active>
9838 <link_type>DIRECT</link_type>
9839 <query>/expert_shell.do?sysparm_sys_id=@{sys_id}&sysparm_initial=true</query>
9840 <roles>x_ausgh_snsc.admin</roles>
9841 </module>
9842 <module>
9843 <title>Automic Import Services</title>
9844 <reference>wizard</reference>
9845 <reference_name>Automic Import Services</reference_name>
9846 <order>20</order>
9847 <active>true</active>
9848 <link_type>DIRECT</link_type>
9849 <query>/expert_shell.do?sysparm_sys_id=@{sys_id}&sysparm_initial=true</query>
9850 <roles>x_ausgh_snsc.admin</roles>
9851 </module>
9852 <module>
9853 <title>Automic OAuth Configuration</title>
9854 <reference>wizard</reference>
9855 <reference_name>Automic OAuth Configuration</reference_name>
9856 <order>30</order>
9857 <active>true</active>
9858 <link_type>DIRECT</link_type>
9859 <query>/expert_shell.do?sysparm_sys_id=@{sys_id}&sysparm_initial=true</query>
9860 <roles>x_ausgh_snsc.admin</roles>
9861 </module>
9862 <module>
9863 <title>Automic SNSC Components</title>
9864 <order>100</order>
9865 <active>true</active>
9866 <link_type>SEPARATOR</link_type>
9867 </module>
9868 <module>
9869 <title>Sara Tables</title>
9870 <order>110</order>
9871 <active>true</active>
9872 <link_type>LIST</link_type>
9873 <table_name>sys_db_object</table_name>
9874 <filter>nameSTARTSWITHx_ausgh_snsc_</filter>
9875 </module>
9876 <module>
9877 <title>Sara Transform Maps</title>
9878 <order>115</order>
9879 <active>true</active>
9880 <link_type>LIST</link_type>
9881 <table_name>sys_transform_map</table_name>
9882 <filter>nameSTARTSWITHx_ausgh_snsc_</filter>
9883 </module>
9884 <module>
9885 <title>Sara System Properties</title>
9886 <reference>system_property</reference>
9887 <reference_name>Automic</reference_name>
9888 <order>120</order>
9889 <active>true</active>
9890 <link_type>DIRECT</link_type>
9891 <query>/sys_properties_category.do?sys_id=@{sys_id}</query>
9892 </module>
9893 <module>
9894 <title>Sara Script Includes</title>
9895 <order>130</order>
9896 <active>true</active>
9897 <link_type>LIST</link_type>
9898 <table_name>sys_script_include</table_name>
9899 <filter>nameSTARTSWITHSara</filter>
9900 </module>
9901 <module>
9902 <title>Sara UI Scripts</title>
9903 <order>140</order>
9904 <active>true</active>
9905 <link_type>LIST</link_type>
9906 <table_name>sys_ui_script</table_name>
9907 <filter>nameSTARTSWITHx_ausgh_snsc.Sara</filter>
9908 </module>
9909 <module>
9910 <title>Sara UI Pages</title>
9911 <order>150</order>
9912 <active>true</active>
9913 <link_type>LIST</link_type>
9914 <table_name>sys_ui_page</table_name>
9915 <filter>nameSTARTSWITHsara_</filter>
9916 </module>
9917 <module>
9918 <title>Sara UI Macros</title>
9919 <order>160</order>
9920 <active>true</active>
9921 <link_type>LIST</link_type>
9922 <table_name>sys_ui_macro</table_name>
9923 <filter>nameSTARTSWITHsara_</filter>
9924 </module>
9925 <module>
9926 <title>Sara Processors</title>
9927 <order>170</order>
9928 <active>true</active>
9929 <link_type>LIST</link_type>
9930 <table_name>sys_processor</table_name>
9931 <filter>nameSTARTSWITHSara</filter>
9932 </module>
9933 <module>
9934 <title>Sara Wizards</title>
9935 <order>180</order>
9936 <active>true</active>
9937 <link_type>LIST</link_type>
9938 <table_name>expert</table_name>
9939 <filter>nameSTARTSWITHAutomic</filter>
9940 </module>
9941 <module>
9942 <title>Sara Schedulers</title>
9943 <order>190</order>
9944 <active>true</active>
9945 <link_type>LIST</link_type>
9946 <table_name>sysauto</table_name>
9947 <filter>nameSTARTSWITHSara</filter>
9948 </module>
9949 <module>
9950 <title>Sara REST Messages</title>
9951 <order>200</order>
9952 <active>true</active>
9953 <link_type>LIST</link_type>
9954 <table_name>sys_rest_message</table_name>
9955 <filter>nameSTARTSWITHSara</filter>
9956 </module>
9957 <module>
9958 <title>Support</title>
9959 <order>900</order>
9960 <active>true</active>
9961 <link_type>SEPARATOR</link_type>
9962 </module>
9963 <module>
9964 <title>Used ServiceNow's Tables</title>
9965 <order>910</order>
9966 <active>true</active>
9967 <link_type>LIST</link_type>
9968 <table_name>sys_db_object</table_name>
9969 <query>name=sc_category^ORname=item_option_new_set^ORname=io_set_item^ORname=sysauto_script^ORname=item_option_new</query>
9970 </module>
9971 <module>
9972 <title>Sara Transform History</title>
9973 <order>915</order>
9974 <active>true</active>
9975 <link_type>LIST</link_type>
9976 <table_name>sys_import_set_run</table_name>
9977 <query>sys_transform_mapSTARTSWITHx_ausgh_snsc</query>
9978 </module>
9979 <module>
9980 <title>Contact Us</title>
9981 <order>920</order>
9982 <active>true</active>
9983 <link_type>DIRECT</link_type>
9984 <query>https://automic.com/contact-us</query>
9985 </module>
9986 <module>
9987 <title>Support</title>
9988 <order>930</order>
9989 <active>true</active>
9990 <link_type>DIRECT</link_type>
9991 <query>https://automic.force.com/support</query>
9992 </module>
9993</modules>
9994
9995
9996 <rest_messages>
9997 <rest_message>
9998 <name>Sara - SAPI Services</name>
9999 <description>Sara Outbound Web Service for SAPI</description>
10000 <rest_endpoint>${sapiEndpoint}</rest_endpoint>
10001 <methods>
10002 <method>
10003 <function_name>GET</function_name>
10004 <http_method>GET</http_method>
10005 </method>
10006 <method>
10007 <function_name>POST</function_name>
10008 <http_method>POST</http_method>
10009 </method>
10010 <method>
10011 <function_name>PUT</function_name>
10012 <http_method>PUT</http_method>
10013 </method>
10014 <method>
10015 <function_name>DELETE</function_name>
10016 <http_method>DELETE</http_method>
10017 </method>
10018 </methods>
10019 </rest_message>
10020 <rest_message>
10021 <name>Sara - OAuth Services</name>
10022 <description>Sara Outbound Web Service for OAuth</description>
10023 <rest_endpoint>${oauthEndpoint}</rest_endpoint>
10024 <methods>
10025 <method>
10026 <function_name>GET</function_name>
10027 <http_method>GET</http_method>
10028 </method>
10029 <method>
10030 <function_name>POST</function_name>
10031 <http_method>POST</http_method>
10032 </method>
10033 <method>
10034 <function_name>PUT</function_name>
10035 <http_method>PUT</http_method>
10036 </method>
10037 <method>
10038 <function_name>DELETE</function_name>
10039 <http_method>DELETE</http_method>
10040 </method>
10041 </methods>
10042 </rest_message>
10043</rest_messages>
10044
10045 </package>
10046</sara>