322 lines
7.2 KiB
JavaScript
322 lines
7.2 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: function() {
|
|
VnObject.prototype.initialize.call(this);
|
|
this.fetchToken();
|
|
}
|
|
|
|
,fetchToken: function() {
|
|
var token = null;
|
|
|
|
if (sessionStorage.getItem('vnToken'))
|
|
token = sessionStorage.getItem('vnToken');
|
|
if (localStorage.getItem('vnToken'))
|
|
token = localStorage.getItem('vnToken');
|
|
|
|
this.token = token;
|
|
}
|
|
|
|
,clearToken: function() {
|
|
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
|
|
* @param {Function} openCallback The function to call when operation is done
|
|
*/
|
|
,open: function(user, pass, remember, callback) {
|
|
if (user !== null && user !== undefined) {
|
|
var params = {
|
|
user: user
|
|
,password: pass
|
|
,remember: remember
|
|
};
|
|
} else
|
|
var params = null;
|
|
|
|
this.lbSend('POST', 'Accounts/login', params,
|
|
this._onOpen.bind(this, callback, remember));
|
|
}
|
|
|
|
/*
|
|
* Called when open operation is done.
|
|
*/
|
|
,_onOpen: function(callback, remember, json, error) {
|
|
if (json) {
|
|
this._connected = true;
|
|
this.token = json.token;
|
|
|
|
var storage = remember ? localStorage : sessionStorage;
|
|
storage.setItem('vnToken', this.token);
|
|
|
|
this.emit('openned');
|
|
} else
|
|
this._closeClient();
|
|
|
|
if (callback)
|
|
callback(this, this._connected, error);
|
|
}
|
|
|
|
/**
|
|
* Closes the connection to the REST service.
|
|
*
|
|
* @param {Function} callback The function to call when operation is done
|
|
*/
|
|
,close: function(callback) {
|
|
this.lbSend('POST', 'Accounts/logout', null,
|
|
this._onClose.bind(this, callback));
|
|
this._closeClient();
|
|
}
|
|
|
|
/*
|
|
* Called when close operation is done.
|
|
*/
|
|
,_onClose: function(callback, json, error) {
|
|
this.emit('closed');
|
|
|
|
if (callback)
|
|
callback(this, null, error);
|
|
}
|
|
|
|
,_closeClient: function() {
|
|
this._connected = false;
|
|
this.clearToken();
|
|
}
|
|
|
|
/**
|
|
* Supplants another user.
|
|
*
|
|
* @param {String} user The user name
|
|
* @param {Function} callback The callback function
|
|
*/
|
|
,supplantUser: function(user, callback) {
|
|
var params = {supplantUser: user};
|
|
this.send('client/supplant', params,
|
|
this._onUserSupplant.bind(this, callback));
|
|
}
|
|
|
|
,_onUserSupplant: function(callback, json, err) {
|
|
if (json)
|
|
this.token = json;
|
|
|
|
if (callback)
|
|
callback(err == null, err);
|
|
}
|
|
|
|
/**
|
|
* Ends the user supplanting and restores the last login.
|
|
*/
|
|
,supplantEnd: function() {
|
|
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: function(restService, params, callback) {
|
|
if (!params)
|
|
params = {};
|
|
|
|
params.srv = 'json:'+ restService;
|
|
|
|
this.sendWithUrl(params, callback, 'POST', '.');
|
|
}
|
|
|
|
,sendForm: function(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: function(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: function(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: function(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();
|
|
}
|
|
|
|
,lbSend: function(method, url, params, callback) {
|
|
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);
|
|
request.onreadystatechange =
|
|
this._onStateChange.bind(this, request, callback);
|
|
request.send(params && JSON.stringify(params));
|
|
|
|
this._addRequest();
|
|
}
|
|
|
|
,_addRequest: function() {
|
|
this._requestsCount++;
|
|
|
|
if (this._requestsCount === 1)
|
|
this.emit('loading-changed', true);
|
|
}
|
|
|
|
,_onStateChange: function(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);
|
|
}
|
|
}
|
|
});
|
|
|