Testare le regole di sicurezza
Durante la creazione dell'app, ti consigliamo di bloccare l'accesso al database Firestore. Tuttavia, prima del lancio, avrai bisogno di regole di sicurezza di Firestore più dettagliate. Con l'emulatore Firestore, oltre a creare un prototipo e a testare le funzionalità e il comportamento generali della tua app, puoi scrivere test di unità che controllano il comportamento delle regole di sicurezza di Firestore.
Guida rapida
Per alcuni casi di test di base con regole semplici, prova l'esempio di avvio rapido.
Comprendi le regole di sicurezza di Firestore
Implementa Firebase Authentication e Regole di sicurezza di Firestore per l'autenticazione, l'autorizzazione e la convalida dei dati serverless quando utilizzi le librerie client per applicazioni web o per dispositivi mobili.
Le Regole di sicurezza di Firestore includono due elementi:
- Un'istruzione
match
che identifica i documenti nel database. - Un'espressione
allow
che controlla l'accesso a questi documenti.
Firebase Authentication verifica gli account utente credenziali e fornisce le basi sistemi di accesso basati su utenti e ruoli.
Ogni richiesta al database da una libreria client mobile/web Firestore viene valutata in base alle tue regole di sicurezza prima di leggere o scrivere dati. Se le regole negano l'accesso a uno qualsiasi dei percorsi dei documenti specificati, l'intera non va a buon fine.
Scopri di più sulle regole di sicurezza di Firestore in Iniziare a utilizzare le regole di sicurezza di Firestore.
Installa l'emulatore
Per installare l'emulatore Firestore, utilizza l'interfaccia a riga di comando di Firebase esegui il comando riportato di seguito:
firebase setup:emulators:firestore
Esegui l'emulatore
Inizia inizializzando un progetto Firebase nella directory di lavoro. Si tratta di un primo passaggio comune quando si utilizza l'interfaccia a riga di comando di Firebase.
firebase init
Avvia l'emulatore utilizzando il seguente comando. L'emulatore verrà eseguito fino a quando non interrompi il processo:
firebase emulators:start --only firestore
In molti casi si desidera avviare l'emulatore, eseguire una suite di test e quindi chiudere
l'emulatore dopo l'esecuzione dei test. Puoi farlo facilmente utilizzando il comando emulators:exec
:
firebase emulators:exec --only firestore "./my-test-script.sh"
Una volta avviato, l'emulatore tenterà di funzionare su una porta predefinita (8080). Puoi cambiare la porta dell'emulatore modificando la sezione "emulators"
del file firebase.json
:
{ // ... "emulators": { "firestore": { "port": "YOUR_PORT" } } }
Prima di eseguire l'emulatore
Prima di iniziare a utilizzare l'emulatore, tieni presente quanto segue:
- L'emulatore caricherà inizialmente le regole specificate nel campo
firestore.rules
del filefirebase.json
. Deve essere specificato il nome di un file locale contenente le regole di sicurezza di Firestore, che vengono applicate a tutti i progetti. Se non fornisci il percorso file locale o utilizzi il comandoloadFirestoreRules
come descritto di seguito, l'emulatore tratta tutti progetti con regole aperte. - Anche se
la maggior parte degli SDK Firebase
funziona direttamente con gli emulatori, solo la libreria
@firebase/rules-unit-testing
supporta la simulazione diauth
nelle regole di sicurezza, semplificando notevolmente i test di unità. Inoltre, la libreria supporta alcune funzionalità specifiche dell'emulatore, come l'eliminazione di tutti i dati, come elencato di seguito. - Gli emulatori accetteranno anche i token di autenticazione Firebase di produzione forniti tramite SDK client e valutano di conseguenza le regole, il che consente la connessione la tua applicazione direttamente agli emulatori nei test di integrazione e manuali.
Esegui test locali delle unità
Eseguire test locali delle unità con l'SDK JavaScript 9
Firebase distribuisce una libreria di test delle unità di Regole di sicurezza sia con la relativa versione SDK JavaScript 9 e versione 8 dell'SDK. Le API della libreria sono significativamente diverso. Consigliamo la libreria di test V9, che è più semplice e richiede meno configurazione per connettersi agli emulatori e quindi evita all'uso delle risorse di produzione. Per garantire la compatibilità con le versioni precedenti, la libreria di test v8 disponibile.
- Metodi di test e funzioni di utilità comuni nell'SDK versione 9
- Metodi di test specifici per l'emulatore nell'SDK v9
Usa il modulo @firebase/rules-unit-testing
per interagire con l'emulatore
eseguito in locale. Se si verificano timeout o errori ECONNREFUSED
, verifica che l'emulatore sia effettivamente in esecuzione.
Ti consigliamo vivamente di utilizzare una versione recente di Node.js per poter utilizzare la notazione async/await
. Quasi tutti i comportamenti che potresti voler testare richiedono funzioni asincrone e il modulo di test è progettato per funzionare con il codice basato su promesse.
La libreria di test delle unità delle regole v9 è sempre a conoscenza degli emulatori e non le risorse di produzione.
Importa la libreria utilizzando le istruzioni di importazione modulari della versione 9. Ad esempio:
import {
assertFails,
assertSucceeds,
initializeTestEnvironment
} from "@firebase/rules-unit-testing"
// Use `const { … } = require("@firebase/rules-unit-testing")` if imports are not supported
// Or we suggest `const testing = require("@firebase/rules-unit-testing")` if necessary.
Dopo l'importazione, l'implementazione dei test delle unità comporta:
- Creazione e configurazione di un
RulesTestEnvironment
con una chiamata ainitializeTestEnvironment
. - Configurare i dati di test senza attivare le regole, per praticità
che ti consente di ignorarli temporaneamente,
RulesTestEnvironment.withSecurityRulesDisabled
. - Configurare la suite di test e gli hook per test prima/dopo con chiamate a
ripulisci i dati e l'ambiente di test, ad esempio
RulesTestEnvironment.cleanup()
oRulesTestEnvironment.clearFirestore()
. - Implementazione di scenari di test che imitano gli stati di autenticazione utilizzando
RulesTestEnvironment.authenticatedContext
eRulesTestEnvironment.unauthenticatedContext
.
Metodi comuni e funzioni di utilità
Vedi anche i metodi di test specifici dell'emulatore nell'SDK v9.
initializeTestEnvironment() => RulesTestEnvironment
Questa funzione inizializza un ambiente di test per il test delle unità di regole. Chiama per la configurazione di test. Per un'esecuzione corretta, è necessario che gli emulatori siano in esecuzione.
La funzione accetta un oggetto facoltativo che definisce un TestEnvironmentConfig
,
che può essere costituito da un ID progetto e da impostazioni di configurazione dell'emulatore.
let testEnv = await initializeTestEnvironment({ projectId: "demo-project-1234", firestore: { rules: fs.readFileSync("firestore.rules", "utf8"), }, });
RulesTestEnvironment.authenticatedContext({ user_id: string, tokenOptions?: TokenOptions }) => RulesTestContext
Questo metodo crea un RulesTestContext
, che si comporta come un utente autenticato
Utente autenticazione. Alle richieste create tramite il contesto restituito verrà allegato un token di autenticazione simulato. Se vuoi, passa un oggetto che definisce rivendicazioni personalizzate
per i payload dei token di autenticazione.
Utilizza l'oggetto contesto test restituito nei test per accedere a eventuali istanze di emulatore configurate, incluse quelle configurate con initializeTestEnvironment
.
// Assuming a Firestore app and the Firestore emulator for this example import { setDoc } from "firebase/firestore"; const alice = testEnv.authenticatedContext("alice", { … }); // Use the Firestore instance associated with this context await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });
RulesTestEnvironment.unauthenticatedContext() => RulesTestContext
Questo metodo crea un RulesTestContext
, che si comporta come un client che
non hanno effettuato l'accesso tramite Authentication. Le richieste create tramite il contesto restituito non avranno token Firebase Auth allegati.
Utilizza l'oggetto di contesto del test restituito nei tuoi test per accedere a qualsiasi emulatore
istanze configurate, incluse quelle configurate con initializeTestEnvironment
.
// Assuming a Cloud Storage app and the Storage emulator for this example import { getStorage, ref, deleteObject } from "firebase/storage"; const alice = testEnv.unauthenticatedContext(); // Use the Cloud Storage instance associated with this context const desertRef = ref(alice.storage(), 'images/desert.jpg'); await assertSucceeds(deleteObject(desertRef));
RulesTestEnvironment.withSecurityRulesDisabled()
Esegui una funzione di configurazione del test con un contesto che si comporta come se le Regole di sicurezza fossero disabilitate.
Questo metodo prende una funzione di callback, che accetta le regole di sicurezza contesto e restituisce una promessa. Il contesto verrà distrutto una volta che la promessa viene risolta/rifiutata.
RulesTestEnvironment.cleanup()
Questo metodo elimina tutti i RulesTestContexts
creati nell'ambiente di test e pulizia delle risorse sottostanti, consentendo un'uscita pulita.
Questo metodo non modifica in alcun modo lo stato degli emulatori. Per reimpostare i dati tra i test, usa il metodo dei dati in chiaro specifico dell'emulatore di applicazioni.
assertSucceeds(pr: Promise<any>)) => Promise<any>
Questa è una funzione di utilità per i casi di test.
La funzione afferma che la Promise fornita che racchiude un'operazione dell'emulatore verrà risolta senza violazioni delle regole di sicurezza.
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });
assertFails(pr: Promise<any>)) => Promise<any>
Questa è una funzione di utilità per i casi di test.
La funzione afferma che la Promise fornita che racchiude un'operazione dell'emulatore verrà rifiutata con una violazione delle regole di sicurezza.
await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });
Metodi specifici dell'emulatore
Consulta anche i metodi di test e le funzioni di utilità comuni nell'SDK versione 9.
RulesTestEnvironment.clearFirestore() => Promise<void>
Questo metodo cancella i dati nel database Firestore che appartiene al
projectId
configurato per l'emulatore Firestore.
RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;
Questo metodo ottiene un'istanza Firestore per il contesto di test. L'istanza dell'SDK client Firebase JS restituita può essere utilizzata con le API SDK client (v9 modulare o v9 compatibile).
Visualizzare le valutazioni delle regole
L'emulatore Firestore ti consente di visualizzare le richieste dei client nell'interfaccia utente di Emulator Suite, incluso il monitoraggio della valutazione per le regole di sicurezza Firebase.
Apri Firestore > Richieste per visualizzare la valutazione dettagliata una sequenza per ogni richiesta.
Generare report di test
Dopo aver eseguito una suite di test, puoi accedere ai report sulla copertura dei test che mostrano in che modo è stata valutata ciascuna delle tue regole di sicurezza.
Per ottenere i report, esegui una query su un endpoint esposto sull'emulatore sia in esecuzione. Per una versione adatta ai browser, utilizza il seguente URL:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage.html
In questo modo, le regole vengono suddivise in espressioni e sottoespressioni su cui puoi eseguire il passaggio del mouse per visualizzare ulteriori informazioni, tra cui il numero di valutazioni e i valori restituiti. Per la versione JSON non elaborata di questi dati, includi il seguente URL nella tua query:
http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage
Differenze tra l'emulatore e la produzione
- Non è necessario creare esplicitamente un progetto Firestore. L'emulatore crea automaticamente tutte le istanze a cui si accede.
- L'emulatore Firestore non funziona con il normale flusso di Firebase Authentication.
Nell'SDK Firebase Test abbiamo invece fornito il metodo
initializeTestApp()
nellarules-unit-testing
, che richiede un campoauth
. L'handle Firebase è stato creato questo metodo si comporterà come se l'autenticazione sia riuscita indipendentemente dall'entità che fornisci. Se passinull
, il valore si comporterà come un utente non autenticato (ad esempio, le regoleauth != null
non andranno a buon fine).
Risolvere i problemi noti
Quando utilizzi l'emulatore Firestore, potresti incontrare i seguenti che le applicazioni presentino problemi di prestazioni. Segui le indicazioni riportate di seguito per risolvere i tuoi comportamenti irregolari in cui ti trovi. Queste note sono scritte tenendo presente la libreria di test di unità delle Regole di sicurezza, ma gli approcci generali sono applicabili a qualsiasi SDK Firebase.
Il comportamento del test non è coerente
Se i test a volte superano e a volte non superano, anche senza modifiche ai test stessi, potrebbe essere necessario verificare che siano sequenziati correttamente.
La maggior parte delle interazioni con l'emulatore è asincrona, quindi verifica che tutto il codice asincrono sia sequenziato correttamente. Puoi correggere la sequenza
concatenare le promesse o usare liberamente la notazione await
.
In particolare, esamina le seguenti operazioni asincrone:
- Impostazione delle regole di sicurezza, ad esempio con
initializeTestEnvironment
. - Lettura e scrittura di dati, ad esempio con
db.collection("users").doc("alice").get()
. - Affermazioni operative, tra cui
assertSucceeds
eassertFails
.
I test passano solo la prima volta che carichi l'emulatore
L'emulatore è stateful. Memorizza tutti i dati scritti in memoria, pertanto tutti i dati andranno persi ogni volta che l'emulatore si arresta. Se esegui più test sullo stesso ID progetto, ogni test può produrre dati che potrebbero influire sui test successivi. Per aggirare questo comportamento, puoi utilizzare uno dei seguenti metodi:
- Utilizza ID progetto univoci per ogni test. Tieni presente che, se scegli di farlo,
dovrai chiamare
initializeTestEnvironment
nell'ambito di ogni test; le regole vengono caricate automaticamente solo per l'ID progetto predefinito. - Ristruttura i test in modo che non interagiscano con i dati scritti in precedenza (ad esempio, utilizza una raccolta diversa per ogni test).
- Elimina tutti i dati scritti durante un test.
La configurazione del test è molto complicata
Quando configuri il test, ti consigliamo di modificare i dati in un modo non consentito dalle regole di sicurezza di Firestore. Se le regole rendono complessa la configurazione del test, prova a utilizzare RulesTestEnvironment.withSecurityRulesDisabled
nei passaggi di configurazione in modo che le letture e le scritture non attivino errori PERMISSION_DENIED
.
Dopodiché, il test può eseguire operazioni come utente autenticato o non autenticato utilizzando rispettivamente RulesTestEnvironment.authenticatedContext
e unauthenticatedContext
. Ciò ti consente di verificare che le regole di sicurezza di Firestore consentano o negano
casi diversi.