【问题标题】:Firebase multi-path update - Permission deniedFirebase 多路径更新 - 权限被拒绝
【发布时间】:2017-07-25 13:16:14
【问题描述】:

几天来,我一直在尝试向我的 Firebase 数据库添加规则,但不断弹出错误,我找不到问题所在。

有错误:

FIREBASE 警告:更新/失败:permission_denied

PERMISSION_DENIED:权限被拒绝

我搜索了解决方案并找到了一些相关的帖子 (Permission denied error during multiple update on Firebase)。似乎显示的错误不对。我虽然得到了这个,因为我没有在我的根路径('/')上设置权限,但根据这篇文章,这不是问题。

我尝试将我的 3 个“写入”规则设置为“真”并且它有效,所以我想问题一定出在我的规则中。

请看下面我的代码。

角度服务:

let event = {
    "title": "Title"
    "uid": "FZON4aEQgKNnRlHqMH7ZwynhTtp1"
}

let uid = this.authService.fbUser.uid;
let eventId = this.db.list('eventsData').push(undefined).key;

let updateObject = {};
updateObject[`eventData/${eventId}`] = event;
updateObject[`userEvents/${uid}/${eventId}`] = true;
updateObject[`eventGuests/${eventId}/${uid}`]= {
  attendance: 2 // and some other data
};

return this.db.object('/').update(updateObject);

数据层次结构:

{
  "eventData" : {
    "-KptoNEw3MKRfacLnqa6" : { //Some data equal to 'event' object in above Angular service }
  },
  "eventGuests" : {
    "-KptoNEw3MKRfacLnqa6" : {
      "FZON4aEQgKNnRlHqMH7ZwynhTtp1" : { // Some data }
    }
  },
  "userEvents" : {
    "FZON4aEQgKNnRlHqMH7ZwynhTtp1" : {
      "-KptoNEw3MKRfacLnqa6" : true
    }
  },
  "users" : {
    "FZON4aEQgKNnRlHqMH7ZwynhTtp1" : { //Some data }
  }
}

Firebase 规则:(我删除了“.read”权限以使代码更清晰,因为它们不是问题的一部分)

{
  "rules": {
    "eventData": {
      "$eventId": {
        // Event owner can update data
        // OLD > ".write": "auth.uid == data.child('uid').val()"
        // NEW
        ".write": "(newData.child('uid').val() == auth.uid) && (!data.exists() || data.child('uid').val() == auth.uid)"
      }
    },
    "eventGuests": {
      "$eventId": {
        "$uid": {
          // Event owner can add someone to the event
          // Actual user can modify his attendance
            ".write": "(auth.uid == root.child('eventData').child($eventId).child('uid').val() ) || (auth.uid == $uid && data.exists() && newData.exists())"
        }
      }
    },
    "userEvents": {
      "$uid": {
        "$eventId": {
            // Event owner can add his event to someone's list
          ".write": "auth.uid == root.child('eventData').child($eventId).child('uid').val()"
        }
      }
    }
  }
}

感谢您的观看!

更新:

自从 Frank 更正了一个错误后,我进行了一些新的测试。

我不是以多路径方式进行更新,而是通过评论我不想运行的那些方式来进行更新。此外,我尝试使用静态值。

let updateObject = {};
updateObject[`eventData/-Kpu9op4_s3jCetav6xn`]= {
    "title": "Title"
    "uid": "FZON4aEQgKNnRlHqMH7ZwynhTtp1"
};
return this.db.object('/').update(updateObject);

然后:

let updateObject = {};
updateObject[`userEvents/${uid}/-Kpu9op4_s3jCetav6xn`]= true;
return this.db.object('/').update(updateObject);

还有:

let updateObject = {};
updateObject[`eventGuests/-Kpu9op4_s3jCetav6xn/${this.authService.fbUser.uid}`]= {
  attendance: 2 // and some other data
};
return this.db.object('/').update(updateObject);

他们三个工作。

但是当我使用多路径(同时3个)运行代码时,我仍然得到权限被拒绝的错误。

【问题讨论】:

  • 为什么每个孩子周围都有数组括号:[`eventData/${key}`]
  • 另请注意,我们不知道event 是什么。请确保您的问题包含minimal, complete code that is needed to reproduce the problem。确保这一点的一种简单方法是对所有内容使用硬编码值。
  • 关于括号,它是我使用外部对象时的残余物(myUpdateObject[eventData/${key}]=myData)。让我更新一下!
  • 我在下面写了第一个错误。但是这些规则中确实发生了太多事情,这使得很难看到问题所在。看看我之前分享的链接,它解释了如何最小化所需的代码。

标签: firebase firebase-realtime-database firebase-security angularfire2


【解决方案1】:

/eventData/$event 出现了第一个错误:

".write": "auth.uid == data.child('uid').val()" 

由于data 是该位置的现有数据,我很确定当没有现有数据时此规则将失效。

你更可能想要:

(newData.child('uid').val() == auth.uid) && 
(!data.exists() || data.child('uid').val() == auth.uid)

【讨论】:

  • 你是对的。这是问题的一部分,但最后我仍然得到同样的错误。我将使用我运行的几个新测试和结果来更新我的答案。
【解决方案2】:

我进行了最后一次测试以确认我的想法。

这就是我的规则在早些时候失败时的样子:

eventGuests : 如果当前用户是事件的所有者,或者当前用户是被修改的用户,则写入

".write": "(auth.uid == root.child('eventData').child($eventId).child('uid').val() ) || (auth.uid == $ uid && data.exists() && newData.exists())"

userEvents : 如果当前用户是事件的所有者,则写入

".write": "auth.uid == root.child('eventData').child($eventId).child('uid').val()"

现在,如果我改用以下方法,那就行了:

(!root.child('eventData').child($eventId).exists() || auth.uid == root.child('eventData').child($eventId ).child('uid').val())

在交易结束之前似乎无法访问交易中的数据。

通过按此确切顺序调用以下...

let updateObject = {};
updateObject[`eventData/${eventId}`] = event;
updateObject[`userEvents/${uid}/${eventId}`] = true;
updateObject[`eventGuests/${eventId}/${uid}`]= {
  attendance: 2 // and some other data
};

...我期待 eventData 被持久化并且可以在 userEventseventGuests 中访问。然后,如果发生错误,系统将回滚。但它看起来不像那样工作。

任何人都可以确认在交易被验证之前无法访问交易中的推送数据吗?

【讨论】:

    猜你喜欢
    • 2022-11-11
    • 2020-02-15
    • 2017-12-26
    • 2020-07-31
    • 2018-03-06
    相关资源
    最近更新 更多