L'Firebase Admin SDK è un insieme di librerie server che ti consente di interagire con Firebase da ambienti privilegiati per eseguire azioni come query e mutazioni su un servizio Firebase Data Connect per la gestione collettiva dei dati e altre operazioni con privilegi elevati e credenziali impersonate.
Admin SDK fornisce un'API per chiamare operazioni in modalità di lettura/scrittura e di sola lettura. Con le operazioni di sola lettura, puoi implementare funzioni amministrative che non possono modificare i dati nei tuoi database.
Configurazione dell'SDK Admin
Per iniziare a utilizzare Firebase Data Connect sul tuo server, devi prima installare e configurare Admin SDK per Node.js.
Inizializza l'SDK Admin negli script
Per inizializzare l'SDK, importa le estensioni Data Connect e dichiara l'ID e la posizione del servizio del tuo progetto.
import { initializeApp } from 'firebase-admin/app';
import { getDataConnect } from 'firebase-admin/data-connect';
// If you'd like to use OAuth2 flows and other credentials to log in,
// visit https://firebase.google.com/docs/admin/setup#initialize-sdk
// for alternative ways to initialize the SDK.
const app = initializeApp();
const dataConnect = getDataConnect({
serviceId: 'serviceId',
location: 'us-west2'
});
Progetta query e mutazioni da utilizzare con Admin SDK
Admin SDK è utile per eseguire operazioni Data Connect, tenendo conto delle seguenti considerazioni.
Comprendere l'SDK e la direttiva operativa @auth(level: NO_ACCESS)
Poiché Admin SDK opera con privilegi, può eseguire qualsiasi query e mutazione indipendentemente dai livelli di accesso impostati utilizzando le direttive @auth, incluso il livello NO_ACCESS.
Se, oltre alle operazioni del client, organizzi le query amministrative
e le mutazioni nei file di origine .gql per l'importazione negli script amministrativi, Firebase ti consiglia di contrassegnare le operazioni amministrative senza alcun
livello di accesso con autorizzazione oppure di impostarle in modo più esplicito come
NO_ACCESS. In entrambi i casi, ciò impedisce l'esecuzione di queste operazioni da
client o in altri contesti non privilegiati.
Utilizzare l'SDK con l'emulatore Data Connect
Negli ambienti di prototipazione e test, può essere utile eseguire il seeding dei dati e altre operazioni sui dati locali. Admin SDK consente di semplificare i flussi di lavoro in quanto può ignorare l'autenticazione e l'autorizzazione per i flussi locali. Puoi anche attivare esplicitamente la conformità alla configurazione di autenticazione e autorizzazione delle tue operazioni con la rappresentazione dell'utente.
Gli SDK Firebase Admin si connettono automaticamente all'emulatore Data Connect
quando è impostata la variabile di ambiente DATA_CONNECT_EMULATOR_HOST:
export DATA_CONNECT_EMULATOR_HOST="127.0.0.1:9399"
Per ulteriori informazioni, vedi:
- La guida per il seeding dei dati nello sviluppo locale
- La documentazione dell'emulatore Data Connect.
Eseguire operazioni amministrative
Admin SDK viene fornito per le operazioni privilegiate sui tuoi dati critici.
L'SDK Admin fornisce tre set di API:
- SDK Admin generati, ovvero SDK type-safe generati dalle tue definizioni
gqlnello stesso modo in cui generi gli SDK client. - Un'interfaccia generale per l'esecuzione di operazioni GraphQL arbitrarie, in cui il codice implementa query e mutazioni e le passa al metodo
executeGraphqldi lettura/scrittura o al metodoexecuteGraphqlReaddi sola lettura. - Un'interfaccia specializzata per le operazioni sui dati collettivi che, anziché
metodi
executeGraphqlgenerici, espone metodi dedicati per le operazioni di mutazione:insert,insertMany,upserteupsertMany.
Gestire i dati con gli SDK generati
Puoi generare SDK Admin
dalle definizioni di gql nello stesso modo in cui generi gli SDK client.
L'SDK Admin generato contiene interfacce e funzioni che corrispondono alle tue definizioni di gql, che puoi utilizzare per eseguire operazioni sul tuo database. Ad esempio, supponiamo di aver generato un SDK per un database di brani,
insieme a una query, getSongs:
import { initializeApp } from "firebase-admin/app";
import { getSongs } from "@dataconnect/admin-generated";
const adminApp = initializeApp();
const songs = await getSongs(
{ limit: 4 },
{ impersonate: { unauthenticated: true } }
);
In alternativa, per specificare una configurazione del connettore:
import { initializeApp } from "firebase-admin/app";
import { getDataConnect } from "firebase-admin/data-connect";
import {
connectorConfig,
getSongs,
} from "@dataconnect/admin-generated";
const adminApp = initializeApp();
const adminDc = getDataConnect(connectorConfig);
const songs = await getSongs(
adminDc,
{ limit: 4 },
{ impersonate: { unauthenticated: true } }
);
Impersonare un utente non autenticato
Gli SDK Admin sono progettati per essere eseguiti da ambienti attendibili e pertanto hanno accesso illimitato ai tuoi database.
Quando esegui operazioni pubbliche con l'SDK Admin, devi evitare di eseguire l'operazione con privilegi amministrativi completi (seguendo il principio del privilegio minimo). Devi invece eseguire l'operazione come utente rappresentato
(vedi la sezione successiva) o come utente non autenticato rappresentato.
Gli utenti non autenticati possono eseguire solo le operazioni contrassegnate come PUBLIC.
Nell'esempio precedente, la query getSongs viene eseguita come utente non autenticato.
Impersonare un utente
Puoi anche eseguire operazioni per conto di utenti specifici passando parte o
tutto un token Firebase Authentication nell'opzione impersonate; come minimo, devi
specificare l'ID utente dell'utente nella rivendicazione sub. (Si tratta dello stesso valore del
valore del server auth.uid
a cui puoi fare riferimento nelle operazioni GraphQL di Data Connect.)
Quando esegui l'impersonificazione di un utente, l'operazione andrà a buon fine solo se i dati utente che hai fornito superano i controlli di autenticazione specificati nella definizione GraphQL.
Se chiami l'SDK generato da un endpoint accessibile pubblicamente, è fondamentale che l'endpoint richieda l'autenticazione e che tu convalidi l'integrità del token di autenticazione prima di utilizzarlo per rappresentare un utente.
Quando utilizzi Cloud Functions richiamabile, il token di autenticazione viene verificato automaticamente e puoi utilizzarlo come nel seguente esempio:
import { HttpsError, onCall } from "firebase-functions/https";
export const callableExample = onCall(async (req) => {
const authClaims = req.auth?.token;
if (!authClaims) {
throw new HttpsError("unauthenticated", "Unauthorized");
}
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
// ...
});
In caso contrario, utilizza il metodo verifyIdToken di Admin SDK per convalidare e decodificare
il token di autenticazione. Ad esempio, supponiamo che l'endpoint sia implementato come una
semplice funzione HTTP e che tu abbia passato il token Firebase Authentication
all'endpoint utilizzando l'intestazione authorization, come di consueto:
import { getAuth } from "firebase-admin/auth";
import { onRequest } from "firebase-functions/https";
const auth = getAuth();
export const httpExample = onRequest(async (req, res) => {
const token = req.header("authorization")?.replace(/^bearer\s+/i, "");
if (!token) {
res.sendStatus(401);
return;
}
let authClaims;
try {
authClaims = await auth.verifyIdToken(token);
} catch {
res.sendStatus(401);
return;
}
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
// ...
});
Solo quando esegui attività amministrative reali, come la migrazione dei dati, da un ambiente sicuro e non accessibile pubblicamente, devi specificare un ID utente che non provenga da un'origine verificabile:
// Never do this if end users can initiate execution of the code!
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
Esecuzione con accesso illimitato
Se stai eseguendo un'operazione che richiede autorizzazioni a livello amministrativo, ometti il parametro impersonate dalla chiamata:
await upsertSong(adminDc, {
title: songTitle_one,
instrumentsUsed: [Instrument.VOCAL],
});
Un'operazione chiamata in questo modo ha accesso completo al database. Se hai
query o mutazioni destinate esclusivamente a scopi amministrativi,
devi definirle con la direttiva @auth(level: NO_ACCESS). In questo modo, solo i chiamanti a livello amministrativo possono eseguire queste operazioni.
Gestire i dati con i metodi executeGraphql
Se devi eseguire operazioni una tantum per le quali non hai definito mutazioni o query gql, puoi utilizzare il metodo executeGraphql o il metodo di sola lettura executeGraphqlRead.
Impersonare un utente non autenticato
Quando esegui operazioni pubbliche con l'SDK Admin, devi evitare di eseguire l'operazione con privilegi amministrativi completi (seguendo il principio del privilegio minimo). Devi invece eseguire l'operazione come utente rappresentato
(vedi la sezione successiva) o come utente rappresentato
non autenticato. Gli utenti non autenticati possono eseguire solo le operazioni contrassegnate come
PUBLIC.
// Query to get posts, with authentication level PUBLIC
const queryGetPostsImpersonation = `
query getPosts @auth(level: PUBLIC) {
posts {
description
}
}`;
// Attempt to access data as an unauthenticated user
const optionsUnauthenticated: GraphqlOptions<undefined> = {
impersonate: {
unauthenticated: true
}
};
// executeGraphql with impersonated unauthenticated user scope
const gqlResponse = await dataConnect.executeGraphql<UserData, undefined>(queryGetPostsImpersonation, optionsUnauthenticated);
Impersonare un utente
Esistono anche casi d'uso in cui vuoi che i tuoi script modifichino i dati utente in base a credenziali limitate, per conto di un utente specifico. Questo approccio rispetta il principio del privilegio minimo.
Per utilizzare questa interfaccia, raccogli le informazioni da un token di autenticazione JWT personalizzato che segue il formato del token Authentication. Consulta anche la guida ai token personalizzati.
// Get the current user's data
const queryGetUserImpersonation = `
query getUser @auth(level: USER) {
user(key: {uid_expr: "auth.uid"}) {
id,
name
}
}`;
// Impersonate a user with the specified auth claims
const optionsAuthenticated: GraphqlOptions<undefined> = {
impersonate: {
authClaims: {
sub: 'QVBJcy5ndXJ1'
}
}
};
// executeGraphql with impersonated authenticated user scope
const gqlResponse = await dataConnect.executeGraphql<UserData, undefined>(queryGetUserImpersonation, optionsAuthenticated);
// gqlResponse -> { "data": { "user": { "id": "QVBJcy5ndXJ1", "name": "Fred" } } }
Utilizzare le credenziali amministrative
Se stai eseguendo un'operazione che richiede autorizzazioni a livello amministrativo, ometti il parametro impersonate dalla chiamata:
// User can be publicly accessible, or restricted to admins
const query = "query getProfile(id: AuthID) { user(id: $id) { id name } }";
interface UserData {
user: {
id: string;
name: string;
};
}
export interface UserVariables {
id: string;
}
const options:GraphqlOptions<UserVariables> = { variables: { id: "QVBJcy5ndXJ1" } };
// executeGraphql
const gqlResponse = await dataConnect.executeGraphql<UserData, UserVariables>(query, options);
// executeGraphqlRead (similar to previous sample but only for read operations)
const gqlResponse = await dataConnect.executeGraphqlRead<UserData, UserVariables>(query, options);
// gqlResponse -> { "data": { "user": { "id": "QVBJcy5ndXJ1", "name": "Fred" } } }
Un'operazione chiamata in questo modo ha accesso completo al database. Se hai
query o mutazioni destinate esclusivamente a scopi amministrativi,
devi definirle con la direttiva @auth(level: NO_ACCESS). In questo modo, solo i chiamanti a livello amministrativo possono eseguire queste operazioni.
Eseguire operazioni collettive sui dati
Firebase consiglia di utilizzare Admin SDK per le operazioni sui dati collettivi nei database di produzione.
L'SDK fornisce i seguenti metodi per lavorare con i dati collettivi. A partire dagli argomenti forniti, ogni metodo crea ed esegue una mutazione GraphQL.
// Methods of the bulk operations API
// dc is a Data Connect admin instance from getDataConnect
const resp = await dc.insert("movie" /*table name*/, data[0]);
const resp = await dc.insertMany("movie" /*table name*/, data);
const resp = await dc.upsert("movie" /*table name*/, data[0]);
const resp = await dc.upsertMany("movie" /*table name*/, data);
Note sul rendimento per le operazioni collettive
Ogni richiesta al backend comporta un round trip a Cloud SQL, quindi più richieste batch vengono inviate, maggiore è la velocità effettiva.
Tuttavia, maggiore è la dimensione del batch, più lunga è l'istruzione SQL generata. Quando viene raggiunto il limite di lunghezza dell'istruzione SQL PostgreSQL, si verifica un errore.
In pratica, sperimenta per trovare le dimensioni del batch appropriate per il tuo carico di lavoro.
Passaggi successivi
- Scopri di più su come inserire dati nei database utilizzando Admin SDK
- Esamina l'API per Admin SDK.
- Utilizza l'interfaccia a riga di comando Firebase e la console Google Cloud per altre operazioni di gestione dei progetti, come la gestione di schemi e connettori e la gestione di servizi e database.