O Firebase Admin SDK é um conjunto de bibliotecas de servidor que permite interagir com o Firebase em ambientes privilegiados para realizar ações como consultas e mutações em um serviço Firebase Data Connect para gerenciamento de dados em massa e outras operações com privilégios elevados e credenciais representadas.
O Admin SDK oferece uma API para chamar operações nos modos de leitura/gravação e somente leitura. Com as operações somente leitura, você tem a tranquilidade de implementar funções administrativas que não podem modificar dados nos seus bancos de dados.
Configuração do SDK Admin
Para começar a usar o com o Firebase Data Connect no seu servidor, você primeiro precisará instalar e configurar o Admin SDK para Node.js.
Inicializar o SDK Admin nos seus scripts
Para inicializar o SDK, importe as extensões Data Connect e declare o ID e o local do serviço do projeto.
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'
});
Criar consultas e mutações para usar com o Admin SDK
O Admin SDK é útil para executar operações Data Connect, considerando o seguinte.
Entender o SDK e a diretiva de operação @auth(level: NO_ACCESS)
Como o Admin SDK opera com privilégios, ele pode executar qualquer
consulta e mutação, independentemente dos níveis de acesso definidos usando as @auth diretivas, incluindo o nível NO_ACCESS.
Se, além das operações do cliente, você organizar suas consultas e mutações administrativas em arquivos de origem .gql para importação em scripts administrativos, o Firebase recomenda que você marque as operações administrativas sem nenhum nível de acesso de autorização ou seja mais explícito e as defina como NO_ACCESS. De qualquer forma, isso impede que essas operações sejam executadas em clientes ou em outros contextos não privilegiados.
Usar o SDK com o emulador Data Connect
Em ambientes de protótipo e teste, pode ser útil realizar o seeding de dados e outras operações em dados locais. O Admin SDK simplifica seus fluxos de trabalho, já que pode ignorar a autenticação e a autorização para fluxos locais. Também é possível ativar explicitamente a conformidade com a configuração de autenticação e autorização das operações com falsificação de identidade do usuário.
Os SDKs Admin do Firebase se conectam automaticamente ao Data Connect
emulador quando a variável de ambiente DATA_CONNECT_EMULATOR_HOST é definida:
export DATA_CONNECT_EMULATOR_HOST="127.0.0.1:9399"
Para mais informações, consulte:
- O guia de seeding de dados no desenvolvimento local
- A documentação do emulador Data Connect.
Executar operações administrativas
O Admin SDK é fornecido para operações privilegiadas nos seus dados críticos.
O SDK Admin oferece três conjuntos de APIs:
- SDKs Admin gerados, que são SDKs com segurança de tipo gerados nas suas definições
gqlda mesma forma que você gera SDKs do cliente. - Uma interface geral para executar operações GraphQL arbitrárias, em que o
código implementa consultas e mutações e as transmite para o método de leitura/gravação
executeGraphqlou o método somente leituraexecuteGraphqlRead. - Uma interface especializada para operações de dados em massa, que, em vez de
métodos
executeGraphqlgenéricos, expõe métodos dedicados para operações de mutação:insert,insertMany,upserteupsertMany.
Gerenciar dados com SDKs gerados
Você gera SDKs Admin
nas suas definições gql da mesma forma que gera SDKs do cliente.
O SDK Admin gerado contém interfaces e funções que correspondem às suas definições gql, que podem ser usadas para realizar operações no banco de dados. Por exemplo, suponha que você tenha gerado 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 destinados a 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 executar a operação com 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.
Os 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 Firebase Authentication token na opção impersonate. No mínimo, é necessário especificar o ID do usuário na declaração "sub". Esse é o mesmo valor do
auth.uid valor do servidor
que pode ser referenciado nas Data Connect operações GraphQL.
Ao representar um usuário, a operação só será bem-sucedida se os dados do usuário 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 representar um usuário.
Ao usar o Cloud Functions chamá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 Admin SDK's verifyIdToken método para validar e decodificar
o token de autenticação. Por exemplo, suponha que o 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 } }
);
// ...
});
Somente ao realizar tarefas administrativas verdadeiras, como migração de dados, em um ambiente seguro e não acessível publicamente, especifique um ID de usuário que não tenha origem em uma fonte verificável:
// Never do this if end users can initiate execution of the code!
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
Executar com acesso irrestrito
Se você estiver realizando uma operação que exige permissões de nível de administrador, omita o parâmetro de representação 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). Isso garante que apenas autores de chamadas de nível de administrador possam executar essas operações.
Gerenciar dados com métodos executeGraphql
Se você precisar executar operações únicas para as quais não definiu gql
mutações ou consultas, use o método executeGraphql ou o método somente leitura
executeGraphqlRead.
Representar um usuário não autenticado
Ao executar operações públicas com o SDK Admin, evite executar a operação com 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. Os usuários não autenticados só podem executar operações marcadas como 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);
Representar um usuário
Há também casos de uso em que você quer que seus scripts modifiquem os dados do usuário com base em credenciais limitadas, em nome de um usuário específico. Essa abordagem segue o princípio do privilégio mínimo.
Para usar essa interface, colete informações de um token de autenticação JWT personalizado que siga o Authentication formato de token. Consulte também o guia de tokens personalizados.
// 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" } } }
Usar credenciais administrativas
Se você estiver realizando uma operação que exige permissões de nível de administrador, omita o parâmetro de representação da chamada:
// 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" } } }
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). Isso garante que apenas autores de chamadas de nível de administrador possam executar essas operações.
Realizar operações de dados em massa
O Firebase recomenda o uso do Admin SDK para operações de dados em massa em bancos de dados de produção.
O SDK fornece os seguintes métodos para trabalhar com dados em massa. Nos argumentos fornecidos, cada método constrói e executa uma mutação 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);
Observações de performance para operações em massa
Cada solicitação para o back-end incorrerá em uma viagem de ida e volta ao Cloud SQL. Portanto, quanto mais você agrupar, maior será a capacidade de processamento.
No entanto, quanto maior o tamanho do lote, maior será a instrução SQL gerada. Quando o limite de comprimento da instrução SQL do PostgreSQL for atingido, você vai encontrar um erro.
Na prática, faça testes para encontrar o tamanho do lote adequado para sua carga de trabalho.
A seguir
- Saiba como fazer o seeding de bancos de dados com dados usando o Admin SDK
- Analise a API do Admin SDK.
- Use a Firebase CLI e o Google Cloud console para outras operações de gerenciamento de projetos, como gerenciar esquemas e conectores e gerenciar serviços e bancos de dados.