UNPKG

3.92 kBJavaScriptView Raw
1import angular from 'angular';
2
3import Auth from '../auth/auth';
4
5/**
6 * @name Auth Ng
7 */
8const angularModule = angular.module('Ring.auth', []);
9
10angularModule.provider('auth', function provider($httpProvider) {
11 /**
12 * @type Auth
13 */
14 let auth;
15 /**
16 * @type {{cleanHash: boolean}} config
17 */
18 const defaultConfig = {
19 cleanHash: false //prevents infinite redirect on angular>1.2.26
20 };
21
22 this.init = authInstance => {
23 auth = authInstance;
24 };
25
26 /**
27 * @param {{
28 * serverUri: string,
29 * redirectUri: string?,
30 * clientId: string?,
31 * scope: string[]?,
32 * cleanHash: boolean?
33 * }} config
34 */
35 this.config = config => {
36 const configCopy = angular.extend({}, defaultConfig, config);
37 auth = new Auth(configCopy);
38 };
39
40 $httpProvider.interceptors.push(['$q', '$injector', 'auth', ($q, $injector, authInstance) => {
41 function urlEndsWith(config, suffix) {
42 return config &&
43 config.url &&
44 config.url.indexOf(suffix) === config.url.length - suffix.length;
45 }
46
47 return {
48 request(config) {
49 if (!authInstance || urlEndsWith(config, '.html') || (config && config.noAuthorization)) {
50 // Don't intercept angular template requests
51 return config;
52 }
53 return authInstance.promise.
54 then(() => authInstance.auth.requestToken()).
55 then(accessToken => {
56 if (accessToken) {
57 config.headers.Authorization = `Bearer ${accessToken}`;
58 }
59 return config;
60 });
61 },
62 responseError(rejection) {
63 if (authInstance && !urlEndsWith(rejection.config, '.html') &&
64 rejection.data != null && Auth.shouldRefreshToken(rejection.data.error)) {
65
66 // Use $injector to avoid circular dependency
67 const $http = $injector.get('$http');
68 const {data, method, params, url} = rejection.config;
69
70 return authInstance.auth.
71 forceTokenUpdate().
72 then(() => $http({data, method, params, url}));
73 }
74
75 return $q.reject(rejection);
76 }
77 };
78 }]);
79
80 this.$get = function get($injector, $log, $sniffer) {
81 // Do not try to init anything without config
82 if (!auth) {
83 $log.warn('Auth wasn\'t initialized');
84 return null;
85 }
86
87 if (auth.config.reloadOnUserChange === false) {
88 auth.addListener('userChange', () => {
89 const $route = $injector.get('$route');
90 $route.reload();
91 });
92 }
93
94 /**
95 * @type {Promise.<string>}
96 */
97 const authInitPromise = auth.init();
98
99 /**
100 * @param {string?} restoreLocationURL
101 */
102 function restoreLocation(restoreLocationURL) {
103 if (restoreLocationURL) {
104 const bases = document.getElementsByTagName('base');
105 let baseURI = auth.config.redirectUri;
106
107 if (bases.length > 0) {
108 baseURI = bases[0].href;
109 }
110
111 if (restoreLocationURL.indexOf(baseURI) === 0) {
112 const $location = $injector.get('$location');
113 let relativeURI = restoreLocationURL.substr(baseURI.length);
114
115 // We have to turn url with hash to simple relative url in HashbangInHtml5 mode
116 // And there is no other and documented way to detect that mode
117 // @see http://stackoverflow.com/a/16678065
118 if ($location.$$html5 && !$sniffer.history) { // eslint-disable-line angular/no-private-call
119 relativeURI = relativeURI.replace(/^#\//, '');
120 }
121
122 $location.url(relativeURI).replace();
123 }
124 }
125 }
126
127 authInitPromise.then(restoreLocation, e => {
128 if (!e.authRedirect) {
129 $log.error(e);
130 }
131 });
132
133 return {
134 auth,
135 requestUser: auth.requestUser.bind(auth),
136 clientId: auth.config.clientId,
137 logout: auth.logout.bind(auth),
138 promise: authInitPromise
139 };
140 };
141});
142
143export default angularModule.name;