Пользователь должен только читать / писать собственные материалы на Firestore - PullRequest
0 голосов
/ 12 сентября 2018

Я заблудился из-за правил 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;    
   }


 }
}

Кто-нибудь знает, чтоЯ делаю неправильно?

Обновление, добавлен код, который я использую для создания пользовательского документа в коллекции пользователей:

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'
      }
    })
  }
}

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

Ошибка исходит от первой строки, где вы пытаетесь получить текущего пользователя:

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

Эта строка выбирает документы, в которых поле user_id соответствует идентификатору текущего пользователя, но ваше правило Firestoreпроверяет, соответствует ли идентификатор пользователя идентификатору документа .Поскольку вы генерируете идентификатор документа с slugify, он не совпадает, что вызывает ошибку разрешений.

Предложение Тодда об изменении правила будет работать, но, вероятно, было бы лучше просто использовать идентификатор пользователя в качестве идентификатора документа и сохранить слаг пользователя в качестве поля.Таким образом, вам не нужно беспокоиться о коллизиях (идентификаторы пользователей будут автоматически уникальными) и не нужно использовать оператор выбора - вы будете знать, что для каждого пользователя существует только один документ, и можете просто получить к нему прямой доступ:

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

В качестве дополнительного примечания у вас, по-видимому, нет никаких причин извлекать пользовательский документ в этот момент (по крайней мере, в вашем примере кода).Если вы действительно используете это только для получения поля user_id, вы можете просто пропустить его, поскольку у вас уже есть идентификатор пользователя из сеанса auth.В этом случае вы должны просто сделать это:

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)
    })
  })
0 голосов
/ 12 сентября 2018

Частично проблема заключается в том, что вы пытаетесь найти документ, в котором поле user_id совпадает с идентификатором пользователя, но ваши правила безопасности говорят: «Разрешить пользователям читать документ, только если идентификатор документ совпадает с идентификатором пользователя ", что совершенно не связано, и я не знаю, действительно ли это так в вашем случае.

Один из вариантов - изменить ваши правила, когда вы говорите: «Эй, вы можете читать / изменять документ, если значение поля user_id равно вашему идентификатору пользователя, что будет примерно так ...

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

... или изменить запрос так, чтобы вы запрашивали конкретный документ, идентификатором которого является UID текущего пользователя.

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

 ref.get() {... }

Но, думаю, не делайте и то и другое одновременно. :)

...