Trying to set up Cloud Firestore security rules using request.path

偶尔善良 提交于 2020-06-16 19:09:22

问题


I am struggling to get my head around some Firestore security concepts. I want to set up a rule based on the request.path property.

My rule is this:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.path[0]=='appUsers';
    }
  }
}

...and I then use AngularFire2 to add a document like this...

this.myAngularFirestore.doc('/appUsers/'+this.auth.auth.currentUser.uid).set({name: this.auth.auth.currentUser.displayName})
      .then(()=>console.log('Added user'))
      .catch(err=>console.log('Could not add user:', err.message));

I thought this should be simple based on the docs but all I ever get is the error - Missing or insufficient permissions.

I know I am logged in correctly and I know the query works if I open up the security with allow read,write: if true; so what am I not getting here? Shouldn't request.path[0] evaluate to the string appUsers here and so allow the data to be written?

Any ideas gratefully accepted as I'm not finding these rules much fun to out together so far.

Cheers all


回答1:


I'd recommend using the built-in path matcher version of this:

service cloud.firestore {
  match /databases/{database}/documents {
    match /appUsers {
      allow read, write;
    }
  }
}

Or, if you really want to specify in the condition:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{pathSegment} {
      allow read, write: if pathSegment == "appUsers";
    }
  }
}

request.path is the full path (e.g. /projects/<projectId>/databases/(default)/documents/appUsers, which means you'd actually want request.path[5] (hence why we provide easier, more readable ways of doing this).

Edit (4/2/18): request.path supports both List and Map access:

  • List: request.path[5] == "appUsers"
  • Map: request.path['pathSegment'] == "appUsers", though note that it only works on wildcarded (e.g. {name}) values



回答2:


Mike McDonald answerer helped me to create a rule that will allow read for all tables unless the collection name is inside an array of "hasReadRules" (the generic allow read statement was preventing me from overriding read rules for some tables because if you have an allow read true somewhere it will override any allow read false that you have in any other rule):

// allow read for all collection that are not in the hadReadRules array
match /{pathSegment}/{document=**} {
  allow read: if !(pathSegment in hasReadRules());
  allow write: if false;
}
// these collection will have their own read rules
function hasReadRules() {
    return ["calculations", "users", "push_notifications"];
}

// below is an example where i want to override the allow
//read rule for a single collection without having to create a read rule for every collection
// If we do this without using the hadReadRules approach it wont work, because the rule bellow will be override by the generic allow read in the first rule statement
match /calculations/{id} {
  allow read: if belongsTo(resource.data.user_uid);
}

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


来源:https://stackoverflow.com/questions/47275346/trying-to-set-up-cloud-firestore-security-rules-using-request-path

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!