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