168 lines
6.0 KiB
JavaScript
Executable File
168 lines
6.0 KiB
JavaScript
Executable File
/**
|
|
base class for data models of the EIC platform
|
|
|
|
instanciation requires 2 parameters, businessObject and privileges.
|
|
- businessObject: a string reference to a set of endpoints provided by the API discovery service (API descriptr can be found in app.config.api)
|
|
- privileges: an array of endpoints references (aka actions) allowed specifically for a certain resource. Those privileges are provided by the middle tier prior accessing the resource. * @category MyEic
|
|
* @category MyEic
|
|
* @subcategory Libraries
|
|
* @extends Model
|
|
*/
|
|
class EICModel extends Model {
|
|
|
|
// data container for the item
|
|
itemData = {};
|
|
// list of available api services for this model
|
|
api = {};
|
|
// privileges granted on this model
|
|
privileges = [];
|
|
|
|
/**
|
|
*
|
|
* @param {string} resource A string reference to the resource (aka business obkect) to be handled (ex: "users" or "project")
|
|
* @param {array} privileges An array of allowed privileges (as string reference. ex: "save", "delete", etc...). Privileges should match a corresponding method in the controller
|
|
*/
|
|
constructor(resource, privileges) {
|
|
super();
|
|
|
|
// if((app.config.hasOwnProperty('api')) && (app.config.api.hasOwnProperty(resource))) {
|
|
// this.api = app.config.api[resource];
|
|
// } else this.config.api = {}
|
|
|
|
this.setPrivileges(resource, privileges);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {*} action
|
|
* @param {*} resource
|
|
* @returns {object}
|
|
*/
|
|
getApiEndpoint(action, resource=null) {
|
|
resource = resource || this.resource;
|
|
for(let ApiBizObj of Object.keys(app.config.api)) {
|
|
|
|
//If called without real ids
|
|
if(ApiBizObj==resource) return(JSON.parse(JSON.stringify(app.config.api[ApiBizObj][action])));
|
|
|
|
//If called with real ids
|
|
let re = new RegExp('^'+ApiBizObj.replace(/\//g,'\\/').replace(/\{\w+\}/gi,'([0-9a-zA-Z]+)')+'$', 'm')
|
|
if(resource.match(re)) {
|
|
if(app.config.api[ApiBizObj].hasOwnProperty(action)) return(JSON.parse(JSON.stringify(app.config.api[ApiBizObj][action])));
|
|
else console.error(`No API endpoint for action "${action}" on resource "${resource}"`)
|
|
}
|
|
}
|
|
console.error(`No API service for resource:${resource}`)
|
|
return({ "method":null, "uri": null });
|
|
}
|
|
|
|
setPrivileges(resource, privileges) {
|
|
this.resource = resource;
|
|
this.privileges = privileges || [];
|
|
}
|
|
|
|
/**
|
|
* Checks if a privilege is available for this profile
|
|
* @param {string} privilege ref
|
|
* @returns {boolean}
|
|
*/
|
|
hasPrivilege(privilege) {
|
|
if(this.privileges.indexOf(privilege) != -1) return(true);
|
|
else {
|
|
//console.warn('You do not have the privilege:',privilege);
|
|
return(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fills the model item properties with provided object
|
|
* @param {object} data
|
|
* @returns {object}
|
|
*/
|
|
async loadData(data) {
|
|
// itemData should be cleared first
|
|
this.itemData = {}
|
|
Object.assign(this.itemData, data); // this way getters are natural
|
|
return this.itemData;
|
|
}
|
|
|
|
/**
|
|
* Generates a stringified JSON output of the itemData object
|
|
* Practical for cloning the model data
|
|
* @returns {string}
|
|
*/
|
|
toString() { return(JSON.stringify(this)); }
|
|
|
|
/**
|
|
* Deep copies updates object into target
|
|
* @param {object} target
|
|
* @param {object} updates
|
|
* @returns {object}
|
|
*/
|
|
merge(current, updates) {
|
|
for (let key of Object.keys(updates)) {
|
|
if (!current.hasOwnProperty(key) || typeof updates[key] !== 'object') current[key] = updates[key];
|
|
else this.merge(current[key], updates[key]);
|
|
}
|
|
return current;
|
|
}
|
|
|
|
/**
|
|
* Returns the current item id. Shortcut for itemData.id
|
|
* @returns {string}
|
|
*/
|
|
get id() { return(this.itemData.id); }
|
|
|
|
/**
|
|
* Tries to match the instance with given data
|
|
*
|
|
* @param {Object} matchValues - { {string} key: {string} valueToMatch }
|
|
* @param {Object} matchExact - { strin{key}: {Boolean} } Defaults to exact match if parameter absent or if key absent.
|
|
* Non-exact match uses valueToMatch as a REGEX. valueToMatch is then a string like "/regex/" or "/regex/flags".
|
|
* @return {boolean} true if match
|
|
*/
|
|
match(matchValues, matchExact = {}){
|
|
for(let key in matchValues){
|
|
let val = matchValues[key];
|
|
if((key in matchExact) && (matchExact[key])){ // equality
|
|
if(this.itemData[key]!=val) return(false);
|
|
} else { //Regex
|
|
let re = new RegExp(val.substring(1, val.lastIndexOf('/')), val.substring(val.lastIndexOf('/')+1));
|
|
if(!re.test(this.itemData[key])) return(false);
|
|
}
|
|
}
|
|
return(true);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {*} error
|
|
* @param {number} error.code
|
|
* @param {string} error.displayMessage
|
|
*/
|
|
onRequestError(error) {
|
|
if([400,404,405,409].indexOf(error.code) > -1) {
|
|
console.warn('Ajax request error:', error);
|
|
ui.growl.append(`${error.displayMessage}`, 'warning', 10000);
|
|
} else if(error.code > 499) {
|
|
console.error('Ajax request error:', error);
|
|
ui.growl.append(
|
|
`Unfortunately, there was a server error.<br>
|
|
Please contact the helpdesk if it persists
|
|
`, 'danger', 5000);
|
|
} else if(error.code==403){
|
|
console.warn(`Ajax request unauthorized in ${this.constructor.name}`, error);
|
|
ui.growl.append(`${error.displayMessage}`, 'danger', 10000);
|
|
} else if((error.code==401) && (app.User.isAuthenticated)){
|
|
console.warn(`Unauthenticated in ${this.constructor.name}`, error);
|
|
app.User.isAuthenticated = false
|
|
app.User.stopKeepAlive()
|
|
app.Router.route('/401', {'triggerUrl' :app.Router.currentRoute.realUrl } );
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
app.registerClass('EICModel',EICModel);
|
|
|