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

时间:2017-03-13 08:01:25

标签: firebase firebase-realtime-database firebase-security

我目前的firebase结构如下所示

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标志修改这些条目 例如,

  1. companyId(读:auth!= null,写:isAdmin == true)
  2. companyName(读取:auth!= null,写:isAdmin == true)
  3. dailySubmissionLimit(读取:auth!= null,写:isAdmin == true)
  4. defaultApproverEmail(读取:auth!= null,写:isAdmin == true)
  5. 电子邮件(读:auth!= null,写:isAdmin == true)
  6. firstName(读取:auth!= null,写:isAdmin == true)
  7. id(读:auth!= null,写:isAdmin == true)
  8. isAccountActive(读取:auth!= null,写:isAdmin == true)
  9. isAdmin(读:auth!= null,写:false)
  10. isPasswordOutdated(读取:auth!= null,写:auth!= null)
  11. lastLoggedIn(读取:auth!= null,写:auth!= null)
  12. lastName(读取:auth!= null,写:isAdmin == true)
  13. passwordChangeDate_epoch(读取:auth!= null,写:auth!= null)
  14. registerationDate(读取:auth!= null,写:isAdmin == true)
  15. 团队(读:auth!= null,写:isAdmin == true)
  16. userDefaults(读取:auth!= null,写:auth!= null)
  17. 因为所有read = auth!= null ..最初,我想我能够读取所有节点,我可以为每个节点设置安全个体规则,如下所示

    {
        "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次而不是一次调用数据库。

    我能想到的另一种方法是通过将数据分类为三个分支来构建数据abit" 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
                            },
                            ...
                        }
                    }
                }
            }
        }
    }
    

    我缺少一个更好的解决方案吗?

1 个答案:

答案 0 :(得分:1)

您是否尝试过此安全规则语法? :

 {
    "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节点的情况下检索用户列表