尝试使用request.path设置Cloud Firestore安全规则

时间:2017-11-13 23:41:21

标签: angular firebase firebase-security angularfire2 google-cloud-firestore

我正在努力解决一些Firestore安全概念。我想根据request.path属性设置规则。

我的规则是:

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

...然后我使用AngularFire2添加这样的文档......

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));

我认为这应该很简单based on the docs,但我得到的只是错误 - Missing or insufficient permissions

我知道我已正确登录,并且如果我使用allow read,write: if true;打开安全性,我知道查询有效,所以我没有到达这里? 不应该request.path[0]在此处评估字符串appUsers,因此允许写入数据吗?

任何想法都感激不尽,因为到目前为止我还没有找到这些规则很有趣。

干杯全部

2 个答案:

答案 0 :(得分:2)

我建议使用内置的路径匹配器版本:

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

或者,如果你真的想在条件中指定:

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

request.path是完整路径(例如/projects/<projectId>/databases/(default)/documents/appUsers,这意味着您实际上需要request.path[5](因此我们提供了更简单,更易读的方法)。

修改(4/2/18):request.path支持ListMap访问:

  • Listrequest.path[5] == "appUsers"
  • Maprequest.path['pathSegment'] == "appUsers",但请注意,它仅适用于通配符(例如{name})值

答案 1 :(得分:0)

迈克·麦克唐纳(Mike McDonald)回答者帮助我创建了一条规则,该规则将允许对所有表进行读取,除非集合名称位于“ hasReadRules”数组中(通用的allow read语句使我无法覆盖某些表的读取规则,因为如果您在某处具有“允许读为真”,它将覆盖您在任何其他规则中具有的“允许读为假”):

// 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;
}