/** 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); } 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.
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);