単純にnullチェックをするだけでは微妙なことになる。
ハマったので議事録的に残す。
firestoreのrulesにはコメントも書き込める。
RDBみたいにちょっと繋げば制約とデータ構造を把握できるが、firestoreだとおそらくこれを見るしかないので該当のカラムに対してvalidationメソッドを明示的に用意するといいかも。
Realtime Databaseでは .validate
が用意されており、明示的に書くことができた。
firestoreではまだこういった仕組みは用意されてないように見え、自信でvalidationを実装する必要がある。
https://firebase.google.com/docs/database/security?hl=ja#section-validation
うーん、可読性が低いのでなんとかしてほしいなー
いい方法があるんだろうか
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userID} {
allow read: if true;
allow create, update: if request.auth != null
&& request.auth.uid == userID
&& isValidUsers();
}
// utilitie functions
function existingData() {
return resource.data
}
function incomingData() {
return request.resource.data
}
function currentUser() {
return request.auth
}
// collection rules
function isValidUsers() {
return isValidNickName()
&& isValidProfileText()
&& isValidIconURL()
&& isValidCreatedAt()
&& isValidUpdatedAt()
}
// document rules
function isValidNickName(){
return (incomingData().keys().hasAll(['nickname']) == false ||
(incomingData().nickname != null
&& incomingData().nickname is string
&& incomingData().nickname.size() > 0
&& incomingData().nickname.size() <= 20))
}
function isValidProfileText(){
return (incomingData().keys().hasAll(['profile_text']) == false ||
(incomingData().profile_text != null
&& incomingData().profile_text is string
&& incomingData().profile_text.size() >= 0
&& incomingData().profile_text.size() <= 500))
}
function isValidIconURL(){
return incomingData().keys().hasAll(['icon_url']) == false ||
(incomingData().icon_url != null && incomingData().icon_url is string)
}
function isValidCreatedAt(){
return incomingData().keys().hasAll(['created_at']) == false ||
(incomingData().created_at != null && incomingData().created_at is timestamp)
}
function isValidUpdatedAt(){
return incomingData().keys().hasAll(['updated_at']) == false ||
(incomingData().updated_at != null && incomingData().updated_at is timestamp)
}
}
}