- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
描述
我在使用Firestore处理删除时遇到问题。简而言之,我为这样的帖子创建了安全规则:
首先,规则中有一些功能:
服务cloud.firestore {
function userRoles() {
return ['admin', 'customer', 'reader'];
}
function userGenders() {
return ['mal', 'female', 'other'];
}
function postVisibilities() {
return ['public', 'private', 'protected'];
}
function postType() {
return ['music', 'motion_design', 'graphic_art'];
}
function isPayment(paymentDoc) {
return paymentDoc != null
&& paymentDoc.date is timestamp
&& paymentDoc.price is number
&& paymentDoc.price is number
&& paymentDoc.price > 0;
}
function isBill(billDoc) {
return billDoc.sellerId is string
&& billDoc.buyerId is string
&& billDoc.postIds != null
&& billDoc.date is timestamp
&& billDoc.paymentDoc != null
&& isPayment(billDoc.paymentDoc);
}
function isAccount(accountDoc) {
return accountDoc.isRegistered is bool
&& accountDoc.addressId is string
&& accountDoc.contactId is string
&& accountDoc.email is string
&& accountDoc.username is string
&& accountDoc.gender is string
&& accountDoc.gender in userGenders()
&& accountDoc.role is string
&& accountDoc.role in userRoles();
}
function isPost(postDoc) {
return postDoc.createdAt is timestamp
&& postDoc.updatedAt is timestamp
&& postDoc.title is string
&& postDoc.text is string
&& postDoc.image is string
&& postDoc.authorId is string
&& postDoc.visibility is string
&& postDoc.visibility in postVisibilities();
}
function isVote(voteDoc) {
return voteDoc.authorId is string
&& voteDoc.reaction is string
&& voteDoc.reaction in ['up', 'down'];
}
function isComment(commentDoc) {
return commentDoc.authorId is string
&& commentDoc.message is string;
}
function isSingle(doc) {
return doc.size() == 1;
}
match /databases/{database}/documents {
function userExists(userId) {
return userId != null && exists(/databases/$(database)/documents/accounts/$(userId));
}
function getUserRole(userId) {
return get(/databases/$(database)/documents/accounts/$(userId)).data.roles;
}
function hatUserRole(userId, role) {
return getRoleForUser(userId) in role;
}
match /{document=**} {
allow read: if true;
allow write: if false;
}
match /accounts/{accountId} {
allow create: if isAccount(request.resource.data)
&& (request.auth.uid == accountId || hatUserRole(request.auth.uid, ['admin']));
allow update: if request.auth.uid == accountId || hatUserRole(request.auth.uid, ['admin']);
allow delete: if hatUserRole(request.auth.uid, ['admin']);
match /contacts/{contactId} {
allow write: if isSingle(request.resource.data)
&& request.auth.uid == accountId;
allow read: if userExists(request.auth.uid);
}
match /favorites/{favoriteId} {
allow write: if isSingle(request.resource.data)
&& request.auth.uid == accountId;
allow read: if userExists(request.auth.uid);
}
match /votes/{voteId} {
allow create: if isVote(request.resource.data)
&& userExists(request.auth.uid);
allow update: if userExists(request.auth.uid)
&& isVote(request.resource.data)
&& request.resource.data.authorId == request.auth.uid
allow delete: if userExists(request.auth.uid)
&& (request.auth.uid == accountId
|| hatUserRole(request.auth.uid, ['admin']))
}
}
match /bills/{billId} {
allow create: if isBill(request.resource.data)
&& userExists(request.resource.data.sellerId)
&& userExists(request.resource.data.buyerId)
&& (request.resource.data.buyerId == request.auth.uid
|| request.resource.data.sellerId == request.auth.uid);
allow update, delete: if false;
allow read: if request.resource.data.buyerId == request.aut.uid
|| request.resource.data.sellerId == request.aut.uid;
}
match /posts/{postId} {
function publicPost() {
return get(/databases/$(database)/documents/posts/$(postId)).data.visibility == 'public';
}
function postVisibility() {
return get(/databases/$(database)/documents/posts/$(postId)).data.visibility;
}
function protectedPost() {
return userExists(request.auth.uid)
&& get(/databases/$(database)/documents/posts/$(postId)).data.visibility == 'public';
}
function findPostAuthor(pathToFind) {
return get(/databases/$(database)/documents/posts/$(pathToFind)).data.authorId
}
allow create, update: if isPost(request.resource.data)
&& userExists(request.auth.uid)
&& request.resource.data.authorId == request.auth.uid;
allow read: if request.resource.data.visibility == 'public';
allow delete: if userExists(request.auth.uid)
&& findPostAuthor(request.resource.id) == request.auth.uid;
match /votes/{voteId} {
allow read: if protectedPost(postId)
|| publicPost(postId);
allow create: if isVote(request.resource.data)
&& postVisibility(postId) in ['public', 'protected']
&& userExists(request.auth.uid);
allow update: if isVote(request.resource.data)
&& request.resource.data.authorId == request.auth.uid;
allow delete: if userExists(request.auth.uid)
&& (request.auth.uid == request.resource.data.authorId
|| hatUserRole(request.auth.uid, ['admin']));
}
match /comments/{commentId} {
allow read: if protectedPost(postId) || publicPost(postId);
allow create: if isComment(request.resource.data)
&& postVisibility(postId) in ['public', 'protected']
&& userExists(request.auth.uid);
allow update: if isComment(request.resource.data)
&& request.resource.data.authorId == request.auth.uid;
allow delete: if userExists(request.auth.uid)
&& (request.auth.uid == request.resource.data.authorId
|| hatUserRole(request.auth.uid, ['admin']));
}
}
}
}
id
:
public deletePost(postId: string): Observable<void> {
const postRef = this.db.collection('posts').doc(postId).ref;
return fromPromise(this.db.firestore.runTransaction((transaction => {
return transaction.get(postRef).then(snapshot => {
if (!snapshot.exists) {
this.snackBar.open('Post doesn\'t exist', 'close');
} else {
const auth = snapshot.data().authorId === this._userId;
if (auth) {
transaction.delete(postRef);
} else {
this.snackBar.open('You\' not allowed to do that!');
}
}
});
})));
}
protected removeElement(elementId: string): Observable<any> {
return fromPromise(this.db.collection(this.dbCollection).doc(elementId).delete());
}
ERROR Error: Server responded with status
at new FirestoreError (index.cjs.js:346)
at T.<anonymous> (index.cjs.js:6901)
at Ab (index.js:23)
at T.push../node_modules/@firebase/webchannel-wrapper/dist/index.js.g.dispatchEvent (index.js:21)
at te (index.js:66)
at ve (index.js:69)
at T.push../node_modules/@firebase/webchannel-wrapper/dist/index.js.g.jb (index.js:67)
at T.push../node_modules/@firebase/webchannel-wrapper/dist/index.js.g.Na (index.js:67)
at XMLHttpRequest.wrapFn (zone.js:1188)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:3815)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)
at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:496)
at invokeTask (zone.js:1540)
at XMLHttpRequest.globalZoneAwareCallback (zone.js:1566)
ERROR Error: Missing or insufficient permissions.
at new FirestoreError (index.cjs.js:346)
at index.cjs.js:7088
at W.<anonymous> (index.cjs.js:7033)
at Ab (index.js:23)
at W.push../node_modules/@firebase/webchannel-wrapper/dist/index.js.g.dispatchEvent (index.js:21)
at Re.push../node_modules/@firebase/webchannel-wrapper/dist/index.js.Re.Ca (index.js:98)
at ye.push../node_modules/@firebase/webchannel-wrapper/dist/index.js.g.Oa (index.js:86)
at dd (index.js:42)
at ed (index.js:39)
at ad (index.js:37)
at L.push../node_modules/@firebase/webchannel-wrapper/dist/index.js.g.Sa (index.js:36)
at L.push../node_modules/@firebase/webchannel-wrapper/dist/index.js.g.nb (index.js:35)
at Ab (index.js:23)
at T.push../node_modules/@firebase/webchannel-wrapper/dist/index.js.g.dispatchEvent (index.js:21)
at ve (index.js:68)
at T.push../node_modules/@firebase/webchannel-wrapper/dist/index.js.g.jb (index.js:67)
at T.push../node_modules/@firebase/webchannel-wrapper/dist/index.js.g.Na (index.js:67)
at XMLHttpRequest.wrapFn (zone.js:1188)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:3815)
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)
at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:496)
at invokeTask (zone.js:1540)
at XMLHttpRequest.globalZoneAwareCallback (zone.js:1566)
rules
中,当我写的时候allow delete: if userExists(request.auth.uid) && findPostAuthor(request.resource.data.id) == request.auth.uid;
Id
直接查看文档,所以request.resource.data.id
不得包含任何内容。 transactions
不起作用,可能是因为它的实际工作方式与我们在其他事务功能上看到的方式确实不同。 angularFire2
时,this.db => AngularFirestore,this.dbCollection =>'posts',在任何帖子的结构中,都有一个
autorId
字段,它是一个字符串。
最佳答案
对于delete
,您需要将request.auth.uid
与resource.data.uid
而不是request.resource.data.uid
进行比较。例如:
match /bookmarks/{id} {
allow create: if request.resource.data.uid == request.auth.uid
allow read, delete: if resource.data.uid == request.auth.uid
}
关于angular - Firestore : Delete document and security rules,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52024666/
在 makefile 中,我可以从另一个规则调用一个规则吗? 类似于: rule1: echo "bye" rule2: date rule3: @ec
我想创建一个只匹配外部链接的 CSS 选择器。问题是它似乎不适用于 :not() 中的多个规则。我不能使用多个 not ( example: ":not():not()") 因为那变成了 ||而不是
我正在动态创建 CSS 动画,所以我需要在我的文档中插入一个 CSS 计时函数。如: @-webkit-keyframes slide { from { -webkit-transfo
错误内容: Error: Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js): HookW
我有这样的文件结构: ---- _base-map.scss ---- _child-map-1.scss ---- _child-map-2.scss ---- _child-map-3.scss
我正在利用 engine.Host 类创建自己的规则引擎实例,并通过 JSON 文件加载规则并调用 set_rulesets() 方法。这一切都运行良好。 持久规则:https://pypi.org/
在无服务器(https://www.serverless.com/framework/docs/providers/aws/events/event-bridge),的EventBridge文档中提到
在无服务器(https://www.serverless.com/framework/docs/providers/aws/events/event-bridge),的EventBridge文档中提到
系统要求我使用最常用的网络规则和应用程序规则配置 Azure 防火墙策略规则集合。 我收集了以下详细信息,其中捕获了最常用的网络规则和应用程序规则。但是我不确定我是否遗漏了任何被认为是最常见的规则?
我想做的是在运行时从 ABNF 语法文件创建一个解析器。我已经在 qi::grammar 中实现了所有 ABNF 规则,如下所示: typedef /*qi::rule or struct conta
对于复杂的多边形(即:自相交),选择缠绕填充规则还是奇偶填充规则会影响多边形的填充方式。 但对于非相交多边形,缠绕或奇偶填充规则之间是否存在任何性能差异。我知道这将是特定于实现的,但哪种算法对于非复杂
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 8 个月前
我正在尝试将 TypeScript 编译添加到现有的 Javascript 项目中。 AFAIK 这应该是可能的(甚至很容易),并且您可以通过代码库逐步传播 TS。不幸的是,这不是我所看到的——在添加
尝试将 Firebase 部署到其托管服务时。我还使用 firebase 工具来发布安全规则。我看到此错误消息: $ firebase deploy Security Rules Error - s
我在使用 ANTLR4 解析某些 SQL 类型的字符串时遇到问题。解析后的字符串是: WHERE a <> 17106 AND b BETWEEN c AND d AND e BTW(f, g) 这是
我已经在 Android 中创建了一个模块以在我的主应用程序中使用,并且似乎有两个文件Consumer-rules.pro 和 proguard-rules.pro。 我想了解以下内容 所有模块代码都
我正在尝试在另一个自定义规则中加载自定义规则,这两个规则均由 Parasoft 规则向导创建。 以下代码是作为方法放在调用规则中的python片段: def somePythonMethod(node
像许多其他问题一样,我正在尝试使用 Boost.Spirit.Qi 将简单语法解析为结构树。 我会尽量提炼我正在尝试做的事情,以尽可能最简单的情况。我有: struct Integer { int
我的samtools_dup规则存在一些问题。 它在/data/mypipeline.smk的第201行中显示“SyntaxError: 规则samtools_dup中的run/shell/scrip
有人可以向我解释一下这两种情况下负载均衡器(v2)后端实际发生的情况吗: 应用入站 NAT 规则。 应用负载平衡规则。 最佳答案 当您有 1 台后端服务器或者您知道要访问哪个后端服务器时,您将使用 N
我是一名优秀的程序员,十分优秀!