Firebase SQL Connect Admin SDK ช่วยให้คุณเรียกใช้คําค้นหาและการเปลี่ยนแปลงจาก สภาพแวดล้อมที่เชื่อถือได้ เช่น Cloud Functions, แบ็กเอนด์ที่กําหนดเอง หรือ เวิร์กสเตชันของคุณเอง คุณสามารถสร้าง Admin SDK ที่กําหนดเองไปพร้อมๆ กับการออกแบบสคีมา คําค้นหา และการเปลี่ยนแปลงที่คุณจะนําไปใช้กับบริการ SQL Connect ได้ในลักษณะเดียวกับการสร้าง SDK สําหรับแอปไคลเอ็นต์ จากนั้นผสานรวมเมธอดจาก SDK นี้เข้ากับตรรกะแบ็กเอนด์หรือสคริปต์การดูแลระบบ
ดังที่เราได้กล่าวไว้ในส่วนอื่นๆ สิ่งสําคัญที่ต้องทราบคือไคลเอ็นต์จะไม่ส่งคําค้นหาSQL Connect และการเปลี่ยนแปลงในเวลาที่ส่งคําขอ แต่เมื่อมีการนําไปใช้ ระบบจะจัดเก็บการดําเนินการ SQL Connect ไว้ในเซิร์ฟเวอร์เหมือนกับ Cloud Functions ซึ่งหมายความว่าทุกครั้งที่คุณนําการเปลี่ยนแปลงไปใช้กับคําค้นหาและการเปลี่ยนแปลง คุณจะต้องสร้าง Admin SDK ขึ้นมาใหม่และนําบริการที่ต้องใช้ SDK เหล่านั้นไปใช้ใหม่ด้วย
ก่อนเริ่มต้น
- ดูข้อมูลเกี่ยวกับการออกแบบสคีมา SQL Connect คําค้นหา และการเปลี่ยนแปลง ในเวิร์กโฟลว์ทั่วไป คุณจะพัฒนาสิ่งเหล่านี้ไปพร้อมๆ กับโค้ดแอปพลิเคชัน รวมถึงบริการที่ใช้ Admin SDK
- Cloud Shell
รวม Admin SDK สําหรับ Node.js เป็นทรัพยากร Dependency ในทุกที่ที่คุณวางแผนจะเรียกใช้ Admin SDK ที่สร้างขึ้น
สร้าง Admin SDK
หลังจากสร้างสคีมา คําค้นหา และการเปลี่ยนแปลง SQL Connect แล้ว คุณจะ สร้าง Admin SDK ที่เกี่ยวข้องได้โดยทำดังนี้
เปิดหรือสร้างไฟล์
connector.yamlแล้วเพิ่มคําจํากัดความadminNodeSdkconnectorId: default generate: adminNodeSdk: outputDir: ../../dataconnect-generated/admin-generated package: "@dataconnect/admin-generated" packageJsonDir: ../..โดยปกติแล้วไฟล์
connector.yamlจะอยู่ในไดเรกทอรีเดียวกับไฟล์ GraphQL (.gql) ที่มีคําจํากัดความของคําค้นหาและการเปลี่ยนแปลง หากคุณสร้าง Client SDK ไว้แล้ว ระบบจะสร้างไฟล์นี้ขึ้นมาแล้วสร้าง SDK
หากคุณติดตั้งส่วนขยาย SQL Connect VS Code ไว้ ส่วนขยายนี้จะอัปเดต SDK ที่สร้างขึ้นให้เป็นเวอร์ชันล่าสุดอยู่เสมอ
หรือใช้ Firebase CLI โดยทำดังนี้
firebase dataconnect:sdk:generateหรือหากต้องการสร้าง SDK ขึ้นมาใหม่โดยอัตโนมัติเมื่อคุณอัปเดตไฟล์
gqlให้ทำดังนี้firebase dataconnect:sdk:generate --watch
เรียกใช้การดําเนินการจาก Admin 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 ในฐานะผู้ใช้ที่ไม่มีการตรวจสอบสิทธิ์
การสวมบทบาทเป็นผู้ใช้
นอกจากนี้ คุณยังดําเนินการในนามของผู้ใช้ที่เฉพาะเจาะจงได้ด้วยการส่งส่วนหนึ่งหรือ
ทั้งหมดของโทเค็น Firebase Authentication ในตัวเลือก impersonate โดยคุณ
ต้องระบุ User ID ของผู้ใช้ในคำกล่าวอ้าง `sub` อย่างน้อย (ซึ่งเป็นค่าเดียวกับค่าเซิร์ฟเวอร์
auth.uidที่คุณอ้างอิงได้ในการดําเนินการ
SQL 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 } }
);
// ...
});
หรือใช้เมธอด Admin SDK's verifyIdToken เพื่อตรวจสอบและถอดรหัส
โทเค็นการตรวจสอบสิทธิ์ ตัวอย่างเช่น สมมติว่าคุณใช้ปลายทางเป็นฟังก์ชัน 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 } }
);
// ...
});
คุณควรระบุ User ID ที่ไม่ได้มาจากแหล่งที่มาที่ตรวจสอบได้ก็ต่อเมื่อดําเนินการดูแลระบบที่แท้จริง เช่น การย้ายข้อมูล จากสภาพแวดล้อมที่ปลอดภัยและเข้าถึงได้แบบไม่สาธารณะ
// 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],
});
การดําเนินการที่เรียกใช้ด้วยวิธีนี้จะมีสิทธิ์เข้าถึงฐานข้อมูลอย่างสมบูรณ์ หากคุณมีคําค้นหาหรือการเปลี่ยนแปลงที่ต้องการใช้เพื่อวัตถุประสงค์ในการดูแลระบบเท่านั้น คุณควรระบุคําค้นหาหรือการเปลี่ยนแปลงเหล่านั้นด้วย Directive @auth(level: NO_ACCESS) การทําเช่นนี้จะช่วยให้มั่นใจได้ว่าเฉพาะผู้เรียกที่อยู่ในระดับผู้ดูแลระบบเท่านั้นที่จะเรียกใช้การดําเนินการเหล่านี้ได้