英文:
Safest and less expensive way to delete comments in FireStore
问题
我正在使用FireStore来开发我的Flutter应用程序。用户可以在某些文章下发表评论,他们还可以回复其他评论。评论具有以下结构:
其中ancestorsId
是一个包含所有父评论ID的列表。
评论可以由发布者或管理员删除。
当删除一条评论时,所有子评论也应该被删除。
如何以最低的成本和安全性来实现这一点?到目前为止,我考虑了以下几种方法:
情况1:使用Go服务器和自定义声明
我可以将用户角色设置为自定义声明。然后,当用户点击删除评论按钮时,它会向服务器发送一个带有评论ID和用户令牌ID的请求。我可以通过令牌ID检查用户是否是管理员。如果不是管理员,则服务器会请求评论数据并检查评论的userId
和令牌用户ID是否匹配。如果这两个条件中的任何一个为真,我可以通过在comments
集合上进行where
请求来获取所有评论的子评论,并使用批处理删除所有相关评论。
问题:
-
自定义声明使用的令牌的有效期为1小时。如果一个疯狂的管理员开始删除所有内容,这可能会造成麻烦,因为他的管理员令牌可以有效期长达1小时。但如果我使用一个服务器,我认为我可以处理这个问题。
-
在删除评论之前,我需要获取评论。这涉及两个操作,因此实际上删除评论操作的价格是删除评论操作价格的两倍。
情况2:使用FireStore规则
我可以仅使用客户端,并使用FireStore规则而不是使用服务器。这意味着我不能再使用自定义声明,而是必须将用户角色存储在users
集合中的一个字段中。我可以使用如下的删除规则:
match /comments/{comment}{
allow delete: if request.auth != null && (request.auth.uid == request.resource.data.userId || isAdmin(request));
}
其中isAdmin
是一个检查用户是否为管理员的函数。
问题:
-
isAdmin
将需要从另一个文档中读取数据,因此会产生费用。 -
这种解决方案不会删除子评论。而且规则不允许用户请求删除另一个用户的评论,除非他是管理员。
有什么解决方案可以以低成本解决我的问题,同时不牺牲安全性?
英文:
I am using FireStore for my Flutter application. Users can post comments under some articles. They can also reply to other comments. Comments have the following structure
where ancestorsId
is a list containing all the parent comments id.
Comments can be deleted by the poster or an admin.
When a comment is deleted, all the children comments should be deleted as well.
How can I do that with safety and at the lowest cost ? I have thought to the following so far:
Case 1: Using a Go server and Custom Claims
I can set user role as a custom claim. Then, when a user clicks on delete comment button, it sends a request to the server with the comment ID and the user Token ID. I can check if the user is admin with the token ID. If it is not the case, the server asks the comment data and check if comment userId
and token user Id match. If one of those two conditions is true, I can get all comment children with a where
request on comments
collection, and delete all involved comments with a batch.
Problems:
-
Custom claims use token, that live for 1 hour. It could create troubles if a crazy admin starts deleting everything, because his admin token can be valid for up to 1 hour. But if I use a server, I think I can manage this.
-
I need to get comments before deleting them. It involves two operations and then the price is actually twice the price of deleting comments operations.
Case 2: Using FireStore rules
I could stick with a client only, and use FireStore rules instead of using a server. It means that I could no longer use custom claims, and I would have to store users role in a field in my users
collection. I could use a delete rule like:
match /comments/{comment}{
allow delete: if request.auth != null && (request.auth.uid == request.resource.data.userId || isAdmin(request));
}
where isAdmin
is a function that checks if the user is an admin.
Problems:
-
isAdmin
will need to read a data from another document and thus cost money -
This solution doesn't delete children comments. And the rule doesn't allow a user to request another user's comment deletion, unless he is admin.
What could be a solution to solve my issue at low cost without putting safety aside ?
答案1
得分: 2
我觉得你实际上只有一个可行的解决方案,因为第二种方法会在数据库中留下孤立的文档。
但是,如果你认为第二种方法对你的应用程序有效,那么你将以读取然后删除一些文档的代价来换取将它们留在数据库中的代价。虽然将文档保留在数据库中的成本很低,但你每个月都要支付这个成本。由于孤立文档的数量将不断增长,它们的存储成本也将不断增加。因此,尽管现在删除它们可能看起来更昂贵,但这只是一次性的成本。
如果你担心运行云函数的成本,要记住云函数有一个相当不错的免费套餐。即使该套餐不足以在生产环境中运行你的代码,至少它足以让你对成本有所了解。
英文:
It seems to me that you really only have one solution that works, as the second approach leaves orphaned documents in the database.
But if you do consider the second approach valid for your app, you're trading the cost of reading-and-then-deleting some documents for the cost of leaving them in the database. While the cost of keeping a document in the database is low, you'll end up paying it every month. Since the number of orphaned documents will keep growing, the storage cost for them will keep growing too. So while deleting them now may seem more expensive, it's just a one time cost.
If you're worried about the cost of running Cloud Functions, keep in mind there's a pretty decent free tier for those. Even if that tier is not enough to run your code in production, it should at least be enough to give you a feeling for what the cost is gonna be.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论