export class AccesRights { constructor(config, debug){ this.debug = debug this.config = config this.rights = config.accessRights } refreshAccessRights(config){ this.rights = config.accessRights } mustSubscribe(uid, roles) { if(roles.indexOf('*')<0) roles.push('*') let chans = [] for(let myRole of roles){ for(let rightBlock of this.rights) { if(!rightBlock.mustSubscribe) continue if((rightBlock.roles=='*') || (rightBlock.roles.indexOf(myRole)>-1)) { chans = this.merge(chans, rightBlock.mustSubscribe.map(item=>item.replace(/\[UID\]/g,uid))) } } } return(chans) } isMandatory(uid, roles, chan){ return(this.mustSubscribe(uid, roles).filter(this.chanMatch.bind(this, chan)).length>0) } canSubscribe(uid, roles, myChan) { if(roles.indexOf('*')<0) roles.push('*') for(let myRole of roles){ for(let rightBlock of this.rights) { if(!rightBlock.canSubscribe) continue if((rightBlock.roles=='*') || (rightBlock.roles.indexOf(myRole)>-1)) { let canSubList = rightBlock.canSubscribe.map(item=>item.replace(/\[UID\]/g, uid)) if(canSubList.find(this.chanMatch.bind(this, myChan))) return(true) } } } //if(this.debug) console.log(`Roles : ${roles} cannot subscribe on ${myChan}`) return(false) } canPublish(uid, roles, myChan) { myChan = myChan.startsWith(this.config.redis.basePrefix) ? myChan.substr(this.config.redis.basePrefix.length) : myChan if(roles.indexOf('*')<0) roles.push('*') for(let myRole of roles){ for(let rightBlock of this.rights) { if(!rightBlock.canPublish) continue if((rightBlock.roles=='*') || (rightBlock.roles.indexOf(myRole)>-1)) { let canPubList = rightBlock.canPublish.map(item=>item.replace(/\[UID\]/g, uid)) if(canPubList.find(this.chanMatch.bind(this, myChan))) return(true) } } } //if(this.debug) console.log(`Roles : ${roles} cannot publish on ${myChan}`) return(false) } canSet(uid, roles, myKey){ myKey = myKey.startsWith(this.config.redis.storePrefix) ? myKey.substr(this.config.redis.storePrefix.length) : myKey if(roles.indexOf('*')<0) roles.push('*') for(let myRole of roles){ for(let rightBlock of this.rights) { if(!rightBlock.canSet) continue if((rightBlock.roles=='*') || (rightBlock.roles.indexOf(myRole)>-1)) { let canSetList = rightBlock.canSet.map(item=>item.replace(/\[UID\]/g, uid)) if(canSetList.find(this.chanMatch.bind(this, myKey))) return(true) } } } //if(this.debug) console.log(`Roles : ${roles} cannot set ${myKey}`) return(false) } canGet(uid, roles, myKey){ myKey = myKey.startsWith(this.config.redis.storePrefix) ? myKey.substr(this.config.redis.storePrefix.length) : myKey if(roles.indexOf('*')<0) roles.push('*') for(let myRole of roles){ for(let rightBlock of this.rights) { if(!rightBlock.canGet) continue if((rightBlock.roles=='*') || (rightBlock.roles.indexOf(myRole)>-1)) { let canGetList = rightBlock.canGet.map(item=>item.replace(/\[UID\]/g, uid)) if(canGetList.find(this.chanMatch.bind(this, myKey))) return(true) } } } //if(this.debug) console.log(`Roles : ${roles} cannot get ${myKey}`) return(false) } canDo(roles, action, uid=null){ if(roles.indexOf('*')<0) roles.push('*') for(let myRole of roles){ for(let rightBlock of this.rights) { if(!rightBlock.canDo) continue if((rightBlock.roles=='*') || (rightBlock.roles.indexOf(myRole)>-1)) { if(rightBlock.canDo.indexOf(action)>-1) { if((rightBlock.uuids) && Array.isArray((rightBlock.uuids))) { // !!! Separate condition so if rightBlock.uuids but not uid in it, we don't give access ! if(rightBlock.uuids.includes(uid)) return(true) // null should never be in config uuids => old style calls are safe } else { // no uuid block => role is sufficient to give access return(true) } } } } } //Anti-shoot-your-foot if((action=='reloadAccessRights') && (roles.includes('EIC_Dev'))) { console.error('Prevented you from shooting your foot ! \nPlease keep least EIC_Dev in reload access rights !') return(true) } //if(this.debug) console.log(`Roles : ${roles} cannot do ${action}`) return(false) } chanMatch(myChan, configChan) { if((!myChan) || (typeof(myChan)!='string')) return(false) let re = new RegExp('^'+configChan.replace(/\*/g,'(.+)')+'$','g') return(myChan.match(re)!=null) } merge(x, y) { let tmp = x for(let yitem of y) if(tmp.indexOf(yitem)<0) tmp.push(yitem) return(tmp) } }