首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >限制用户可以创建的产品文档数量

限制用户可以创建的产品文档数量
EN

Stack Overflow用户
提问于 2020-12-05 14:59:09
回答 2查看 530关注 0票数 2

我有一个角形网页应用,作为无服务器后端技术的Firebase。目前网络应用程序的目的是让注册用户为提供的产品创建文档。虽然业务用户可以创建无限的产品文档,但是免费用户应该只能创建一个产品文档。

集合:

{id: string, isBusiness: boolean, name: string, email: string, productIds: string[]}

  • products - {id: string, title: string, description: string, userId: string}

-

  • 用户

每当用户创建新产品-doc时

代码语言:javascript
复制
  public createProduct(id: string, product: Product) {
    return this.afStore.collection('products').doc(id).set(product, { merge: true });
  }

我使用触发器onCreate运行一个云函数,将创建的product的id添加到相应用户-doc的productIds字段中。这允许我检查前端if(!user.isBusiness && productIds.length > 1),以限制为免费用户帐户创建多个产品文档。

然而,我最近做了一次笔试,不小心发现,如果您在多个浏览器选项卡上打开网站,同时在每个选项卡上运行createProduct()功能,所有这些选项卡都将执行,允许非业务用户拥有多个产品文档。

有人处理过类似的情况吗?我不知道是否有一种方法可以避免这种情况出现在Firestore安全规则中,或者在活动事务完成之前还有什么需要等待的地方。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-12-16 18:09:08

当前的实现受到了竞争条件的影响:“非业务”用户可能会创建任意数量的产品,直到第一个productId被写入用户文档。

在我看来,解决这一问题最直接的方法是用productId预先填充非商业用户,并限制他们分配新用户的能力。

  • 在创建非业务用户时,您可以为他们创建/保留一个唯一的productId,这些用户可以使用,也可以不使用。将其存储在用户文档中。
  • 当非企业用户创建产品时,他们只能将数据写入到该productId中。虽然不需要修复所描述的用例,但取决于您的安全需求,您可能希望通过安全规则或云函数来执行此操作。
  • 无论有多少并发选项卡试图创建产品,它们总是写入同一个productId.

代码语言:javascript
复制
public createProduct(id: string, product: Product, user: User) {
    if (user.isBusiness) {
      return this.afStore.collection('products').doc(id).set(product, { merge: true });
    } else {
      return this.afStore.collection('products').doc(user.reservedProductId).set(product, { merge: true });
    }    
}

警告:与任何前端代码一样,这不会阻止恶意参与者按照他们的喜好操作它。如果这种行为是出于安全考虑,则需要限制非业务用户对产品集合的写访问。考虑实现适当的安全规则/云功能。你只能信任后端。

票数 2
EN

Stack Overflow用户

发布于 2020-12-05 15:52:10

在用户中创建一个productCounter节点。然后将您的规则与以下内容合并:

代码语言:javascript
复制
    {
      "rules": {
        "cascade_your_nodes": {
          "products": {
            "$productId" : {
              .".write": "root.child('YOUR_PATHS').child('users').child(auth.uid).child('productCounter').val() < 1 || data.exists() || root.child('YOUR_PATHS').child('users').child(auth.uid).child('isBusiness').val()"
            }
          }
        }
      }
    }

推理:如果不与任何现有规则冲突,则只有在以下情况下才允许写入任何productId

请求

  1. uid节点的productCounter小于1

root.child('YOUR_PATHS').child('users').child(auth.uid).child('productCounter').val() < 1

如果该节点中存在任何数据,则为

  1. (允许对节点进行更新)

data.exists()

如果请求

  1. 节点有isBusinesstrue

root.child('YOUR_PATHS').child('users').child(auth.uid).child('isBusiness').val()

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65158299

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档