Разрешить создание только одного документа в Firestore, запретить обновление, редактирование и т. Д. - PullRequest
0 голосов
/ 06 мая 2019

Я пишу своеобразное приложение Quiz, используя VueJS и Firebase Firestore.

Пока что я сделал все, кроме этой последней части.

Пользователи могут отвечать на вопросы безавторизовался.

И на последнем этапе есть еще один последний вопрос.Каждый может ответить на этот вопрос, но я должен быть в состоянии определить, кто первый.

До сих пор я пытался проверить, является ли сбор ответов пустым, это работает, но время ответа является проблемой, и я могулегко воспроизвести двух или более пользователей, отвечающих одновременно и имеющих сообщение, что они являются победителями.

В настоящее время я пытаюсь выполнить транзакции, но не могу понять, как определить, существует ли документ.Вот пример кода:

let vm = this;
fsdb.runTransaction(function (transaction) {
    let voteDocRef = fsdb.collection('final_vote').doc('vote');
    return transaction.get(voteDocRef).then(function (voteDoc) {
        if (!voteDoc.exists) {
            voteDocRef.set({voted: true}).then(function () {
                vm.trueAnswer(index);
                return 'set executed!';
            }).catch(function () {
                vm.falseAnswer(index);
                throw 'Someone already voted!';
            });
            return 'Document created!';
        } else {
            throw 'Someone already voted!';
        }
    });

vm.trueAnswer и vm.falseAnswer - это методы, которые я использую для отображения всплывающего сообщения.

И этот метод вызывается после того, как пользовательотправляет ответ.

Сначала я попробовал с правилами, которые каждый может читать, писать ... но теперь я пытаюсь ограничить запись только, если документ не существует.Вот текущий набор правил:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }

    match /{collectionName}/{docId} {
      allow create: if collectionName == 'final_vote' && docId == 'vote';
    }
  }
}

Пока что это работает не так, как ожидалось.

Есть идеи о том, как подойти к этому?

1 Ответ

0 голосов
/ 07 мая 2019

Не могли бы вы попробовать следующий код?

let vm = this;
fsdb.runTransaction(function (transaction) {
    let voteDocRef = fsdb.collection('final_vote').doc('vote');
    return transaction.get(voteDocRef).then(function (voteDoc) {
        if (voteDoc.data().voted !== true) {
            voteDocRef.set({voted: true}).then(function () {
                vm.trueAnswer(index);
                return 'set executed!';
            }).catch(function () {
                vm.falseAnswer(index);
                throw 'Someone already voted!';
            });
            return 'Document created!';
        } else {
            throw 'Someone already voted!';
        }
    });
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }

    match /final_vote/{docId} {
      allow create, update: if true;
    }
  }
}

Я думаю, что final_votes лучше, чем final_vote в качестве имени коллекции.

...