View difference between Paste ID: Jy2mzLgj and BY39pJEM
SHOW: | | - or go back to the newest paste.
1
/* interceptor.js (angularjs 1.2.x version) */
2
angular.module('security.interceptor', ['security.retryQueue'])
3
.factory('securityInterceptor', ['$injector', 'securityRetryQueue', '$cookieStore', function ($injector, queue, $cookieStore) {
4
	return {
5
		response: function(originalResponse)
6
		{
7
			return originalResponse;
8
		},
9
		responseError: function (originalResponse) {
10
			var exception;
11
			if (originalResponse.headers){
12
				exception = originalResponse.headers('x-eva-api-exception');
13
			}
14
			if (originalResponse.status === 401 && (exception === 'token_not_found' || exception === 'token_expired')){
15
				queue.pushRetryFn(exception, function retryRequest() {
16
					return $injector.get('$http')(originalResponse.config);
17
				});	
18
			}
19
			return originalResponse;
20
		}
21
	};
22
}])
23
.config(['$httpProvider', function($httpProvider) {
24
	$httpProvider.interceptors.push('securityInterceptor');
25
}]);
26
27
28
/* interceptor.js (angularjs 1.0.8 version) */
29
30
angular.module('security.interceptor', ['security.retryQueue'])
31
.factory('securityInterceptor', ['$injector', 'securityRetryQueue', function($injector, queue) {
32
	return function(promise) {
33
		return promise.then(null, function(originalResponse) {
34
			var exception;
35
			if(originalResponse.headers) { 
36
				exception = originalResponse.headers('x-eva-api-exception');
37
			}
38
			if(originalResponse.status === 401 && (exception === 'token_not_found' || exception === 'token_expired')) {
39
				promise = queue.pushRetryFn(exception, function retryRequest() {
40
					return $injector.get('$http')(originalResponse.config);
41
				});
42
			}
43
			return promise;
44
		});
45
	};
46
}])
47
.config(['$httpProvider', function($httpProvider) {
48
	$httpProvider.responseInterceptors.push('securityInterceptor');
49
}])
50
51
/* retryQueue.js */
52
angular.module('security.retryQueue', [])
53
.factory('securityRetryQueue', ['$q', '$log', function($q, $log) {
54
	var retryQueue = [];
55
	var service = {
56
		// The security service puts its own handler in here!
57
		onItemAddedCallbacks: [],
58
		hasMore: function() {
59
			console.log('retryQueue.js -> hasMore: ' + retryQueue.length);
60
			return retryQueue.length > 0;
61
		},
62
		push: function(retryItem) {
63
			retryQueue.push(retryItem);
64
			// Call all the onItemAdded callbacks
65
			angular.forEach(service.onItemAddedCallbacks, function(cb) {
66
				try {
67
					console.log('retryQueue.js -> push: ' + retryItem.reason);
68
					cb(retryItem);
69
				} catch(e) {
70
					$log.error('securityRetryQueue.push(retryItem): callback threw an error' + e);
71
				}
72
			});
73
		},
74
		pushRetryFn: function(reason, retryFn) {
75
			console.log('retryQueue.js -> pushRetryFn called');
76
			console.log('retryQueue.js -> pushRetryFn reason: ' + reason);
77
			console.log('retryQueue.js -> pushRetryFn retryFn: ' + retryFn);
78
			// The reason parameter is optional
79
			console.log('retryQueue.js -> arguments: ' + arguments);
80
			console.log('retryQueue.js -> arguments: ' + arguments.length);
81
			if ( arguments.length === 1) {
82
				console.log('retryQueue.js -> reason in pushRetryFn: ' + reason);
83
				retryFn = reason;
84
				reason = undefined;
85
			}
86
			
87
			// The deferred object that will be resolved or rejected by calling retry or cancel
88
			var deferred = $q.defer();
89
			var retryItem = {
90
				reason: reason,
91
				retry: function() {
92
					console.log('retryQueue.js -> pushRetryFn with reason ' + reason);
93
					// Wrap the result of the retryFn into a promise if it is not already
94
					$q.when(retryFn()).then(function(value) {
95
						console.log('retryQueue.js -> resolve pushRetryFn with retry and value: ' + value);
96
						// If it was successful then resolve our deferred
97
						deferred.resolve(value);
98
					}, function(value) {
99
						// Othewise reject it
100
						console.log('retryQueue.js -> reject pushRetryFn with reject and value: ' + value);
101
						deferred.reject(value);
102
					});
103
				},
104
				cancel: function() {
105
					// Give up on retrying and reject our deferred
106
					deferred.reject();
107
				}
108
			};
109
			console.log('retryQueue.js -> pushRetryFn push retryItem: ' + retryItem.reason);
110
			service.push(retryItem);
111
			return deferred.promise;
112
		},
113
		retryReason: function() {
114
			return service.hasMore() && retryQueue[0].reason;
115
		},
116
		cancelAll: function() {
117
			while(service.hasMore()) {
118
				retryQueue.shift().cancel();
119
			}
120
		},
121
		retryAll: function() {
122
			while(service.hasMore()) {
123
				retryQueue.shift().retry();
124
			}
125
		}
126
	};
127
	return service;
128
}]);
129
130
131
/* security.js  */
132
angular.module('security.service', ['session.service', 'security.signin', 'security.retryQueue', 'security.tokens', 'ngCookies'])
133
.factory('security', ['$location', 'securityRetryQueue', '$q', 'TokenHandler', '$cookieStore', 'Session', 'i18nNotifications', 'User', function($location, queue, $q, TokenHandler, $cookieStore, Session, i18nNotifications, User) {
134
	function redirect(url) {
135
		url = url || '/';
136
		$location.path(url);
137
	}
138
139
	var skipRequests = false;
140
141
	// Register a handler for when an item is added to the retry queue
142
	queue.onItemAddedCallbacks.push(function(retryItem) {
143
		if ( queue.hasMore() ) {
144
			if(skipRequests) {return;}
145
			// make sure only one token is created by skiping subsequant authentication requests
146
			console.log('security.js -> set skipRequests to true');
147
			skipRequests = true;
148
			if(retryItem.reason === 'token_expired') {
149
				service.refreshToken().then(function(result) {
150
					if(result) { 
151
						var currentToken = TokenHandler.get();
152
						console.log('security.js -> currentToken before queue.retryAll() call:' + currentToken);
153
						console.log('security.js ->  result before queue.retryAll() call:' + currentToken);
154
						queue.retryAll(); 
155
					}
156
					// user has to authorize with credentials
157
					else 
158
					{ 
159
						service.signout(); 
160
					}
161
					skipRequests = false;
162
					console.log('security.js -> set skipRequests to false');
163
				});
164
			} else {
165
				// user has to authorize with credentials
166
				skipRequests = false;
167
				console.log('security.js -> set skipRequests to false before signout');
168
				service.signout();
169
			}
170
		}
171
	});
172
173
	var service = {
174
		// get a new valid token using the refresh token
175
		refreshToken: function() {
176
			console.log('security.js -> refreshToken called, d created');
177
			var d = $q.defer();
178
			var token = TokenHandler.getRefreshToken();
179
			// cannot refresh token if not found on the client
180
			if(!token) { 
181
				console.log('security.js -> token not found on a client');
182
				d.resolve(false); 
183
			}
184
185
			console.log('security.js -> token found on a client: ' + token);
186
			var session = new Session({
187
				refreshToken: token
188
			});
189
190
			console.log('security.js -> calling session.tokenRefresh');
191
			session.tokenRefresh(function(result) {
192
				if(result) {
193
					console.log('security.js -> result OK, d.resolve(true), setting token with a accessToken: ' + result.accessToken + ' and refresh token: ' + result.refreshToken);
194
					d.resolve(true);
195
					TokenHandler.set(result);
196
				} else {
197
					console.log('security.js -> result NOT ok, d.resolve(false)');
198
					d.resolve(false);
199
				}
200
			});
201
202
			console.log('security.js -> returning d.promise');
203
			return d.promise;
204
		}
205
	};
206
207
	return service;
208
}]);
209
210
/* httpHeaders.js */
211
angular.module('services.httpHeaders', [])
212
.factory('HttpHeaders', ['$injector', function($injector) {
213
	var http = $injector.get('$http');
214
	var service = {
215
		initHeaders: function() {
216
		},
217
		// set session token used to authorize the user against the api
218
		setAuthorizationToken: function(token) {
219
			console.log('httpHeaders.js -> setting authorization token: ' + token);
220
			http.defaults.headers.common['Authorization'] = 'Bearer ' + token;
221
		},
222
223
		clearAuthorizationHeader: function()  {
224
			http.defaults.headers.common['Authorization'] = null;	
225
		}
226
	};
227
	return service;
228
}]);
229
230
/* tokenHandler.js */
231
angular.module('security.tokens', ['ngResource'])
232
.factory('TokenHandler', ['HttpHeaders', '$cookieStore', function(HttpHeaders, $cookieStore) {
233
	var token = null;
234
235
	function initToken() {
236
		if(!token) {
237
			token = $cookieStore.get('authorization-token');
238
		}
239
	}
240
241
	var service = {
242
		// set a new token and save to cookies		
243
		set: function(newToken) {
244
			token = newToken;
245
			$cookieStore.put('authorization-token', token);
246
			HttpHeaders.setAuthorizationToken(token.accessToken);		
247
		},
248
249
		// try to init the token from cookies
250
		init: function() {
251
			initToken();
252
			if(!token) {return;}
253
			HttpHeaders.setAuthorizationToken(token.accessToken);	
254
		},
255
256
		// clear token and remove it from cookies
257
		clear: function() {
258
			$cookieStore.remove('authorization-token');
259
			token = {};
260
			HttpHeaders.clearAuthorizationHeader();
261
		},
262
263
		// return currently active token
264
		get: function() {
265
			initToken();
266
			if(token) {return token.accessToken;}
267
			else {return null;}
268
		},
269
270
		// return the refresth token
271
		getRefreshToken: function() {
272
			initToken();
273
			if(token) {
274
				console.log('tokenHandler.js -> getRefreshToken: ' + token);
275
				return token.refreshToken;
276
			}
277
			else {
278
				console.log('token was not found, returning null');
279
				return null;
280
			}
281
		}
282
	};
283
	service.init();
284
	return service;
285
}]);