Com os SDKs Admin do Firebase Data Connect, é possível chamar consultas e mutações de ambientes confiáveis, como o Cloud Functions, back-ends personalizados ou sua própria estação de trabalho. Da mesma forma que você gera SDKs para seus apps cliente, é possível gerar um SDK Admin personalizado em paralelo ao criar os esquemas, as consultas e as mutações que você implanta no serviço Data Connect. Em seguida, integre métodos desse SDK à lógica de back-end ou aos scripts de administração.
Como mencionamos em outro lugar, é importante observar que as consultas e mutações do Data Connect não são enviadas pelos clientes no momento da solicitação. Em vez disso, quando implantadas, as operações do Data Connect são armazenadas no servidor, como o Cloud Functions. Isso significa que, sempre que você implantar mudanças nas consultas e mutações, também será necessário regenerar os SDKs de administrador e reimplantar os serviços que dependem deles.
Antes de começar
- Saiba como criar esquemas, consultas e mutações do Data Connect. Em um fluxo de trabalho típico, você os desenvolve em paralelo ao código do aplicativo, incluindo serviços que usam SDKs Admin.
- Instale a CLI do Firebase.
- Inclua o SDK Admin para Node.js como uma dependência em qualquer lugar em que você planeja chamar os SDKs Admin gerados.
Gerar SDKs Admin
Depois de criar os esquemas, consultas e mutações do Data Connect, você pode gerar um SDK de administrador correspondente:
Abra ou crie um arquivo
connector.yamle adicione uma definição deadminNodeSdk:connectorId: default generate: adminNodeSdk: outputDir: ../../dataconnect-generated/admin-generated package: "@dataconnect/admin-generated" packageJsonDir: ../..O arquivo
connector.yamlgeralmente está no mesmo diretório que os arquivos GraphQL (.gql) que contêm suas definições de consulta e mutação. Se você já gerou SDKs de cliente, esse arquivo já foi criado.Gere o SDK.
Se você tiver a extensão Data Connect do VS Code instalada, ela sempre manterá os SDKs gerados atualizados.
Caso contrário, use a CLI do Firebase:
firebase dataconnect:sdk:generateOu, para regenerar automaticamente os SDKs ao atualizar os arquivos
gql:firebase dataconnect:sdk:generate --watch
Executar operações de um SDK Admin
O SDK Admin gerado contém interfaces e funções que correspondem às suas definições de gql, que podem ser usadas para realizar operações no seu banco de dados. Por exemplo, suponha que você gerou um SDK para um banco de dados de músicas,
junto com uma 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 } }
);
Ou, para especificar uma configuração de 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 } }
);
Representar um usuário não autenticado
Os SDKs Admin são projetados para serem executados em ambientes confiáveis e, portanto, têm acesso irrestrito aos seus bancos de dados.
Ao executar operações públicas com o SDK Admin, evite usar privilégios de administrador completos (seguindo o princípio do privilégio mínimo). Em vez disso, execute a operação como um usuário representado
(consulte a próxima seção) ou como um usuário não autenticado representado.
Usuários não autenticados só podem executar operações marcadas como PUBLIC.
No exemplo acima, a consulta getSongs é executada como um usuário
não autenticado.
Representar um usuário
Também é possível realizar operações em nome de usuários específicos transmitindo parte ou
todo um token Firebase Authentication na opção impersonate. No mínimo, você
precisa especificar o ID do usuário na subdeclaração. Esse é o mesmo valor do auth.uid do servidor que você pode referenciar nas operações do GraphQL do Data Connect.
Ao simular um usuário, a operação só será concluída se os dados fornecidos passarem nas verificações de autenticação especificadas na definição do GraphQL.
Se você estiver chamando o SDK gerado de um endpoint acessível publicamente, é fundamental que o endpoint exija autenticação e que você valide a integridade do token de autenticação antes de usá-lo para simular um usuário.
Ao usar Cloud Functions invocável, o token de autenticação é verificado automaticamente, e você pode usá-lo como no exemplo a seguir:
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 } }
);
// ...
});
Caso contrário, use o método verifyIdToken do Admin SDK para validar e decodificar o token de autenticação. Por exemplo, suponha que seu endpoint seja implementado como uma função HTTP simples e que você tenha transmitido o token Firebase Authentication para o endpoint usando o cabeçalho authorization, como é padrão:
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 } }
);
// ...
});
Só especifique um ID de usuário que não tenha origem em uma fonte verificável ao realizar tarefas administrativas reais, como migração de dados, em um ambiente seguro e não acessível ao público:
// Never do this if end users can initiate execution of the code!
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
Execução com acesso irrestrito
Se você estiver realizando uma operação que exige permissões de nível de administrador, omita o parâmetro "impersonate" da chamada:
await upsertSong(adminDc, {
title: songTitle_one,
instrumentsUsed: [Instrument.VOCAL],
});
Uma operação chamada dessa maneira tem acesso completo ao banco de dados. Se você tiver consultas ou mutações destinadas apenas a fins administrativos, defina-as com a diretiva @auth(level: NO_ACCESS). Assim, apenas chamadores no nível de administrador podem executar essas operações.