Как ограничить число детей в реальном времени с помощью Firebase [duplicate]

Используйте оператор while, пока пользователь не вводит истинное значение, и если входное значение не является числом или это значение null, пропустите его и попробуйте снова и так далее. В примере я попытался ответить на действительно ваш вопрос. Если мы предположим, что наш возраст составляет от 1 до 150, тогда принимается входное значение, иначе это неправильное значение. Для завершения программы пользователь может использовать клавишу 0 и вводить ее как значение.

Примечание: прочитайте комментарии вверху кода.

# If your input value is only a number then use "Value.isdigit() == False".
# If you need an input that is a text, you should remove "Value.isdigit() == False".
def Input(Message):
    Value = None
    while Value == None or Value.isdigit() == False:
        try:        
            Value = str(input(Message)).strip()
        except InputError:
            Value = None
    return Value

# Example:
age = 0
# If we suppose that our age is between 1 and 150 then input value accepted,
# else it's a wrong value.
while age <=0 or age >150:
    age = int(Input("Please enter your age: "))
    # For terminating program, the user can use 0 key and enter it as an a value.
    if age == 0:
        print("Terminating ...")
        exit(0)

if age >= 18 and age <=150: 
    print("You are able to vote in the United States!")
else:
    print("You are not able to vote in the United States.")
7
задан Kato 25 March 2014 в 23:02
поделиться

2 ответа

Использование существующих свойств выполняется с помощью root или parent и довольно просто.

{
  "rules": {
    "things": {
      // assuming value is being stored as an integer
      ".validate": "newData.val() <= root.child('max')"
    }
  }
}

Однако определение количества записей и их принудительное выполнение несколько сложнее, чем просто написать правило безопасности:

  • , поскольку нет .length on объект, нам нужно сохранить, сколько записей существует
  • , нам нужно обновить это число в безопасном / реальном времени
  • , нам нужно знать номер записи, которую мы имеем добавление относительно этого счетчика

Наивный подход

. Один подход бедных людей, предполагая, что предел является чем-то небольшим (например, 5 записей), состоял бы в простом перечислении их в правилах безопасности:

{
  "rules": {
    "things": {
      ".write": "newData.hasChildren()", // is an object
      "thing1": { ".validate": true },
      "thing2": { ".validate": true },
      "thing3": { ".validate": true },
      "thing4": { ".validate": true },
      "thing5": { ".validate": true },
      "$other": { ".validate": false
    }
  }
}

Реальный пример

Такая структура данных, как это работает:

/max/<number>
/things_counter/<number>
/things/$record_id/{...data...}

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

var fb = new Firebase(URL);
fb.child('thing_counter').transaction(function(curr) {
   // security rules will fail this if it exceeds max
   // we could also compare to max here and return undefined to cancel the trxn
   return (curr||0)+1;
}, function(err, success, snap) {
   // if the counter updates successfully, then write the record
   if( err ) { throw err; }
   else if( success ) {
      var ref = fb.child('things').push({hello: 'world'}, function(err) {
         if( err ) { throw err; }
         console.log('created '+ref.name());
      });
   }
});

И каждый раз, когда запись удаляется, счетчик должен быть уменьшен.

var recordId = 'thing123';
var fb = new Firebase(URL);
fb.child('thing_counter').transaction(function(curr) {
   if( curr === 0 ) { return undefined; } // cancel if no records exist
   return (curr||0)-1;
}, function(err, success, snap) {
   // if the counter updates successfully, then write the record
   if( err ) { throw err; }
   else if( success ) {
      var ref = fb.child('things/'+recordId).remove(function(err) {
         if( err ) { throw err; }
         console.log('removed '+recordId);
      });
   }
});

Теперь о правилах безопасности:

{
  "rules": {
    "max": { ".write": false },

    "thing_counter": {
      ".write": "newData.exists()", // no deletes
      ".validate": "newData.isNumber() && newData.val() >= 0 && newData.val() <= root.child('max').val()"
    },

    "things": {
      ".write": "root.child('thing_counter').val() < root.child('max').val()"
    }
  }
}

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

Другие ресурсы и Мысли

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

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

15
ответ дан Kato 21 August 2018 в 04:32
поделиться
  • 1
    Это было очень тщательно - спасибо, что нашли время, чтобы провести меня через это. Очень полезно. Быстрый вопрос о $id >= 'rec'+root.child('incid/counter').val(), где $id равен значению counter, найденному в вашей скрипке. Если пользователь удаляет запись $id say 3, мы можем остаться с 1,2,4,5, в этот момент эти правила будут падать справа? Как я могу с этим справиться? – Dan Kanze 26 March 2014 в 15:46
  • 2
    Привет, Да, это две разные стратегии: одна для создания уникальных инкрементных записей, другая - для обеспечения максимальной. Для объединения двух, которые я не делал здесь, потребовалось бы немного интриги. – Kato 26 March 2014 в 18:50
  • 3
    Я пытаюсь представить себе, как можно было бы даже обеспечить соблюдение обоих, если $id не было целым числом, которое соответствует текущему значению counter. Что делать, если .write находится в объектном свойстве, разделяющем muiltiple records, или если каждый $id был случайным? У вас есть идеи, которые не требуют $id для увеличения с помощью counter? – Dan Kanze 26 March 2014 в 20:15
  • 4
    Это единственная идея для полностью клиентского подхода, который я вызываю. Вы всегда можете развернуть процесс узла примерно в 20 строках кода для отслеживания пути, подсчета записей, обеспечения максимальной и т. Д. – Kato 26 March 2014 в 21:51
  • 5
    Да, если $id хочет оторваться от этого шаблона, я думаю, что это то, что мне нужно сделать. – Dan Kanze 26 March 2014 в 21:58

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

https://github.com/firebase/functions -samples / дерево / мастер / лимитных детей

1
ответ дан Gonzalo 21 August 2018 в 04:32
поделиться
  • 1
    Спасибо Гонсало. Это быстрое и мощное решение. Это связано с тем, что можно поставить логику и ограничить своих пользователей ограничениями на стороне клиента, однако в Облачных функциях так легко поймать всех, кто пытается обойти правила, которые вы предоставили на стороне клиента. Проверьте firebase.google.com/docs/functions – katmanco 27 August 2017 в 15:54
Другие вопросы по тегам:

Похожие вопросы: