Menguji Aturan Keamanan Cloud Firestore

Saat membuat aplikasi, Anda mungkin ingin mengunci akses ke database Cloud Firestore. Namun, sebelum memulai, Anda memerlukan Aturan Keamanan Cloud Firestore yang lebih tertata. Dengan emulator Cloud Firestore, Anda dapat menulis pengujian unit yang akan memeriksa perilaku Aturan Keamanan Cloud Firestore Anda.

Quickstart

Untuk beberapa kasus pengujian dasar dengan aturan sederhana, cobalah Quickstart javaScript atau Quickstart typeScript.

Memahami Aturan Keamanan Cloud Firestore

Terapkan Firebase Authentication dan Aturan Keamanan Cloud Firestore untuk autentikasi, otorisasi, serta validasi data tanpa server saat Anda menggunakan library klien seluler dan web.

Aturan Keamanan Cloud Firestore mencakup dua bagian:

  1. Pernyataan match yang menunjukkan dokumen dalam database Anda.
  2. Ekspresi allow yang mengontrol akses ke dokumen tersebut.

Firebase Authentication memverifikasi kredensial pengguna dan memberikan landasan untuk sistem akses berbasis pengguna dan peran.

Sebelum membaca atau menulis data, setiap permintaan database dari library klien seluler/web Cloud Firestore dievaluasi terhadap aturan keamanan Anda. Apabila aturan tersebut menolak akses ke salah satu lokasi dokumen yang ditentukan, seluruh permintaan akan gagal.

Pelajari lebih lanjut tentang Aturan Keamanan Cloud Firestore di bagian Memulai Aturan Keamanan Cloud Firestore.

Menginstal emulator

Untuk menginstal emulator Cloud Firestore, gunakan Firebase CLI dan ikuti langkah-langkah berikut.

  1. Instal emulator Cloud Firestore:

     firebase setup:emulators:firestore
     

  2. Mulai emulator menggunakan perintah berikut. Emulator berjalan selama semua pengujian Anda.

     firebase serve --only firestore
     

Sebelum menjalankan emulator

Sebelum Anda mulai menggunakan emulator, perhatikan hal-hal berikut:

  • Satu-satunya SDK yang saat ini mendukung emulator adalah Node.js SDK. Kami telah menyediakan modul @firebase/testing untuk mempermudah interaksi dengan emulator.
  • Emulator mendukung tanda CLI --rules opsional. Emulator mengharapkan nama file lokal yang berisi Aturan Keamanan Cloud Firestore dan menerapkan aturan tersebut untuk semua project. Jika Anda tidak menyediakan lokasi file lokal atau menggunakan metode loadFirestoreRules seperti yang dijelaskan di bawah, emulator akan memperlakukan semua project sebagai aturan terbuka.

Menjalankan pengujian lokal

Gunakan modul @firebase/testing untuk berinteraksi dengan emulator yang berjalan secara lokal. Jika Anda menemukan error ECONNREFUSED atau waktu tunggu, periksa kembali apakah emulator sedang berjalan atau tidak.

Kami sangat menyarankan untuk menggunakan Node.js versi terbaru agar Anda dapat menggunakan notasi async/await. Hampir semua perilaku yang mungkin ingin Anda uji melibatkan fungsi asinkron, dan modul pengujian dirancang untuk digunakan dengan kode berbasis Promise.

Modul ini menampilkan metode-metode berikut:

  • initializeTestApp({ projectId: <name>, auth: <auth> }) => FirebaseApp

    Metode ini menampilkan aplikasi Firebase yang diinisialisasi sesuai dengan ID project dan variabel autentikasi yang ditentukan dalam opsi. Gunakan metode ini untuk membuat aplikasi yang diautentikasi sebagai pengguna khusus untuk digunakan dalam pegujian.

     firebase.initializeTestApp({
       projectId: "my-test-project",
       auth: { uid: "alice", email: "alice@example.com" }
     });
    
  • initializeAdminApp({ projectId: <name> }) => FirebaseApp

    Metode ini menampilkan aplikasi Firebase admin yang diinisialisasi. Aplikasi ini mengabaikan aturan keamanan saat melakukan pembacaan dan penulisan. Gunakan metode ini untuk membuat aplikasi yang diautentikasi sebagai admin guna menyiapkan status untuk pengujian.

    firebase.initializeAdminApp({ projectId: "my-test-project" });
    
  • apps() => [FirebaseApp] Metode ini menampilkan semua aplikasi pengujian dan admin yang saat ini diinisialisasi. Gunakan ini untuk membersihkan aplikasi di antara pengujian atau setelah pengujian.

     Promise.all(firebase.apps().map(app => app.delete()))
    
  • loadFirestoreRules({ projectId: <name>, rules: <rules> }) => Promise

    Metode ini mengirim aturan ke database yang berjalan secara lokal. Perlu objek yang menentukan aturan sebagai string. Gunakan metode ini untuk menetapkan aturan database Anda.

     firebase.loadFirestoreRules({
       projectId: "my-test-project",
       rules: fs.readFileSync("/path/to/firestore.rules", "utf8")
     });
    
  • assertFails(pr: Promise) => Promise

    Metode ini menampilkan promise yang ditolak jika input berhasil atau yang berhasil jika input ditolak. Gunakan metode ini untuk menegaskan jika pembacaan atau penulisan database gagal.

    firebase.assertFails(app.firestore().collection("private").doc("super-secret-document").get());
    
  • assertSucceeds(pr: Promise) => Promise

    Metode ini menampilkan promise yang berhasil jika input berhasil dan ditolak jika input ditolak. Gunakan metode ini untuk menegaskan jika pembacaan atau penulisan database berhasil:

    firebase.assertSucceeds(app.firestore().collection("public").doc("test-document").get());
    
  • clearFirestoreData({ projectId: <name> }) => Promise

    Metode ini menghapus semua data yang terkait dengan project tertentu dalam instance Firestore yang dijalankan secara lokal. Gunakan metode ini untuk menghapus setelah pengujian.

    firebase.clearFirestoreData({
     projectId: "my-test-project"
    });
    

