hedera-web/js/vn/json-connection.js

314 lines
6.8 KiB
JavaScript

var VnObject = require('./object');
var JsonException = require('./json-exception');
/**
* Handler for JSON rest connections.
*/
module.exports = new Class({
Extends: VnObject
,_connected: false
,_requestsCount: 0
,token: null
/**
* Initilizes the connection object.
*/
,initialize() {
VnObject.prototype.initialize.call(this);
this.fetchToken();
}
,fetchToken() {
var token = null;
if (sessionStorage.getItem('vnToken'))
token = sessionStorage.getItem('vnToken');
if (localStorage.getItem('vnToken'))
token = localStorage.getItem('vnToken');
this.token = token;
}
,clearToken() {
this.token = null;
localStorage.removeItem('vnToken');
sessionStorage.removeItem('vnToken');
}
/**
* Opens the connection to the REST service.
*
* @param {String} user The user name
* @param {String} password The user password
* @param {Boolean} remember Specifies if the user should be remembered
* @return {Promise} Resolved when operation is done
*/
,async open(user, pass, remember) {
let params;
if (user !== null && user !== undefined) {
params = {
user: user
,password: pass
,remember: remember
};
} else
params = null;
try {
const json = await this.lbSend('POST', 'Accounts/login', params);
var storage = remember ? localStorage : sessionStorage;
storage.setItem('vnToken', json.token);
this.token = json.token;
this._connected = true;
this.emit('openned');
} catch(err) {
this._closeClient();
throw err;
}
}
/**
* Closes the connection to the REST service.
*
* @return {Promise} Resolved when operation is done
*/
,async close() {
await this.lbSend('POST', 'Accounts/logout');
this._closeClient();
this.emit('closed');
}
,_closeClient() {
this._connected = false;
this.clearToken();
}
/**
* Supplants another user.
*
* @param {String} user The user name
* @param {Function} callback The callback function
*/
,supplantUser(user, callback) {
var params = {supplantUser: user};
this.send('client/supplant', params,
this._onUserSupplant.bind(this, callback));
}
,_onUserSupplant(callback, json, err) {
if (json)
this.token = json;
if (callback)
callback(err == null, err);
}
/**
* Ends the user supplanting and restores the last login.
*/
,supplantEnd() {
this.lbSend('POST', 'Accounts/logout');
this.fetchToken();
}
/**
* Executes the specified REST service with the given params and calls
* the callback when response is received.
*
* @param {String} restService The service path
* @param {Map} params The params to pass to the service
* @param {Function} callback The response callback
*/
,send(restService, params, callback) {
if (!params)
params = {};
params.srv = 'json:'+ restService;
this.sendWithUrl(params, callback, 'POST', '.');
}
,sendForm(form, callback) {
var params = {};
var elements = form.elements;
for (var i = 0; i < elements.length; i++)
if (elements[i].name)
params[elements[i].name] = elements[i].value;
this.sendWithUrl(params, callback, 'POST', form.action);
}
,sendFormMultipart(form, callback) {
var formData = new FormData(form);
var request = new XMLHttpRequest();
request.open('POST', form.action, true);
if (this.token)
request.setRequestHeader('Authorization', this.token);
request.onreadystatechange =
this._onStateChange.bind(this, request, callback);
request.send(formData);
this._addRequest();
}
,sendFormData(formData, callback) {
var request = new XMLHttpRequest();
request.open('POST', '', true);
if (this.token)
request.setRequestHeader('Authorization', this.token);
request.onreadystatechange =
this._onStateChange.bind(this, request, callback);
request.send(formData);
this._addRequest();
}
/*
* Called when REST response is received.
*/
,sendWithUrl(params, callback, method, url) {
var request = new XMLHttpRequest();
request.open(method, url, true);
request.setRequestHeader('Content-Type',
'application/x-www-form-urlencoded');
if (this.token)
request.setRequestHeader('Authorization', this.token);
request.onreadystatechange =
this._onStateChange.bind(this, request, callback);
request.send(Vn.Url.makeUri(params));
this._addRequest();
}
,async lbSend(method, url, params) {
var request = new XMLHttpRequest();
request.open(method, `api/${url}`, true);
request.setRequestHeader('Content-Type',
'application/json;charset=utf-8');
if (this.token)
request.setRequestHeader('Authorization', this.token);
this._addRequest();
return await new Promise((resolve, reject) => {
function callback(data, err) {
if (err) return reject(err);
resolve(data);
}
request.onreadystatechange =
this._onStateChange.bind(this, request, callback);
request.send(params && JSON.stringify(params));
});
}
,_addRequest() {
this._requestsCount++;
if (this._requestsCount === 1)
this.emit('loading-changed', true);
}
,_onStateChange(request, callback) {
if (request.readyState !== 4)
return;
this._requestsCount--;
if (this._requestsCount === 0)
this.emit('loading-changed', false);
var data = null;
var error = null;
try {
if (request.status == 0) {
var ex = new JsonException();
ex.message = _('The server does not respond, please check your Internet connection');
throw ex;
}
var contentType = null;
try {
contentType = request
.getResponseHeader('Content-Type')
.split(';')[0]
.trim();
} catch (err) {
console.warn(err);
}
if (contentType != 'application/json') {
var ex = new JsonException();
ex.message = request.statusText;
ex.code = request.status;
throw ex;
}
var json;
var jsData;
if (request.responseText)
json = JSON.parse(request.responseText);
if (json)
jsData = json.data || json;
if (request.status >= 200 && request.status < 300) {
data = jsData;
} else {
var exception = jsData.exception;
var error = jsData.error;
if (exception) {
exception = exception
.replace(/\\/g, '.')
.replace(/Exception$/, '')
.replace(/^Vn\.Web\./, '');
var ex = new JsonException();
ex.exception = exception;
ex.message = jsData.message;
ex.code = jsData.code;
ex.file = jsData.file;
ex.line = jsData.line;
ex.trace = jsData.trace;
} else if (error) {
var ex = new Error();
ex.name = error.name;
ex.message = error.message;
ex.code = error.code;
ex.statusCode = request.status;
}
throw ex;
}
} catch (e) {
data = null;
error = e;
}
if (callback)
try {
callback(data, error);
error = null;
} catch (e) {
error = e;
}
if (error) {
if (error.exception == 'SessionExpired')
this.clearToken();
this.emit('error', error);
}
}
});