از Admin SDK با Data Connect استفاده کنید، از Admin SDK با Data Connect استفاده کنید

کیت توسعه نرم‌افزاری مدیریت فایربیس Firebase Admin SDK مجموعه‌ای از کتابخانه‌های سرور است که به شما امکان می‌دهد از محیط‌های دارای امتیاز بالا با فایربیس تعامل داشته باشید تا اقداماتی مانند انجام کوئری‌ها و جهش‌ها را در سرویس Firebase Data Connect برای مدیریت داده‌های انبوه و سایر عملیات با امتیازات بالا و اعتبارنامه‌های جعل هویت انجام دهید.

Admin SDK یک API برای فراخوانی عملیات در هر دو حالت خواندن/نوشتن و فقط خواندنی در اختیار شما قرار می‌دهد. با عملیات فقط خواندنی، خیالتان از بابت پیاده‌سازی توابع مدیریتی که نمی‌توانند داده‌ها را در پایگاه‌های داده شما تغییر دهند، راحت است.

تنظیمات SDK ادمین

برای شروع استفاده از Firebase Data Connect روی سرور خود، ابتدا باید Admin SDK برای Node.js نصب و راه‌اندازی کنید .

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 به شما امکان می‌دهد گردش‌های کاری خود را ساده کنید زیرا می‌تواند احراز هویت و مجوز را برای جریان‌های محلی نادیده بگیرد. (همچنین می‌توانید صریحاً با جعل هویت کاربر، از پیکربندی احراز هویت و مجوز عملیات خود پیروی کنید.)

SDK های Firebase Admin به طور خودکار با تنظیم متغیر محیطی DATA_CONNECT_EMULATOR_HOST به شبیه ساز Data Connect متصل می شوند:

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

جعل هویت یک کاربر احراز هویت نشده

SDK های مدیریتی برای اجرا در محیط‌های قابل اعتماد در نظر گرفته شده‌اند و بنابراین دسترسی نامحدودی به پایگاه‌های داده شما دارند.

وقتی عملیات عمومی را با SDK ادمین اجرا می‌کنید، باید از اجرای عملیات با امتیازات کامل ادمین (با پیروی از اصل حداقل امتیاز) خودداری کنید. در عوض، باید عملیات را یا به عنوان یک کاربر جعل هویت شده (به بخش بعدی مراجعه کنید) یا به عنوان یک کاربر جعل هویت شده و احراز هویت نشده اجرا کنید. کاربران احراز هویت نشده فقط می‌توانند عملیات علامت‌گذاری شده به عنوان PUBLIC را اجرا کنند.

در مثال بالا، کوئری getSongs به عنوان یک کاربر احراز هویت نشده اجرا می‌شود.

جعل هویت کاربر

شما همچنین می‌توانید با ارسال بخشی یا تمام توکن Firebase Authentication در گزینه‌ی impersonate ، عملیات را از طرف کاربران خاص انجام دهید؛ حداقل باید شناسه‌ی کاربری کاربر را در sub claim مشخص کنید. (این همان 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 } }
);

اجرا با دسترسی نامحدود

اگر عملیاتی را انجام می‌دهید که به مجوزهای سطح مدیر نیاز دارد، پارامتر جعل هویت را از فراخوانی حذف کنید:

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

از اعتبارنامه‌های اداری استفاده کنید

اگر عملیاتی را انجام می‌دهید که به مجوزهای سطح مدیر نیاز دارد، پارامتر جعل هویت را از فراخوانی حذف کنید:

// 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) تعریف کنید. انجام این کار تضمین می‌کند که فقط فراخوانی‌کنندگان سطح ادمین می‌توانند این عملیات را اجرا کنند.

انجام عملیات داده انبوه

فایربیس توصیه می‌کند برای عملیات داده‌های حجیم در پایگاه‌های داده عملیاتی 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);

یادداشت‌های عملکرد برای عملیات انبوه

هر درخواست به backend یک سفر رفت و برگشت به Cloud SQL را متحمل می‌شود، بنابراین هرچه تعداد درخواست‌ها بیشتر باشد، توان عملیاتی بالاتر می‌رود.

با این حال، هرچه اندازه دسته بزرگتر باشد، دستور SQL تولید شده طولانی‌تر است. هنگامی که به محدودیت طول دستور SQL در PostgreSQL برسید، با خطا مواجه خواهید شد.

در عمل، برای یافتن اندازه دسته مناسب برای حجم کار خود، آزمایش کنید.

بعدش چی؟