@aca-1/a2-composer
Version:
Angular 2 Interface for composer
512 lines • 23.3 kB
JavaScript
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