Menghasilkan laporan pengujian

Setelah menjalankan serangkaian pengujian, Anda dapat mengakses laporan cakupan pengujian yang menunjukkan evaluasi dari setiap aturan keamanan Anda.

Untuk mendapatkan laporan, buat kueri untuk endpoint yang terekspos pada emulator selagi endpoint ini berjalan. Untuk versi yang cocok dengan browser, gunakan URL berikut:

http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage.html

URL ini memerinci aturan Anda ke dalam ekspresi dan subekspresi yang dapat Anda klik untuk mengetahui informasi lebih lanjut, termasuk jumlah evaluasi dan nilai yang ditampilkan. Untuk versi JSON mentah data ini, sertakan URL berikut dalam kueri Anda:

http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage

Perbedaan antara emulator dan produksi

  1. Anda tidak harus secara eksplisit membuat project Cloud Firestore. Emulator secara otomatis membuat setiap instance yang diakses.
  2. Emulator Cloud Firestore tidak memiliki interaksi yang berfungsi dengan produk Firebase lainnya. Secara khusus, alur Firebase Authentication normal tidak akan berfungsi. Sebagai gantinya, kami telah menyediakan metode initializeTestApp() dalam modul pengujian, yang menempati kolom auth. Pengendali Firebase yang dibuat menggunakan metode ini akan berperilaku seolah-olah telah berhasil diautentikasi sebagai entity apa pun yang Anda berikan. Jika Anda meneruskan null, pengendali tersebut akan berperilaku sebagai pengguna tak terautentikasi (misalnya aturan auth != null akan gagal).
  3. Emulator Cloud Firestore mempertahankan data. Hal ini dapat memengaruhi hasil Anda. Untuk menjalankan pengujian secara independen, tetapkan project ID yang berbeda untuk setiap pengujian independen. Saat Anda memanggil firebase.initializeAdminApp atau firebase.initializeTestApp, tambahkan ID pengguna, stempel waktu, atau bilangan bulat acak ke projectID. Anda juga dapat menyelesaikan kondisi race dengan menunggu diselesaikannya promise melalui kata kunci async atau await di JavaScript.

Mengatasi masalah yang diketahui

Saat menggunakan emulator Cloud Firestore, Anda mungkin mengalami masalah yang diketahui di bawah ini. Ikuti panduan berikut untuk memecahkan masalah perilaku tidak teratur yang Anda alami.

Perilaku pengujian tidak konsisten

Jika pengujian Anda sesekali lolos dan gagal, bahkan tanpa perubahan apa pun pada pengujian itu sendiri, Anda mungkin perlu memastikan apakah pengujian ini telah diurutkan dengan benar atau belum. Sebagian besar interaksi dengan emulator bersifat asinkron, jadi periksa kembali apakah semua kode asinkron telah diurutkan dengan benar. Anda dapat memperbaiki urutan tersebut baik dengan merangkai promise, atau menggunakan notasi await secara bebas.

Secara khusus, tinjau operasi asinkron berikut: - Menetapkan aturan keamanan, misalnya dengan firebase.loadFirestoreRules. - Membaca dan menulis data, misalnya dengan db.collection("users").doc("alice").get(). - Pernyataan operasional, termasuk firebase.assertSucceeds dan firebase.assertFails.

Pengujian hanya lolos saat pertama kali Anda memuat emulator

Emulator bersifat stateful. Emulator menyimpan semua data yang ditulis ke dalam memori, sehingga data apa pun akan hilang setiap kali emulator nonaktif. Jika Anda menjalankan beberapa pengujian terhadap project id yang sama, setiap pengujian dapat menghasilkan data yang mungkin memengaruhi pengujian berikutnya. Anda dapat menggunakan salah satu metode berikut untuk mengabaikan perilaku ini:

  • Gunakan project ID unik untuk setiap pengujian.
  • Ubah struktur pengujian Anda agar tidak berinteraksi dengan data tertulis sebelumnya (misalnya, gunakan koleksi yang berbeda untuk setiap pengujian).
  • Hapus semua data tertulis selama pengujian.

Penyiapan pengujian sangat rumit

Anda dapat menguji skenario yang tidak diizinkan berdasarkan Aturan Keamanan Cloud Firestore Anda. Misalnya, sulit untuk menguji apakah pengguna yang tidak diautentikasi dapat mengedit data, karena Anda tidak dapat mengedit data sebagai pengguna yang tidak diautentikasi.

Jika aturan Anda memperumit penyiapan pengujian, coba gunakan klien yang diotorisasi admin untuk mengabaikan aturan. Anda dapat melakukannya dengan firebase.initializeAdminApp. Pembacaan dan penulisan dari klien yang diotorisasi admin akan mengabaikan aturan serta tidak memicu error PERMISSION_DENIED.

Kirim masukan tentang...

Butuh bantuan? Kunjungi halaman dukungan kami.