具有多个子节点的节点的Firebase安全规则

具有多个子节点的节点的Firebase安全规则,firebase,firebase-realtime-database,firebase-security,Firebase,Firebase Realtime Database,Firebase Security,我当前的firebase结构如下所示 最初,我的安全看起来像 { "rules": { "users": { "$companyId": { "$userId": { ".read": "auth != null", ".write": "auth != null", } }

我当前的firebase结构如下所示

最初,我的安全看起来像

{
    "rules": {
        "users": {
            "$companyId": {
                "$userId": {
                    ".read": "auth != null",
                    ".write": "auth != null",
                }
            }
        }
    }
}
这一切都很好,因为我可以通过

// get user information from database
getUserInformation(companyId: string, uid: string) {
    let path = '/users/' + companyId + '/' + uid;
    return this.af.database.object(path, { preserveSnapshot: true })
}
但是,我想为这个分支添加更多的安全性,这样用户就不能通过写操作(读取是可以的)更新前端的代码来修改其中的一些条目。 我希望用户能够根据isAdmin标志修改这些条目 比如说,

  • companyId(读:auth!=null,写:isAdmin==true)
  • 公司名称(读:auth!=null,写:isAdmin==true)
  • dailySubmissionLimit(读:auth!=null,写:isAdmin==true)
  • defaultApproverEmail(读:auth!=null,写:isAdmin==true)
  • 电子邮件(读:auth!=null,写:isAdmin==true)
  • firstName(读:auth!=null,写:isAdmin==true)
  • id(读:auth!=null,写:isAdmin==true)
  • isAccountActive(读:auth!=null,写:isAdmin==true)
  • isAdmin(读:auth!=null,写:false)
  • ISPasswordOutlated(读:auth!=null,写:auth!=null)
  • lastLoggedIn(读:auth!=null,写:auth!=null)
  • lastName(读:auth!=null,写:isAdmin==true)
  • passwordChangeDate_epoch(读:auth!=null,写:auth!=null)
  • registerationDate(读:auth!=null,写:isAdmin==true)
  • 团队(读:auth!=null,写:isAdmin==true)
  • userDefaults(读:auth!=null,写:auth!=null)
  • 因为所有读取=auth!=无效的起初,我认为因为我能够读取所有节点,所以我可以为每个节点设置单独的安全规则,如下所示

    {
        "rules": {
            "users": {
                "$companyId": {
                    "$userId": {
                        "companyId": {
                            ".read": "auth != null",
                            ".write": "(auth != null) && (root.child('users').child($companyId).child(auth.uid).child('isAdmin').val() == true)"
                        },
                        "isAdmin": {
                            ".read": "auth != null",
                            ".write": "false"
                        },
                        "lastLoggedIn": {
                            ".read": "auth != null",
                            ".write": "auth != null"
                        },
                        ...
                    }
                }
            }
        }
    }
    
    但是,当我尝试getUserInformation()时,此操作失败,因为我正在查询'/users/'+companyId+'/'+uid',并且该特定分支的安全规则未知

    我猜作为替代,我可以查询每个节点,而不是“/users/'+companyId+”/'+uid+'/companyId”,并使用forkJoin或某种排序组合数据。 这将是非常低效的,因为我现在调用数据库是第n次而不是一次

    我能想到的另一种方法是通过将数据分为三个分支“userCanModify”、“adminCanModify”、“noOnCanModify”,以不同的方式构造数据。然后根据需要为这三个节点设置安全规则。 但这对我来说更像是一种黑客行为,因为我必须将数据重新构造为一种非常奇怪的格式。此外,我还需要提出三个请求才能全面了解用户的详细信息

    {
        "rules": {
            "users": {
                "$companyId": {
                    "$userId": {
                        "userCanModify": {
                            "lastLoggedIn": {
                                ".read": "auth != null",
                                ".write": "auth != null"
                            },
                            ...
                        }, 
                        "adminCanModify": {
                            "companyId": {
                                ".read": "auth != null",
                                ".write": "(auth != null) && (root.child('users').child($companyId).child(auth.uid).child('isAdmin').val() == true)"
                            }, 
                            "companyName": {
                                ".read": "auth != null",
                                ".write": "(auth != null) && (root.child('users').child($companyId).child(auth.uid).child('isAdmin').val() == true)"
                            },
                            ...
                        }, 
                        "noOneCanModify": {
                            "isAdmin": {
                                "read": true, 
                                "write": false
                            },
                            ...
                        }
                    }
                }
            }
        }
    }
    

    有没有更好的解决方案是我所缺少的?

    您尝试过这种安全规则语法吗?:

     {
        "rules": {
            "users": {
                "$companyId": {
                    "$userId": {
                        "$companyIdbis": {
                            ".read": "auth != null",
                            ".write": "root.child('users').child($companyId).child($userId) === auth.uid &&  data.child('isAdmin').exist()"
                        },
    
                        "isAdmin": {
                            ".read": "auth != null",
                            ".write": "false"
                        },
                        "lastLoggedIn": {
                            ".read": "auth != null",
                            ".write": "auth != null"
                        },
                        ...
                    }
                }
            }
        }
    }
    
    (如果我没有错:

    data.child('isAdmin').exist()"
    
    应等同于:

      `root.child('users').child($companyId).child($userId).child($companyIdbis).child('isAdmin').exist()"`
    
    [编辑]: 但我建议您采用“扁平结构”,将用户和公司喜欢的节点分开:

    Users
        userId
            compagnyId : true
            etc ...
    Compagnies
        compagnyId
            etc ...
    

    这允许您检索用户列表,而无需浏览所有compagnies节点

    ,这意味着我需要向每个节点发出多个请求,以获取用户的完整信息