Административные SDK Firebase Data Connect позволяют вызывать запросы и мутации из доверенных сред, таких как Cloud Functions, настраиваемые бэкенды или ваша собственная рабочая станция. Подобно тому, как вы генерируете SDK для клиентских приложений, вы можете создать собственный административный SDK параллельно с разработкой схем, запросов и мутаций, которые вы разворачиваете в сервисе Data Connect. Затем вы интегрируете методы из этого SDK в логику бэкенда или скрипты администрирования.
Как мы уже упоминали ранее, важно отметить, что запросы и мутации Data Connect не отправляются клиентами в момент запроса. Вместо этого, при развёртывании, операции Data Connect сохраняются на сервере, как облачные функции. Это означает, что при каждом развёртывании изменений в запросах и мутациях вам также необходимо повторно генерировать административные SDK и заново развёртывать все службы, которые от них зависят.
Прежде чем начать
- Узнайте о разработке схем, запросов и мутаций Data Connect . В типичном рабочем процессе вы будете разрабатывать их параллельно с кодом вашего приложения, включая любые службы, использующие административные SDK.
- Установите Firebase CLI .
- Включите Admin SDK для Node.js в качестве зависимости везде, где вы планируете вызывать сгенерированные admin SDK.
Генерация административных SDK
После создания схем, запросов и мутаций Data Connect вы можете сгенерировать соответствующий административный SDK:
Откройте или создайте файл
connector.yamlи добавьте определениеadminNodeSdk:connectorId: default generate: adminNodeSdk: outputDir: ../../dataconnect-generated/admin-generated package: "@dataconnect/admin-generated" packageJsonDir: ../..Файл
connector.yamlобычно находится в том же каталоге, что и файлы GraphQL (.gql), содержащие определения запросов и мутаций. Если вы уже сгенерировали клиентские SDK, этот файл уже создан.Сгенерируйте SDK.
Если у вас установлено расширение Data Connect VS Code, оно всегда будет поддерживать сгенерированные SDK в актуальном состоянии.
В противном случае используйте Firebase CLI:
firebase dataconnect:sdk:generateИли для автоматической регенерации SDK при обновлении файлов
gql:firebase dataconnect:sdk:generate --watch
Выполнение операций из административного 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) . Это гарантирует, что выполнять эти операции смогут только вызывающие пользователи с правами администратора.