将 Admin SDK 与 Data Connect 搭配使用

Firebase Admin SDK 是一组服务器库,让您可以从特权环境与 Firebase 进行交互,以执行以下操作:使用提升的权限和冒充凭据对 Firebase Data Connect 服务执行查询和变更操作,以便进行批量数据管理和其他操作。

Admin SDK 为您提供了一个 API,可用于在读写模式和只读模式下调用操作。借助只读操作,您可以放心地实现无法修改数据库中数据的管理功能。

Admin SDK 设置

如需开始在服务器上使用 Firebase Data Connect,您首先需要为 Node.js 安装并设置 Admin SDK

在脚本中初始化 Admin SDK

如需初始化 SDK,请导入 Data Connect 扩展程序并声明项目服务 ID 和位置。


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'
});

设计要与 Admin SDK 搭配使用的查询和更改

Admin SDK 在测试 Data Connect 操作时非常有用,但需要注意以下事项。

了解 SDK 和 @auth(level: NO_ACCESS) 操作指令

由于 Admin SDK 是使用特权运行的,因此无论使用 @auth 指令设置了哪种访问权限级别(包括 NO_ACCESS 级别),它都可以执行您的任何查询和更改。

如果您在客户端操作之外,还在 .gql 源文件中整理了管理查询和更改,以便导入到管理脚本中,Firebase 建议您将管理操作标记为无任何授权访问权限级别,或者更明确地将其设为 NO_ACCESS。无论是哪种方式,这都会阻止从客户端或其他非特权上下文执行此类操作。

将 SDK 与 Data Connect 模拟器搭配使用

在原型和测试环境中,对本地数据执行数据种子和其他操作会很有用。Admin SDK 会忽略本地流程的身份验证和授权,因此可简化工作流。

设置 DATA_CONNECT_EMULATOR_HOST 环境变量后,Firebase Admin SDK 会自动连接到 Data Connect 模拟器:

export DATA_CONNECT_EMULATOR_HOST="127.0.0.1:9399"

如需了解详情,请参阅以下主题:

实现常见使用场景

Admin SDK 用于对关键数据执行特权操作。

Admin SDK 提供了两个接口:

  • 适用于大多数读写或只读操作的通用接口,您的代码会在其中实现查询和更改,并将其传递给读写 executeGraphql 方法或只读 executeGraphqlRead 方法。
  • 一种专门用于批量数据操作的接口,它会公开用于更改操作的专用方法(insertinsertManyupsertupsertMany),而不是通用的 executeGraphql 方法。

使用 executeGraphql 方法管理用户数据

Admin SDK 的一个典型用例是管理用户数据。

使用管理员凭据

最简单的方法是使用管理员凭据访问用户数据。

// 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" } } }

冒用用户凭据

在某些情况下,您可能希望脚本代表特定用户根据受限凭据修改用户数据。此方法遵循最小权限原则。

如需使用此接口,请从遵循 Authentication 令牌格式的自定义 JWT 身份验证令牌中收集信息。另请参阅自定义令牌指南

// 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" } } }

使用 executeGraphql 方法管理公共数据

您可以使用 SDK 处理公开可用的数据,并冒充未经身份验证的用户。

// 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);

执行批量数据操作

Firebase 建议您使用 Admin SDK 对生产数据库执行批量数据操作。

该 SDK 提供了以下用于处理批量数据的方法。每个方法都会根据提供的参数构建和执行 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);

批量操作的性能说明

对后端的每个请求都会产生一次往返 Cloud SQL 的开销,因此批量处理的次数越多,吞吐量就越高。

不过,批量大小越大,生成的 SQL 语句就越长。当达到 PostgreSQL SQL 语句长度限制时,您会遇到错误。

在实践中,请通过实验找到适合您的工作负载的批处理大小。

后续步骤