Try something like this:
// Rules for a band document and its subcollections
match /bands/{bandID}{
function isBandOwner(userID){
// Determine if user is a band owner
return get(/databases/$(database)/documents/bands/$(bandID)).data.members[userID].role == 'OWNER';
}
// Anyone can read
allow read;
// Only authenticated owners can write to band doc
allow write: if request.auth != null && isBandOwner(request.auth.uid);
// Rules for all of a band's subcollections
match /{document=**}{
// Anyone can read
allow read;
// Only authenticated owners can write to a band's subcollections
allow write: if request.auth != null && isBandOwner(request.auth.uid);
}
}
To try it out, let's also restrict reads and try to read some test documents:
allow read: if isBandOwner(request.auth.uid);
Set up Firebase Auth with Google Sign-in and try to read from Cloud Firestore:
<script src="https://www.gstatic.com/firebasejs/5.5.9/firebase.js"></script>
<script>
// Initialize Firebase
// TODO: Replace with your project's customized code snippet
var config = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
projectId: "<PROJECT_ID>",
storageBucket: "<BUCKET>.appspot.com",
messagingSenderId: "<SENDER_ID>",
};
firebase.initializeApp(config);
//Sign in with Google
var provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider).then(function(result) {
// This gives you a Google Access Token. You can use it to access the Google API.
var token = result.credential.accessToken;
// The signed-in user info.
var user = result.user;
console.log(`UserId: ${user.uid}`)
// Try reading Firestore docs
var db = firebase.firestore();
// Disable deprecated features
db.settings({
timestampsInSnapshots: true
});
// This doc has members.[my-uid].role = "OWNER"
// Read should succeed
db.doc("bands/abc").get().then((doc) => {
console.log(`${doc.id} => ${doc.data().name}`);
});
// This doc has members.[my-uid].role = "BANDMEMBER"
// Read should fail
db.doc("bands/def").get().then((doc) => {
console.log(`${doc.id} => ${doc.data().name}`);
});
// ...
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
console.log('error login');
});
</script>