2017-02-14 9 views
0

В приложении iOS, которое я создаю с использованием Firebase, у каждого пользователя есть уникальное имя пользователя, которое создается после того, как они подписываются с электронной почтой и паролем.Почему это правило безопасности базы данных Firebase с && и || не работает

Таким образом, если пользователь с эл.адресом [email protected] подписался, а потом пришлось создать уникальное имя, которое не находится в базе данных имени пользователя фрагмент базы данных будет выглядеть следующим образом:

"usernames" : { 
     "test" : "r6KPesUr1qORfIJke07SloZHeNW2", 
     "test1" : "jSMSkY9rHtdNkXoLrsFmCAXdY9n2", 
     "test7" : "jnFhJbgCjZeJFx0hspObqoskQej2", 
     "test8" : "HtnULzU0lnZKYva2M2Wepl6N8wE3" 
    }, 

    "users" : { 
     "HtnULzU0lnZKYva2M2Wepl6N8wE3" : { 
      "email" : "[email protected]", 
      "username" : "test8" 
     }, 
     "boX6rtJ98haWVxNoXfSq21maCVU2" : { 
      "email" : "[email protected]" 
     }, 
     "jSMSkY9rHtdNkXoLrsFmCAXdY9n2" : { 
      "email" : "[email protected]", 
      "username" : "test1" 
     }, 
     "jnFhJbgCjZeJFx0hspObqoskQej2" : { 
      "email" : "[email protected]", 
      "username" : "test7" 
     }, 
     "r6KPesUr1qORfIJke07SloZHeNW2" : { 
      "email" : "[email protected]", 
      "username" : "test" 
     } 
    } 

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

// USERNAMES 
    "usernames": { 
     ".read": "auth.uid != null", 
     ".write": "auth.uid != null", 
     "$username": { 
      ".validate": "(!root.child('usernames').hasChild($username.toLowerCase()) && newData.val() == auth.uid && 
          root.child('users').hasChild(auth.uid)) && 

          (root.child('users/'+auth.uid+'/username').val().toLowerCase() == $username || 
          !root.child('users/'+auth.uid+'/username').exists())"     
     }         
    } 

Для правил проверки я хотел бы, чтобы эти три заявления, как должен имущие

(!root.child('usernames').hasChild($username.toLowerCase()) && 
    newData.val() == auth.uid && 
    root.child('users').hasChild(auth.uid)) 

и с этими двумя заявлении один из них должен быть верно

"(root.child('users/'+auth.uid+'/username').val().toLowerCase() == $username || 
    (!root.child('users/'+auth.uid+'/username').exists()" 

так что если пользователь хотел зарегистрироваться с test5 как там имя пользователя со следующим json, тогда он не будет работать с моими текущими правилами безопасности из-за первой части оператор OR.

 "users": { 
     "boX6rtJ98haWVxNoXfSq21maCVU2": { 
       "username": "test5" 
      } 
    } 

Что я делаю неправильно?

+0

Трудно разобрать правила. Можете ли вы изменить свой вопрос, чтобы включить минимальный код, который будет отклонен этим правилом проверки, но который вы хотите разрешить? –

+0

@FrankvanPuffelen уверенный вещь. Я добавил, как будет выглядеть база данных, и json, который впоследствии не будет написан для создания уникального имени пользователя для пользователя с электронным письмом [email protected] – Edward

+0

OK. Я попытался выяснить ваш случай использования. Но из таких сложных правил сложно понять, поэтому я выделил один (ну два) конкретного случая использования и сосредоточился на этом. –

ответ

1

Похоже, что вы хотите две вещи случаться для пользователя, чтобы претендовать на имя пользователя:

  1. узел написан под /users/$uid/username с именем пользователя
  2. узел написано под /usernames/$username с их UID

Ваш фрагмент JSON, который вы сейчас пишете, содержит только # 1. Он не содержит ничего о написании имени пользователя под /usernames. Поэтому правило отклонит его, потому что вы подтверждаете, что имя пользователя должно существовать и быть заявлено для этого пользователя.

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

"users/boX6rtJ98haWVxNoXfSq21maCVU2/username": "test5", 
"usernames/test5": "boX6rtJ98haWVxNoXfSq21maCVU2" 

Ваши правила будут:

"usernames": { 
    "$username": { 
    ".validate": "!data.exists() && 
     newData.exists() && 
     newData.parent().parent().child('users').child(auth.uid).child('username').val() === $username" 
    }         
} 
"users": { 
    "$uid": { 
    "username": { 
     ".validate": "!data.exists() && 
     newData.exists() && 
     newData.parent().parent().parent().child('usernames').child(newData.val()).val() === $uid" 
    } 
    } 
} 

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

+0

Я думаю, вам нужно удалить скобки из newData() для конечных правил как в «users», так и «usernames» – Edward

+0

Я не уверен, что понимаю, что вы имеете в виду. Не стесняйтесь предлагать редактирование. –