Commit 11de6e45 authored by Tristan Cavelier's avatar Tristan Cavelier

erp5storage.js upgraded to JIO v2

parent 6021fe13
...@@ -3,9 +3,6 @@ ...@@ -3,9 +3,6 @@
* Released under the LGPL license. * Released under the LGPL license.
* http://www.gnu.org/licenses/lgpl.html * http://www.gnu.org/licenses/lgpl.html
*/ */
/*jslint indent: 2, maxlen: 80, nomen: true */
/*global jIO: true, $: true, complex_queries: true */
// JIO Erp5 Storage Description : // JIO Erp5 Storage Description :
// { // {
// type: "erp5" // type: "erp5"
...@@ -32,426 +29,416 @@ ...@@ -32,426 +29,416 @@
// //
// secured_login: {string} (not implemented) // secured_login: {string} (not implemented)
// } // }
jIO.addStorageType("erp5", function (spec, my) {
/*jslint indent: 2, maxlen: 80, nomen: true */
/*global define, jIO, jQuery, complex_queries */
(function (dependencies, module) {
"use strict";
if (typeof define === 'function' && define.amd) {
return define(dependencies, module);
}
module(jIO, jQuery);
}(['jio', 'jquery'], function (jIO, $) {
"use strict"; "use strict";
var priv = {}, that = my.basicStorage(spec, my), erp5 = {};
// ATTRIBUTES // function ERP5Storage(spec) {
priv.url = null; var priv = {}, that = this, erp5 = {};
priv.mode = "generic";
priv.auth_type = "none";
priv.encoded_login = null;
// CONSTRUCTOR // // ATTRIBUTES //
/** priv.url = null;
* Init the erp5 storage connector thanks to the description priv.mode = "generic";
* @method __init__ priv.auth_type = "none";
* @param {object} description The description object priv.encoded_login = null;
*/
priv.__init__ = function (description) { // CONSTRUCTOR //
priv.url = description.url || ""; /**
priv.url = priv.removeSlashIfLast(priv.url); * Init the erp5 storage connector thanks to the description
if (description.mode === "erp5_only") { * @method __init__
priv.mode = "erp5_only"; * @param {object} description The description object
} */
if (description.encoded_login) { priv.__init__ = function (description) {
priv.encoded_login = description.encoded_login; priv.url = description.url || "";
} else { priv.url = priv.removeSlashIfLast(priv.url);
if (description.username) { if (description.mode === "erp5_only") {
priv.encoded_login = priv.mode = "erp5_only";
"__ac_name=" + priv.convertToUrlParameter(description.username) + }
"&" + (typeof description.password === "string" ? if (description.encoded_login) {
"__ac_password=" + priv.encoded_login = description.encoded_login;
priv.convertToUrlParameter(description.password) + "&" : "");
} else { } else {
priv.encoded_login = ""; if (description.username) {
priv.encoded_login =
"__ac_name=" + priv.convertToUrlParameter(description.username) +
"&" + (typeof description.password === "string" ?
"__ac_password=" +
priv.convertToUrlParameter(description.password) + "&" : "");
} else {
priv.encoded_login = "";
}
} }
}
};
// OVERRIDES //
that.specToStore = function () {
// TODO: secured password
// The encoded_login can be seen by anyone, we must find a way to secure it!
// secured_login = encrypt(encoded_login)
// encoded_login = decrypt(secured_login)
return {
"url": priv.url,
"mode": priv.mode,
"encoded_login": priv.encoded_login
}; };
};
that.validateState = function () {
if (typeof priv.url !== "string" || priv.url === "") {
return "The erp5 server URL is not provided";
}
if (priv.encoded_login === null) {
return "Impossible to create the authorization";
}
return "";
};
// TOOLS // // TOOLS //
/** /**
* Replace substrings to another strings * Replace substrings to another strings
* @method recursiveReplace * @method recursiveReplace
* @param {string} string The string to do replacement * @param {string} string The string to do replacement
* @param {array} list_of_replacement An array of couple * @param {array} list_of_replacement An array of couple
* ["substring to select", "selected substring replaced by this string"]. * ["substring to select", "selected substring replaced by this string"].
* @return {string} The replaced string * @return {string} The replaced string
*/ */
priv.recursiveReplace = function (string, list_of_replacement) { priv.recursiveReplace = function (string, list_of_replacement) {
var i, split_string = string.split(list_of_replacement[0][0]); var i, split_string = string.split(list_of_replacement[0][0]);
if (list_of_replacement[1]) { if (list_of_replacement[1]) {
for (i = 0; i < split_string.length; i += 1) { for (i = 0; i < split_string.length; i += 1) {
split_string[i] = priv.recursiveReplace( split_string[i] = priv.recursiveReplace(
split_string[i], split_string[i],
list_of_replacement.slice(1) list_of_replacement.slice(1)
); );
}
} }
} return split_string.join(list_of_replacement[0][1]);
return split_string.join(list_of_replacement[0][1]); };
};
/** /**
* Changes & to %26 * Changes & to %26
* @method convertToUrlParameter * @method convertToUrlParameter
* @param {string} parameter The parameter to convert * @param {string} parameter The parameter to convert
* @return {string} The converted parameter * @return {string} The converted parameter
*/ */
priv.convertToUrlParameter = function (parameter) { priv.convertToUrlParameter = function (parameter) {
return priv.recursiveReplace(parameter, [[" ", "%20"], ["&", "%26"]]); return priv.recursiveReplace(parameter, [[" ", "%20"], ["&", "%26"]]);
}; };
/** /**
* Removes the last character if it is a "/". "/a/b/c/" become "/a/b/c" * Removes the last character if it is a "/". "/a/b/c/" become "/a/b/c"
* @method removeSlashIfLast * @method removeSlashIfLast
* @param {string} string The string to modify * @param {string} string The string to modify
* @return {string} The modified string * @return {string} The modified string
*/ */
priv.removeSlashIfLast = function (string) { priv.removeSlashIfLast = function (string) {
if (string[string.length - 1] === "/") { if (string[string.length - 1] === "/") {
return string.slice(0, -1); return string.slice(0, -1);
} }
return string; return string;
}; };
/** /**
* Modify an ajax object to add default values * Modify an ajax object to add default values
* @method makeAjaxObject * @method makeAjaxObject
* @param {object} json The JSON object * @param {object} json The JSON object
* @param {object} option The option object * @param {object} option The option object
* @param {string} method The erp5 request method * @param {string} method The erp5 request method
* @param {object} ajax_object The ajax object to override * @param {object} ajax_object The ajax object to override
* @return {object} A new ajax object with default values * @return {object} A new ajax object with default values
*/ */
priv.makeAjaxObject = function (json, option, method, ajax_object) { priv.makeAjaxObject = function (json, option, method, ajax_object) {
ajax_object.type = "POST"; ajax_object.type = "POST";
ajax_object.dataType = "json"; ajax_object.dataType = "json";
ajax_object.data = [ ajax_object.data = [
{"name": "doc", "value": JSON.stringify(json)}, {"name": "doc", "value": JSON.stringify(json)},
{"name": "option", "value": JSON.stringify(option)}, {"name": "option", "value": JSON.stringify(option)},
{"name": "mode", "value": priv.mode} {"name": "mode", "value": priv.mode}
]; ];
ajax_object.url = priv.url + "/JIO_" + method + ajax_object.url = priv.url + "/JIO_" + method +
"?" + priv.encoded_login + "_=" + Date.now(); "?" + priv.encoded_login + "_=" + Date.now();
ajax_object.async = ajax_object.async === false ? false : true; ajax_object.async = ajax_object.async === false ? false : true;
ajax_object.crossdomain = ajax_object.crossdomain === false ? false : true; ajax_object.crossdomain =
ajax_object.headers = ajax_object.headers || {}; ajax_object.crossdomain === false ? false : true;
return ajax_object; ajax_object.headers = ajax_object.headers || {};
}; return ajax_object;
};
/** /**
* Runs all ajax requests for erp5Storage * Runs all ajax requests for erp5Storage
* @method ajax * @method ajax
* @param {object} json The JSON object * @param {object} json The JSON object
* @param {object} option The option object * @param {object} option The option object
* @param {string} method The erp5 request method * @param {string} method The erp5 request method
* @param {object} ajax_object The request parameters (optional) * @param {object} ajax_object The request parameters (optional)
*/ */
priv.ajax = function (json, option, method, ajax_object) { priv.ajax = function (json, option, method, ajax_object) {
return $.ajax(priv.makeAjaxObject(json, option, method, ajax_object || {})); return $.ajax(
//.always(then || function () {}); priv.makeAjaxObject(json, option, method, ajax_object || {})
}; );
//.always(then || function () {});
};
/** /**
* Creates error objects for this storage * Creates error objects for this storage
* @method createError * @method createError
* @param {string} url url to clean up * @param {string} url url to clean up
* @return {object} error The error object * @return {object} error The error object
*/ */
priv.createError = function (status, message, reason) { priv.createError = function (status, message, reason) {
var error = { return {
"status": status, "status": status,
"message": message, "message": message,
"reason": reason "reason": reason
};
}; };
switch (status) {
case 404:
error.statusText = "Not found";
break;
case 405:
error.statusText = "Method Not Allowed";
break;
case 409:
error.statusText = "Conflicts";
break;
case 24:
error.statusText = "Corrupted Document";
break;
}
error.error = error.statusText.toLowerCase().split(" ").join("_");
return error;
};
/** /**
* Converts ajax error object to a JIO error object * Converts ajax error object to a JIO error object
* @method ajaxErrorToJioError * @method ajaxErrorToJioError
* @param {object} ajax_error_object The ajax error object * @param {object} ajax_error_object The ajax error object
* @param {string} message The error message * @param {string} message The error message
* @param {string} reason The error reason * @param {string} reason The error reason
* @return {object} The JIO error object * @return {object} The JIO error object
*/ */
priv.ajaxErrorToJioError = function (ajax_error_object, message, reason) { priv.ajaxErrorToJioError = function (ajax_error_object, message, reason) {
var jio_error_object = {}; var jio_error_object = {};
jio_error_object.status = ajax_error_object.status; jio_error_object.status = ajax_error_object.status;
jio_error_object.statusText = ajax_error_object.statusText; jio_error_object.statusText = ajax_error_object.statusText;
jio_error_object.error = jio_error_object.error =
ajax_error_object.statusText.toLowerCase().split(" ").join("_"); ajax_error_object.statusText.toLowerCase().split(" ").join("_");
jio_error_object.message = message; jio_error_object.message = message;
jio_error_object.reason = reason; jio_error_object.reason = reason;
return jio_error_object; return jio_error_object;
}; };
/** /**
* Function that create an object containing jQuery like callbacks * Function that create an object containing jQuery like callbacks
* @method makeJQLikeCallback * @method makeJQLikeCallback
* @return {object} jQuery like callback methods * @return {object} jQuery like callback methods
*/ */
priv.makeJQLikeCallback = function () { priv.makeJQLikeCallback = function () {
var result = null, emptyFun = function () {}, jql = { var result = null, emptyFun = function () {
"respond": function () { return;
result = arguments; }, jql = {
}, "respond": function () {
"to_return": { result = arguments;
"always": function (func) { },
if (result) { "to_return": {
func.apply(func, result); "always": function (func) {
jql.to_return.always = emptyFun; if (result) {
} else { func.apply(func, result);
jql.respond = func; jql.to_return.always = emptyFun;
} else {
jql.respond = func;
}
return jql.to_return;
} }
return jql.to_return;
} }
} };
return jql;
}; };
return jql;
};
/** /**
* Use option object and converts a query to a compatible ERP5 Query. * Use option object and converts a query to a compatible ERP5 Query.
* *
* @param {Object} option The command options * @param {Object} option The command options
*/ */
priv.convertToErp5Query = function (option) { priv.convertToErp5Query = function (option) {
option.query = complex_queries.QueryFactory.create(option.query || ""); option.query = complex_queries.QueryFactory.create(option.query || "");
if (option.wildcard_character === undefined || if (option.wildcard_character === undefined ||
(option.wildcard_character !== null && (option.wildcard_character !== null &&
typeof option.wildcard_character !== 'string')) { typeof option.wildcard_character !== 'string')) {
option.wildcard_character = '%'; option.wildcard_character = '%';
} else { } else {
option.wildcard_character = option.wildcard_character || ''; option.wildcard_character = option.wildcard_character || '';
} }
option.query.onParseSimpleQuery = function (object) { option.query.onParseSimpleQuery = function (object) {
if (option.wildcard_character.length === 1 && if (option.wildcard_character.length === 1 &&
object.parsed.operator === '=') { object.parsed.operator === '=') {
object.parsed.operator = 'like'; object.parsed.operator = 'like';
if (option.wildcard_character === '%') { if (option.wildcard_character === '%') {
object.parsed.value = object.parsed.value =
object.parsed.value.replace(/_/g, '\\_'); object.parsed.value.replace(/_/g, '\\_');
} else if (option.wildcard_character === '_') { } else if (option.wildcard_character === '_') {
object.parsed.value = object.parsed.value =
object.parsed.value.replace(/%/g, '\\%').replace(/_/g, '%'); object.parsed.value.replace(/%/g, '\\%').replace(/_/g, '%');
} else { } else {
object.parsed.value = object.parsed.value =
object.parsed.value.replace( object.parsed.value.replace(
/([%_])/g, /([%_])/g,
'\\$1' '\\$1'
).replace( ).replace(
new RegExp(complex_queries.stringEscapeRegexpCharacters( new RegExp(complex_queries.stringEscapeRegexpCharacters(
option.wildcard_character option.wildcard_character
), 'g'), ), 'g'),
'%' '%'
); );
}
} }
} };
option.query = option.query.parse();
}; };
option.query = option.query.parse();
};
// ERP5 REQUESTS // // ERP5 REQUESTS //
/** /**
* Sends a request to ERP5 * Sends a request to ERP5
* @method erp5.genericRequest * @method erp5.genericRequest
* @param {object} doc The document object * @param {object} doc The document object
* @param {object} option The option object * @param {object} option The option object
* @param {string} method The ERP5 request method * @param {string} method The ERP5 request method
*/ */
erp5.genericRequest = function (json, option, method) { erp5.genericRequest = function (method, json, option) {
var jql = priv.makeJQLikeCallback(), error = null; var jql = priv.makeJQLikeCallback(), error = null;
priv.ajax(json, option, method).always(function (one, state, three) { priv.ajax(json, option, method).always(function (one, state) {
if (state === "parsererror") { if (state === "parsererror") {
return jql.respond(priv.createError(
24,
"Cannot parse data",
"Corrupted data"
), undefined);
}
if (state !== "success") {
error = priv.ajaxErrorToJioError(
one,
"An error occured on " + method,
"Unknown"
);
if (one.status === 404) {
error.reason = "Not Found";
}
return jql.respond(error, undefined);
}
if (one.err !== null) {
return jql.respond(one.err, undefined);
}
if (one.response !== null) {
return jql.respond(undefined, one.response);
}
return jql.respond(priv.createError( return jql.respond(priv.createError(
24, 24,
"Cannot parse data", "Cannot parse data",
"Corrupted data" "Corrupted data"
), undefined); ), undefined);
});
return jql.to_return;
};
// JIO COMMANDS //
/**
* The ERP5 storage generic command
* @method genericCommand
* @param {object} command The JIO command object
* @param {string} method The ERP5 request method
*/
priv.genericCommand = function (method, command, param, option) {
if (complex_queries !== undefined &&
method === 'allDocs' &&
option.query) {
priv.convertToErp5Query(option);
} }
if (state !== "success") { erp5.genericRequest(
error = priv.ajaxErrorToJioError( method,
one, param,
"An error occured on " + method, option
"Unknown" ).always(function (err, response) {
); if (err) {
if (one.status === 404) { return command.error(err);
error.reason = "Not Found";
} }
return jql.respond(error, undefined); if (['get', 'getAttachment', 'allDocs'].indexOf(method) === -1) {
} return command.success(response);
if (one.err !== null) { }
return jql.respond(one.err, undefined); return command.success({"data": response});
} });
if (one.response !== null) { };
return jql.respond(undefined, one.response);
}
return jql.respond(priv.createError(
24,
"Cannot parse data",
"Corrupted data"
), undefined);
});
return jql.to_return;
};
// JIO COMMANDS // /**
/** * Creates a new document
* The ERP5 storage generic command * @method post
* @method genericCommand * @param {object} command The JIO command
* @param {object} command The JIO command object */
* @param {string} method The ERP5 request method that.post = function (command, metadata, options) {
*/ priv.genericCommand("post", command, metadata, options);
priv.genericCommand = function (command, method) { };
var option = command.cloneOption();
if (complex_queries !== undefined &&
method === 'allDocs' &&
option.query) {
priv.convertToErp5Query(option);
}
erp5.genericRequest(
command.cloneDoc(),
option,
method
).always(function (err, response) {
if (err) {
return that.error(err);
}
return that.success(response);
});
};
/** /**
* Creates a new document * Creates or updates a document
* @method post * @method put
* @param {object} command The JIO command * @param {object} command The JIO command
*/ */
that.post = function (command) { that.put = function (command, metadata, options) {
priv.genericCommand(command, "post"); priv.genericCommand("put", command, metadata, options);
}; };
/** /**
* Creates or updates a document * Add an attachment to a document
* @method put * @method putAttachment
* @param {object} command The JIO command * @param {object} command The JIO command
*/ */
that.put = function (command) { that.putAttachment = function (command, param, options) {
priv.genericCommand(command, "put"); priv.genericCommand("putAttachment", command, param, options);
}; };
/** /**
* Add an attachment to a document * Get a document
* @method putAttachment * @method get
* @param {object} command The JIO command * @param {object} command The JIO command
*/ */
that.putAttachment = function (command) { that.get = function (command, param, options) {
priv.genericCommand(command, "putAttachment"); priv.genericCommand("get", command, param, options);
}; };
/** /**
* Get a document * Get an attachment
* @method get * @method getAttachment
* @param {object} command The JIO command * @param {object} command The JIO command
*/ */
that.get = function (command) { that.getAttachment = function (command, param, options) {
priv.genericCommand(command, "get"); priv.genericCommand("getAttachment", command, param, options);
}; };
/** /**
* Get an attachment * Remove a document
* @method getAttachment * @method remove
* @param {object} command The JIO command * @param {object} command The JIO command
*/ */
that.getAttachment = function (command) { that.remove = function (command, param, options) {
priv.genericCommand(command, "getAttachment"); priv.genericCommand("remove", command, param, options);
}; };
/** /**
* Remove a document * Remove an attachment
* @method remove * @method removeAttachment
* @param {object} command The JIO command * @param {object} command The JIO command
*/ */
that.remove = function (command) { that.removeAttachment = function (command, param, options) {
priv.genericCommand(command, "remove"); priv.genericCommand("removeAttachment", command, param, options);
}; };
/** /**
* Remove an attachment * Gets a document list from a distant erp5 storage
* @method removeAttachment * Options:
* @param {object} command The JIO command * - {boolean} include_docs Also retrieve the actual document content.
*/ * @method allDocs
that.removeAttachment = function (command) { * @param {object} command The JIO command
priv.genericCommand(command, "removeAttachment"); */
}; that.allDocs = function (command, param, options) {
priv.genericCommand("allDocs", command, param, options);
};
/** /**
* Gets a document list from a distant erp5 storage * Checks a document state
* Options: * @method check
* - {boolean} include_docs Also retrieve the actual document content. * @param {object} command The JIO command
* @method allDocs */
* @param {object} command The JIO command that.check = function (command, param, options) {
*/ priv.genericCommand("check", command, param, options);
that.allDocs = function (command) { };
priv.genericCommand(command, "allDocs");
}; /**
* Restore a document state to a coherent state
* @method repair
* @param {object} command The JIO command
*/
that.repair = function (command, param, options) {
priv.genericCommand("repair", command, param, options);
};
priv.__init__(spec);
/** if (typeof priv.url !== "string" || priv.url === "") {
* Checks a document state throw new TypeError("The erp5 server URL is not provided");
* @method check }
* @param {object} command The JIO command if (priv.encoded_login === null) {
*/ throw new TypeError("Impossible to create the authorization");
that.check = function (command) { }
priv.genericCommand(command, "check"); }
};
/** jIO.addStorage("erp5", ERP5Storage);
* Restore a document state to a coherent state
* @method repair
* @param {object} command The JIO command
*/
that.repair = function (command) {
priv.genericCommand(command, "repair");
};
priv.__init__(spec); }));
return that;
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment