parse-server icon indicating copy to clipboard operation
parse-server copied to clipboard

Parse Roles nested hierarchy either not working, not possible or misleading docs

Open REPTILEHAUS opened this issue 3 years ago • 2 comments
trafficstars

Issue Description

I have a complex role based design suitable for a SaaS using latest parse SDK/Server

Multiple organisation's (parent role) which have sub roles (admin, editor, viewer), the sub roles should have permissions only to interact and operate within the context of the organisation. The code which I use to create these base roles is as follows but also maybe i am doing this wrong, lets add in Apple as an organisation, so Microsoft, Apple, admin, editor and viewer are all created in a for loop calling the below function (later I assign each of these roles to be sub roles, correct ?).

        try {
            const { roleName } = request.params
    
            let role_name = slugify(roleName) 

            let roleExists: any = await new Parse.Query(Parse.Role).equalTo("name", roleName).first(masterKey)  
            if(!roleExists) {
                let perms = new Parse.Role(role_name, new Parse.ACL());
                let result = await perms.save(null, masterKey)                 
                resolve(result)
            }   
            resolve(true)
            // reject(`role ${roleName} already exists`)
        } catch (error) {
            console.log(error)
            reject(error)
        }   

So now I have "Microsoft" and "Apple" roles - these are the parent level role to which all other i.e admin, editor, viewer shall be sub roles. I have the logic in place to add sub roles to each Parent role:

        try {    
            let child: any = await new Parse.Query(Parse.Role).equalTo("name", childRole).first(masterKey)  
            let parent: any = await new Parse.Query(Parse.Role).equalTo("name", parentRole).first(masterKey)              
    
            let query = new Parse.Query(Parse.Role);
                query.equalTo("name", parentRole);
            let role =  <any>await query.first(masterKey)
                role.relation("roles").add(child);        
            await role.save(null, masterKey);        
    
            let nestedRoles = await parent.getRoles().query().find(masterKey)
                console.log("nestedRoles "+JSON.stringify(nestedRoles))        
            resolve(nestedRoles)            
    
        } catch (error) {
            console.log(error)
            reject(error)
        }

So now our Role structure is like this:

Microsoft => admin => editor => viewer
Apple => admin => editor => viewer

So now I call each parent role, I query for its direct descendant sub roles and I add myself as a user for each of these roles

    return new Promise( async (resolve, reject) => { 
     
        try {
            const user = request.user
            const { parentRoleName } = request.params
            
            let parentRole: any = await new Parse.Query(Parse.Role).equalTo("name", parentRoleName).first(masterKey)    
            

            let nestedRoles = await parentRole.getRoles().query().find(masterKey)

            if(nestedRoles.length) {
                nestedRoles.forEach( async (role: any) => {
                    let childRole: any = await new Parse.Query(Parse.Role).equalTo("name", role.get('name') ).first(masterKey)                       
                        childRole.getUsers().add(user)
                    let saveit = await childRole.save(null, masterKey)
                    console.log(saveit)
                });
                resolve( JSON.parse(JSON.stringify(nestedRoles)))                
            } else {
                reject(`${parentRoleName} has no sub/child roles under it.`)
            }
           
        } catch (error) {
            console.log(error)
            reject(error)
        }          
    })

In the parse dashboard, I see all roles, each of the above on the same hierarcy so:

Apple
editor
viewer
admin
Microsoft

if I click on Apple/Microsoft then inside each of these, on the role relations I see as expected editor, viewer and admin.

however if i go back outside to the main 1st level list and click on admin, editor, viewer I see my user object

So if i add editor, viewer, admin to any user then have this feature across both Apple and Microsoft, I get the logic of adding users to roles, adding roles to other roles but how do you lock it down in such a way that each user is assigned to an organization and they have roles within just that organization.

right now my org acl is looking like:

role:admin {
    w: true
    r: true    
}

role:super {
    w: true
    r: true    
}

role:microsoft {
    w: true
    r: true    
}

but i would have thought that because using nested Roles it would first be:

role:super {
    w: true
    r: true
    role:microsoft {
        w: true
        r: true  
        role:admin {
            w: true
            r: true                 
        }            
    }      
}

Role based docs are really lacking, id be happy to try flesh this out because parse security out of the box is not so good, its vital that people understand Roles, ACL proper use of masterkey etc

Steps to reproduce

code provided above

Actual Outcome

as mentioned above

Expected Outcome

as mentioned above

Server

  • Parse Server version: latest
  • Operating system: linux
  • Local or remote host (AWS, Azure, Google Cloud, Heroku, Digital Ocean, etc): local and remove on aws

Database

  • System (MongoDB or Postgres): mongo
  • Database version: 4
  • Local or remote host (MongoDB Atlas, mLab, AWS, Azure, Google Cloud, etc): MongoDB Atlas

Client

  • SDK (iOS, Android, JavaScript, PHP, Unity, etc): JavaScript
  • SDK version: latest

Logs

none to provide

REPTILEHAUS avatar Jul 28 '22 14:07 REPTILEHAUS

Thanks for opening this issue!

  • ❌ Please edit your post and use the provided template when creating a new issue. This helps everyone to understand your post better and asks for essential information to quicker review the issue.

This seems to be either a code support question or an issue for the docs repository. If you want to take on improving role based docs, maybe as you're researching how things work to articulate them you'll be able to answer your own question.

mtrezza avatar Jul 28 '22 16:07 mtrezza