Firebase Admin SDK — это набор серверных библиотек, которые позволяют взаимодействовать с Firebase из привилегированных сред для выполнения таких действий, как выполнение запросов и мутаций в службе Firebase Data Connect для управления большими объемами данных и других операций с повышенными привилегиями и олицетворенными учетными данными.
Admin SDK предоставляет API для вызова операций как в режиме чтения/записи, так и в режиме только для чтения. Операции только для чтения позволяют вам спокойно реализовывать административные функции, не изменяющие данные в ваших базах данных.
Настройка SDK администратора
Чтобы начать использовать Firebase Data Connect на своем сервере, вам сначала необходимо установить и настроить Admin SDK для Node.js.
Инициализируйте Admin SDK в своих скриптах
Чтобы инициализировать SDK, импортируйте расширения Data Connect и укажите идентификатор и местоположение службы вашего проекта.
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 позволяет упростить рабочие процессы, поскольку он может игнорировать аутентификацию и авторизацию для локальных потоков. (Вы также можете явно включить соответствие настройкам аутентификации и авторизации ваших операций с помощью олицетворения пользователя.)
Firebase Admin SDK автоматически подключается к эмулятору Data Connect , если установлена переменная среды DATA_CONNECT_EMULATOR_HOST :
export DATA_CONNECT_EMULATOR_HOST="127.0.0.1:9399"
Более подробную информацию см.:
Выполнение административных операций
Admin SDK предоставляется для привилегированных операций с вашими критически важными данными.
Admin SDK предоставляет три набора API:
- Сгенерированные административные SDK, представляющие собой типобезопасные SDK, сгенерированные из ваших определений
gqlтаким же образом, каким вы генерируете клиентские SDK. - Общий интерфейс для запуска произвольных операций GraphQL, в котором ваш код реализует запросы и мутации и передает их методу
executeGraphqlдля чтения и записи или методуexecuteGraphqlReadдоступному только для чтения. - Специализированный интерфейс для операций с большими объемами данных, который вместо универсальных методов
executeGraphqlпредоставляет выделенные методы для операций мутации:insert,insertMany,upsertиupsertMany.
Управление данными с помощью сгенерированных SDK
Административные SDK генерируются из определений gql таким же образом, как и клиентские SDK.
Сгенерированный административный 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 предназначены для запуска из доверенных сред и, следовательно, имеют неограниченный доступ к вашим базам данных.
При запуске публичных операций с помощью административного SDK следует избегать запуска операции с полными правами администратора (следуя принципу наименьших привилегий). Вместо этого следует запускать операцию либо от имени пользователя, выполняющего роль имперсонации (см. следующий раздел), либо от имени неаутентифицированного пользователя, выполняющего роль имперсонации. Неаутентифицированные пользователи могут выполнять только операции, помеченные как PUBLIC .
В приведенном выше примере запрос getSongs выполняется от имени неаутентифицированного пользователя.
Выдача себя за пользователя
Вы также можете выполнять операции от имени конкретных пользователей, передавая часть или весь токен Firebase Authentication в параметре impersonate ; как минимум, необходимо указать идентификатор пользователя в подзаявке. (Это то же значение, что и значение сервера auth.uid на которое можно ссылаться в операциях Data Connect GraphQL.)
Если вы выдаете себя за пользователя, операция завершится успешно только в том случае, если предоставленные вами данные пользователя пройдут проверку подлинности, указанную в вашем определении 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 } }
);
// ...
});
В противном случае используйте метод verifyIdToken из Admin SDK для проверки и декодирования токена аутентификации. Например, предположим, что ваша конечная точка реализована как простая HTTP-функция, и вы передали ей токен Firebase Authentication с помощью заголовка authorization , как это принято стандартно:
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 } }
);
// ...
});
Только при выполнении настоящих административных задач, таких как перенос данных из безопасной, непублично доступной среды, следует указывать идентификатор пользователя, который не получен из проверяемого источника:
// 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 .
Выдача себя за неавторизованного пользователя
При запуске публичных операций с помощью административного 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);
Выдача себя за пользователя
Существуют также случаи, когда ваши скрипты должны изменять пользовательские данные на основе ограниченных учётных данных от имени конкретного пользователя. Такой подход соответствует принципу наименьших привилегий.
Чтобы использовать этот интерфейс, соберите информацию из настроенного токена аутентификации JWT, соответствующего формату токена Authentication . См. также руководство по настроенным токенам .
// 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-запрос. При достижении ограничения на длину SQL-запроса PostgreSQL возникнет ошибка.
На практике экспериментируйте, чтобы найти подходящий размер партии для вашей рабочей нагрузки.
Что дальше?
- Узнайте о наполнении баз данных данными с помощью Admin SDK
- Ознакомьтесь с API для Admin SDK .
- Используйте Firebase CLI и консоль Google Cloud для других операций по управлению проектами, таких как управление схемами и коннекторами , а также управление службами и базами данных .