首页 文章

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

提问于
浏览
0

我目前的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 })
}

但是,我想为此分支添加更多安全性,以便用户无法更新前端的代码以通过写入操作修改其中一些条目(Read is OK) . 我想让用户能够根据isAdmin标志修改这些条目例如,

  • companyId(读:auth!= null,写:isAdmin == true)

  • companyName(读取:auth!= null,写:isAdmin == true)

  • dailySubmissionLimit(读取:auth!= null,写:isAdmin == true)

  • defaultApproverEmail(读取:auth!= null,写:isAdmin == true)

  • email(读取:auth!= null,写:isAdmin == true)

  • firstName(读取:auth!= null,写:isAdmin == true)

  • id(读:auth!= null,写:isAdmin == true)

  • isAccountActive(读取:auth!= null,写:isAdmin == true)

  • isAdmin(读取:auth!= null,写:false)

  • isPasswordOutdated(读取: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)

因为所有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次而不是一次 .

我能想到的另一种方法是通过将数据分为三个分支“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 回答

  • 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节点

相关问题