2
0

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.

Firestoreセキュリティルールを設定してみる

Last updated at Posted at 2020-10-05

0. 始めに

(本記事は、拙作 Firestoreセキュリティルールを読み解く の続きになっています!)
前回で、Firestoreにデフォルトで設定されているルールを読み解いたので、今回は自分でルールを設定してみようと思います。
今回は、読み書きに対して正しくルールが設定されているかを見ていきます。

0.Firestoreセキュリティルールを読み解く ← 前回
1.Firestoreセキュリティルールを設定してみる ← 今回★

1.準備

動作環境ですが、筆者は以下の環境で動作確認しています。
 OS : Windows10 Home
 Node : v11.13.0
 yarn : v1.22.4

また、事前にFirebseプロジェクトの作成を行っておきます。
(詳細な手順は述べませんが、プロジェクト作成について詳しく知りたい場合は、参考までに拙作の記事をご覧ください:Firebaseでデプロイしよう!)

2. モデルとなるサイトの用意

 Firestoreにデータを登録するための入力フォームと、登録されたデータを表示するためのリストが付いたサイトをサクッと用意します1。一番上のフォームに何かしら文字を入力して、「送信」を押すことでfirestore側に登録され、「更新」でfirestoreに登録されている全データが表示される仕組みになってます。

image.png

入力と表示のコードはこんな感じ

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>firestore-otameshi</title>
</head>
<body>
    <form action="submit">
        <input id="addData" type="text">
    </form>
    <button type="button" onclick="addData()">送信</button>
    <button type="button" onclick="getData()">更新</button>
    <h5>Firestore-dataList</h5>
    <div id="dataList"></div>

    <script src="https://www.gstatic.com/firebasejs/7.22.0/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/7.22.0/firebase-firestore.js"></script>
    <script src="./index.js"></script>
    <script src="./config.js"></script>
</body>
</html>

Firestore側へ登録データ取得が失敗したら、エラーログを表示する仕組みにしています(参考2より)。
firebaseのAPI KEYは何となく別ファイルで用意しておきました2

index.js
// 受け取ったHTMLを表示
dispData = (html) => {
    document.querySelector("#dataList").innerHTML = html
}

// フォームのデータをfirestoreに追加
addData = () => {
    const inputData = document.getElementById("addData")

    if (!inputData.value) return
    firebase.firestore().collection("dataList").add({
        text: inputData.value
    })
    .then(() => {
        console.log("success!")
    })
    .catch((error) => {
        dispData(`データの追加に失敗しました (${error})`)
    })
}

// firestoreからデータを取得
getData = () => {
    firebase.firestore().collection("dataList").get().then((querySnapshot) => {
        let html = "<ul>"
        querySnapshot.forEach((doc) => {
            const data = doc.data()
            html += `<li>${data.text}</li>`
        })
        html += "</ul>"

        dispData(html)
    })
    .catch((error)=> {
        dispData(`データの取得に失敗しました (${error})`)
    })
}
config.js
// Initialize Firebase
firebase.initializeApp({
    apiKey: "XXXXXXXXXXXXXXXXXXXXXXXX",
    authDomain: "firestore-otameshi.firebaseapp.com",
    databaseURL: "https://XXXXXXXXXXXXXXXXX.firebaseio.com",
    projectId: "firestore-otameshi",
    storageBucket: "XXXXXXXXXXXXXXXXXXXX.appspot.com",
    messagingSenderId: "XXXXXXXXXXX",
    appId: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    measurementId: "XXXXXXXXXXXXXXXXXXX"
})

3. ルール設定前の挙動

まずは、read, writeの両方を許可した状態でデータの登録と取得を行います。
設定するルールはこちら↓3 ほぼデフォルトのルールですが、dataListという名前のコレクションに対して適用されるように、コレクション名とその内部のドキュメントを表す変数をdataとしておきます

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /dataList/{data} {
      allow read, write: if true;
    }
  }
}

(ホントはgifを貼りたいですが、)上記のルールだと登録も取得もうまくいきます。

4. ルール設定後の挙動

続いて、ルールを設定してみます。まずは、書き込み禁止から。

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /dataList/{data} {
      allow read: if true;
      allow write: if false;
    }
  }
}

フォームに入力して送信を押すと、確かに権限がなくてエラーが発生している事が分かります(上記で設定したエラー文言が表示されています)。

image.png

また下記のように記述する事で、全く関係のないコレクション(dummyList)に対してルールを設定しても、dataListには適用されない事も確認できます4

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /dataList/{data} {
   		allow read, write: if true;
    }
    match /dummyList/{data} {
      allow read: if true;
      allow write: if false;
    }
  }
}

続いて読み込み権限を付与していない場合も同様に確認できます

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /dataList/{data} {
   		allow write: if true;
      allow read: if false;
    }
  }
}

image.png

終わりに

今回はreadwriteにフォーカスしていますが、2つはそれぞれgetlistcreate, update, deleteに細分化して、もっと細かな制御もできます。

参考

1.Cloud Firestore セキュリティ ルールを構造化する
2.[Firebase] Firestoreで読み書きする (Web編)

  1. と言いつつ、作るのにかなり時間が掛かってしまったのでした(笑)

  2. とは言え、API KEYのスコープがグローバルになっているの、良くない気がする

  3. どの言語のシンタックスハイライト使ったものか、よくわからなかったのですが、何にしたものでしょう。。。?

  4. 更に、全くルールを設定していないコレクションには、全ての操作が禁止されます

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?