用户应该只在Firestore上读/写自己的提交

问题描述 投票:1回答:2

我迷失了Firestore规则。

我希望经过身份验证的用户能够阅读他们自己的提交,但我仍然没有获得足够的权限。我正在将userId写入每个提交。

// add submit to submits collection in firestore
    db.collection('submits').add({
      user: this.user,
      number: this.number,
      timestamp: moment.utc(this.timestamp).format(),
      usage: this.usage
    })

在这里,我检查登录的用户并获取他提交的用户

 let ref = db.collection('users')

// get current user
ref.where('user_id', '==', firebase.auth().currentUser.uid).get()
  .then(snapshot => {
    snapshot.forEach(doc => {
      this.user = doc.data()
      this.user = doc.data().user_id
    })
  })
  .then(() => {
    // fetch the user previous submits from the firestore
    db.collection('submits').where('user', '==', this.user).get()
      .then(snapshot => {
        // console.log(snapshot)
        snapshot.forEach(doc => {
          let submit = doc.data()
          submit.id = doc.id
          submit.timestamp = moment(doc.data().timestamp).format('lll')
          this.previousSubmits.push(submit)
        })
      })
  })
  }

这些是我的火场规则

service cloud.firestore {
match /databases/{database}/documents {

// Make sure the uid of the requesting user matches name of the user
// document. The wildcard expression {userId} makes the userId variable
// available in rules.
match /users/{userId} {
  allow read, update, delete: if request.auth.uid == userId;
  allow create: if request.auth.uid != null;
}

// check if the user is owner of submits he is requesting
match /submits/{document=**} {
     allow read: if resource.data.user == request.auth.uid;
         allow write: if request.auth.uid != null;    
   }


 }
}

有谁知道我做错了什么?

更新,添加了用于在users集合中创建用户文档的代码:

signup () {
  if (this.alias && this.email && this.password) {
    this.slug = slugify(this.alias, {
      replacement: '-',
      remove: /[$*_+~.()'"!\-:@]/g,
      lower: true
    })
    let ref = db.collection('users').doc(this.slug)
    ref.get().then(doc => {
      if (doc.exists) {
        this.feedback = 'This alias already exists'
      } else {
        firebase.auth().createUserWithEmailAndPassword(this.email, this.password)
          .then(cred => {
            ref.set({
              alias: this.alias,
              household: this.household,
              user_id: cred.user.uid
            })
          }).then(() => {
            this.$router.push({ name: 'Dashboard' })
          })
          .catch(err => {
            console.log(err)
            this.feedback = err.message
          })
        this.feedback = 'This alias is free to use'
      }
    })
  }
}
javascript firebase google-cloud-firestore firebase-security
2个回答
2
投票

部分问题是您正在尝试搜索user_id字段等于用户ID的文档,但您的安全规则是:“只有当文档的ID与文档的ID相同时才允许用户读取文档用户的ID“,这完全不相关,我不知道你的情况是否真的如此。

一种选择是改变你的规则,你会说:“嘿,如果user_id字段的值等于你的用户ID,你可以读取/更改文档,这将是这样的......

match /users/{userId} {
  allow read, update, delete: if request.auth.uid == resource.data.user_id;
  // ...
}

...或更改查询,以便查询ID为当前用户的UID的特定文档。

 let ref = db.collection('users').document(currentUser.uid)

 ref.get() {... }

但是,我想,不要同时做两件事。 :)


1
投票

该错误来自您尝试获取当前用户的第一行:

ref.where('user_id', '==', firebase.auth().currentUser.uid).get()

此行选择user_id字段与当前用户的ID匹配的文档,但您的Firestore规则正在检查用户的ID是否与文档的ID匹配。由于您使用slugify生成文档ID,因此它不匹配,这会导致权限错误。

Todd对规则更改的建议可行,但最好只使用用户ID作为文档ID,并将用户的slug存储为字段。这样您就不必担心冲突(用户ID将自动唯一)并且不必使用select语句 - 您将知道每个用户只有一个文档,并且可以直接访问它:

ref.doc(firebase.auth().currentUser.uid).get()

作为旁注,您实际上似乎没有任何理由在那时检索用户文档(至少在您的示例代码中)。如果您真的只使用它来获取user_id字段,那么您可以跳过它,因为您已经拥有auth会话中的用户ID。在这种情况下,你应该这样做:

this.user = firebase.auth().currentUser.uid
db.collection('submits').where('user', '==', this.user).get()
  .then(snapshot => {
    // console.log(snapshot)
    snapshot.forEach(doc => {
      let submit = doc.data()
      submit.id = doc.id
      submit.timestamp = moment(doc.data().timestamp).format('lll')
      this.previousSubmits.push(submit)
    })
  })
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.