1
2
3 var utils = sap.logon.Utils;
4 var TIMEOUT = 2000;
5
6 var _oLogonCore;
7 var _oLogonView;
8 var _hasLogonSuccessEventFired = false;
9
10 var _providedContext;
11
12 var init = function (successCallback, errorCallback, applicationId, context, customView) {
13
14
15 document.addEventListener("resume",
16 function(){
17 resume(
18 function() { fireEvent('onSapResumeSuccess', arguments);},
19 function() { fireEvent('onSapResumeError', arguments);}
20 );
21 },
22 false);
23
24 // The success callback used for the call to _oLogonCore.initLogon(...)
25 var initSuccess = function(){
26 utils.log('LogonController: LogonCore successfully initialized.');
27
28 // Now that Logon is initialized, registerOrUnlock is automatically called.
29 registerOrUnlock( successCallback, errorCallback );
30 }
31
32 var initError = function(error){
33 // If a parameter describing the error is given, pass it along.
34 // Otherwise, construct something to call the error callback with.
35 if( error ) {
36 errorCallback( error );
37 } else {
38 errorCallback( utils.Error('ERR_INIT_FAILED') );
39 }
40 }
41
42 utils.log('LogonController.init enter');
43 utils.log(applicationId);
44 module.exports.applicationId = applicationId;
45
46 // Make note of the context given (if any)
47 if( context ){
48 _providedContext = context;
49 }
50
51 _oLogonView = customView;
52 if (!_oLogonView) {
53 _oLogonView = sap.logon.IabUi;
54 }
55
56 //coLogonCore.cordova.require("com.sap.mp.cordova.plugins.logon.LogonCore");
57 _oLogonCore = sap.logon.Core;
58 _oLogonCore.initLogon(initSuccess, initError, applicationId);
59
60 //update exports definition
61 module.exports.core = _oLogonCore;
62 }
63
64 var fireEvent = function (eventId, args) {
65 if (typeof eventId === 'string') {
66 //var event = document.createEvent('Events');
67 //event.initEvent(eventId, false, false);
68
69 if (!window.CustomEvent) {
70 window.CustomEvent = function(type, eventInitDict) {
71 var newEvent = document.createEvent('CustomEvent');
72 newEvent.initCustomEvent(
73 type,
74 !!(eventInitDict && eventInitDict.bubbles),
75 !!(eventInitDict && eventInitDict.cancelable),
76 (eventInitDict ? eventInitDict.detail : null));
77 return newEvent;
78 };
79 }
80
81 var event = new CustomEvent(eventId, { 'detail':{ 'id': eventId, 'args': args }});
82
83 setTimeout(function() {
84 document.dispatchEvent(event);
85 }, 0);
86 } else {
87 throw 'Invalid eventId: ' + JSON.stringify(event);
88 }
89 }
90
91 var FlowRunner = function(onsuccess, onerror, pLogonView, pLogonCore) {
92
93 var onFlowSuccess;
94 var onFlowError;
95 var onFlowCancel;
96
97 var logonView;
98 var logonCore;
99 var flow;
100
101
102
103 logonView = pLogonView;
104 logonCore = pLogonCore;
105
106 onFlowSuccess = function onFlowSuccess() {
107 utils.logJSON('onFlowSuccess');
108 logonView.close();
109 onsuccess.apply(this, arguments);
110 }
111
112 onFlowError = function onFlowError() {
113 utils.logJSON('onFlowError');
114 logonView.close();
115 onerror.apply(this, arguments);
116 }
117
118 onFlowCancel = function onFlowCancel(){
119 utils.logJSON('onFlowCancel');
120 //logonView.close();
121 onFlowError(new utils.Error('ERR_USER_CANCELLED'));
122 }
123
124 var handleCoreStateOnly = function(currentState){
125 handleCoreResult(null, currentState);
126 }
127
128 var handleCoreResult = function (currentContext, currentState) {
129 if (typeof currentContext === undefined) currentContext = null;
130
131 //workaround for defaultPasscodeAllowed
132 if (currentState) {
133 if (currentContext && currentContext.policyContext && currentContext.policyContext.defaultAllowed){
134 currentState.defaultPasscodeAllowed = true;
135 }
136 else {
137 currentState.defaultPasscodeAllowed = false;
138 }
139 }
140
141 utils.logJSON(currentContext, 'handleCoreResult currentContext');
142 utils.logJSON(currentState, 'handleCoreResult currentState');
143
144
145 utils.logJSON(flow.name);
146 var matchFound = false;
147 var rules = flow.stateTransitions;
148
149
150 ruleMatching:
151 for (key in rules){
152
153 var rule = flow.stateTransitions[key];
154 //utils.logJSON(rule, 'rule');
155
156 //utils.logJSON(rule.condition, 'rule.condition');
157 if (typeof rule.condition === 'undefined') {
158 throw 'undefined condition in state transition rule';
159 }
160
161
162 if (rule.condition.state === null) {
163 if (currentState)
164 {
165 continue ruleMatching; // non-null state (and rule) mismatch
166 }
167 //else {
168 // // match:
169 // // rule.condition.state === null &&
170 // // (typeof currentState === 'undefined') // null or undefined
171 //}
172 }
173 else if (rule.condition.state !== 'undefined' && currentState){
174 utils.log('stateMatching');
175
176 stateMatching:
177 for (field in rule.condition.state) {
178 utils.log(field);
179 if (rule.condition.state[field] === currentState[field])
180 {
181 utils.log('field matching ' + field);
182 continue stateMatching; // state field match
183 }
184 else {
185 utils.log('field mismatching ' + field);
186 continue ruleMatching; // state field (and rule) mismatch
187 };
188 }
189 }
190
191 if (rule.condition.context === null) {
192 if (currentContext)
193 {
194 continue ruleMatching; // non-null context (and rule) mismatch
195 }
196 //else {
197 // // match:
198 // // rule.condition.context === null &&
199 // // (typeof currentContext === 'undefined') // null or undefined
200 //}
201 }
202 else if (rule.condition.context !== 'undefined' && currentContext){
203
204 utils.log('contextMatching');
205 contextMatching:
206 for (field in rule.condition.context) {
207 utils.log(field);
208 if (rule.condition.context[field] === currentContext[field])
209 {
210 utils.log('field matching ' + field);
211 continue contextMatching; // context field match
212 }
213 else {
214 utils.log('field mismatching ' + field);
215 continue ruleMatching; // context field (and rule) mismatch
216 };
217 }
218 }
219 utils.log('match found');
220 utils.logJSON(rule, 'rule');
221
222 if (typeof rule.action === 'function') {
223 rule.action(currentContext);
224 }
225 else if (typeof rule.action === 'string') {
226 // the action is a screenId
227 var screenId = rule.action;
228 utils.log('handleCoreResult: ' + screenId);
229 utils.logKeys(flow.screenEvents[screenId]);
230 if(!currentContext){
231 currentContext = {};
232 }
233
234 if( !currentContext.registrationContext && _providedContext ){
235 // The current registrationContext is null, and we have been given a context when initialized,
236 // so use the one we were given.
237 currentContext.registrationContext = _providedContext;
238 } else if (currentContext.registrationContext && _providedContext && !currentContext.registrationReadOnly){
239 for (key in _providedContext) {
240 //if (!currentContext.registrationContext[key]){
241 currentContext.registrationContext[key] = _providedContext[key];
242 //}
243 }
244 }
245
246 logonView.showScreen(screenId, flow.screenEvents[screenId], currentContext);
247
248 }
249 else {
250 onFlowError(new utils.Error('ERR_INVALID_ACTION'));
251 }
252
253 matchFound = true;
254 break ruleMatching;
255 }
256
257 if (!matchFound) {
258 onFlowError(new utils.Error('ERR_INVALID_STATE'));
259 }
260 }
261
262
263 this.run = function(FlowClass) {
264 utils.log('FlowRunner.run ' + FlowClass.name);
265 flow = new FlowClass(logonCore, logonView, handleCoreResult, onFlowSuccess, onFlowError, onFlowCancel);
266 utils.logKeys(flow , 'new flow ');
267 logonCore.getState(handleCoreStateOnly, onFlowError);
268 }
269
270 }
271
272
273 var MockFlow = function MockFlow(logonCore, logonView, onCoreResult, onFlowSuccess, onFlowError, onFlowCancel) {
274 //wrapped into a function to defer evaluation of the references to flow callbacks
275 //var flow = {};
276
277 this.name = 'mockFlowBuilder';
278
279 this.stateTransitions = [
280 {
281 condition: {
282 state: {
283 secureStoreOpen: false,
284 }
285 },
286 action: 'SCR_MOCKSCREEN'
287 },
288 {
289 condition: {
290 state: {
291 secureStoreOpen: true,
292 }
293 },
294 action: 'SCR_MOCKSCREEN'
295 },
296
297 ];
298
299 this.screenEvents = {
300 'SCR_TURN_PASSCODE_ON': {
301 onsubmit: onFlowSuccess,
302 oncancel: onFlowCancel,
303 onerror: onFlowError,
304 }
305 };
306
307 utils.log('flow constructor return');
308 //return flow;
309 }
310
311 var RegistrationFlow = function RegistrationFlow(logonCore, logonView, onCoreResult, onFlowSuccess, onFlowError, onFlowCancel) {
312 //wrapped into a function to defer evaluation of the references to flow callbacks
313
314 this.name = 'registrationFlowBuilder';
315
316 var registrationInProgress = false;
317
318 var onCancelSSOPin = function() {
319 onFlowError(errorWithDomainCodeDescription("MAFLogon","0","SSO Passcode set screen was cancelled"));
320 }
321
322 var onCancelRegistration = function() {
323 onFlowError(errorWithDomainCodeDescription("MAFLogon","1","Registration screen was cancelled"));
324 }
325
326 // internal methods
327 var showScreen = function(screenId) {
328 return function(coreContext) {
329 logonView.showScreen(screenId, this.screenEvents[screenId], coreContext);
330 }.bind(this);
331 }.bind(this);
332
333 var onUnlockSubmit = function(context){
334 utils.logJSON(context, 'logonCore.unlockSecureStore');
335 logonCore.unlockSecureStore(onCoreResult, onUnlockError, context)
336 }
337
338 var onUnlockError = function(error) {
339 utils.logJSON("onUnlockError: " + JSON.stringify(error));
340
341 // TODO switch case according to the error codes
342 logonView.showNotification("ERR_UNLOCK_FAILED");
343 }
344
345 var noOp = function() { }
346
347 var onRegistrationBackButton = function() {
348 if (registrationInProgress == true) {
349 utils.log('back button pushed, no operation is required as registration is running');
350 }
351 else {
352 onCancelRegistration();
353 }
354 }
355
356 var onUnlockVaultWithDefaultPasscode = function(){
357 utils.log('logonCore.unlockSecureStore - default passcode');
358 var unlockContext = {"unlockPasscode":null};
359 logonCore.unlockSecureStore(onCoreResult, onFlowError, unlockContext)
360 }
361
362 var onRegSucceeded = function(context, state) {
363 onCoreResult(context, state);
364 registrationInProgress = false;
365 }
366
367 var onRegError = function(error){
368 utils.logJSON(error, 'registration failed');
369 logonView.showNotification(getRegistrationErrorText(error));
370 registrationInProgress = false;
371 }
372
373 var onRegSubmit = function(context){
374 utils.logJSON(context, 'logonCore.startRegistration');
375 registrationInProgress = true;
376 logonCore.startRegistration(onRegSucceeded, onRegError, context)
377 }
378
379 var onCreatePasscodeSubmit = function(context){
380 utils.logJSON(context, 'logonCore.persistRegistration');
381 logonCore.persistRegistration(onCoreResult, onCreatePasscodeError, context);
382 }
383
384 var onCancelRegistrationError = function(error){
385 utils.logJSON("onCancelRegistrationError: " + JSON.stringify(error));
386 logonView.showNotification(getRegistrationCancelError(error));
387 }
388
389 var onCreatePasscodeError = function(error) {
390 utils.logJSON("onCreatePasscodeError: " + JSON.stringify(error));
391 logonView.showNotification(getSecureStoreErrorText(error));
392 }
393
394 var onSSOPasscodeSetError = function(error) {
395 utils.logJSON("onSSOPasscodeSetError: " + JSON.stringify(error));
396 logonView.showNotification(getSSOPasscodeSetErrorText(error));
397 }
398
399 var callGetContext = function(){
400 utils.log('logonCore.getContext');
401 logonCore.getContext(onCoreResult, onFlowError);
402 }
403
404 var onFullRegistered = function()
405 {
406 var getContextSuccessCallback = function(result){
407
408 if(!_hasLogonSuccessEventFired) {
409 fireEvent("onSapLogonSuccess", arguments);
410 _hasLogonSuccessEventFired = true;
411 }
412
413 onFlowSuccess(result);
414 }
415 utils.log('logonCore.getContext');
416 logonCore.getContext(getContextSuccessCallback, onFlowError);
417 }
418
419 var onForgotAppPasscode = function(){
420 utils.log('logonCore.deleteRegistration');
421 logonCore.deleteRegistration(onFlowError, onFlowError);
422 }
423
424 var onForgotSsoPin = function(){
425 utils.log('forgotSSOPin');
426 logonView.showNotification("ERR_FORGOT_SSO_PIN");
427 }
428
429 var onSkipSsoPin = function(){
430 utils.logJSON('logonCore.skipClientHub');
431 logonCore.skipClientHub(onCoreResult, onFlowError);
432 }
433
434 var callPersistWithDefaultPasscode = function(context){
435 utils.logJSON(context, 'logonCore.persistRegistration');
436 context.passcode = null;
437 logonCore.persistRegistration(
438 onCoreResult,
439 onFlowError,
440 context)
441 }
442
443 // exported properties
444 this.stateTransitions = [
445 {
446 condition: {
447 state: {
448 secureStoreOpen: false,
449 status: 'fullRegistered',
450 defaultPasscodeUsed: true
451 }
452 },
453 action: onUnlockVaultWithDefaultPasscode
454 },
455
456 {
457 condition: {
458 state: {
459 secureStoreOpen: false,
460 status: 'fullRegistered'
461 }
462 },
463 action: 'SCR_UNLOCK'
464 },
465
466
467 {
468 condition: {
469 state: {
470 //secureStoreOpen: false, //TODO clarify
471 status: 'fullRegistered',
472 stateClientHub: 'availableNoSSOPin'
473 }
474 },
475 action: 'SCR_SSOPIN_SET'
476 },
477 {
478 condition: {
479 state: {
480 secureStoreOpen: false,
481 status: 'new'
482 },
483 context: null
484 },
485 action: callGetContext
486 },
487
488 {
489 condition: {
490 state: {
491 secureStoreOpen: false,
492 status: 'new',
493 stateClientHub: 'availableNoSSOPin'
494 }
495 },
496 action: 'SCR_SSOPIN_SET'
497 },
498
499 {
500 condition: {
501 state: {
502 secureStoreOpen: false,
503 status: 'new',
504 stateClientHub: 'availableInvalidSSOPin'
505 }
506 },
507 action: 'SCR_SSOPIN_SET'
508 },
509
510 {
511 condition: {
512 state: {
513 secureStoreOpen: false,
514 status: 'new',
515 stateClientHub: 'availableValidSSOPin'
516 },
517 context : {
518 credentialsByClientHub : true,
519 registrationReadOnly : true
520 }
521 },
522 action: function(context){
523 utils.logJSON(context, 'logonCore.startRegistration');
524 logonCore.startRegistration(onCoreResult, onFlowError, context.registrationContext);
525 }
526 },
527 {
528 condition: {
529 state: {
530 secureStoreOpen: false,
531 status: 'new',
532 stateClientHub: 'availableValidSSOPin',
533 stateAfaria: 'initializationSuccessful'
534 },
535 context : {
536 registrationReadOnly : true,
537 afariaRegistration: 'certificate'
538 }
539 },
540 action: function(context){
541 utils.logJSON(context, 'logonCore.startRegistration');
542 logonCore.startRegistration(onCoreResult, onFlowError, context.registrationContext);
543 }
544 },
545 {
546 condition: {
547 state: {
548 secureStoreOpen: false,
549 status: 'new',
550 stateClientHub: 'availableValidSSOPin'
551 },
552 context : {
553 registrationReadOnly :true,
554 credentialsByClientHub : false
555 }
556 },
557 action: 'SCR_ENTER_CREDENTIALS'
558 },
559
560
561 {
562 condition: {
563 state: {
564 secureStoreOpen: false,
565 status: 'new',
566 //stateClientHub: 'notAvailable' | 'availableValidSSOPin' | 'skipped' | 'error'
567 stateAfaria: 'initializationFailed'
568 }
569 },
570 action: 'SCR_REGISTRATION'
571 },
572
573 {
574 condition: {
575 state: {
576 secureStoreOpen: false,
577 status: 'new',
578 //stateClientHub: 'notAvailable' | 'availableValidSSOPin' | 'skipped' | 'error'
579 }
580 },
581 action: 'SCR_REGISTRATION'
582 },
583
584 {
585 condition: {
586 state: {
587 secureStoreOpen: false,
588 status: 'new',
589 //stateClientHub: 'notAvailable' | 'availableValidSSOPin' | 'skipped' | 'error'
590 stateAfaria: 'initializationFailed'
591 }
592 },
593 action: 'SCR_REGISTRATION'
594 },
595
596 {
597 condition: {
598 state: {
599 secureStoreOpen: false,
600 status: 'registered',
601 defaultPasscodeUsed: true,
602 // defaultPasscodeAllowed: true,
603 }
604 },
605 action: 'SCR_SET_PASSCODE_OPT_OFF'
606 },
607 {
608 condition: {
609 state: {
610 secureStoreOpen: false,
611 status: 'registered',
612 defaultPasscodeUsed: false,
613 defaultPasscodeAllowed: true,
614 }
615 },
616 action: 'SCR_SET_PASSCODE_OPT_ON'
617 },
618 {
619 condition: {
620 state: {
621 secureStoreOpen: false,
622 status: 'registered',
623 // defaultPasscodeAllowed: false,
624 }
625 },
626 action: 'SCR_SET_PASSCODE_MANDATORY'
627 },
628
629
630 {
631 condition: {
632 state: {
633 //secureStoreOpen: false, //TODO clarify
634 status: 'fullRegistered',
635 stateClientHub: 'availableInvalidSSOPin'
636 }
637 },
638 action: 'SCR_SSOPIN_CHANGE'
639 },
640 {
641 condition: {
642 state: {
643 secureStoreOpen: true,
644 status: 'fullRegistered',
645 stateClientHub: 'notAvailable'
646 }
647 },
648 action: onFullRegistered
649 },
650 {
651 condition: {
652 state: {
653 secureStoreOpen: true,
654 status: 'fullRegistered',
655 stateClientHub: 'availableValidSSOPin'
656 }
657 },
658 action: onFullRegistered
659 },
660 {
661 condition: {
662 state: {
663 secureStoreOpen: true,
664 status: 'fullRegistered',
665 stateClientHub: 'skipped'
666 }
667 },
668 action: onFullRegistered
669 },
670
671
672
673 ];
674
675 this.screenEvents = {
676 'SCR_SSOPIN_SET': {
677 onsubmit: function(context){
678 utils.logJSON(context, 'logonCore.setSSOPasscode');
679 logonCore.setSSOPasscode(onCoreResult, onSSOPasscodeSetError, context);
680 },
681 oncancel: onCancelSSOPin,
682 onerror: onFlowError,
683 onforgot: onForgotSsoPin,
684 onskip: onSkipSsoPin
685 },
686
687 'SCR_SSOPIN_CHANGE': {
688 onsubmit: function(context){
689 utils.logJSON(context, 'logonCore.setSSOPasscode');
690 logonCore.setSSOPasscode(onCoreResult, onSSOPasscodeSetError, context);
691 },
692 oncancel: onSkipSsoPin,
693 onerror: onFlowError,
694 onforgot: onForgotSsoPin
695 },
696
697 'SCR_UNLOCK': {
698 onsubmit: onUnlockSubmit,
699 oncancel: noOp,
700 onerror: onFlowError,
701 onforgot: onForgotAppPasscode,
702 onerrorack: noOp
703 },
704
705 'SCR_REGISTRATION': {
706 onsubmit: onRegSubmit,
707 oncancel: onCancelRegistration,
708 onerror: onFlowError,
709 onbackbutton: onRegistrationBackButton
710 },
711
712 'SCR_ENTER_CREDENTIALS' : {
713 onsubmit: onRegSubmit,
714 oncancel: onCancelRegistration,
715 onerror: onFlowError
716 },
717 'SCR_SET_PASSCODE_OPT_ON': {
718 onsubmit: onCreatePasscodeSubmit,
719 oncancel: noOp,
720 onerror: onFlowError,
721 ondisable: showScreen('SCR_SET_PASSCODE_OPT_OFF'),
722 onerrorack: noOp
723 },
724 'SCR_SET_PASSCODE_OPT_OFF': {
725 onsubmit: callPersistWithDefaultPasscode,
726 oncancel: noOp,
727 onerror: onFlowError,
728 onenable: showScreen('SCR_SET_PASSCODE_OPT_ON'),
729 onerrorack: noOp
730 },
731 'SCR_SET_PASSCODE_MANDATORY': {
732 onsubmit: onCreatePasscodeSubmit,
733 oncancel: noOp,
734 onerror: onFlowError,
735 onerrorack: noOp
736 },
737
738
739
740 };
741
742
743 utils.log('flow constructor return');
744 }
745
746
747
748 var ChangePasswordFlow = function ChangePasswordFlow(logonCore, logonView, onCoreResult, onFlowSuccess, onFlowError, onFlowCancel) {
749 //wrapped into a function to defer evaluation of the references to flow callbacks
750
751 this.name = 'changePasswordFlowBuilder';
752
753
754 // internal methods
755
756 var callUnlockFlow = function(){
757 utils.log(this.name + ' triggered unlock');
758 registerOrUnlock(onCoreResult,onFlowError);
759 }
760
761 var onChangePasswordSubmit = function(context){
762 utils.logJSON(context, 'logonCore.changePassword');
763 // this logonCore call does not return with context
764 logonCore.changePassword(onPasswordChanged, onFlowError, context);
765 }
766
767
768 var onPasswordChanged = function(){
769 utils.log('onPasswordChanged');
770 logonCore.getContext(onFlowSuccess, onFlowError);
771 }
772
773 // exported properties
774 this.stateTransitions = [
775 {
776 condition: {
777 state: {
778 secureStoreOpen: false,
779 }
780 },
781 action: callUnlockFlow,
782 },
783 {
784 condition: {
785 state: {
786 secureStoreOpen: true,
787 }
788 },
789 action: 'SCR_CHANGE_PASSWORD'
790 },
791
792 ];
793
794 this.screenEvents = {
795 'SCR_CHANGE_PASSWORD': {
796 onsubmit: onChangePasswordSubmit,
797 oncancel: onFlowCancel,
798 onerror: onFlowError
799 }
800 };
801
802
803 utils.log('flow constructor return');
804 }
805
806 var ManagePasscodeFlow = function ManagePasscodeFlow(logonCore, logonView, onCoreResult, onFlowSuccess, onFlowError, onFlowCancel) {
807 //wrapped into a function to defer evaluation of the references to flow callbacks
808
809 this.name = 'managePasscodeFlowBuilder';
810
811 // internal methods
812 var showScreen = function(screenId) {
813 return function(coreContext) {
814 logonView.showScreen(screenId, this.screenEvents[screenId], coreContext);
815 }.bind(this);
816 }.bind(this);
817
818
819 var callChangePasscode = function(context){
820 utils.logJSON(context, 'logonCore.changePasscode');
821 logonCore.changePasscode(
822 onCoreResult,
823 onChangePasscodeError,
824 context)
825 }
826
827 var onChangePasscodeError = function(error) {
828 utils.logJSON("onChangePasscodeError: " + JSON.stringify(error));
829 logonView.showNotification(getSecureStoreErrorText(error));
830 }
831
832 var noOp = function() { }
833
834 var callDisablePasscode = function(context){
835 utils.logJSON(context, 'logonCore.disablePasscode');
836 context.passcode = null;
837 logonCore.changePasscode(
838 onCoreResult,
839 onFlowError,
840 context)
841 }
842
843 var callGetContext = function(){
844 utils.log('logonCore.getContext');
845 logonCore.getContext(onCoreResult, onFlowError);
846 }
847
848 var onPasscodeEnable = function(context){
849 utils.logJSON(context, this.name + ' onPasscodeEnable: ');
850 //logonCore.changePasscode(onFlowSuccess, onFlowError, context);
851 onFlowError();
852 }
853
854 // exported properties
855 this.stateTransitions = [
856 {
857 condition: {
858 state: {
859 secureStoreOpen: true,
860 },
861 context: null
862 },
863 action: callGetContext
864 },
865 {
866 condition: {
867 state: {
868 secureStoreOpen: false,
869 }
870 },
871 action: onFlowError
872 },
873 {
874 condition: {
875 state: {
876 secureStoreOpen: true,
877 defaultPasscodeUsed: true,
878 // defaultPasscodeAllowed: true,
879 }
880 },
881 action: 'SCR_MANAGE_PASSCODE_OPT_OFF'
882 },
883 {
884 condition: {
885 state: {
886 secureStoreOpen: true,
887 defaultPasscodeUsed: false,
888 defaultPasscodeAllowed: true,
889 }
890 },
891 action: 'SCR_MANAGE_PASSCODE_OPT_ON'
892 },
893 {
894 condition: {
895 state: {
896 secureStoreOpen: true,
897 //defaultPasscodeUsed: [DONTCARE],
898 defaultPasscodeAllowed: false,
899 }
900 },
901 action: 'SCR_MANAGE_PASSCODE_MANDATORY'
902 },
903
904
905 ];
906
907 this.screenEvents = {
908 'SCR_MANAGE_PASSCODE_OPT_ON': {
909 onsubmit: onFlowSuccess,
910 oncancel: onFlowSuccess,
911 onerror: onFlowError,
912 ondisable: showScreen('SCR_CHANGE_PASSCODE_OPT_OFF'),
913 onchange: showScreen('SCR_CHANGE_PASSCODE_OPT_ON')
914 },
915 'SCR_MANAGE_PASSCODE_OPT_OFF': {
916 onsubmit: onFlowSuccess,
917 oncancel: onFlowSuccess,
918 onerror: onFlowError,
919 onenable: showScreen('SCR_SET_PASSCODE_OPT_ON')
920 },
921 'SCR_MANAGE_PASSCODE_MANDATORY': {
922 onsubmit: onFlowSuccess,
923 oncancel: onFlowSuccess,
924 onerror: onFlowError,
925 onchange: showScreen('SCR_CHANGE_PASSCODE_MANDATORY')
926 },
927
928
929 'SCR_SET_PASSCODE_OPT_ON': {
930 onsubmit: callChangePasscode,
931 oncancel: onFlowCancel,
932 onerror: onFlowError,
933 ondisable: showScreen('SCR_SET_PASSCODE_OPT_OFF'),
934 onerrorack: noOp
935 },
936 'SCR_SET_PASSCODE_OPT_OFF': {
937 onsubmit: callDisablePasscode,
938 oncancel: onFlowCancel,
939 onerror: onFlowError,
940 onenable: showScreen('SCR_SET_PASSCODE_OPT_ON'),
941 onerrorack: noOp
942 },
943 'SCR_CHANGE_PASSCODE_OPT_ON': {
944 onsubmit: callChangePasscode,
945 oncancel: onFlowCancel,
946 onerror: onFlowError,
947 ondisable: showScreen('SCR_CHANGE_PASSCODE_OPT_OFF'),
948 onerrorack: noOp
949 },
950 'SCR_CHANGE_PASSCODE_OPT_OFF': {
951 onsubmit: callDisablePasscode,
952 oncancel: onFlowCancel,
953 onerror: onFlowError,
954 onenable: showScreen('SCR_CHANGE_PASSCODE_OPT_ON'),
955 onerrorack: noOp
956 },
957 'SCR_CHANGE_PASSCODE_MANDATORY': {
958 onsubmit: callChangePasscode,
959 oncancel: onFlowCancel,
960 onerror: onFlowError,
961 onerrorack: noOp
962 },
963
964 };
965
966
967 utils.log('flow constructor return');
968 }
969
970 var ShowRegistrationFlow = function ShowRegistrationFlow(logonCore, logonView, onCoreResult, onFlowSuccess, onFlowError, onFlowCancel) {
971 //wrapped into a function to defer evaluation of the references to flow callbacks
972
973 this.name = 'showRegistrationFlowBuilder';
974
975 var showRegistrationInfo = function(context) {
976 logonView.showScreen('SCR_SHOW_REGISTRATION', this.screenEvents['SCR_SHOW_REGISTRATION'], context);
977 }.bind(this);
978
979 var callGetContext = function(){
980 utils.log('logonCore.getContext');
981 logonCore.getContext(onCoreResult, onFlowError);
982 }
983
984 // exported properties
985 this.stateTransitions = [
986 {
987 condition: {
988 state: {
989 secureStoreOpen: true,
990
991 },
992 context: null
993 },
994 action: callGetContext
995 },
996 {
997 condition: {
998 secureStoreOpen: true,
999 },
1000 action: showRegistrationInfo
1001 }
1002
1003 ];
1004
1005 this.screenEvents = {
1006 'SCR_SHOW_REGISTRATION': {
1007 oncancel: onFlowSuccess,
1008 onerror: onFlowError
1009 }
1010 };
1011
1012
1013 utils.log('flow constructor return');
1014 }
1015
1016 // === flow launcher methods =====================================
1017
1018
1019 var resume = function (onsuccess, onerror) {
1020
1021 var onUnlockSuccess = function(){
1022 _oLogonCore.onEvent(onsuccess, onerror, 'RESUME');
1023 }
1024
1025 var onGetStateSuccess = function(state) {
1026 //call registration flow only if the status is fullregistered in case of resume, so logon screen will not loose its input values
1027 if (state.status == 'fullRegistered') {
1028 registerOrUnlock(onUnlockSuccess, onerror);
1029 }
1030 }
1031
1032 getState(onGetStateSuccess, onerror);
1033 }
1034
1035
1036 var get = function (onsuccess, onerror, key) {
1037
1038 var onUnlockSuccess = function(){
1039 _oLogonCore.getSecureStoreObject(onsuccess, onerror, key);
1040 }
1041
1042 registerOrUnlock(onUnlockSuccess, onerror);
1043 }
1044
1045
1046
1047 var set = function (onsuccess, onerror, key, value) {
1048
1049 var onUnlockSuccess = function(){
1050 _oLogonCore.setSecureStoreObject(onsuccess, onerror, key, value);
1051 }
1052
1053 registerOrUnlock(onUnlockSuccess, onerror);
1054 }
1055
1056
1057
1058 var lock = function (onsuccess, onerror) {
1059 _oLogonCore.lockSecureStore(onsuccess, onerror);
1060 }
1061
1062 var getState = function (onsuccess, onerror) {
1063 _oLogonCore.getState(onsuccess, onerror);
1064 }
1065
1066
1067 var registerOrUnlock = function(onsuccess, onerror) {
1068 var flowRunner = new FlowRunner(onsuccess, onerror, _oLogonView, _oLogonCore);
1069 flowRunner.run(RegistrationFlow);
1070 }
1071
1072 var changePassword = function(onsuccess, onerror) {
1073
1074 var onUnlockSuccess = function(){
1075 var innerFlowRunner = new FlowRunner(onsuccess, onerror, _oLogonView, _oLogonCore);
1076 innerFlowRunner.run(ChangePasswordFlow);
1077 }
1078
1079 registerOrUnlock(onUnlockSuccess, onerror);
1080 }
1081
1082
1083 var forgottenPasscode = function(onsuccess, onerror) {
1084
1085 var onUnlockSuccess = function(){
1086 var innerFlowRunner = new FlowRunner(onsuccess, onerror, _oLogonView, _oLogonCore);
1087 innerFlowRunner.run(MockFlow);
1088 }
1089
1090 registerOrUnlock(onUnlockSuccess, onerror);
1091 }
1092
1093 var managePasscode = function(onsuccess, onerror) {
1094
1095 var onUnlockSuccess = function(){
1096 var innerFlowRunner = new FlowRunner(onsuccess, onerror, _oLogonView, _oLogonCore);
1097 innerFlowRunner.run(ManagePasscodeFlow);
1098 }
1099
1100 registerOrUnlock(onUnlockSuccess, onerror);
1101 }
1102
1103 var showRegistrationData = function(onsuccess, onerror) {
1104 var onUnlockSuccess = function(){
1105 var innerFlowRunner = new FlowRunner(onsuccess, onerror, _oLogonView, _oLogonCore);
1106 innerFlowRunner.run(ShowRegistrationFlow);
1107 }
1108
1109 registerOrUnlock(onUnlockSuccess, onerror);
1110 }
1111
1112 var getSecureStoreErrorText = function(error) {
1113 utils.logJSON('LogonController.getSecureStoreErrorText: ' + JSON.stringify(error));
1114
1115 var errorText;
1116
1117 if(error.errorCode === '14' && error.errorDomain === 'MAFSecureStoreManagerErrorDomain')
1118 errorText = "ERR_PASSCODE_TOO_SHORT";
1119 else if(error.errorCode === '10' && error.errorDomain === 'MAFSecureStoreManagerErrorDomain')
1120 errorText = "ERR_PASSCODE_REQUIRES_DIGIT";
1121 else if(error.errorCode === '13' && error.errorDomain === 'MAFSecureStoreManagerErrorDomain')
1122 errorText = "ERR_PASSCODE_REQUIRES_UPPER";
1123 else if(error.errorCode === '11' && error.errorDomain === 'MAFSecureStoreManagerErrorDomain')
1124 errorText = "ERR_PASSCODE_REQUIRES_LOWER";
1125 else if(error.errorCode === '12' && error.errorDomain === 'MAFSecureStoreManagerErrorDomain')
1126 errorText = "ERR_PASSCODE_REQUIRES_SPECIAL";
1127 else if(error.errorCode === '15' && error.errorDomain === 'MAFSecureStoreManagerErrorDomain')
1128 errorText = "ERR_PASSCODE_UNDER_MIN_UNIQUE_CHARS";
1129 else {
1130 errorText = "ERR_SETPASSCODE_FAILED";
1131 }
1132
1133 return errorText;
1134 }
1135
1136 var getSSOPasscodeSetErrorText = function(error) {
1137 utils.logJSON('LogonController.getSSOPasscodeSetErrorText: ' + JSON.stringify(error));
1138
1139 var errorText;
1140
1141 if (error.errorDomain === 'MAFLogonCoreErrorDomain') {
1142 if (error.errorCode === '16') {
1143 errorText = "ERR_SSO_PASSCODE_SET_ERROR";
1144 }
1145 }
1146
1147 return errorText;
1148 }
1149
1150 var getRegistrationErrorText = function(error) {
1151 utils.logJSON('LogonController.getRegistrationErrorText: ' + JSON.stringify(error));
1152
1153 var errorText;
1154
1155 if (error.errorDomain === 'MAFLogonCoreErrorDomain') {
1156 if (error.errorCode === '80003') {
1157 errorText = "ERR_REG_FAILED_WRONG_SERVER";
1158 }
1159 //in case of wrong application id
1160 else if (error.errorCode === '404') {
1161 errorText = "ERR_REG_FAILED";
1162 }
1163 else if (error.errorCode === '401') {
1164 errorText = "ERR_REG_FAILED_UNATHORIZED";
1165 }
1166 else {
1167 errorText = "ERR_REG_FAILED";
1168 }
1169 }
1170
1171 return errorText;
1172 }
1173
1174 var getRegistrationCancelError = function(error) {
1175 utils.logJSON('LogonController.getRegistrationCancelError: ' + JSON.stringify(error));
1176
1177 var errorText;
1178
1179 errorText = "ERR_REGISTRATION_CANCEL";
1180
1181 return errorText;
1182 }
1183
1184 var errorWithDomainCodeDescription = function(domain, code, description) {
1185 var error = {
1186 errorDomain: domain,
1187 errorCode: code,
1188 errorMessage: description
1189 };
1190
1191 return error;
1192 }
1193
1194
1195
1196
1197 // =================== exported (public) members ====================
1198
1199 /**
1200 * The Logon plugin provides screen flows to register an app with an SAP Mobile Platform server.<br/>
1201 * <br/>
1202 * The logon plugin is a component of the SAP Mobile Application Framework (MAF), exposed as a Cordova plugin. The basic
1203 * idea is that it provides screen flows where the user can enter the values needed to connect to an SAP Mobile Platform 3.0 server and
1204 * stores those values in its own secure data vault. This data vault is separate from the one provided with the
1205 * encrypted storage plugin. In an OData based SAP Mobile Platform 3.0 application, a client must onboard or register with the SAP Mobile Platform 3.0
1206 * server to receive an application connection ID for a particular app. The application connection ID must be sent
1207 * along with each request that is proxied through the SAP Mobile Platform 3.0 server to the OData producer.<br/>
1208 * <br/>
1209 * <b>Adding and Removing the Logon Plugin</b><br/>
1210 * The Logon plugin is added and removed using the
1211 * <a href="http://cordova.apache.org/docs/en/edge/guide_cli_index.md.html#The%20Command-line%20Interface">Cordova CLI</a>.<br/>
1212 * <br/>
1213 * To add the Logon plugin to your project, use the following command:<br/>
1214 * cordova plugin add <full path to directory containing Kapsel plugins>\logon<br/>
1215 * <br/>
1216 * To remove the Logon plugin from your project, use the following command:<br/>
1217 * cordova plugin rm com.sap.mp.cordova.plugins.logon
1218 *
1219 * @namespace
1220 * @alias Logon
1221 * @memberof sap
1222 */
1223 module.exports = {
1224
1225 /**
1226 * Initialization method to set up the Logon plugin. This will register the application with the SMP server and also authenticate the user
1227 * with servers on the network. This step must be done first prior to any attempt to communicate with the SMP server.
1228 *
1229 * @method
1230 * @param {sap.Logon~successCallback} successCallback The function that is invoked if initialization is successful. The current
1231 * context is passed to this function as the parameter.
1232 * @param {sap.Logon~errorCallback} errorCallback The function that is invoked in case of an error.
1233 * @param {string} applicationId The unique ID of the application. Must match the application ID on the SAP Mobile Platform server.
1234 * @param {object} [context] The context with default values for application registration. See {@link sap.Logon~successCallback} for the structure
1235 * of the context object. Note that all properties of the context object are optional, and you only need to specify the properties
1236 * for which you want to provide default values for. The values will be presented to the application users during the registration process and given them
1237 * a chance to override these values during runtime.
1238 * @param {string} [logonView="com/sap/mp/logon/iabui"] The cordova module ID of a custom renderer for the logon,
1239 * implementing the [showScreen(), close()] interface. Please use the defaul module unless you are absolutely sure that you can provide your own
1240 * custom implementation. Please refer to JavaScript files inside your Kapsel project's plugins\logon\www\common\modules\ folder as example.
1241 * @example
1242 * // a custom UI can be loaded here
1243 * var logonView = sap.logon.IabUi;
1244 *
1245 * // The app ID
1246 * var applicationId = "someAppID";
1247 *
1248 * // You only need to specify the fields for which you want to set the default. These values are optional because they will be
1249 * // used to prefill the fields on Logon's UI screen.
1250 * var defaultContext = {
1251 * "serverHost" : "defaultServerHost.com"
1252 * "https" : false,
1253 * "serverPort" : "8080",
1254 * "user" : "user1",
1255 * "password" : "Zzzzzz123",
1256 * "communicatorId" : "REST",
1257 * "securityConfig" : "sec1",
1258 * "passcode" : "Aaaaaa123",
1259 * "unlockPasscode" : "Aaaaaa123"
1260 * };
1261 *
1262 * var app_context;
1263 *
1264 * var successCallback = function(context){
1265 * app_context = context;
1266 * }
1267 *
1268 * var errorCallback = function(errorInfo){
1269 * alert("error: " + JSON.stringify(errorInfo));
1270 * }
1271 * sap.Logon.init(successCallback, errorCallback, applicationId, defaultContext, logonView);
1272 */
1273 init: init,
1274
1275 /**
1276 * The application ID with which {@link sap.Logon.init} was called. It is available here so it is easy to access later.
1277 * @example
1278 * // After calling the init function
1279 * alert("The app ID for this app is: " + sap.Logon.applicationId);
1280 */
1281 applicationId: null,
1282 /**
1283 * Direct reference to the logon core object used by the Logon plugin. This is needed to perform more complex operations that
1284 * are not generally needed by applications. <br/>
1285 * There are several functions that can be accessed on the core object:<br/>
1286 * getState(successCallback,errorCallback) returns the state object of the application to the success callback in the form of a JavaScript object.<br/>
1287 * getContext(successCallback,errorCallback) returns the context object of the application to the success callback in the form of a JavaScript object.<br/>
1288 * deleteRegistration(successCallback,errorCallback) deletes the application's registration from the SAP Mobile Platform server and removes<br/>
1289 * application data on device.<br/>
1290 * @example
1291 * var successCallback = function(result){
1292 * alert("Result: " + JSON.stringify(result));
1293 * }
1294 * var errorCallback = function(errorInfo){
1295 * alert("Error: " + JSON.stringify(errorInfo));
1296 * }
1297 * sap.Logon.core.getState(successCallback,errorCallback);
1298 * sap.Logon.core.getContext(successCallback,errorCallback);
1299 * sap.Logon.core.deleteRegistration(successCallback,errorCallback);
1300 */
1301 core: _oLogonCore, //Must be updated after init
1302
1303 /**
1304 * Get an (JSON serializable) object from the DataVault for a given key.
1305 * @method
1306 * @param {sap.Logon~getSuccessCallback} onsuccess The function that is invoked
1307 * upon success. It is called with the resulting object as a single parameter.
1308 * This can be null or undefined, if no object is defined for the given key.
1309 * @param {sap.Logon~errorCallback} onerror The function to invoke in case of error.
1310 * @param {string} key The key with which to query the DataVault.
1311 * @example
1312 * var errorCallback = function(errorInfo){
1313 * alert("Error: " + JSON.stringify(errorInfo));
1314 * }
1315 * var getSuccess = function(value){
1316 * alert("value retrieved from the store: " + JSON.stringify(value));
1317 * }
1318 * var setSuccess = function(){
1319 * sap.Logon.get(getSuccess,errorCallback,'someKey');
1320 * }
1321 * sap.Logon.set(setSuccess,errorCallback,'someKey', 'some string (could also be an object).');
1322 */
1323 get: get,
1324
1325 /**
1326 * Set an (JSON serializable) object in the DataVault.
1327 * @method
1328 * @param {sap.Logon~successCallbackNoParameters} onsuccess The function to invoke upon success.
1329 * onsuccess will be called without parameters for this method.
1330 * @param {sap.Logon~errorCallback} onerror The function to invoke in case of error.
1331 * @param {string} key The key to store the provided object on.
1332 * @param {object} value The object to be set on the given key. Must be JSON serializable (ie:
1333 * cannot contain circular references).
1334 * @example
1335 * var errorCallback = function(errorInfo){
1336 * alert("Error: " + JSON.stringify(errorInfo));
1337 * }
1338 * var getSuccess = function(value){
1339 * alert("value retrieved from the store: " + JSON.stringify(value));
1340 * }
1341 * var setSuccess = function(){
1342 * sap.Logon.get(getSuccess,errorCallback,'someKey');
1343 * }
1344 * sap.Logon.set(setSuccess,errorCallback,'someKey', 'some string (could also be an object).');
1345 */
1346 set: set,
1347
1348 /**
1349 * Locks the Logon plugin's secure data vault.
1350 * @method
1351 * @param {sap.Logon~successCallbackNoParameters} onsuccess The function to invoke upon success.
1352 * @param {sap.Logon~errorCallback} onerror The function to invoke in case of error.
1353 * @example
1354 * var errorCallback = function(errorInfo){
1355 * alert("Error: " + JSON.stringify(errorInfo));
1356 * }
1357 * var successCallback = function(){
1358 * alert("Locked!");
1359 * }
1360 * sap.Logon.lock(successCallback,errorCallback);
1361 */
1362 lock: lock,
1363
1364 /**
1365 * Unlock the Logon plugin's secure data vault if it has been locked (due to being inactive, or
1366 * {@link sap.Logon.lock} being called), then the user is prompted for the passcode to unlock the
1367 * application.<br/>
1368 * If the application is already unlocked, then nothing will be done.<br/>
1369 * If the application has passcode disabled, then passcode prompt will not be necessary.
1370 * In all cases if an error does not occur, the success callback is invoked with the current logon context
1371 * as the parameter.
1372 * @method
1373 * @param {sap.Logon~successCallback} onsuccess - The callback to call if the screen flow succeeds.
1374 * onsuccess will be called with the current logon context as a single parameter.
1375 * @param {sap.Logon~errorCallback} onerror - The callback to call if the screen flow fails.
1376 * @example
1377 * var errorCallback = function(errorInfo){
1378 * alert("Error: " + JSON.stringify(errorInfo));
1379 * }
1380 * var successCallback = function(context){
1381 * alert("Registered and unlocked. Context: " + JSON.stringify(context));
1382 * }
1383 * sap.Logon.unlock(successCallback,errorCallback);
1384 */
1385 unlock: registerOrUnlock,
1386
1387 /**
1388 * This is an alias for registerOrUnlock. Calling this function is equivalent
1389 * to calling {@link sap.Logon.unlock} since both of them are alias to registerOrUnlock.
1390 * @method
1391 * @private
1392 */
1393 registerUser: registerOrUnlock,
1394
1395 /**
1396 * This function registers the user and creates a new unlocked DataVault to store the registration
1397 * information.<br/>
1398 * If the user has already been registered, but the application is locked (due to being inactive, or
1399 * {@link sap.Logon.lock} being called), then the user is prompted for the passcode to unlock the
1400 * application.<br/>
1401 * If the application is already unlocked, then nothing will be done.<br/>
1402 * In all cases if an error does not occur, the success callback is invoked with the current logon context
1403 * as the parameter.
1404 * @method
1405 * @param {sap.Logon~successCallback} onsuccess - The callback to call if the screen flow succeeds.
1406 * onsuccess will be called with the current logon context as a single parameter.
1407 * @param {sap.Logon~errorCallback} onerror - The callback to call if the screen flow fails.
1408 * @example
1409 * var errorCallback = function(errorInfo){
1410 * alert("Error: " + JSON.stringify(errorInfo));
1411 * }
1412 * var successCallback = function(context){
1413 * alert("Registered and unlocked. Context: " + JSON.stringify(context));
1414 * }
1415 * sap.Logon.registerOrUnlock(successCallback,errorCallback);
1416 * @private
1417 */
1418 registerOrUnlock: registerOrUnlock,
1419
1420 /**
1421 * This method will launch the UI screen for application users to manage and update the data vault passcode or,
1422 * if the SMP server's Client Passcode Policy allows it, enable or disable the passcode to the data vault.
1423 *
1424 * @method
1425 * @param {sap.Logon~successCallbackNoParameters} onsuccess - The function to invoke upon success.
1426 * @param {sap.Logon~errorCallback} onerror - The function to invoke in case of error.
1427 * @example
1428 * var errorCallback = function(errorInfo){
1429 * alert("Error: " + JSON.stringify(errorInfo));
1430 * }
1431 * var successCallback = function(context){
1432 * alert("Passcode successfully managed.");
1433 * }
1434 * sap.Logon.managePasscode(successCallback,errorCallback);
1435 */
1436 managePasscode: managePasscode,
1437
1438 /**
1439 * This method will launch the UI screen for application users to manage and update the back end passcode that Logon stores in the
1440 * data vault that is used to authenticate the client to the server.
1441 *
1442 * @method
1443 * @param {sap.Logon~successCallbackNoParameters} onsuccess - The callback to call if the screen flow succeeds.
1444 * onsuccess will be called without parameters for this method.
1445 * @param {sap.Logon~errorCallback} onerror The function that is invoked in case of an error.
1446 * @example
1447 * var errorCallback = function(errorInfo){
1448 * alert("Error: " + JSON.stringify(errorInfo));
1449 * }
1450 * var successCallback = function(context){
1451 * alert("Password successfully changed.");
1452 * }
1453 * sap.Logon.changePassword(successCallback,errorCallback);
1454 */
1455 changePassword: changePassword,
1456
1457 /**
1458 * Calling this method will show a UI screen with values used for registrating application.
1459 * @method
1460 * @param {sap.Logon~successCallbackNoParameters} onsuccess - The callback to call if the screen flow succeeds.
1461 * onsuccess will be called without parameters for this method.
1462 * @param {sap.Logon~errorCallback} onerror The function that is invoked in case of an error.
1463 * @example
1464 * var errorCallback = function(errorInfo){
1465 * alert("Error: " + JSON.stringify(errorInfo));
1466 * }
1467 * var successCallback = function(context){
1468 * alert("The showRegistrationData screenflow was successful.");
1469 * }
1470 * sap.Logon.showRegistrationData(successCallback,errorCallback);
1471 */
1472 showRegistrationData: showRegistrationData,
1473
1474 };
1475
1476 /**
1477 * Callback function that is invoked in case of an error.
1478 *
1479 * @callback sap.Logon~errorCallback
1480 *
1481 * @param {Object} errorObject An object containing properties: 'errorCode', 'errorMessage', and 'errorDomain'.
1482 * The 'errorCode' is just a number uniquely identifying the error. The 'errorMessage'
1483 * property is a string with more detailed information of what went wrong. The 'errorDomain' property specifies
1484 * the domain that the error occurred in.
1485 */
1486
1487 /**
1488 * Callback function that is invoked upon successfully registering or unlocking or retrieving the context.
1489 *
1490 * @callback sap.Logon~successCallback
1491 *
1492 * @param {Object} context An object containing the current logon context. Two properties of particular importance
1493 * are applicationEndpointURL, and applicationConnectionId.
1494 * The context object contains the following properties:<br/>
1495 * "registrationContext": {<br/>
1496 * "serverHost": Host of the server.<br/>
1497 * "domain": Domain for server. Can be used in case of SAP Mobile Platform communication.<br/>
1498 * "resourcePath": Resource path on the server. The path is used mainly for path based reverse proxy but can contain a custom relay server path as well.<br/>
1499 * "https": Marks whether the server should be accessed in a secure way.<br/>
1500 * "serverPort": Port of the server.<br/>
1501 * "user": Username in the backend.<br/>
1502 * "password": Password for the backend user.<br/>
1503 * "farmId": FarmId of the server. Can be nil. Used in case of Relay server or SiteMinder.<br/>
1504 * "communicatorId": Id of the communicator manager that will be used for performing the logon. Possible values: IMO / GATEWAY / REST<br/>
1505 * "securityConfig": Security configuration. If nil, the default configuration is used.<br/>
1506 * "mobileUser": Mobile User. Used in case of IMO manual user creation.<br/>
1507 * "activationCode": Activation Code. Used in case of IMO manual user creation.<br/>
1508 * "gatewayClient": The key string that identifies the client on the gateway. Used in Gateway only registration mode. The value will be used as adding the parameter: sap-client=<gateway client><br/>
1509 * "gatewayPingPath": The custom path of the ping URL on the gateway. Used in case of Gateway only registration mode.<br/>
1510 * }<br/>
1511 * "applicationEndpointURL": Contains the application endpoint URL after a successful registration.<br/>
1512 * "applicationConnectionId": ID to get after a successful SUP REST registration. Needs to be set in the download request header with key X-SUP-APPCID<br/>
1513 * "afariaRegistration": manual / automatic / certificate<br/>
1514 * "policyContext": Contains the password policy for the secure store {<br/>
1515 * "alwaysOn":<br/>
1516 * "alwaysOff":<br/>
1517 * "defaultOn":<br/>
1518 * "hasDigits":<br/>
1519 * "hasLowerCaseLetters":<br/>
1520 * "hasSpecialLetters":<br/>
1521 * "hasUpperCaseLetters":<br/>
1522 * "defaultAllowed":<br/>
1523 * "expirationDays":<br/>
1524 * "lockTimeout":<br/>
1525 * "minLength":<br/>
1526 * "minUniqueChars":<br/>
1527 * "retryLimit":<br/>
1528 * }<br/>
1529 * "registrationReadOnly": specifies whether context values are coming from clientHub / afaria<br/>
1530 * "policyReadOnly": specifies whether passcode policy is coming from afaria<br/>
1531 * "credentialsByClientHub": specifies whether credentials are coming from clientHub
1532 */
1533
1534 /**
1535 * Callback function that will be invoked with no parameters.
1536 *
1537 * @callback sap.Logon~successCallbackNoParameters
1538 */
1539
1540 /**
1541 * Callback function that is invoked upon successfully retrieving an object from the DataVault.
1542 *
1543 * @callback sap.Logon~getSuccessCallback
1544 *
1545 * @param {Object} value The object that was stored with the given key. Can be null or undefined if no object was stored
1546 * with the given key.
1547 */
1548
1549