keyboard_tabSkip to content
listVue Firebase Masterclass

ใส่ Firestore rule

สารบัญ

Firestore Security Rule คืออะไร ?

เอกสารต้นฉบับ: https://firebase.google.com/docs/firestore/security/get-started

Firestore Security Rule คือ set ของ configurations ที่ระบุเอาไว้ว่าใครที่สามารถอ่านและเขียนข้อมูลลงได้บ้าง

  • ฉบับ local (หรือ development บนเครื่อง) จะสามารถแก้ผ่าน firestore.rules ที่สร้างจาก firebase init ตรงๆได้
  • ฉบับ server จะสามารถแก้ผ่านหน้าเว็บ Firebase > Firestore > Rules

rule-01

ในหัวข้อนี้เราจะปรับกันที่ local กันก่อน แล้วเดี๋ยวก่อน deployment เราจะทำการย้าย Firestore Security Rule อีกที

กั้นข้อมูล user

โดย เงื่อนไขคือ

  • ดึงได้เฉพาะข้อมูลของ user ตัวเอง (ถ้าไม่ใช่ admin)
  • ไม่เว้นแม้แต่ moderator ก็มาเห็น user คนอื่นไม่ได้ (เมื่อลองมาเปิด path ตรงๆ)
  • ถ้าเป็น admin = สามารถดูข้อมูลทุกคนได้

ที่ firestore.rules

service cloud.firestore {
  match /databases/{database}/documents {
    function isAdmin() {
      return request.auth.uid != null || get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin';
    }

    match /users/{userId} {
      allow read, write: if request.auth != null && (request.auth.uid == userId || isAdmin());
    }
  }
}

กั้นข้อมูล Frontend ให้เห็นแค่ status 'open' เท่านั้น

เพิ่มเงื่อนไขนี้เข้ามาใน firestore.rules

rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
    match /products/{productId} {
      allow read: if (request.auth != null && isAdmin()) || (resource.data.status == 'open');
      allow write: if (request.auth != null && isAdmin()) || (resource.data.status == 'open');
    }
  }
}

ทีนี้เราจะเจอว่าหน้าบ้านไม่สามารถเรียกใช้ข้อมูลได้ ให้ปรับการเรียก product ฝั่ง Frontend ใหม่เป็น

ที่ stores/user/product.js

javascript
import { defineStore } from 'pinia'

import {
  collection,
  getDocs,
  // เพิ่ม query กับ where เข้ามา
  query,
  where
} from 'firebase/firestore'

export const useUserProductStore = defineStore('user-product', {
  state: () => ({
    list: [],
    loaded: false,
    page: 1,
    limit: 2
  }),
  actions: {
    async loadProduct () {
      // เพิ่ม where และ query ในการเรียก condition ตาม rule
      const productsCol = query(collection(db, 'products'), where('status', '==', 'open'))
      const productSnapshop = await getDocs(productsCol)
      const productList = productSnapshop.docs.map(doc => doc.data())
      if (productList && productList.length > 0) {
        this.list = productList
      }
      this.loaded = true
    },
    /* function อื่นเหมือนเดิม */
  }
})

ผลลัพธ์ของ code นี้ ให้ลอง setup product เป็น status close ดู = จะเจอว่า product ที่เป็น close จะไม่แสดงออกมาได้

rule-02