超入門Firestore Security Ruleプログラミング (Vue.jsのサンプルコード付き

## はじめに
Firebase初めてで且つ、Firestore入門時にSecurity Ruleを見て、なんじゃこれってなる方は多いかと思います。
Security Ruleも1つの言語として扱って法則や書き方、各スコープに暗黙的に追加される変数等を把握して**抵抗をなく快適に**Security Ruleプログラミングできたらいいなと思います。

## ゴール
Security Ruleの書き方を学んでFirestoreをコードのバグや、クラッカーの驚異から守る。

## 1. ruleをwebconsoleで気軽に試す
firebaseで自身の練習用プロジェクトを選択して入り、Firestore console画面のルールタブをクリックする
画面はこんな感じになってるはず
<img width="1612" alt="スクリーンショット 2018-10-30 11.03.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/141711/d030d047-88ee-dfe0-2319-de5d8c3c71a1.png">

## ruleをローカルで管理する
firebase、firestoreの環境構築済みを想定しています。

自身のプロジェクトにある``firebase.json``を開き、firestore項目のrule項目にfirestoreのsecurity ruleファイル名を指定します。

### 例

```json:firebase.json
{
  "firestore": {
    "rules": "firestore.rules"
  },
}
```

この場合、自身のfirebase.jsonと同じディレクトリに``firestore.rules``ファイルを作成する
そうすれば以下コマンドでデプロイする時に一緒にルールもデプロイされる

```
$ firebase deploy
```

勿論以下のコマンドでruleだけをデプロイすることもできる

```
$ firebase deploy --only firestore:rules
```

### 余談
もちろんこのように好きな名前をつけることもできる

```json:firebase.json
{
  "firestore": {
    "rules": "piyopiyo.rules"
  },
}
```

## ruleをローカルで管理する時に役立つツール
筆者は主にvscodeを使っていますが、vscodeにはFirebase開発をサポートするいくつかの拡張機能があります。

例: security rule周りを良い感じにしてくれるやつ
<img width="1257" alt="スクリーンショット 2018-10-30 11.07.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/141711/be8331c1-c599-6185-a649-ed809c9fab0f.png">

これを入れると``*.rules``がこんな感じにシンタックスされまる
<img width="832" alt="スクリーンショット 2018-10-30 11.01.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/141711/b50392e3-99b5-9323-8a96-f2b5535a9786.png">
とても良い感じですね！


## 文法編
ではここからSecurity Ruleの基本的な文法に関して話していきます！

## 題材
今回はこのsecurity ruleを元に解説をしていきます。

```javascript:firestore.rules
service cloud.firestore {
  match /databases/{database}/documents {
    function isAuthenticated() {
      return request.auth != null;
    }
    function isMyDoc(userId) {
      return request.auth.uid == userId;
    }
    match /user/{userId} {
      allow read: if isAuthenticated();
      allow write: if isMyDoc(userId);
    }
    match /privateuser/{userId} {
      allow read, write: if isMyDoc(userId);
    }
  }
}
```

### 怖くないよ構文
実は今回のこのruleのサンプルは、Javascriptのシンタックスハイライトを使っています。
そう、security ruleの構文はJavascriptに凄く似ているんです！

---

### なんじゃこれ！！ その1

まずはこれなんだ！？ってなると思います。
実は調べてないので自分も知りませんが、まぁJavaとかのpublic void main的な奴じゃないかなと思います。
まぁ、知らなくてもコードに影響ないのでおまじないでいいでしょ！ (もし知ってる人いたら教えてくれると嬉しいです☺

#### サンプル

```javascript
service cloud.firestore {
  match /databases/{database}/documents {
  }
}
```

---

### なんじゃこれ！！ その2

これJSの関数じゃん！ってなると思います。
はい、関数構文のシンタックス全く同じです☺

#### サンプル

```javascript
function isAuthenticated() {
   return request.auth != null;
}
```

---

### なんじゃこれ！！ その3

このrequest変数ってなんじゃ！どこにも定義されてないぞ！ってなると思います。
はい、このrequest変数はブラウザのwindow変数とかと同じようにグローバルに元から埋め込まれている変数です！
え！じゃあ他にも色々と定義済みな変数ってあるの！？と身構えるかもしれませんが、きっと多分おそらくないと思います(2018/11/30日時点)。
[参考にしたソースはこれ](https://firebase.google.com/docs/firestore/security/secure-data?hl=ja#the_request_variable)です。

request変数はオブジェクトで色んなプロパティがとかが生えてます。
その辺も参考にしたソースのリンクを参照してください。

#### サンプル

```javascript
function isAuthenticated() {
   return request.auth != null;
}
```

---

### この関数結局どういう意味じゃあ！

この関数はログイン判定をする関数です。
関数がtrueを返せばログイン済み、falseを返せば未ログインです。

#### サンプル

```javascript
function isAuthenticated() {
   return request.auth != null;
}
```

---

### ログインしてるユーザーにしかこのドキュメント見せたくないんじゃあ！
``isAuthenticated``でログイン判定ができるので以下のように使えばログインしてる人しかこのドキュメントは読み込めません。

#### サンプル

```javascript
service cloud.firestore {
  match /databases/{database}/documents {
    function isAuthenticated() {
      return request.auth != null;
    }
    match /user/{userId} {
      allow read: if isAuthenticated();
    }
  }
}
```

これreadしか書いてないじゃん！この場合writeってどうなるの！？って思った方は鋭いです！
firestoreは基本このように誰に読み取り・書き込みの許可を出すのかを書かなければ基本全部禁止されています。
つまりこのコードの場合、全てのドキュメントへの書き込みは全ユーザーに禁止されているって事んです！とても安全でシンプルでしょう！

---

### 俺のドキュメントは俺が好きに書き込みたいんじゃあ！
本人のドキュメントかどうかを判定するにはこのルールは良い感じです。
ログインされていた場合、authにはuidがつきます。そのuidとアクセスしたドキュメントのuidが一致したら書き込みを許可しますよ！ってルールです。

#### サンプル

```javascript:firestore.rules
service cloud.firestore {
  match /databases/{database}/documents {
    function isMyDoc(userId) {
      return request.auth.uid == userId;
    }
    match /user/{userId} {
      allow write: if isMyDoc(userId);
    }
  }
}
```

### 最後に
とりあえず自分の入門編としてはこの辺までにしようともいます。
この記法だけでも大体のニーズにあったルールはかけるんじゃないでしょうか。
当たり前ですが[公式ドキュメント](https://firebase.google.com/docs/firestore/security/secure-data?hl=ja#the_request_variable)の方がとても詳細に書かれているので、もしこの内容を見てfirestoreのルール書いてみたい！って思って頂けましたら是非ともそちらもご参照ください。

また、自分が書いてるfirebase + vue.jsのサンプルコードもございますので、もしvue.js + firebaseで快適な開発してみたいって方がいましたら、ご参考にまでどうぞ
https://github.com/k-okina/book-management