31
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Cloud Firestoreのセキュリティルールの書き方

Last updated at Posted at 2019-08-13

はじめに

firestoreのセキュリティルールの記述方法に関する記事がそんなに多くないので書いてみました
どういう設計にすれば良いとか、どれくらいお金がかかるとか、そもそもfirestoreとはなんぞやみたいなことは書いてませんので、ご了承ください

基本

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{user} {
      allow read: if request.auth.uid != null;  //ログインしていれば閲覧を許可
      allow write: if request.auth.uid != null;  //ログインしていれば書込を許可
    }
  }
}

コレクション名はキャメルケースにしてください
ケバブケースではセキュリティルールを設定できませんでした

ワイルドカードを使用して、配下のドキュメント全てにルールを設定できる

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read: if request.auth.uid != null;
    }
  }
} 

ワイルドカード使用時の注意

同じドキュメントに対して一つでも許可をする記述があると、他の項目で拒否の設定をしても許可されてしまいます

// NG例
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read;
    }
    match /users/{user} {
      allow read: if request.auth.uid != null;
    }
  }
}

上記の場合だと、{document=**}の項目で全てのユーザーに対して読込を許可しているため、{user}でログインユーザーのみ閲覧可の設定をしても全てのユーザーが閲覧できてしまいます

サブコレクションは入れ子にできる

match /databases/{database}/documents {
  match /users/{user} {
    allow read: if request.auth.uid != null;
    match /children/{child} {
      allow read: if request.auth.uid != null;
      allow write: if request.auth.uid != null;
    }
  }
}

他のコレクションを参照できる

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read: if request.auth.uid != null;
            write: if request.auth.uid != null;
      match /children/{child} {
        allow read: if request.auth.uid != null;
        allow create: if request.auth.uid != null &&
                      // userドキュメントのemailフィールドと、ログインユーザーのemailが一致すれば許可
                      get(/databases/$(database)/documents/users/$(userId)).data.email == request.auth.token.email && 
                      // usersコレクションにログインユーザーのIDと同じIDのドキュメントが存在すれば許可
                      exists(/databases/$(database)/documents/users/$(request.auth.uid)) == true;
      }              
    }
  }
}

get()で他コレクションのドキュメントを取得できます
exists()はドキュメントが存在すればtrue、存在しなければfalseを返します
{}内の値を$()で代入することができます
これらを使用して、ログインしているユーザーのデータしか編集できないようにするといった設定が可能です

条件を関数化できる

match /databases/{database}/documents {
  function isLogin() {
    return request.auth.uid != null;
  }
  match /users/{user} {
    allow read: if isLogin();
    match /children/{child} {
      allow read: if isLogin();
      allow write: if isLogin();
    }
  }
}

read/writeはさらに細かく分類できる

  • read
  • get
  • list
  • write
  • create
  • update
  • delete

バリデーション

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{user} {
      allow read: if request.auth.uid != null;
      allow create, update: if request.auth.uid != null &&
                            resquest.resource.data.name is string; //データ型を指定
                            resquest.resource.data.name.size() <= 50;  //文字数を指定
                            resquest.resource.data.email.matches('.*@domain[.]com') == true;  //文字列が一致するかをチェック
    }
  }
}

request.resource.dataで送られてくる値を取得することができる

設定可能なデータ型一覧
https://firebase.google.com/docs/reference/rules/rules?hl=ja

referenceの場合

firestoreではドキュメントのフィールドに対して、他のドキュメントを参照するリファレンスを設定することができます
スクリーンショット 2019-08-13 9.52.24.png
この場合のデータ型指定↓

service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{user} {
      allow read: if request.auth.uid != null;
      match /children/{child} {
        allow read: if request.auth.uid != null;
        allow create: if request.auth.uid != null &&
                      resquest.resource.data.parent is path; //reference型であれば許可
      }              
    }
  }
}

シミュレータ

firestoreにはセキュリティルールの記述を確認するためのシミュレータが用意されています
ドキュメントのモックを作成し、ルールが設定できているのかを簡単にテストすることができます

シミュレータの使い方はこちら
https://qiita.com/sgr-ksmt/items/a9032557aba9fd2f7843

ただ、このシミュレータは完全ではないようで、他コレクションを参照するis path get() exists()についてはテストすることができません(2019/8/10現在)
それ以外のところでは簡単にルールをテストできるため、とても便利だと思います

最後に

読んでくださり、ありがとうございました
アドバイス、ご指摘等あればコメントよろしくお願いします

参考サイト

公式リファレンス
https://firebase.google.com/docs/firestore/security/secure-data?hl=ja#multiple_rules_for_the_same_document

その他
https://medium.com/google-cloud-jp/firestore3-9518331f8748
https://tech-blog.sgr-ksmt.org/2018/12/11/194022/

31
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?