# 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`