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 指令設定的存取層級為何,Admin SDK 都能執行任何查詢和突變,包括 NO_ACCESS 層級。
如果您在用戶端作業旁,將管理查詢和變動整理到 .gql 來源檔案中,以便匯入管理指令碼,Firebase 建議您標記沒有任何授權存取層級的管理作業,或更明確地將這些作業設為 NO_ACCESS。無論是哪種方式,都能防止這類作業從用戶端或在其他非具備權限的環境中執行。
搭配 Data Connect 模擬器使用 SDK
在原型和測試環境中,對本機資料執行資料植入和其他作業可能很有用。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 提供三組 API:
- 產生的 Admin SDK,也就是從
gql定義產生的型別安全 SDK,產生方式與產生用戶端 SDK 相同。 - 用於執行任意 GraphQL 作業的一般介面,您的程式碼會實作查詢和變動,並將其傳遞至讀寫
executeGraphql方法或唯讀executeGraphqlRead方法。 - 專為大量資料作業設計的介面,而非一般
executeGraphql方法,而是公開用於變動作業的專屬方法:insert、insertMany、upsert和upsertMany。
使用產生的 SDK 管理資料
您可以從 gql 定義產生管理員 SDK,方式與產生用戶端 SDK 相同。
產生的 Admin SDK 包含與 gql 定義相應的介面和函式,可用於對資料庫執行作業。舉例來說,假設您為歌曲資料庫產生 SDK,並提供查詢 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 } }
);
如要指定連接器設定,請使用:
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 } }
);
模擬未經驗證的使用者
Admin SDK 應從受信任的環境執行,因此可無限制存取資料庫。
使用 Admin SDK 執行公開作業時,請避免以完整管理員權限執行作業 (遵循最低權限原則)。您應該以模擬使用者 (請參閱下一節) 或模擬未經驗證的使用者身分執行作業。未通過驗證的使用者只能執行標示為 PUBLIC 的作業。
在上述範例中,getSongs 查詢是以未經驗證的使用者身分執行。
模擬使用者身分
您也可以在 impersonate 選項中傳遞部分或全部的 Firebase Authentication 權杖,代表特定使用者執行作業;至少必須在子項聲明中指定使用者的使用者 ID。(這與您可在 Data Connect GraphQL 作業中參照的auth.uid伺服器值相同)。
模擬使用者時,只有在您提供的使用者資料通過 GraphQL 定義中指定的驗證檢查,作業才會成功。
如果您是從可公開存取的端點呼叫產生的 SDK,請務必要求端點進行驗證,並先驗證驗證符記的完整性,再使用該符記模擬使用者。
使用可呼叫的 Cloud Functions 時,系統會自動驗證驗證權杖,您可以按照下列範例使用:
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 } }
);
// ...
});
否則,請使用 Admin SDK 的 verifyIdToken 方法驗證及解碼驗證權杖。舉例來說,假設您的端點是以純 HTTP 函式實作,且您已使用 authorization 標頭將 Firebase Authentication 權杖傳遞至端點 (這是標準做法):
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 } }
);
// ...
});
只有在安全且無法公開存取的環境中執行資料遷移等管理工作時,才應指定並非來自可驗證來源的使用者 ID:
// Never do this if end users can initiate execution of the code!
const favoriteSongs = await getMyFavoriteSongs(
undefined,
{ impersonate: { authClaims } }
);
以不受限的存取權執行
如果您執行的作業需要管理員層級的權限,請從呼叫中省略 impersonate 參數:
await upsertSong(adminDc, {
title: songTitle_one,
instrumentsUsed: [Instrument.VOCAL],
});
以這種方式呼叫的作業可完整存取資料庫。如果您有僅供管理用途的查詢或突變,請使用 @auth(level: NO_ACCESS) 指令定義。這麼做可確保只有管理員層級的呼叫者可以執行這些作業。
使用 executeGraphql 方法管理資料
如要執行未定義 gql 變動或查詢的一次性作業,可以使用 executeGraphql 方法或唯讀 executeGraphqlRead 方法。
模擬未經驗證的使用者
使用 Admin SDK 執行公開作業時,請避免以完整管理員權限執行作業 (遵循最低權限原則)。請改為以模擬使用者 (請參閱下一節) 或模擬未經驗證的使用者身分執行作業。未通過驗證的使用者只能執行標示為 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);
模擬使用者身分
此外,您可能也會希望指令碼能代表特定使用者,根據有限的憑證修改使用者資料。這種做法符合最低權限原則。
如要使用這個介面,請從符合 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" } } }
使用管理員憑證
如果您執行的作業需要管理員層級的權限,請從呼叫中省略 impersonate 參數:
// 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" } } }
以這種方式呼叫的作業可完整存取資料庫。如果您有僅供管理用途的查詢或突變,請使用 @auth(level: NO_ACCESS) 指令定義。這麼做可確保只有管理員層級的呼叫者可以執行這些作業。
執行大量資料作業
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 陳述式長度上限時,就會發生錯誤。
在實務上,請嘗試找出適合工作負載的批次大小。
後續步驟
- 瞭解如何使用 Admin SDK 將資料植入資料庫
- 查看 Admin SDK 的 API。
- 如要執行其他專案管理作業,例如管理結構定義和連接器,以及管理服務和資料庫,請使用 Firebase CLI 和 Google Cloud 控制台。