Los SDK de administrador de Firebase Data Connect te permiten llamar a tus consultas y mutaciones desde entornos de confianza, como Cloud Functions, backends personalizados o tu propia estación de trabajo. De la misma manera que generas SDK para tus apps cliente, puedes generar un SDK de Admin personalizado en paralelo mientras diseñas los esquemas, las consultas y las mutaciones que implementas en tu servicio de Data Connect. Luego, integras métodos de este SDK en tu lógica de backend o secuencias de comandos de administración.
Como mencionamos en otro lugar, es importante tener en cuenta que los clientes no envían las consultas y mutaciones en el momento de la solicitud.Data Connect En cambio, cuando se implementan, las operaciones Data Connect se almacenan en el servidor como Cloud Functions. Esto significa que, cada vez que implementes cambios en tus consultas y mutaciones, también deberás volver a generar los SDK de Admin y volver a implementar los servicios que dependen de ellos.
Antes de comenzar
- Obtén información para diseñar esquemas, consultas y mutaciones Data Connect. En un flujo de trabajo típico, los desarrollarás en paralelo con el código de tu aplicación, incluidos los servicios que usan SDK de Admin.
- Instala Firebase CLI.
- Incluye el SDK de Admin para Node.js como una dependencia donde planees llamar a los SDK de Admin generados.
Genera SDK de Admin
Después de crear tus esquemas, consultas y mutaciones de Data Connect, puedes generar un SDK de Admin correspondiente:
Abre o crea un archivo
connector.yamly agrega una definiciónadminNodeSdk:connectorId: default generate: adminNodeSdk: outputDir: ../../dataconnect-generated/admin-generated package: "@dataconnect/admin-generated" packageJsonDir: ../..Por lo general, el archivo
connector.yamlse encuentra en el mismo directorio que los archivos GraphQL (.gql) que contienen tus definiciones de consulta y mutación. Si ya generaste SDK cliente, este archivo ya se creó.Genera el SDK.
Si tienes instalada la extensión de Data Connect para VS Code, siempre mantendrá actualizados los SDK generados.
De lo contrario, usa Firebase CLI:
firebase dataconnect:sdk:generateO bien, para volver a generar automáticamente los SDK cuando actualices tus archivos
gql:firebase dataconnect:sdk:generate --watch
Ejecuta operaciones desde un SDK de Admin
El SDK de Admin generado contiene interfaces y funciones que corresponden con tus definiciones gql, que puedes usar para realizar operaciones en tu base de datos. Por ejemplo, supongamos que generaste un SDK para una base de datos de canciones, junto con una consulta, 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 } }
);
O bien, para especificar una configuración del conector:
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 } }
);
Cómo suplantar a un usuario no autenticado
Los SDK de Admin están diseñados para ejecutarse desde entornos de confianza y, por lo tanto, tienen acceso sin restricciones a tus bases de datos.
Cuando ejecutas operaciones públicas con el SDK de Admin, debes evitar ejecutar la operación con privilegios de administrador completos (siguiendo el principio de privilegio mínimo). En su lugar, debes ejecutar la operación como un usuario suplantado (consulta la siguiente sección) o como un usuario no autenticado suplantado.
Los usuarios no autenticados solo pueden ejecutar operaciones marcadas como PUBLIC.
En el ejemplo anterior, la consulta getSongs se ejecuta como un usuario no autenticado.
Cómo suplantar a un usuario
También puedes realizar operaciones en nombre de usuarios específicos pasando parte o
la totalidad de un Firebase Authentication token en la opción impersonate. Como mínimo, debes especificar el ID de usuario del usuario en la reclamación sub. (Este es el mismo valor que el
auth.uid valor del servidor
al que puedes hacer referencia en Data Connect operaciones de GraphQL).
Cuando suplantas a un usuario, la operación solo se realizará correctamente si los datos del usuario que proporcionaste pasan las verificaciones de autenticación especificadas en tu definición de GraphQL.
Si llamas al SDK generado desde un extremo de acceso público, es fundamental que el extremo requiera autenticación y que valides la integridad del token de autenticación antes de usarlo para suplantar a un usuario.
Cuando usas invocables Cloud Functions, el token de autenticación se verifica automáticamente y puedes usarlo como en el siguiente ejemplo:
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 } }
);
// ...
});
De lo contrario, usa el Admin SDK del verifyIdToken para validar y decodificar
el token de autenticación. Por ejemplo, supongamos que tu extremo se implementa como una
función HTTP simple y que pasaste el Firebase Authentication token
a tu extremo con el authorization encabezado, como es estándar:
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 cuando realices tareas administrativas verdaderas, como la migración de datos, desde un entorno seguro y no accesible de forma pública, debes especificar un ID de usuario que no provenga de una fuente verificable:
// Never do this if end users can initiate execution of the code!
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
Ejecuta con acceso sin restricciones
Si realizas una operación que requiere permisos de nivel de administrador, omite el parámetro impersonate de la llamada:
await upsertSong(adminDc, {
title: songTitle_one,
instrumentsUsed: [Instrument.VOCAL],
});
Una operación llamada de esta manera tiene acceso completo a la base de datos. Si tienes consultas o mutaciones que solo se usarán con fines de administración, debes definirlas con la directiva @auth(level: NO_ACCESS). De esta manera, se garantiza que solo los emisores de nivel de administrador puedan ejecutar estas operaciones.