Buka konsol

Menulis Condition untuk Aturan Keamanan

Panduan ini dikembangkan dari panduan membuat struktur aturan keamanan untuk menunjukkan cara menambahkan condition ke Aturan Keamanan Cloud Firestore. Jika Anda belum menguasai dasar-dasar Aturan Keamanan Cloud Firestore, baca panduan memulai.

Elemen penyusun utama Aturan Keamanan Cloud Firestore adalah condition. Condition adalah operasi boolean yang menentukan apakah operasi tertentu diizinkan atau ditolak. Gunakan aturan keamanan untuk menulis condition yang memeriksa autentikasi pengguna, memvalidasi data masuk, atau mengakses bagian lain dalam database Anda.

Autentikasi

Salah satu pola aturan keamanan yang paling umum adalah mengontrol akses berdasarkan status autentikasi pengguna. Misalnya, aplikasi Anda mungkin hanya ingin mengizinkan pengguna yang telah login untuk menulis data:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to access documents in the "cities" collection
    // only if they are authenticated.
    match /cities/{city} {
      allow read, write: if request.auth.uid != null;
    }
  }
}

Pola umum lainnya adalah memastikan bahwa pengguna hanya dapat membaca dan menulis data mereka sendiri:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches the 'author_id' field
    // of the document
    match /users/{user} {
      allow read, update, delete: if request.auth.uid == resource.data.author_id;
      allow create: if request.auth.uid != null;
    }
  }
}

Jika aplikasi Anda menggunakan Firebase Authentication, variabel request.auth akan berisi informasi autentikasi untuk klien yang meminta data. Untuk mengetahui informasi lebih lanjut tentang request.auth, lihat dokumen referensi.

Validasi data

Banyak aplikasi yang menyimpan informasi kontrol akses sebagai kolom pada dokumen di database. Aturan Keamanan Cloud Firestore dapat mengizinkan atau menolak akses secara dinamis berdasarkan data dokumen:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

Variabel resource mengacu pada dokumen yang diminta, dan resource.data adalah peta dari semua kolom dan nilai yang tersimpan dalam dokumen tersebut. Untuk mengetahui informasi lebih lanjut tentang variabel resource, lihat dokumentasi referensi.

Ketika menulis data, Anda mungkin ingin membandingkan data yang masuk dengan data yang ada. Dalam hal ini, jika kumpulan aturan Anda mengizinkan penulisan tertunda, variabel request.resource akan memuat status waktu mendatang dari dokumen tersebut. Untuk operasi update yang hanya mengubah sub-kumpulan kolom dokumen, variabel request.resource akan memuat status dokumen tertunda setelah pengoperasian. Anda dapat memeriksa nilai kolom ini di request.resource untuk mencegah update data yang tidak diinginkan atau tidak konsisten:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure all cities have a positive population and
    // the name is not changed
    match /cities/{city} {
      allow update: if request.resource.data.population > 0
                    && request.resource.data.name == resource.data.name;
    }
  }
}

Mengakses dokumen lain

Aturan keamanan Anda dapat memanfaatkan fungsi get() dan exists() untuk mengevaluasi permintaan yang masuk berdasarkan dokumen lain di database. Fungsi get() dan exists() sama-sama memerlukan lokasi dokumen yang ditentukan secara lengkap. Ketika menggunakan variabel untuk membuat lokasi get() dan exists(), Anda harus melepaskan variabel secara eksplisit menggunakan sintaks $(variable).

Pada contoh di bawah, variabel database ditangkap oleh pernyataan kecocokan match /databases/{database}/documents dan digunakan untuk membentuk lokasi:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      // Make sure a 'users' document exists for the requesting user before
      // allowing any writes to the 'cities' collection
      allow create: if exists(/databases/$(database)/documents/users/$(request.auth.uid))

      // Allow the user to delete cities if their user document has the
      // 'admin' field set to 'true'
      allow delete: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true
    }
  }
}

Untuk penulisan, Anda dapat menggunakan fungsi getAfter() untuk mengakses status dokumen setelah sebuah transaksi atau batch penulisan selesai, namun sebelum transaksi atau batch tersebut dijalankan. Seperti get(), fungsi getAfter() mengambil lokasi dokumen yang ditentukan secara lengkap. Anda dapat menggunakan getAfter() untuk menentukan set penulisan yang harus dilakukan bersama sebagai sebuah transaksi atau batch.

Fungsi kustom

Saat aturan keamanan Anda menjadi semakin kompleks, Anda mungkin ingin mengemas kumpulan condition ke dalam fungsi yang dapat digunakan kembali di semua kumpulan aturan. Aturan keamanan mendukung fungsi kustom. Sintaks untuk fungsi kustom mirip dengan JavaScript, namun fungsi aturan keamanan ditulis dalam bahasa khusus domain yang memiliki beberapa batasan penting:

  • Fungsi hanya dapat berisi 1 pernyataan return. Fungsi tidak boleh berisi logika lain apa pun. Misalnya, fungsi tidak dapat membuat variabel perantara, menjalankan loop, atau memanggil layanan eksternal.
  • Fungsi dapat secara otomatis mengakses fungsi dan variabel dari cakupan tempat ditetapkannya. Misalnya, fungsi yang ditetapkan ke dalam cakupan service cloud.firestore memiliki akses ke variabel resource dan memiliki fungsi bawaan seperti get() dan exists().
  • Fungsi dapat memanggil fungsi lain namun mungkin tidak secara berulang. Total tumpukan panggilan dibatasi sampai 10.

Fungsi ditetapkan dengan kata kunci function dan menerima 0 atau lebih argumen. Misalnya, Anda mungkin ingin menggabungkan 2 jenis condition yang digunakan dalam contoh di atas menjadi 1 fungsi:

service cloud.firestore {
  match /databases/{database}/documents {
    // True if the user is signed in or the requested data is 'public'
    function signedInOrPublic() {
      return request.auth.uid != null || resource.data.visibility == 'public';
    }

    match /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

Dengan menggunakan fungsi, aturan keamanan akan lebih mudah dipertahankan seiring semakin kompleksnya aturan. Untuk informasi lebih lanjut tentang fungsi yang ditetapkan developer, baca dokumentasi referensi.

Langkah berikutnya