UNPKG

@aca-1/a2-composer

Version:
512 lines 23.3 kB
import { Location } from '@angular/common'; import { Injectable, Injector, ReflectiveInjector } from '@angular/core'; import { Headers, Http } from '@angular/http'; import { ActivatedRoute, Router } from '@angular/router'; import { Observable } from 'rxjs/Observable'; import { Md5 } from 'ts-md5/dist/md5'; import { COMPOSER } from '../../settings'; import { DataStoreService } from '../data-store.service'; import { MockHttp } from './mock-http'; import { OAuthService } from './oauth2.service'; var MAX_ERROR_COUNT = 5; var CommsService = (function () { function CommsService(route, router, http_service, oAuthService, store, loc, injector) { var _this = this; this.route = route; this.router = router; this.http_service = http_service; this.oAuthService = oAuthService; this.store = store; this.loc = loc; this.injector = injector; this.trust = false; this.refresh = false; this.login_promise = null; this.retry = {}; this.debug = true; this.http = null; this.valid_params = [ 'loginUrl', 'loginRedirect', 'refreshUrl', 'redirectUri', 'refreshUri', 'clientId', 'issuer', 'scope', 'oidc', 'logoutUrl', 'login_local', ]; this.http = this.http_service; store.local.getItem('trust').then(function (value) { _this.trust = (value === 'true'); }); this.sub = this.route.queryParams.subscribe(function (params) { _this.trust = params.trust === 'true' ? params.trust === 'true' : _this.trust; if (_this.trust) { store.local.setItem('trust', 'true'); } if (params.logout && params.logout === 'true') { _this.oAuthService.logOut(); } }); this.oAuthService.tryLogin().then(function () { return; }, function () { return; }); } CommsService.prototype.setupOAuth = function (options) { var oauth = this.oAuthService; if (options) { console.log(options); for (var i in options) { if (i !== undefined && i !== null && this.valid_params.indexOf(i) >= 0) { oauth[i] = options[i]; } } } }; CommsService.prototype.mock = function (enable) { if (enable === void 0) { enable = true; } if (enable && this.http instanceof Http) { var resolvedProviders = ReflectiveInjector.resolve([MockHttp]); var childInjector = ReflectiveInjector.fromResolvedProviders(resolvedProviders, this.injector); var http = childInjector.get(MockHttp); this.http = http; } else if (this.http instanceof MockHttp && this.http_service) { this.http = this.http_service; } }; CommsService.prototype.tryLogin = function () { COMPOSER.log('COMMS', "Trying Login"); this.login().then(function () { COMPOSER.log('COMMS', "Got Access Token."); }); }; CommsService.prototype.needsLogin = function () { return this.oAuthService.needsLogin(); }; CommsService.prototype.get = function (url, options) { var _this = this; return new Observable(function (observer) { _this.processOptions(url, null, options).then(function (req) { if (req.auth) { _this.http.get(req.url, req.options) .map(function (res) { return res.json(); }) .subscribe(function (data) { return observer.next(data); }, function (err) { return _this.error(err, req, observer); }, function () { return observer.complete(); }); } else { _this.error({ status: 401, message: 'No auth token.' }, req, observer); } }); }); }; CommsService.prototype.post = function (url, body, options) { var _this = this; return new Observable(function (observer) { _this.processOptions(url, body, options).then(function (req) { req.type = 'post'; if (req.auth) { _this.http.post(req.url, req.body, req.options) .map(function (res) { return res.json(); }) .subscribe(function (data) { return observer.next(data); }, function (err) { return _this.error(err, req, observer); }, function () { return observer.complete(); }); } else { _this.error({ status: 401, message: 'No auth token.' }, req, observer); } }); }); }; CommsService.prototype.put = function (url, body, options) { var _this = this; return new Observable(function (observer) { _this.processOptions(url, body, options).then(function (req) { req.type = 'put'; if (req.auth) { _this.http.put(req.url, req.body, req.options) .map(function (res) { return res.json(); }) .subscribe(function (data) { return observer.next(data); }, function (err) { return _this.error(err, req, observer); }, function () { return observer.complete(); }); } else { _this.error({ status: 401, message: 'No auth token.' }, req, observer); } }); }); }; CommsService.prototype.delete = function (url, options) { var _this = this; return new Observable(function (observer) { _this.processOptions(url, null, options).then(function (req) { req.type = 'delete'; _this.http.delete(req.url, req.options) .map(function (res) { return res.json(); }) .subscribe(function (data) { return observer.next(data); }, function (err) { return _this.error(err, req, observer); }, function () { return observer.complete(); }); }); }); }; CommsService.prototype.hash = function (str) { return Md5.hashStr(str, false); }; CommsService.prototype.login = function () { var _this = this; if (this.login_promise === null) { COMPOSER.log('COMMS', "Attempting login."); this.login_promise = new Promise(function (resolve, reject) { _this.performLogin(resolve, reject); }); } return this.login_promise; }; CommsService.prototype.logout = function () { this.oAuthService.logOut(); }; Object.defineProperty(CommsService.prototype, "token", { get: function () { return this.login(); }, enumerable: true, configurable: true }); Object.defineProperty(CommsService.prototype, "hasToken", { get: function () { if (this.http instanceof MockHttp) { return new Promise(function (resolve) { resolve(true); }); } else { return this.oAuthService.hasValidAccessToken(); } }, enumerable: true, configurable: true }); CommsService.prototype.isLoggedIn = function () { return this.token ? true : (this.refresh ? null : false); }; CommsService.prototype.refreshToken = function (resolve, reject, retries) { var _this = this; if (retries === void 0) { retries = 1; } var oauth = this.oAuthService; this.refresh = true; oauth.refresh_url.then(function (url) { var tokens; _this.http.post(url, '') .map(function (res) { return res.json(); }) .subscribe(function (data) { return tokens = data; }, function (err) { var err_codes = [0, 400, 401, 403]; if (err && (err_codes.indexOf(err.status) || (err.status === 0 && err.ok === false)) && url.indexOf(_this.hash(location.origin + "/oauth-resp.html")) < 0 && retries < 10) { COMPOSER.log('COMMS', "Failed token refresh request for " + url); oauth.getRefreshToken().then(function (rt) { oauth.redirectUri = location.origin + "/oauth-resp.html"; var client_id = _this.hash(location.origin + "/oauth-resp.html"); _this.store.local.getItem(client_id + "_refresh_token").then(function (rt_root) { if (rt && !rt_root) { _this.store.local.setItem(oauth.clientId + "_refresh_token", rt); } setTimeout(function () { _this.refreshToken(resolve, reject, retries + 1); }, 500 * retries); }); }); } else { _this.processLoginError(err, reject); } }, function () { COMPOSER.log('COMMS', "Got new tokens:", tokens); _this.updateToken(tokens, resolve); setTimeout(function () { _this.loginDone(); }, 100); }); }); }; CommsService.prototype.setLoginStatus = function (status) { var oauth = this.oAuthService; if (status === true) { this.store.session.setItem(oauth.clientId + "_login", 'true'); } else { this.store.session.removeItem(oauth.clientId + "_login"); } }; CommsService.prototype.clearStore = function () { var oauth = this.oAuthService; oauth.clearAuth(); }; CommsService.prototype.checkAuth = function (cb_fn) { var _this = this; COMPOSER.log('COMMS', "Checking Auth."); if (this.login_promise === null) { var parts = this.oAuthService.loginUrl.split('/'); var uri_1 = parts.splice(0, 3).join('/'); this.oAuthService.authorizationHeader().then(function (token) { var headers = new Headers({ Authorization: (token ? token : '') }); _this.http.get(uri_1 + '/auth/oauth/token/info', { headers: headers }).subscribe(function (data) { return cb_fn(data); }, function (err) { return _this.processLoginError(err, function () { return; }); }, function () { return; }); }); } }; CommsService.prototype.performLogin = function (resolve, reject) { var _this = this; if (this.http instanceof MockHttp) { this.login_promise = null; return resolve('mock_token'); } var oauth = this.oAuthService; if (!oauth || !oauth.clientId || oauth.clientId === '') { setTimeout(function () { _this.performLogin(resolve, reject); }, 500); return; } oauth.hasValidAccessToken().then(function (valid) { if (valid) { COMPOSER.log('COMMS', "Valid access token availiable."); oauth.getAccessToken().then(function (token) { resolve(token); setTimeout(function () { _this.loginDone(); }, 100); }); } else { COMPOSER.log('COMMS', "No valid access token available."); oauth.tryLogin().then(function (status) { oauth.hasValidAccessToken().then(function (valid_after_load) { if (valid_after_load) { COMPOSER.log('COMMS', "Valid access token availiable."); oauth.getAccessToken().then(function (token) { resolve(token); setTimeout(function () { _this.loginDone(); }, 100); }); } else { if (_this.trust) { COMPOSER.log('COMMS', "Device is trusted"); oauth.response_type = 'code'; _this.store.local.getItem(oauth.clientId + "_refresh_token").then(function (refresh) { if (refresh || oauth.code) { COMPOSER.log('COMMS', "Refresh token found. Refreshing access token..."); if (oauth.clientId === '') { resolve({ message: 'OAuth not setup, retrying after 100ms' }); setTimeout(function () { _this.loginDone(); _this.login(); }, 100); } else { _this.refreshToken(resolve, reject); } } else { COMPOSER.log('COMMS', "No Refresh Token or Code"); var path = location.href; if (location.hash.indexOf(path) >= 0 && location.href.indexOf(location.origin + '/#/') >= 0) { if (path.indexOf('?') >= 0) { path = path.split('?')[0]; } } var here = path; _this.store.local.setItem("oauth_redirect", here); oauth.initImplicitFlow(); setTimeout(function () { _this.loginDone(); }, 100); } }); } else { COMPOSER.log('COMMS', "Device is not trusted."); oauth.response_type = 'token'; COMPOSER.log('COMMS', "Starting login process..."); var path = location.href; if (location.hash.indexOf(path) >= 0 && location.href.indexOf(location.origin + '/#/') >= 0) { if (path.indexOf('?') >= 0) { path = path.split('?')[0]; } } var here = path; _this.store.local.setItem("oauth_redirect", here); oauth.initImplicitFlow(); setTimeout(function () { _this.loginDone(); }, 100); } } }); }); } }); }; CommsService.prototype.loginDone = function () { this.cleanUrl(); this.login_promise = null; }; CommsService.prototype.processLoginError = function (err, reject) { var _this = this; var oauth = this.oAuthService; this.storeError('login', err); if (err.status === 400 || err.status === 401) { COMPOSER.log('COMMS', "Error with credentials. Getting new credentials..."); this.clearStore(); this.oAuthService.code = undefined; setTimeout(function () { _this.loginDone(); }, 100); this.login().then(function () { return; }, function (login_err) { reject(login_err); }); } else { setTimeout(function () { location.reload(); }, 5000); setTimeout(function () { _this.loginDone(); }, 100); } }; CommsService.prototype.storeError = function (type, error) { var _this = this; var days = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']; var months = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'NOV', 'DEC']; var date = new Date(); var hour = date.getHours(); hour = hour < 10 ? '0' + hour : hour; var min = date.getMinutes(); min = min < 10 ? '0' + min : min; var sec = date.getSeconds(); sec = sec < 10 ? '0' + sec : sec; var now = days[date.getDay()] + " " + date.getDate() + " " + months[date.getMonth()] + " " + hour + ":" + min + ":" + sec; now = now.toLowerCase(); this.store.local.setItem((type + "_error: " + now), JSON.stringify(error)); this.store.local.getItem(type + "_error").then(function (value) { var error_list = []; if (value) { error_list = JSON.parse(value); if (error_list) { error_list.push(now); if (error_list.length >= MAX_ERROR_COUNT) { for (var i = 0; i < error_list.length - MAX_ERROR_COUNT; i++) { _this.store.local.removeItem(type + "_error: " + error_list[i]); } error_list.splice(0, error_list.length - MAX_ERROR_COUNT); } } else { error_list = [now]; } } else { error_list = [now]; } _this.store.local.setItem(type + "_error", JSON.stringify(error_list)); }); }; CommsService.prototype.updateToken = function (data, resolve) { var _this = this; var oauth = this.oAuthService; if (data.access_token) { this.store.local.setItem(oauth.clientId + "_access_token", data.access_token); } if (data.refresh_token) { this.store.local.setItem(oauth.clientId + "_refresh_token", data.refresh_token); } if (data.expires_in) { var expiry = ((new Date()).getTime() + data.expires_in * 1000); this.store.local.setItem(oauth.clientId + "_expires_at", expiry.toString()); } if (resolve) { resolve(); } setTimeout(function () { _this.loginDone(); }, 100); }; CommsService.prototype.cleanUrl = function () { var _this = this; var path = this.loc.path(false); if (location.search.indexOf('access_token') >= 0 || location.search.indexOf('code') >= 0) { this.loc.go(path, ''); setTimeout(function () { _this.store.local.removeItem('oauth_redirect'); _this.store.local.removeItem('oauth_finished'); }, 5000); } else if (path.indexOf('?') >= 0 && (path.indexOf('access_token') >= 0 || path.indexOf('code') >= 0)) { this.loc.go(path.split('?')[0], ''); setTimeout(function () { _this.store.local.removeItem('oauth_redirect'); _this.store.local.removeItem('oauth_finished'); }, 5000); } }; CommsService.prototype.processOptions = function (url, body, options) { var _this = this; var oauth = this.oAuthService; return this.oAuthService.authorizationHeader().then(function (auth_header) { var headers = new Headers({ Authorization: auth_header }); if (options && options.headers) { if (options.headers.values) { var h = options.headers.values(); var k = options.headers.keys(); for (var i in h) { if (k[i].toLowerCase() !== 'authorization') { headers.append(k[i], h[i][0]); } } } else { var keys = Object.keys(options.headers); for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { var key = keys_1[_i]; if (key.toLowerCase() !== 'authorization') { headers.append(key, options.headers[key]); } } } } var req = { type: 'get', body: body, url: url, auth: ((auth_header !== '' && auth_header.indexOf('Bearer nul') < 0) || _this.http instanceof MockHttp), }; if (!req.options) { req.options = { headers: headers, }; } else if (!req.options.headers) { req.options.headers = headers; } return req; }); }; CommsService.prototype.error = function (err, req, obs) { var _this = this; var hash = this.hash(req.url + req.body); if (!this.retry[hash]) { this.retry[hash] = 0; } if ((err.status === 401 || (err.status === 0 && err.ok === false)) && this.retry[hash] < 10) { setTimeout(function () { _this.login() .then(function (res) { _this.retry[hash] = _this.retry[hash] ? _this.retry[hash] + 1 : 1; setTimeout(function () { _this.refresh = false; if (req.type === 'get' || req.type === 'delete') { _this[req.type](req.url, req.options).subscribe(function (data) { return obs.next(data); }, function (retry_err) { return obs.error(retry_err); }, function () { obs.complete(); _this.retry[hash] = 0; }); } else { _this[req.type](req.url, req.body, req.options).subscribe(function (data) { return obs.next(data); }, function (retry_err) { return obs.error(retry_err); }, function () { obs.complete(); _this.retry[hash] = 0; }); } }, 500 * _this.retry[hash]); }, function (retry_err) { COMPOSER.error('COMMS', "Error logging in.", retry_err); _this.clearStore(); location.reload(); _this.retry[hash] = 0; }); }, 200); } else { COMPOSER.log('COMMS', "Error processing request.", err); obs.error(err); this.retry[hash] = 0; } }; return CommsService; }()); export { CommsService }; CommsService.decorators = [ { type: Injectable }, ]; CommsService.ctorParameters = function () { return [ { type: ActivatedRoute, }, { type: Router, }, { type: Http, }, { type: OAuthService, }, { type: DataStoreService, }, { type: Location, }, { type: Injector, }, ]; }; //# sourceMappingURL=comms.service.js.map