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に登録されている全データが表示される仕組みになってます。
入力と表示のコードはこんな感じ
<!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。
// 受け取った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})`)
})
}
// 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;
}
}
}
フォームに入力して送信を押すと、確かに権限がなくてエラーが発生している事が分かります(上記で設定したエラー文言が表示されています)。
また下記のように記述する事で、全く関係のないコレクション(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;
}
}
}
終わりに
今回はread
とwrite
にフォーカスしていますが、2つはそれぞれget
とlist
、create
, update
, delete
に細分化して、もっと細かな制御もできます。
参考
1.Cloud Firestore セキュリティ ルールを構造化する
2.[Firebase] Firestoreで読み書きする (Web編)