部署到firebase时获得400,规则语法错误

时间:2017-09-06 14:46:58

标签: firebase firebase-realtime-database firebase-security

当我运行`firebase deploy'时,我收到以下错误:

Error: HTTP Error: 400, Rules Syntax Error: undefined

这是我的rules.json的样子:

{
  "rules": {
    "users": {
      "$id": {
        "account": {
          ".validate": "newData.hasChildren(['email', 'fullName']) && newData.child('fullName').val().matches(/^\\w.*\\w/)",
          "email": {
            ".validate": "newData.isString() && newData.val().matches(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\\\.[A-Z]{2,4}$/i)"
          },
          "fullName": {
            ".validate": "newData.isString()"
          },
          "$other": {
            ".validate": "false"
          },
          ".write": "$id == auth.uid"
        }
      }
    },
    "quizzes": {
      "$id": {
        ".validate": "newData.hasChildren(['owner', 'created'])",
        "owner": {
          ".validate": "newData.isString()"
        },
        "created": {
          ".validate": "newData.isNumber()"
        },
        "rounds": {
          "$key1": {
            ".validate": "newData.hasChildren(['name', 'questionTime'])",
            "questions": {
              "$key2": {
                ".validate": "newData.isString() && newData.parent().parent().parent().parent().parent().parent().child('questions').child(newData.val()).val() != null"
              },
              ".validate": "newData.hasChildren()"
            },
            "name": {
              ".validate": "newData.isString()"
            },
            "questionTime": {
              ".validate": "newData.isNumber()"
            },
            "$other": {
              ".validate": "false"
            }
          },
          ".validate": "newData.hasChildren()"
        },
        "sessions": {
          "$key3": {
            ".validate": "newData.isString() && newData.parent().parent().parent().parent().child('sessions').child(newData.val()).val() != null"
          },
          ".validate": "newData.hasChildren()"
        },
        "$other": {
          ".validate": "false"
        },
        ".read": "data.child('owner').val() != null && data.child('owner').val() == auth.id || data.child('sessions').val() != null",
        ".write": "newData.child('owner').val() != null && newData.child('owner').val() == auth.uid"
      }
    },
    "questions": {
      "$id": {
        ".validate": "newData.hasChildren(['owner', 'details'])",
        "owner": {
          ".validate": "newData.isString()"
        },
        "details": {
          ".validate": "newData.hasChildren() && newData.hasChildren(['question', 'answer']) || newData.hasChildren() && newData.hasChildren(['question', 'correctAnswer']) || newData.hasChildren() && newData.hasChildren(['audioURL', 'title', 'artist']) || newData.hasChildren() && newData.hasChildren(['imageURL', 'question', 'answer'])",
          "question": {
            ".validate": "newData.isString() || newData.isString() || newData.isString()"
          },
          "answer": {
            ".validate": "newData.isString() || newData.isString()"
          },
          "$other": {
            ".validate": "false"
          },
          "answers": {
            "$key4": {
              ".validate": "newData.isString()"
            },
            ".validate": "newData.hasChildren()"
          },
          "correctAnswer": {
            ".validate": "newData.isString()"
          },
          "audioURL": {
            ".validate": "newData.isString()"
          },
          "title": {
            ".validate": "newData.isString()"
          },
          "artist": {
            ".validate": "newData.isString()"
          },
          "imageURL": {
            ".validate": "newData.isString()"
          }
        },
        "$other": {
          ".validate": "false"
        },
        ".write": "data.val() == null && newData.child('owner').val() == auth.uid || data.val() != null && newData.val() != null && data.child('owner').val() == auth.uid || data.val() != null && newData.val() == null && data.child('owner').val() == auth.uid"
      }
    },
    "sessions": {
      "$id": {
        ".validate": "newData.hasChildren(['quiz', 'created', 'currentRound']) && newData.parent().parent().child('quizzes').child(newData.child('quiz').val()).val() != null",
        "quiz": {
          ".validate": "newData.isString()"
        },
        "created": {
          ".validate": "newData.isNumber()"
        },
        "currentRound": {
          ".validate": "newData.isNumber()"
        },
        "$other": {
          ".validate": "false"
        },
        ".write": "data.val() == null && newData.parent().parent().child('quizzes').child(newData.val()).child('owner').val() == auth.uid || data.val() != null && newData.val() != null && newData.parent().parent().child('quizzes').child(data.val()).child('owner').val() == auth.uid || data.val() != null && newData.val() == null && newData.parent().parent().child('quizzes').child(data.val()).child('owner').val() == auth.uid",
        ".read": "true"
      },
      "$sid": {
        "participants": {
          "$pid": {
            ".validate": "newData.hasChildren(['name', 'score'])",
            "name": {
              ".validate": "newData.isString()"
            },
            "score": {
              ".validate": "newData.isNumber()"
            },
            "$other": {
              ".validate": "false"
            }
          }
        }
      }
    }
  }
}

这是从以下bolt文件生成的:

path /users/{id}/account is UserAccount {
    write() {
        return id == auth.uid
    }
}

type UserAccount {
    email: Email
    fullName: String

    validate() {this.fullName.test(/^\w.*\w/)}
}

type Email extends String {
    validate(){
        return this.test(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$/i)
    }
}

path /quizzes/{id} is Quiz {
    write() {
        return this.owner !== null && this.owner == auth.uid
    }

    read() {
        return (this.owner != null && this.owner == auth.id) || this.sessions != null
    }
}

type Quiz {
    owner : String
    created : Number
    rounds : QuizRound[]
    sessions : SessionRef[]
}

type QuizRound {
    questions : QuestionRef[]
    name : String
    questionTime : Number
}

type QuestionRef extends String {
    validate() {
        root.questions[this] != null
    }
}

type SessionRef extends String {
    validate() {
        root.sessions[this] != null
    }
}

path /questions/{id} is Question {
    create() {
        return this.owner == auth.uid
    }

    update() {
        return prior(this.owner) == auth.uid
    }

    delete() {
        return prior(this.owner) == auth.uid
    }
}

type Question {
    owner : String
    details : TextQuestion | MultipleChoiceQuestion | SongQuestion | PhotoQuestion
}

type TextQuestion {
    question: String
    answer: String
}

type MultipleChoiceQuestion {
    question: String
    answers: String[]
    correctAnswer: String
}

type SongQuestion {
    audioURL: String
    title: String
    artist: String
}

type PhotoQuestion {
    imageURL : String
    question : String
    answer : String
}

path /sessions/{id} is Session {
    read() { true }
    create() {
        return root.quizzes[this].owner == auth.uid
    }

    update() {
        return root.quizzes[prior(this)].owner == auth.uid
    }

    delete() {
        return root.quizzes[prior(this)].owner == auth.uid
    }
}

type Session {
    quiz : String
    created : Number

    currentRound : Number

    validate() {
        root.quizzes[this.quiz] != null
    }

}

path /sessions/{sid}/participants/{pid} is Participant {

}

type Participant {
    name : String
    score : Number
}

1 个答案:

答案 0 :(得分:1)

将生成的代码粘贴到firebase控制台,并尝试上传它,给了我一个更明确的错误:

Error saving rules - Line 141: Cannot have multiple default rules ('$id' and '$sid')

在生成的输出中,我在sessions": $ id and $ sid`下有2个通配符位置,因为在我的bolt路径中,我在2个路径中使用了2个不同的变量名。