/
stateManager.ts
142 lines (100 loc) · 5.25 KB
/
stateManager.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
///<reference path="../../typings/tsd.d.ts" />
namespace config.stateManager {
export const namespace = 'config.stateManager';
class StateManagerConfig {
static $inject = ['$stateProvider', '$locationProvider', '$urlRouterProvider', '$compileProvider', 'stateHelperServiceProvider'];
constructor(private $stateProvider, private $locationProvider, private $urlRouterProvider, private $compileProvider, private stateHelperServiceProvider) {
StateManagerConfig.configureRouter($locationProvider, $urlRouterProvider);
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension):/);
StateManagerConfig.registerStates($stateProvider, stateHelperServiceProvider);
}
private static registerStates($stateProvider, stateHelperServiceProvider) {
//add base state
$stateProvider
.state('app', {
abstract: true,
})
;
// Loop through each sub-module state and register them
angular.forEach(stateHelperServiceProvider.getStates(), (state:global.IStateDefinition) => {
$stateProvider.state(state.name, state.options);
});
}
private static configureRouter($locationProvider, $urlRouterProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise(function ($injector, $location) {
var $state = $injector.get('$state');
$state.go(app.guest.error.namespace, {
title: "Page not found",
message: 'Could not find a state associated with url "' + $location.$$url + '"',
url: $location.$$absUrl
});
});
}
}
class StateManagerInit {
static $inject = ['$rootScope', 'ngRestAdapter', 'ngJwtAuthService', '$state', '$mdToast', 'authService'];
constructor(private $rootScope:ng.IRootScopeService,
private ngRestAdapter:NgRestAdapter.NgRestAdapterService,
private ngJwtAuthService:NgJwtAuth.NgJwtAuthService,
private $state:ng.ui.IStateService,
private $mdToast:ng.material.IToastService,
private authService:common.services.auth.AuthService
) {
this.registerStatePermissions();
}
/**
* Register the state change start transition
* 1) Verify if the user must be logged in to state
* 2) If so and user is not logged in, stop the transition and prompt the user to log in after waiting for
* the auth service to initialise
* 3) Once the user has authenticated redirect them to the state they were trying to access
* 4) If they fail to authenticate, return them to the home state.
*/
private registerStatePermissions = ():void => {
this.$rootScope.$on('$stateChangeStart', (event, toState:global.IState, toParams, fromState:global.IState, fromParams):ng.IPromise<any> => {
if (this.userMustBeLoggedIn(toState) && !this.ngJwtAuthService.loggedIn) {
event.preventDefault();
//defer prompting for login until the auth service has completed all checks
return this.authService.initialisedPromise.finally(() => {
if(this.ngJwtAuthService.loggedIn){ //user is still not logged in after authentication initialisation
return this.$state.go(toState.name, toParams);
}
return this.showLoginAndRedirectTo(toState, toParams, fromState);
});
}
});
};
/**
* Show the login to the user then redirect to their intended state or the home state if login fails.
* @param toState
* @param toParams
* @param fromState
* @returns {IPromise<TResult>}
*/
private showLoginAndRedirectTo = (toState:global.IState, toParams, fromState:global.IState):ng.IPromise<any> => {
return this.ngJwtAuthService.requireCredentialsAndAuthenticate()
.then(() => this.$state.go(toState.name, toParams),
(err) => {
let returnTo = fromState.name ? fromState.name : 'app.guest.home';
let attemptedStateName = this.$state.href(toState, toParams);
return this.$state.go(returnTo).then(() => {
this.$mdToast.show(
this.$mdToast.simple()
.hideDelay(2000)
.position('top right')
.content("You are not permitted to access " + attemptedStateName)
);
}); //go back home
})
};
private userMustBeLoggedIn = (state:global.IState) => {
return !!state.data.loggedIn;
}
}
angular.module(namespace, [
'config.siteModules' //include the site modules after stateManager has been configured so all states can be loaded
])
.config(StateManagerConfig)
.run(StateManagerInit);
}