【问题标题】:Deleting data on RealTime Database - Firebase删除实时数据库上的数据 - Firebase
【发布时间】:2018-09-18 19:28:04
【问题描述】:

我正在使用 firebase 实时数据库,并为数据库设置了以下规则,

{
  "rules": {
    ".read": "auth !== null",
    ".write": "auth !== null"
  }
}

但是当我尝试删除一个条目时,它给了我一个错误,说权限被拒绝,如下所示。

Database: Client doesn't have permission to access the desired data. (database/permission-denied).

我该怎么办?我不明白为什么我可以按照当前规则完成所有读写操作而不是删除。

谁能帮我解决这个问题?

注意: 与 Firebase 模拟器相关的结果图片

检查 firebase.auth().currentUser 时:

deleteUserAccount(userId) {
 let knownLocationRef = this.database.ref('lastKnown/' + userId);
 let promises = [];
 console.log('auth details', this.auth.currentUser);
 console.log('auth details null', this.auth.currentUser !== null); //returns true
         knownLocationRef.once('value').then( (data) => {
            console.log('data ', data.val());
            if (data.val() !== null) {
                let prevLat = data.val().lat;
                let prevLong = data.val().long;
                console.log('auth details', this.auth.currentUser);
                console.log('auth details null', this.auth.currentUser !== null); //returns false
                promises.push(knownLocationRef.remove());
            }
        });
         return Promise.all(promises);
 }

【问题讨论】:

  • auth != null 表示客户端使用Firebase Auth 模块进行身份验证。 Auth 为所有请求添加一个令牌以表明它们已登录。
  • @JamesPoag - 是的,我明白这一点。而且我已经配置了 Firebase 身份验证,并且尝试删除数据的用户也经过身份验证。用户可以毫无问题地读取和写入数据到数据库。
  • 嗯。你知道如何在 firebase 控制台中使用数据库规则模拟器吗?尝试将空值写入分支以模拟删除(移除)。
  • @JamesPoag:是的,我也试过了。但是随后我允许模拟写入。由于我无法在有关模拟器的评论中添加图像,因此我将使用模拟结果的图像更新问题
  • 您使用的是哪个客户端 SDK?您可以使用null 执行写入而不是删除/删除吗? (用于调试目的)

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


【解决方案1】:

以下是您的代码以及您如何处理承诺的一些问题:

function deleteUserAccount(userId) {
  let knownLocationRef = this.database.ref('lastKnown/' + userId);
  let promises = []; // good idea for collecting a list of distinct 
                     // promises, maybe not here

  // This is a promise, 'then' is a continuation from which you can return 
  // either a data result or another promise
  knownLocationRef.once('value').then((data) => {
    // if data is valid, return another promise
    if (data.val() !== null) {
      // ...

      // If you were looping and collecting promises, then this might help, 
      // but you don't want to collect inner promises.
      promises.push(knownLocationRef.remove());
    }
  });

  // This returns before everything in `.then` executes
  return Promise.all(promises);
}

这是一个固定版本:

function deleteUserAccount(userId) {
  let knownLocationRef = this.database.ref('lastKnown/' + userId);
  let promises = []; // For the sake of argument, I will use this to collect 
                     // outer promises.

  // normally I would return here, but as an example, I'll uses the 
  // promises array
  promises.push(knownLocationRef.once('value').then((data) => {
    // if data is valid, return another promise
    if (data.val() !== null) {
      // ...

      // Return a Promise from a promise
      return knownLocationRef.remove();
    }

    return null; // no data to process
  }));

  // wait on outer promises
  return Promise.all(promises)
    .catch(console.log); // log errors from any promise
}

这是一个没有额外 promises 数组的版本。

function deleteUserAccount(userId) {
  let knownLocationRef = this.database.ref('lastKnown/' + userId);

  return knownLocationRef.once('value')
    .then((data) => {
      // if data is valid, return another promise
      if (data.val() !== null) {

        // Return a Promise from a promise
        return knownLocationRef.remove();
      }

      return null; // no data to process
    })
    .catch(console.log);
}

【讨论】:

  • 我已经用firebase.auth().currentUser 检查结果更新了问题。我不明白为什么它在方法内部变为 null 而在方法外部不为 null
  • 顺便说一句,ESLint for React Native 是一个非常有用的 linter,可以捕获其中的一些错误。它试图鼓励正确使用承诺。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-08
  • 2021-06-04
  • 1970-01-01
  • 2020-01-17
  • 2018-12-07
  • 2021-11-02
  • 2020-08-17
相关资源
最近更新 更多