Ограничение доступа детей / полей с помощью правил безопасности

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

Скрыть все номинации, которые не имеютеще не утвержденСкрыть личные поля от отправки (телефон, статус утверждения, дата создания и т. Д.)

Мои текущие правила таковы:

{
    "rules": {
        "nominations": {
            ".read": true,

            "$nominationId": {
                ".read": "data.child('state').val() == 'approved' || auth != null", // Only read approved nominations if not authenticated
                ".write": "!data.exists()", // Only allow new nominations to be created

                "phone": {
                    ".read": "auth != null" // Only allow authenticated users to read phone number
                },

                "state": {
                    ".read": "auth != null", // Only allow authenticated users to read approval state
                    ".write": "auth != null" // Only allow authenticated users to change state
                }
            }
        }
    }
}

Дочерние правила (например,$nomination) нене может прочитать весь ребенок от родителя. Если я слушаюchild_added наhttps://my.firebaseio.com/nominations он с радостью возвращает всех детей и все их данные даже с соблюдением вышеуказанных правил безопасности.

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

Обновить

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

Новая структура данных выглядит следующим образом:

my-firebase
    |
    `- nominations
        |
        `- entries
        |   |
        |   `- private
        |   `- public
        |
        `- status
            |
            `- pending
            `- approved
            `- rejected

Каждая номинация хранится вentries с личными данными, такими как номер телефона, адрес электронной почты и т. д. вprivate и общедоступные данные в разделе.public

Обновленные правила следующие:

{
    "rules": {
        "nominations": {
            "entries": {
                "$id": {
                    ".write": "!data.exists()",

                    "public": {
                        ".read": true,
                    },

                    "private": {
                        ".read": "auth != null"
                    }
                }
            },

            "status": {
                "pending": {
                    ".read": "auth != null",

                    "$id": {
                        ".write": "root.child('nominations/entries').child($id).exists() && (auth != null || newData.val() == true)"
                    }
                },

                "approved": {
                    ".read": true,

                    "$id": {
                        ".write": "root.child('nominations/entries').child($id).exists() && auth != null"
                    }
                },


                "rejected": {
                    ".read": "auth != null",

                    "$id": {
                        ".write": "root.child('nominations/entries').child($id).exists() && auth != null"
                    }
                }
            }
        }
    }
}

И реализация JavaScript:

var db = new Firebase('https://my.firebaseio.com')
var nominations = db.child('nominations')

var entries = nominations.child('entries')

var status = nominations.child('status')
var pending = status.child('pending')
var approved = status.child('approved')
var rejected = status.child('rejected')

// Create nomination via form input (not shown)
var createNomination = function() {
    var data = {
        public: {
            name: 'Foo',
            age: 20
        },

        private: {
            createdAt: new Date().getTime(),
            phone: 123456
        }
    }

    var nomination = entries.push()
    nomination.setWithPriority(data, data.private.createdAt)

    pending.child(nomination.name()).set(true)    
}

// Retrieve current nomination status
var getStatus = function(id, callback) {
    approved.child(id).once('value', function(snapshot) {
        if (snapshot.val()) {
            callback(id, 'approved')
        } else {
            rejected.child(id).once('value', function(snapshot) {
                callback(id, snapshot.val() ? 'rejected' : 'pending')
            })
        }
    })
}

// Change status of nomination
var changeStatus = function(id, from, to) {
    status.child(from).child(id).remove()
    status.child(to).child(id).set(true)
}

Единственная часть реализации I 'Когда я борюсь с изменениями статуса, мой нынешний подход может быть улучшен:

_.each([pending, approved, rejected], function(status) {
    status.on('child_added', function(snapshot) {
        $('#' + snapshot.name()).removeClass('pending approved rejected').addClass(status.name())
    })
})

Я планировал использоватьchild_changed наnominations/status но у меня нетне смог заставить его работать надежно.

Ответы на вопрос(3)

Ваш ответ на вопрос