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