Das Firebase Admin SDK ist eine Reihe von Serverbibliotheken, mit denen Sie in privilegierten Umgebungen mit Firebase interagieren können, um Aktionen wie das Ausführen von Abfragen und Mutationen für einen Firebase SQL Connect-Dienst zur Massendatenverwaltung und andere Vorgänge mit erhöhten Berechtigungen und imitierten Anmeldedaten auszuführen.
Die Admin SDK bietet eine API zum Aufrufen von Vorgängen im Lese-/Schreibmodus und im schreibgeschützten Modus. Mit den schreibgeschützten Vorgängen können Sie administrative Funktionen implementieren, die keine Daten in Ihren Datenbanken ändern können.
Admin SDK einrichten
Wenn Sie Firebase SQL Connect auf Ihrem Server verwenden möchten, müssen Sie zuerst Admin SDK für Node.js installieren und einrichten.
Admin SDK in Ihren Skripts initialisieren
Um das SDK zu initialisieren, importieren Sie die SQL Connect-Erweiterungen und deklarieren Sie die Dienst-ID und den Standort Ihres Projekts.
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'
});
Abfragen und Mutationen für die Verwendung mit Admin SDK entwerfen
Admin SDK ist nützlich, um SQL Connect-Vorgänge auszuführen. Dabei sind die folgenden Aspekte zu berücksichtigen.
SDK und @auth(level: NO_ACCESS)-Vorgangsanweisung verstehen
Da Admin SDK mit Berechtigungen arbeitet, können damit alle Ihre Abfragen und Mutationen unabhängig von den mit @auth-Direktiven festgelegten Zugriffsebenen ausgeführt werden, einschließlich der Ebene NO_ACCESS.
Wenn Sie neben Ihren Clientvorgängen Ihre administrativen Abfragen und Mutationen in .gql-Quelldateien für den Import in administrative Skripts organisieren, empfiehlt Firebase, die administrativen Vorgänge ohne Autorisierungszugriffsebene zu kennzeichnen oder sie expliziter als NO_ACCESS festzulegen. So oder so wird verhindert, dass solche Vorgänge von Clients oder in anderen nicht privilegierten Kontexten ausgeführt werden.
SDK mit dem SQL Connect-Emulator verwenden
In Prototyp- und Testumgebungen kann es nützlich sein, Daten-Seeding und andere Vorgänge für lokale Daten auszuführen. Mit Admin SDK können Sie Ihre Workflows vereinfachen, da die Authentifizierung und Autorisierung für lokale Abläufe ignoriert werden kann. Sie können auch explizit zustimmen, dass die Authentifizierungs- und Autorisierungskonfiguration Ihrer Vorgänge mit dem Wechsel der Nutzeridentität eingehalten wird.
Die Firebase Admin SDKs stellen automatisch eine Verbindung zum SQL Connect-Emulator her, wenn die Umgebungsvariable DATA_CONNECT_EMULATOR_HOST festgelegt ist:
export DATA_CONNECT_EMULATOR_HOST="127.0.0.1:9399"
Weitere Informationen finden Sie unter:
Verwaltungsvorgänge ausführen
Die Admin SDK wird für privilegierte Vorgänge an Ihren kritischen Daten bereitgestellt.
Das Admin SDK bietet drei Gruppen von APIs:
- Generierte Admin-SDKs: Das sind typsichere SDKs, die aus Ihren
gql-Definitionen generiert werden, genau wie Client-SDKs. - Eine allgemeine Schnittstelle zum Ausführen beliebiger GraphQL-Vorgänge, in der Ihr Code Abfragen und Mutationen implementiert und sie an die Lese-/Schreibmethode
executeGraphqloder die schreibgeschützte MethodeexecuteGraphqlReadübergibt. - Eine spezielle Schnittstelle für Bulk-Datenvorgänge, die anstelle generischer
executeGraphql-Methoden spezielle Methoden für Mutationsvorgänge bereitstellt:insert,insertMany,upsertundupsertMany.
Daten mit generierten SDKs verwalten
Sie generieren Admin-SDKs aus Ihren gql-Definitionen auf dieselbe Weise wie Client-SDKs.
Das generierte Admin SDK enthält Schnittstellen und Funktionen, die Ihren gql-Definitionen entsprechen. Damit können Sie Vorgänge in Ihrer Datenbank ausführen. Angenommen, Sie haben ein SDK für eine Datenbank mit Songs zusammen mit einer Anfrage getSongs generiert:
import { initializeApp } from "firebase-admin/app";
import { getSongs } from "@dataconnect/admin-generated";
const adminApp = initializeApp();
const songs = await getSongs(
{ limit: 4 },
{ impersonate: { unauthenticated: true } }
);
So geben Sie eine Connector-Konfiguration an:
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 } }
);
Identität eines nicht authentifizierten Nutzers annehmen
Admin SDKs sind für die Ausführung in vertrauenswürdigen Umgebungen vorgesehen und haben daher uneingeschränkten Zugriff auf Ihre Datenbanken.
Wenn Sie öffentliche Vorgänge mit dem Admin SDK ausführen, sollten Sie vermeiden, den Vorgang mit vollständigen Administratorberechtigungen auszuführen (Prinzip der geringsten Berechtigung). Stattdessen sollten Sie den Vorgang entweder als imitierten Nutzer (siehe nächster Abschnitt) oder als imitierten nicht authentifizierten Nutzer ausführen.
Nicht authentifizierte Nutzer können nur Vorgänge ausführen, die mit PUBLIC gekennzeichnet sind.
Im Beispiel oben wird die Abfrage getSongs als nicht authentifizierter Nutzer ausgeführt.
Identität eines anderen Nutzers annehmen
Sie können auch Vorgänge im Namen bestimmter Nutzer ausführen, indem Sie einen Teil oder das gesamte Firebase Authentication-Token in der Option impersonate übergeben. Sie müssen mindestens die Nutzer-ID des Nutzers im untergeordneten Anspruch angeben. Das ist derselbe Wert wie der auth.uid-Serverwert, auf den Sie in SQL Connect-GraphQL-Vorgängen verweisen können.
Wenn Sie einen Nutzer imitieren, ist der Vorgang nur erfolgreich, wenn die von Ihnen angegebenen Nutzerdaten die in Ihrer GraphQL-Definition angegebenen Authentifizierungsprüfungen bestehen.
Wenn Sie das generierte SDK über einen öffentlich zugänglichen Endpunkt aufrufen, ist es wichtig, dass für den Endpunkt eine Authentifizierung erforderlich ist und dass Sie die Integrität des Authentifizierungstokens validieren, bevor Sie es verwenden, um die Identität eines Nutzers anzunehmen.
Wenn Sie aufrufbare Cloud Functions verwenden, wird das Authentifizierungstoken automatisch überprüft. Sie können es wie im folgenden Beispiel verwenden:
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 } }
);
// ...
});
Verwenden Sie andernfalls die Methode verifyIdToken der Admin SDK, um das Authentifizierungstoken zu validieren und zu decodieren. Angenommen, Ihr Endpunkt ist als einfache HTTP-Funktion implementiert und Sie haben das Firebase Authentication-Token wie üblich über den authorization-Header an Ihren Endpunkt übergeben:
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 } }
);
// ...
});
Nur wenn Sie echte Verwaltungsaufgaben wie die Datenmigration in einer sicheren, nicht öffentlich zugänglichen Umgebung ausführen, sollten Sie eine Nutzer-ID angeben, die nicht aus einer überprüfbaren Quelle stammt:
// Never do this if end users can initiate execution of the code!
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
Mit uneingeschränktem Zugriff ausführen
Wenn Sie einen Vorgang ausführen, für den Berechtigungen auf Administratorebene erforderlich sind, lassen Sie den Parameter „impersonate“ im Aufruf weg:
await upsertSong(adminDc, {
title: songTitle_one,
instrumentsUsed: [Instrument.VOCAL],
});
Eine auf diese Weise aufgerufene Operation hat vollständigen Zugriff auf die Datenbank. Wenn Sie Abfragen oder Mutationen haben, die nur für Verwaltungszwecke verwendet werden sollen, sollten Sie sie mit der Direktive @auth(level: NO_ACCESS) definieren. So wird sichergestellt, dass nur Aufrufer auf Administratorebene diese Operationen ausführen können.
Daten mit executeGraphql-Methoden verwalten
Wenn Sie einmalige Vorgänge ausführen müssen, für die Sie keine gql-Mutationen oder ‑Abfragen definiert haben, können Sie die Methode executeGraphql oder die schreibgeschützte Methode executeGraphqlRead verwenden.
Benutzerdefinierte verschachtelte relationale Vorgänge (1:n) mit executeGraphql ausführen
Wenn Sie Vorgänge aus dem Admin SDK in einer privilegierten Umgebung aufrufen, müssen Sie die @allow-Anweisung für Ihre Variablen für standardmäßige flache (nicht verschachtelte) Einfügungen (z. B. das Einfügen einzelner Film- oder Schauspielerdatensätze) nicht angeben.
Bei verschachtelten relationalen Einfügungen (z. B. beim Einfügen eines Films zusammen mit den ersten Rezensionen) müssen Sie die @allow-Anweisung jedoch weiterhin in der Variablendefinition deklarieren, um die verschachtelten relationalen Felder im kompilierten Variablenschema statisch zuzulassen.
// Custom GraphQL mutation with nested relational insert
const customMutation = `
mutation CustomBatchInsert(
$data: [Movie_Data!]!
@allow(fields: "title genre reviews_on_movie { rating reviewText }")
) {
movie_insertMany(data: $data)
}
`;
const variables = {
data: [
{
title: "Interstellar",
genre: "Sci-Fi",
reviews_on_movie: [
{
rating: 5,
reviewText: "Visually stunning and emotionally powerful.",
user: { id: "user-789" }
}
]
}
]
};
const response = await dataConnect.executeGraphql(customMutation, { variables });
Identität eines nicht authentifizierten Nutzers annehmen
Wenn Sie öffentliche Vorgänge mit dem Admin SDK ausführen, sollten Sie vermeiden, den Vorgang mit vollständigen Administratorberechtigungen auszuführen (Prinzip der geringsten Berechtigung). Stattdessen sollten Sie den Vorgang entweder als imitierten Nutzer (siehe nächster Abschnitt) oder als imitierten nicht authentifizierten Nutzer ausführen. Nicht authentifizierte Nutzer können nur Vorgänge ausführen, die mit PUBLIC gekennzeichnet sind.
// 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);
Identität eines anderen Nutzers annehmen
Es gibt auch Anwendungsfälle, in denen Sie möchten, dass Ihre Skripts Nutzerdaten im Namen eines bestimmten Nutzers auf Grundlage eingeschränkter Anmeldedaten ändern. Dieser Ansatz entspricht dem Prinzip der geringsten Berechtigung.
Um diese Schnittstelle zu verwenden, müssen Sie Informationen aus einem benutzerdefinierten JWT-Authentifizierungstoken abrufen, das dem Tokenformat Authentication entspricht. Weitere Informationen
// 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" } } }
Administratoranmeldedaten verwenden
Wenn Sie einen Vorgang ausführen, für den Berechtigungen auf Administratorebene erforderlich sind, lassen Sie den Parameter „impersonate“ im Aufruf weg:
// 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" } } }
Eine auf diese Weise aufgerufene Operation hat vollständigen Zugriff auf die Datenbank. Wenn Sie Abfragen oder Mutationen haben, die nur für Verwaltungszwecke verwendet werden sollen, sollten Sie sie mit der Direktive @auth(level: NO_ACCESS) definieren. So wird sichergestellt, dass nur Aufrufer auf Administratorebene diese Operationen ausführen können.
Bulk-Dateneinfügungsvorgänge ausführen
Firebase empfiehlt die Verwendung von Admin SDK für Bulk-Datenvorgänge in Produktionsdatenbanken.
Das SDK bietet die folgenden Methoden für die Arbeit mit Bulk-Daten. Aus den bereitgestellten Argumenten wird mit jeder Methode eine GraphQL-Mutation erstellt und ausgeführt.
// Methods of the bulk operations API
// dc is a SQL 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);
Verschachtelte relationale Vorgänge (1-zu-N)
Die Admin SDK unterstützt relationale Daten in Bulk-Vorgängen:
// Example of inserting a movie with nested reviews
const moviesData = [
{
title: "Interstellar",
genre: "Sci-Fi",
reviews_on_movie: [
{
rating: 5,
reviewText: "Visually stunning and emotionally powerful.",
user: { id: "user-789" }
}
]
}
];
// Atomically insert movies and their reviews in a single database round-trip.
const response = await dc.insertMany("movie", moviesData);
Hinweise zur Leistung bei Bulk-Vorgängen
Für jede Anfrage an das Back-End ist ein Roundtrip zu Cloud SQL erforderlich. Je mehr Anfragen Sie also in einem Batch zusammenfassen, desto höher ist der Durchsatz.
Je größer die Batchgröße ist, desto länger ist jedoch die generierte SQL-Anweisung. Wenn das Längenlimit für PostgreSQL-SQL-Anweisungen erreicht ist, tritt ein Fehler auf.
In der Praxis sollten Sie experimentieren, um die passende Batchgröße für Ihre Arbeitslast zu ermitteln.
Nächste Schritte
- Informationen zum Befüllen von Datenbanken mit Daten mithilfe der Admin SDK
- Sehen Sie sich die API für Admin SDK an.
- Verwenden Sie die Firebase CLI und die Google Cloud-Konsole für andere Projektverwaltungsaufgaben, z. B. Schemas und Connectors verwalten und Dienste und Datenbanken verwalten.