Правило безопасности Firestore get() не работает

В firestore я хочу, чтобы пользователь имел доступ только к документу, если пользователь находится в teamid упомянутой в документе. Теперь у меня есть другая коллекция, называемая teams где у меня есть пользователи, сопоставленные как { user_id = true }. Поэтому в правилах Firestore есть следующее:

return get(/databases/$(database)/documents/teams/$(resource.data.teamid)).data.approvedMembers[request.auth.uid] == true;

Теперь это правило не работает и не выполняет запрос, запрошенный в базу данных интерфейсом. Но когда я заменю $(resource.data.teamid) моим фактическим значением teamid следующим образом,

return get(/databases/$(database)/documents/teams/234234jk2jk34j23).data.approvedMembers[request.auth.uid] == true;

... он работает так, как ожидалось.

Теперь мой вопрос заключается в том, что я неправильно использую resource или не поддерживается resource в запросах get() или exists() в правилах Firestore?

Править

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

    function isTeamMember() {
        return get(/databases/$(database)/documents/teams/$(resource.data.teamid)).data.approvedMembers[request.auth.uid] == true;
        // return exists(/databases/$(database)/documents/teams/$(resource.data.teamid));
    }

    match /{document=**} {
        allow read, write: if isTeamMember();
    }
  }
}

Если вы заметили правило с комментариями, exists() также не работает в этом случае.

Ответ 1

У вас есть этот match:

match /{document=**} {
    allow read, write: if isTeamMember();
}

Это будет соответствовать любому документу в базе данных. Это означает, что при вызове isTeamMember() он не гарантирует, что resource представляет собой team документ. Если у вас есть подколлекции в teams и пишите их, то resource будет документ субколлекции.

Ответ 2

Спасибо, что обратились к Твиттеру. После нашего чата, вот вывод:

Запрос документов с использованием правила безопасности

Вы не можете использовать правило безопасности в качестве фильтра. Чтобы заставить это работать, вы также должны добавить .where('teamid', '==', yourTeamId)

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

Использование пользовательских требований

Вы можете настроить пользовательские требования в токенах аутентификации. Вот пример того, как их устанавливать, и они используют их в ваших правилах

Настройка пользовательских требований

Для этого вам потребуется использовать SDK Admin.

auth = firebase.auth();

const userId = 'exampleUserId';
const customClaims = {teams: {myTeam1: true, myTeam2: true}};

return auth.setCustomUserClaims(userId, customClaims)
  .then(() => {
    console.log('Custom claim created');
    return auth.getUser(userId);
  })
  .then(userRecord => {
    console.log('name: ${userRecord.displayName}');
    console.log('emailVerified: ${userRecord.emailVerified}');
    console.log('email: ${userRecord.email}');
    console.log('emailVerified: ${userRecord.emailVerified}');
    console.log('phoneNumber: ${userRecord.phoneNumber}');
    console.log('photoURL: ${userRecord.photoURL}');
    console.log('disabled: ${userRecord.disabled}');
    console.log('customClaims: ${JSON.stringify(userRecord.customClaims)}');
  })
  .catch(err => {
    console.error(err);
  });

Применение правила безопасности

allow read, write: if request.auth.token.teams.$(resource.data.teamId) == true;

Я все еще не уверен на 100%, что это также не потребует от вас фильтрации от teamid. Пожалуйста, проверьте его и верните.