---
# System prepended metadata

title: 'Firebase with Android Studio part-13 : Security Rules with Firestore'
tags: [Firebase, Android, kotlin]

---

# Firebase with Android Studio part-13 : Security Rules with Firestore 

## 開始吧
* 在Fire Store選取"規則"分頁，可以看到預設的Rules
![](https://i.imgur.com/5YvbUVo.png)

### 預設值
* rules_version是用於編寫Firebase rule的語言版本，目前最新版是2，如果沒寫這一行，預設會用1
* service cloud.firestore是描述底下的rule套用於firestore這個服務
* match /databases/{database}/documents裡面就是要放定義的rule了

```javascript=
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if
          request.time < timestamp.date(2021, 8, 5);
    }
  }
}
```

### match區塊
* 它定義了rule適用的路徑或者是集合
* match區塊內必須包含allow語句
* match可以用巢狀結構
* 巢狀match路徑必須相對於父層的路徑
    * 如上方預設值，第一層match路徑指向所有集合的documents，巢狀match指向該documents底下所有的document

### allow區塊
* 這個區塊就是定義實際的規則

| 方法   | 請求類型                   |
| ------ | -------------------------- |
| 簡易   | ----------------           |
| read   | 任何類型的讀取請求         |
| write  | 任何類型的寫請求           |
| 標準   | -----------------          |
| get    | 對單個文檔或文件的讀取請求 |
| list   | 查詢和集合的讀取請求       |
| create | 編寫新文檔或文件           |
| update | 寫入現有文檔或文件         |
| delete | 刪除數據                   |

### 試著修改預設值
* 這邊建立兩個集合:country & level
* 各自存放兩個文件:taiwan & thailand
* 各自存放一個欄位:population & write
![](https://i.imgur.com/GWiRP8R.png)
![](https://i.imgur.com/JCG984g.png)
```javascript=
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
  //從底下這邊開始修改
  //底下match區塊是我們rule的作用區域是level這個集合，{}裡面放測試的路徑，稍後測試會提到
    match /level/{level} {
    //底下是rule本身，允許讀寫只要它的發出請求時間在xxx之前，這是之前我們創建資料庫選擇測試模式，30天後自動刪除的原因
      allow read, write: if
          request.time < timestamp.date(2021, 8, 5);
    }
    //底下我們替country這個集合寫一個rule，讀取我們直接打開，那寫入的部分，我們給他條件，在country這個集合底下的{文件}，它的欄位population <500就可以寫入
    match /country/{country} {
    	allow read: if true;
      allow write:if resource.data.population < 500;
    }
  }
}
```
* 使用測試工具
![](https://i.imgur.com/HzEIyDx.png)
* 輸入條件
    * 要測試寫入，所以類型選update
    * 位置:因為要測試country這個集合
    * country/後面就是要放文件，對應到code的{}裡面
![](https://i.imgur.com/Vxt5FHo.png)
* 建立文件
    * 建立我們要測試的條件欄位
    * 我們的規則寫<500，所以這邊可以填個600做測試
![](https://i.imgur.com/7QCBdwr.png)
* 就可以按執行察看結果
* 假設我們針對單一文件寫rule
    * 針對不同文件定義不同條件
```javascript=
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /level/{level} {
      allow read, write: if
          request.time < timestamp.date(2021, 8, 5);
    }
    //父層作用範圍把它定義在country這個集合
    match /country {
        //再用巢狀定義在taiwan這個文件
        match /taiwan {
      	allow write:if resource.data.population > 500;
    		allow read: if true;
        }
        //巢狀定義在thailand這個文件
        match /thailand {
      	    allow read: if true
            allow write:if resource.data.population >1000
      }
    }
  }
}
```
![](https://i.imgur.com/UZlCR27.png)

* 如果要判斷某個欄位要等於某個值才允許寫入
    * 這邊比較奇怪的是如果不寫request就不行
    * 但上面的例子用resource.data.population >1000卻是正常的，我試著把request加在這前面卻也可以正常執行...謎!!!
```javascript=
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /level/{level} {
      allow read: if true;
      //透過request取得can_write這個欄位是否為true
      allow write: if request.resource.data.can_write == true;
    }
  }
}
```
* 如果A集合的文件寫入條件需要B集合的文件判斷是否有權限才能寫入呢?
    * 用get()，/databases/$(database)/documents/，這是預設寫法，後面接續填入目標集合跟文件
    * 底下的規則是，要寫入country的thailand文件，它需要population大於500，而且level這個集合的mamber文件中的can_write欄位必須為true
```javascript=
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /level/{level} {
      allow read: if true;
      allow write: if request.resource.data.can_write == true;
         // request.time < timestamp.date(2021, 8, 5);
    }
    match /country {
    	match /taiwan {
      	allow write:if resource.data.population > 500;
    		allow read: if true;
      }
      match /thailand {
      	allow read: if true
        //這裡用&&加入第二個條件
        allow write:if resource.data.population >1000 &&
        	get(/databases/$(database)/documents/level/member).data.can_write == true;
      }
    }
  }
}
```

官方文件還有很多內容[來看看吧](https://firebase.google.com/docs/rules/rules-language?authuser=0#storage)

參考資料
[Philipp Lackner's channel](https://www.youtube.com/watch?v=C999kVz96_w)


###### tags: `Firebase` `kotlin` `Android`