gpt4 book ai didi

javascript - 在 mongoDB 中创建一个 firebase 样式的权限层次结构

转载 作者:行者123 更新时间:2023-11-30 14:13:03 25 4
gpt4 key购买 nike

MongoDB 的新手,并使用 NodeJS 的 mongodb package ,我正在尝试根据用户的权限级别检索和更新项目,这些项目也存储在一个集合中。

我了解如何获取所有项目:

 const collection = db.collection('events');
// Find some documents
collection.find({}).toArray(function(err, docs) {
assert.equal(err, null);
console.log("Found the following records");
console.log(docs)
callback(docs);
});

但我想知道是否给定以下数据结构:

{
events: {
1: {
id: 1,
name: "first event",
},
2: {
id: 2,
name: "2nd event",
},
3: {
id: 3,
name: "3rd event",
},
},
permissions: {
events: {
1: {
user1: "read",
user2: "write",
},
2: {
user2: "write",
},
3: {
user1: "readwrite",
user2: "write",
},
},
},
}

如果您以 User1 身份登录,上述获取代码是否可以根据指定的权限仅获取 user1 具有读取权限的相关事件?

对于更新、删除和插入等 CRUDS,我可以运行单独的查询并查看用户是否具有所需的访问权限。但是,get 查询很常见,恕我直言应该很简单,所以我想知道如何优雅地完成这种过滤?

最佳答案

首先,我会简化您的数据模型,因为有一种东西很可能会在以后的道路上咬住您。您不应像在事件文档中那样使用值作为键。显然,这些是数组,并且数组元素已经具有可以引用的 id。

此外,您的数据模型(以及随后我派生的模型)仅适用于几千个事件,因为有一个 16MB limit on documents。 .为了缓解这种情况,我将向您展示一个更新的数据模型以及如何处理它。

一个事​​件文档

数据模型

这是我更新的数据模型。我们基本上摆脱了冒充键的不必要的值。

{
"events": [{
"id": 1,
"name": "first event",
},
{
"id": 2,
"name": "2nd event",
},
{
"id": 3,
"name": "3rd event",
}
],
"permissions": [{
"event": 1,
"perms": [{
"user": "user1",
"permission": "read",
},
{
"user": "user2",
"permission": "write"
}
]
},
{
"event": 2,
"perms": [{
"user": "user2",
"permission": "write"
}]
},
{
"event": 3,
"perms": [{
"user": "user1",
"permission": "readwrite"
},
{
"user": "user2",
"permission": "write"
},
]
}
],
}

您仍然可以通过 db.events.find({"events.id":1},{"events.$":1}) 搜索特定事件。这当然适用于事件的每个其他属性。

权限检查

用户是否有权对特定文档执行特定操作的基本问题可以改写为

Get me all documents with the properties I am interested in AND for which user Y has the permission to do Z.

这转化为一个相当简单的查询:

db.events.find({
// The event we want...
"events.id": 1,
// ...shall be returned provided the following conditions are met
"permissions": {
$elemMatch: {
// The permissions for event with id 1...
"event": 1,
"perms": {
$elemMatch: {
// ...allow the user in question...
"user": "user1",
// ... to read said event.
"permission": "read"
}
}
}
}
}, {
// Subsequently, we return all matching events in all documents...
"events.$": 1
})

我们在这里使用的是查询条件被评估为逻辑AND。如果用户没有我们请求的权限(在本例中为“读取”),则不会返回任何文档。

每个事件一个文档

数据模型

但是,如前所述,MongoDB 文档有 16MB 的大小限制。因此,如果您有很多事件,或者甚至当您不确定可能有多少事件时,我们应该从不同(甚至更简单)的 Angular 来解决问题:每个事件一个文档。数据模型变得非常简单:

// db.events.insertMany([
{
"_id": 1,
"name": "first event",
"permissions":[
{
"user":"user1",
"permission": "read"
},
{
"user":"user2",
"permission":"write"
}
]
},
{
"_id":2,
"name": "2nd event",
"permissions":[
{
"user": "user2",
"permission": "write"
}
]
},
{
"_id":3,
"name": "3rd event",
"permissions":[
{
"user": "user1",
"permission": "readwrite"
},
{
"user": "user2",
"permission": "write"
},
]
}
// ])

权限检查

现在,假设我们要检查用户 1 是否真的可以读取(包括读写)事件 3,如果可以,则返回它。变得比以前更简单:

db.events.find({
// The event we want...
"_id": 3,
// ...in case...
"permissions": {
$elemMatch: {
// ... user1...
"user": "user1",
// ..has either the permission...
$or: [{
// ...to read or...
"permission": "read"
}, {
// ... to readwrite.
"permission": "readwrite"
}]
}
}
}, {
// Either way, do not return the permissions.
permissions: 0
})

结论

无论您将选择两者中的哪种数据模型,您都可以将上述查询用作query part of your update statements。 :

db.events.update(<queryFromAbove>,{[...]})

不用说,我强烈建议使用“每个事件一个文档”的方法。

但是,您需要记住两件事。

如果出现问题,您需要进行额外的查询以找出问题所在。该事件可能完全不存在,或者用户可能没有执行查询/更新所需的权限。但是,由于这应该是异常(exception)情况,所以我个人可以接受。

要记住的另一件事是,您需要确保用户永远无法更改权限数组。出于相当明显的原因。

关于javascript - 在 mongoDB 中创建一个 firebase 样式的权限层次结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54055290/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com