|
@@ -1,5 +1,6 @@
|
|
|
(async() => {
|
|
|
const Sequelize = require("sequelize");
|
|
|
+ const Op = Sequelize.Op
|
|
|
const sequelize = new Sequelize("test", "","",{
|
|
|
host: 'localhost',
|
|
|
dialect: 'mysql',
|
|
@@ -24,23 +25,53 @@
|
|
|
get(){
|
|
|
return this.getDataValue("slice").split(",")
|
|
|
},
|
|
|
- set(newValue){
|
|
|
+ set(newValue){ //TODO: update users before with groups
|
|
|
newValue = "length" in newValue ? newValue.join(",") : newValue
|
|
|
return this.setDataValue("slice", newValue)
|
|
|
}
|
|
|
}
|
|
|
- },{
|
|
|
+ },{
|
|
|
getterMethods: {
|
|
|
async all(){
|
|
|
- const Op = Sequelize.Op
|
|
|
+ if (this._all) return this._all
|
|
|
+
|
|
|
this._subSlicesList = this.slice.filter(id => id[0] == "#" || id[0] == "-") //detect - or #
|
|
|
.map( id => +id.substr(1)) //cut first char + toInt
|
|
|
- let subSlices = await Slice.find({where: {id: {[Op.in]: this._subSlicesList}}})
|
|
|
- for (let subSlice of subSlices){
|
|
|
- this._subSlicesList = this._subSlicesList.filter(id => subSlice.id !== id)
|
|
|
- this._subSlicesList = [...this._subSlicesList,... await subSlice.all()]
|
|
|
+ this._roles = this.slice.filter(id => id[0] >= 'a' && id[0] <= 'z' )
|
|
|
+ this._userIds = this.slice.filter(id => id[0] >= '0' && id[0] <= '9' )
|
|
|
+
|
|
|
+ if (this._subSlicesList.length) {
|
|
|
+ let subSlices = await Slice.findAll({where: {id: {[Op.in]: this._subSlicesList}}})
|
|
|
+ if (subSlices) for (let subSlice of subSlices){
|
|
|
+ this._subSlicesList = this._subSlicesList.filter(id => subSlice.id !== id)
|
|
|
+ let subSliceAll = await subSlice.all
|
|
|
+ this._subSlicesList = [...this._subSlicesList,... subSliceAll.slices]
|
|
|
+ this._roles = [...this._roles, ...subSliceAll.roles]
|
|
|
+ this._userIds = [...this._userIds, ...subSliceAll.userIds]
|
|
|
+ }
|
|
|
}
|
|
|
- return this._subSlicesList
|
|
|
+
|
|
|
+ this._all = {slices: this._subSlicesList, roles: this._roles, userIds: this._userIds}
|
|
|
+
|
|
|
+ return this._all
|
|
|
+ },
|
|
|
+ async allRoles(){
|
|
|
+ return (await this.all).roles
|
|
|
+ },
|
|
|
+ async allSlices(){
|
|
|
+ return (await this.all).slices
|
|
|
+ },
|
|
|
+ async allUserIds(){
|
|
|
+ return (await this.all).userIds
|
|
|
+ },
|
|
|
+
|
|
|
+ roles(){
|
|
|
+ return this.slice.filter(id => id[0] >= 'a' && id[0] <= 'z' )
|
|
|
+ },
|
|
|
+
|
|
|
+ groups(){
|
|
|
+ return this.slice.filter(id => id[0] == "#" || id[0] == "-") //detect - or #
|
|
|
+ .map( id => +id.substr(1)) //cut first char + toInt
|
|
|
}
|
|
|
},
|
|
|
indexes: [
|
|
@@ -61,11 +92,129 @@
|
|
|
data: Sequelize.TEXT
|
|
|
})
|
|
|
|
|
|
- await sequelize.sync()
|
|
|
+ async function filldb(){
|
|
|
+ await sequelize.sync()
|
|
|
+
|
|
|
+ console.log('synced')
|
|
|
+
|
|
|
+ let [vasya, petya, kolya] = await Promise.all([
|
|
|
+ User.create({login: "Vasya", password: "qwe"}),
|
|
|
+ User.create({login: "Petya", password: "qwe"}),
|
|
|
+ User.create({login: "Kolya", password: "qwe"}),
|
|
|
+ ])
|
|
|
+
|
|
|
+ let groupSlice = await Slice.create({
|
|
|
+ permission: 'group',
|
|
|
+ model: 'group',
|
|
|
+ slice: [`${vasya.id}`, `${petya.id}`]
|
|
|
+ })
|
|
|
+
|
|
|
+ let [vasyaSlice, petyaSlice, kolyaSlice] = await Promise.all([
|
|
|
+ Slice.create({model: 'user', permission: 'user', modelId: vasya.id, slice: ["user", `#${groupSlice.id}`]}),
|
|
|
+ Slice.create({model: 'user', permission: 'user', modelId: petya.id, slice: ["user", `#${groupSlice.id}`]}),
|
|
|
+ Slice.create({model: 'user', permission: 'user', modelId: kolya.id, slice: ["user" ]})
|
|
|
+ ])
|
|
|
+
|
|
|
+ let [hiddenContent, roleContent, groupContent] = await Promise.all([
|
|
|
+ Content.create({title: 'Hidden', data: 'HIDDEN'}),
|
|
|
+ Content.create({title: 'Role', data: 'ROLE'}),
|
|
|
+ Content.create({title: 'Group', data: 'GROUP'}),
|
|
|
+ ])
|
|
|
+
|
|
|
+ let [hiddenSlice, roleSlice, groupContentSlice] = await Promise.all([
|
|
|
+ Slice.create({model: 'content', permission: 'read', modelId: hiddenContent.id, slice: []}),
|
|
|
+ Slice.create({model: 'content', permission: 'read', modelId: roleContent.id, slice: ["user"]}),
|
|
|
+ Slice.create({model: 'content', permission: 'read', modelId: groupContent.id, slice: [`#${groupSlice.id}`]}),
|
|
|
+ ])
|
|
|
+ }
|
|
|
+
|
|
|
+ //filldb()
|
|
|
|
|
|
function sliced(model){
|
|
|
+ return async userId => {
|
|
|
+ let user = await User.findByPk(userId)
|
|
|
+ if (!user) throw new ReferenceError(`user with userId ${userId} doesn't exists`)
|
|
|
+
|
|
|
+ let userSlice = await Slice.findOne({where: {
|
|
|
+ model: 'user', //TODO configure this
|
|
|
+ modelId: userId,
|
|
|
+ permission: 'user'
|
|
|
+ }})
|
|
|
+
|
|
|
+
|
|
|
+ let [userRoles, userGroups] = [userSlice.roles, userSlice.groups]
|
|
|
+
|
|
|
+ //console.log(userRoles, userGroups)
|
|
|
|
|
|
+ let mapMethodToPermission = {
|
|
|
+ read: ["count", "findAll", "findAndCountAll", "findByPk", "findOne", "max", "min", "sum"],
|
|
|
+ write: ["create", "destroy","findCreateFind","findOrCreate","update","upsert" ]
|
|
|
+ }
|
|
|
+
|
|
|
+ //sequelize.addHook('beforeCreate', (...params) => console.log(params))
|
|
|
+ let modelProxy = new Proxy(model, {
|
|
|
+ get(model, method){
|
|
|
+ let found = false
|
|
|
+ for (var permission in mapMethodToPermission) {
|
|
|
+ if (mapMethodToPermission[permission].includes(method)){
|
|
|
+ found = true
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!found){
|
|
|
+ console.log(`not found ${method}`)
|
|
|
+ return model[method]
|
|
|
+ }
|
|
|
+ let checker = async slice => {
|
|
|
+ let intersect = (await slice.allRoles).filter(role => userRoles.includes(role))
|
|
|
+ return (intersect.length || (await slice.allUserIds).includes(userId + ''))
|
|
|
+ }
|
|
|
+ let wrappers = {
|
|
|
+ async read(...params){
|
|
|
+ console.log('read wrapper')
|
|
|
+ let result = await model[method](...params)
|
|
|
+ if (result instanceof Array){
|
|
|
+ let ids = result.map(instance => instance.id)
|
|
|
+ let slices = await Slice.findAll({where: {
|
|
|
+ model: model.getTableName(),
|
|
|
+ modelId: {[Op.in]: ids},
|
|
|
+ permission,
|
|
|
+ }})
|
|
|
+ let filteredResult = []
|
|
|
+ for (let slice of slices){
|
|
|
+ let instance = result.filter(instance => instance.id === slice.modelId)[0]
|
|
|
+ //role check
|
|
|
+ if (await checker(slice)) {
|
|
|
+ filteredResult.push(instance)
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return filteredResult
|
|
|
+ }
|
|
|
+ if ('id' in result){ //one record
|
|
|
+ let slice = await Slice.findOne({where: {
|
|
|
+ model: model.getTableName(),
|
|
|
+ modelId: result.id,
|
|
|
+ permission,
|
|
|
+ }})
|
|
|
+ return (await checker(slice)) ? result : null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return wrappers[permission]
|
|
|
+ },
|
|
|
+ })
|
|
|
+
|
|
|
+ return modelProxy
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ let SlicedContent = await sliced(Content)(3)
|
|
|
+
|
|
|
+ let allContent = await SlicedContent.findByPk(3)
|
|
|
+ console.log(allContent)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
let delay = ms => new Promise(r => setTimeout(r, ms))
|
|
|
})()
|