Prechádzať zdrojové kódy

slicedSavable (permissions) pre alpha of pre proto :-D

Ivan Asmer 5 rokov pred
rodič
commit
9807a91669
2 zmenil súbory, kde vykonal 95 pridanie a 9 odobranie
  1. 15 6
      index.js
  2. 80 3
      mm.js

+ 15 - 6
index.js

@@ -7,9 +7,11 @@ const delay       = ms => new Promise(r => setTimeout(r.bind(ms), ms))
     const mongoClient = new MongoClient("mongodb://localhost:27017/", { useNewUrlParser: true });
     const client      = await mongoClient.connect()
     const db          = client.db('mm')
-    const Savable     = mm(db)
+    const Savable     = mm(db).Savable
+    const SlicedSavable = mm(db).sliceSavable([ObjectID("5c9571219be797377361c65a"), 'user', 'admin'])
+    //const SlicedSavable = mm(db).sliceSavable([])
 
-    class Notebook extends Savable{
+    class Notebook extends SlicedSavable{
         static get relations(){
             return {
                 owner: "notebook"
@@ -17,7 +19,7 @@ const delay       = ms => new Promise(r => setTimeout(r.bind(ms), ms))
         }
     }
 
-    class User extends Savable{
+    class User extends SlicedSavable{
         static get relations(){
             return {
                 children: "parent",
@@ -76,7 +78,14 @@ const delay       = ms => new Promise(r => setTimeout(r.bind(ms), ms))
         let now   = start
 
         let prevI = 0
-        let person = await Savable.m.User.findOne()
+        let person
+        for (let uP of Savable.m.User.find({},null,{sort:['_id', -1], limit: [1]})){
+            person = await uP
+            console.log(person)
+        }
+
+        //let person = [...Savable.m.User.find({},null,{sort:['_id', 1], limit: [1]})][0]
+        //console.log('order-huyorder', person)
         let prevPerson;
         for (var i=0;i<limit;i++){
             prevPerson = person || prevPerson
@@ -87,8 +96,8 @@ const delay       = ms => new Promise(r => setTimeout(r.bind(ms), ms))
                 person = await Savable.m.User.findOne()
             }
 
-            console.log(prevPerson._id)
-            await prevPerson.delete()
+            //console.log(prevPerson && prevPerson._id)
+            //await prevPerson.delete()
             //if (persons.includes(person)){
                 //console.log('WAS HERE',person._id, person.name, person.surname, person.createdAt)
             //}

+ 80 - 3
mm.js

@@ -4,7 +4,6 @@ const asynchronize = require('./asynchronize').asynchronize
 let i=0;
 
 module.exports = db => {
-
     class Savable {
         constructor(obj, ref, empty=false){
             this._id    = null
@@ -261,8 +260,15 @@ module.exports = db => {
                     }
 
                     return  obj[_class] = {
-                        * find(query, projection){
+                        * find(query, projection, cursorCalls){
                             let cursor = db.collection(_class).find(query, projection)
+                            for (let [method, params] of Object.entries(cursorCalls)){
+                                if (typeof cursor[method] !== "function"){
+                                    throw new SyntaxError(`Wrong cursor method ${method}`)
+                                }
+
+                                cursor = cursor[method](...params)
+                            }
                             let cursorGen = asynchronize({s: cursor.stream(), 
                                                           chunkEventName: 'data', 
                                                           endEventName: 'close'})
@@ -302,5 +308,76 @@ module.exports = db => {
 
     Savable.classes                                  = {Savable}
 
-    return Savable
+    /**
+     * sliceSavable - slice (limit) Savables for some permission
+     * Array userACL - array of objectIDs, words or savable refs - current user, group objectid, or `tags` or `role` (ACL)
+     */
+
+    function sliceSavable(userACL){
+        userACL = userACL.map(tag => tag.toString())
+        class SlicedSavable extends Savable {
+            constructor(...params){
+                super  (...params)
+
+                if (!this._empty){
+                    this.___permissionsPrepare()
+                }
+                else {
+                    this.___owner = userACL[0] instanceof ObjectID ? userACL : ObjectID(userACL[0])
+                }
+            }
+
+            ___permissionsPrepare(){
+                if (this._empty)          return
+                if (!this.___permissions) this.___permissions = {}
+
+                for (let [perm, acl] of Object.entries(this.__proto__.constructor.defaultPermissions)){
+                    if (!this.___permissions[perm]){
+                        this.___permissions[perm] = [...acl]
+                    }
+                }
+            }
+
+            ___permissionCan(permission){
+                const acl = (this.___permissions && 
+                                this.___permissions[permission] || 
+                                    this.__proto__.constructor.defaultPermissions[permission]).map(tag => tag.toString())
+                if (acl.includes('owner') && this.___owner && userACL.includes(this.___owner.toString())){
+                    return true
+                }
+                for (let uTag of userACL){
+                    if (acl.includes(uTag)){
+                        return true
+                    }
+                }
+                return false
+            }
+
+            populate(...params){ //place to check read permission
+                if (!this.___permissionCan('read')){
+                    throw new ReferenceError(`No Access To Entity ${this._id} of class ${this._class}`)
+                }
+                super.populate(...params)
+            }
+
+            static get defaultPermissions(){
+                return {
+                    //savable refs, objectid's, words like 'tags' or 'roles'
+                    read: ['owner', 'user'],
+                    write: ['owner', 'admin'],
+                    create: ['user'],
+                    delete: ['admin'],
+
+                    /*permission
+                     * TODO: permissions for read and write permissions
+                     *
+                     */
+                }
+            }
+        }
+
+        return SlicedSavable
+    }
+
+    return {Savable, sliceSavable}
 }