Получение документа коллекции, защищенного uid, через который не работает - PullRequest
0 голосов
/ 17 апреля 2020

В моем приложении, как только пользователь вошел в систему через Firebase auth, я хочу получить дополнительные данные из моей базы данных firestore.

Я не хочу, чтобы пользователи могли просматривать документы других пользователей, поэтому Я создал для этого правило:

match /users/{userId} {
  function isAuthenticated() {
    return request.auth != null;
  }

  function userIsSelf() {
    return request.auth.uid == userId;
  }

  allow read: if
  isAuthenticated()
  && userIsSelf();
}

По моему мнению, то, что я написал, теоретически должно позволить текущему зарегистрированному пользователю видеть данные только о себе, и это прекрасно работало на «игровой площадке правил».

Однако, когда я пробую этот код в приложении, я получаю сообщение об ошибке: FirebaseError: Missing or insufficient permissions.

Я думаю, это как-то связано с тем, как Firestore извлекает данные?

Я запрашиваю это, выбирая коллекцию users с where, которая возвращает только тех пользователей, у которых есть uid, совпадающий с зарегистрированным пользователем:

const querySnapshot = await firebase.firestore().collection("users").where("uid", "==", uid).get().catch(err => {
    console.error('could not fetch user', err)
})

if (!querySnapshot || querySnapshot.empty) {
    dispatch('logout')
    throw new Error('Cannot find logged in user\'s data in database')
} 

const userData = querySnapshot.docs[0].data()
commit('setUser', userData)

Я создал свой firestore Правила выглядят так:

rules_version = '2';

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

    function isAuthenticated() {
      return request.auth != null;
    }
    function isAdmin(uid) {
      return get(/databases/$(database)/documents/users/$(uid)).data.role == 'admin'
    }

    // Allow admin to do everything
    match /{document=**} {
        allow read, write: if isAdmin(request.auth.uid)
    }

    // Only allow users to read/write to themselfs
    match /users/{userId} {

      function userIsSelf() {
        return request.auth.uid == userId;
      }
      function roleIsUserOrSameAsDocument() {
        return request.resource.data.role == 'user' || request.resource.data.role == resource.data.role;
      }

        allow read: if
        isAuthenticated()
        && userIsSelf();

      allow write: if
        isAuthenticated()
        && userIsSelf()
        && roleIsUserOrSameAsDocument();
    }
  }
}

1 Ответ

2 голосов
/ 17 апреля 2020

Ваш запрос не соответствует вашим правилам. Ваш запрос пытается получить все документы, в которых поле uid соответствует указанному uid:

firebase.firestore()
    .collection("users")
    .where("uid", "==", uid)

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

Ваши правила разрешают вместо этого этот запрос:

firebase.firestore()
    .collection("users")
    .doc(uid)

Если вы на самом деле вы хотите разрешить пользователю доступ к любому документу, в котором его UID совпадает с полем uid в документе, вам нужно настроить его следующим образом:

match /users/{userId} {
  function isAuthenticated() {
    return request.auth != null;
  }

  function checkDocUid() {
    return request.resource.data.uid == request.auth.uid;
  }

  allow read: if isAuthenticated() && checkDocUid();
}

Обратите внимание, что request.auth.uid является текущим аутентификацией ' d uid пользователя и request.resource.data.uid - это значение поля uid в документе.

Всегда помните, что ваш запрос должен точно соответствовать правилам, а правила безопасности не являются фильтрами .

...