از SDK های مدیریت تولید شده استفاده کنید

کیت‌های توسعه نرم‌افزار (SDK) مدیریت Firebase Data Connect به شما امکان می‌دهند کوئری‌ها و جهش‌های خود را از محیط‌های قابل اعتماد مانند توابع ابری، بک‌اندهای سفارشی یا ایستگاه کاری خودتان فراخوانی کنید. تقریباً به همان روشی که SDKها را برای برنامه‌های کلاینت خود تولید می‌کنید، می‌توانید همزمان با طراحی طرحواره‌ها، کوئری‌ها و جهش‌هایی که در سرویس Data Connect خود مستقر می‌کنید، یک SDK مدیریت سفارشی نیز به صورت موازی تولید کنید. سپس، متدهای این SDK را در منطق بک‌اند یا اسکریپت‌های مدیریتی خود ادغام می‌کنید.

همانطور که در جای دیگری اشاره کردیم، توجه به این نکته مهم است که کوئری‌ها و جهش‌های Data Connect در زمان درخواست توسط کلاینت‌ها ارسال نمی‌شوند. در عوض، هنگام استقرار، عملیات Data Connect مانند توابع ابری روی سرور ذخیره می‌شوند. این بدان معناست که هر زمان که تغییراتی را در کوئری‌ها و جهش‌های خود اعمال می‌کنید، باید SDKهای ادمین را نیز بازسازی کرده و هر سرویسی را که به آنها متکی است، مجدداً مستقر کنید.

قبل از اینکه شروع کنی

تولید SDK های مدیریتی

پس از ایجاد طرحواره‌ها، کوئری‌ها و جهش‌های Data Connect، می‌توانید یک SDK مدیریتی مربوطه ایجاد کنید:

  1. یک فایل connector.yaml باز یا ایجاد کنید و تعریف adminNodeSdk را به آن اضافه کنید:

    connectorId: default
    generate:
      adminNodeSdk:
        outputDir: ../../dataconnect-generated/admin-generated
        package: "@dataconnect/admin-generated"
        packageJsonDir: ../..
    

    فایل connector.yaml معمولاً در همان دایرکتوری فایل‌های GraphQL (.gql) که شامل تعاریف پرس‌وجو و جهش شما هستند، یافت می‌شود. اگر قبلاً SDKهای کلاینت را ایجاد کرده‌اید، این فایل از قبل ایجاد شده است.

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

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

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