Правила безопасности Firebase Cloud Firestore для updateData FieldValue.arrayUnion ([значение]) [swift] - PullRequest
0 голосов
/ 28 февраля 2020

У меня есть документ в Cloud Firestore.

Структура поля «события» выглядит следующим образом:

{
"events" : [ 
    "eventID-1": [
        "value1",
        "value2"    
        ],
    "eventID-2": [
        "value2",
        "value3"    
        ],
    "eventID-3": [
        "value3",
        "value4"    
        ]
    ]
}

enter image description here

Обновление [swift]:

self.db.collection("collection").document(document).updateData([
  "events.eventID-1": FieldValue.arrayUnion([value2])
...

Как составить правила безопасности Firebase Cloud Firestore:

  1. значение было уникальным. То есть при записи проверьте, не существует ли значение в массивах eventID-1, eventID-2, eventID-3 ....

  2. Проверьте (длина) полученное значение для записи

Я только что понял, как проверить входящие данные, что это карта и что мы получаем только одно значение.

match /databases/{database}/documents {
    match /collection/{documentID} {
      allow write: if request.resource.data is map
                   && request.writeFields.size() == 1
    }
}

UPD : Рассмотрено:

  1. Проверка длины строки в запросе
allow write : if request.resource.data.events.values()[0].size() < 100
Проверка уникальности в списке
allow write : if (request.resource.data.events.keys()[0] in resource.data.events.keys()) == false

Но я так и не понял, как решить свои проблемы ((((Помогите !!!

Ответы [ 2 ]

2 голосов
/ 01 марта 2020

Вот попытка:

allow write: if request.writeFields.size() == 1
    && geteventarray_after().size() == geteventarray_before().size() + 1 // Making sure that the size increased so that is is unique
    && getnewelement().size() < 100     // Making sure the new element size is < 100
    && getnewelement() is string        // Other valdiations...

    function getsubstr(str, from, to) {
      return str[from:to];
    }
    function geteventarrayname() {
      return getsubstr(input, "events.".size(), request.writeFields[0].size());
    }
    function geteventarray(map) {
      return map.get(["events", geteventarrayname()], [])
    }
    function geteventarray_after() {
      return geteventarray(request.resource.data);
    }
    function geteventarray_before() {
      return geteventarray(resource.data);
    }
    function getnewelement() {
      return geteventarray_after()[geteventarray_after().size()-1];  // It is added at the end
    }

РЕДАКТИРОВАТЬ: это не проверено, но должно быть хорошее начало

1 голос
/ 28 февраля 2020

Чтобы проверить, существуют ли существующие значения, которые вы могли бы использовать array-contains или что-то подобное, вот документация , где есть несколько примеров, и будет выглядеть примерно так:

let docRef = db.collection("events");
let query = docRef.whereField("events", arrayContains: "newValue")
query.getDocuments() { (querySnapshot, err) in
    if let err = err {
        print("Error getting documents: \(err)")
    } else {
        if (querySnapshot!.isEmpty) {
           //do what have to if the value do not exist
        } else {
           //do what have to if the value exists
        }
    }
}

Конечно, это только пример, но он должен послужить хорошей отправной точкой для того, что вам нужно, также важно отметить, что это будет на стороне вашего приложения, а не на правилах Firebase.

Для измерение длины, так как вы добавляете только 1 значение за раз, вы можете сделать следующее в своем правиле Firebase:

allow write: if request.resource.data is map
               && request.writeFields.size() == 1 
               && request.resource.data.map.values[0].length < 100 //whatever value you want

Надеюсь, это помогло вам.

...