关于ios:Firestore安全规则在模拟器中有效,但在应用程序中失败

Firestore security rule works in simulator but fails in app

我对此Cloud Firestore安全规则有疑问:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
service cloud.firestore {
  match /databases/{database}/documents {
    match /stages/{stageId} {
      match /collections/{collectionId} {
        match /pois/{poiId} {
          allow read;
          allow write: if request.auth != null ||
            request.method =="update" &&
            request.resource.data.keys() == ["pm"];
          }

        }

    }    
  }
}

在代码中,我尝试使用值字典更新作为未经身份验证的用户的现有文档的字段pm。 Firestore日志显示此请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
2018-06-26 12:46:05.476997+0100 app[59292:3472939] 5.3.0 - [Firebase/Firestore][I-FST000001] FSTWriteStream 60c000107230 mutation request: <GCFSWriteRequest 0x60c0006e9e00>: {
    writes {
      update {
        name:"projects/myApp/databases/(default)/documents/stages/dev/collections/ETzbIXBn0Z5FOsCHtHlv/pois/zJELKLTWupuMkYQNb9gl"
        fields {
          key:"pm"
          value {
            map_value {
              fields {
                key:"subLocality"
                value {
                  string_value:"Albufeira"
                }
              }
              fields {
                key:"locality"
                value {
                  string_value:"Albufeira"
                }
              }
              fields {
                key:"country"
                value {
                  string_value:"Portugal"
                }
              }
              fields {
                key:"postalCode"
                value {
                  string_value:"8200-142"
                }
              }
              fields {
                key:"adminArea"
                value {
                  string_value:"Faro"
                }
              }
              fields {
                key:"timezone"
                value {
                  string_value:"Europe/Lisbon"
                }
              }
              fields {
                key:"thoroughfare"
                value {
                  string_value:"Rua Primeiro de Dezembro"
                }
              }
              fields {
                key:"name"
                value {
                  string_value:"Rua Primeiro de Dezembro"
                }
              }
              fields {
                key:"isoCountryCode"
                value {
                  string_value:"PT"
                }
              }
            }
          }
        }
      }
      update_mask {
        field_paths:"pm"
      }
      current_document {
        exists: true
      }
    }
    stream_token:"\\031\\020hB\\002\\201\\364\\265\\265"
}

此请求因"缺少权限或权限不足"而失败。

当我使用此模拟数据将update转换为stages/dev/collections/ETzbIXBn0Z5FOsCHtHlv/pois/zJELKLTWupuMkYQNb9gl

1
{"__name__":"/databases/(default)/documents/stages/dev/collections/ETzbIXBn0Z5FOsCHtHlv/pois/zJELKLTWupuMkYQNb9gl","data":{"pm":{"adminArea":"Germany","testArea":"Munich"}}}

模拟器允许更新。

在我的代码(Swift项目/ iOS)中,我在现有文档参考上使用updateData方法。

作为参数,我传递了这个数组:

1
["pm": ["adminArea":"Faro","name":"Rua Primeiro de Dezembro","postalCode":"8200-142","locality":"Albufeira","subLocality":"Albufeira","isoCountryCode":"PT","timezone":"Europe/Lisbon","thoroughfare":"Rua Primeiro de Dezembro","country":"Portugal"]]

知道我在做什么错吗?谢谢!


事实证明

1
request.resource.data.keys() == ["pm"];

在部署时没有按预期方式工作(即使它在模拟器中也是如此)。

替换

1
request.writeFields.size() == 1 &&"pm" in request.writeFields;

帮了我大忙。

模拟规则是迈向实用产品的重要一步(Hello Google:调试规则???),但前提是它们在模拟器中的作用与在实时部署中的作用相同...


您可以重写此

1
request.resource.data.keys() == ["pm"];

with

1
request.writeFields == ["pm"];