如何解决尝试通过 Next.js API 路由上的 admin.firestore.v1.FirestoreAdminClient 导出备份错误:无法加载默认凭据
我正在尝试运行此代码来实现 Firestore 备份。
但这是我第一次将其部署到 Next.js 项目中。
我会在我的 /api/backup
端点上点击它。
const backupHandler: NextApiHandler = async (req,res) => {
try {
const admin = initializefirebaseAdmin();
const PROJECT_ID = getProjectId();
const client = new admin.firestore.v1.FirestoreAdminClient();
const DB_NAME = client.databasePath(PROJECT_ID,'(default)');
const TODAY = getToday(); // YYYY-MM-DD
const hashId = generateId().slice(0,5);
const BUCKET = `gs://${PROJECT_ID}.appspot.com`;
const FOLDER = `firestore-backup/${TODAY}-${hashId}`;
const FULL_PATH = `${BUCKET}/${FOLDER}`;
await client.exportDocuments({
name: DB_NAME,outputUriPrefix: FULL_PATH,collectionIds: [] // CAN LIST SPECIFIC COLLECTIONS
});
console.log(`Backup successfully exported`);
return res.status(200).send("Ok");
}
catch(err) {
console.log(err);
return res.status(500).send("Server error");
}
};
type FirebaseAdmin = typeof import("firebase-admin/lib/firebase-namespace")
const getServiceAccount = () : admin.ServiceAccount => {
if (process.env.VERCEL_ENV === "production"
|| process.env.VERCEL_GIT_COMMIT_REF === "staging") {
return SERVICE_ACCOUNT.PROD;
}
else return SERVICE_ACCOUNT.TEST;
};
export const initializefirebaseAdmin = (): FirebaseAdmin => {
const account = getServiceAccount(); // THIS GETS THE SERVICE ACOUNT (VIA THE DOWNLOADED .json FILE)
const PROJECT_ID = getProjectId();
if (!admin.apps.length) {
admin.initializeApp({
credential: admin.credential.cert(account),databaseURL: `https://${PROJECT_ID}.firebaseio.com` // I TRIED WITH AND WITHOUT THIS LINE: SAME RESULT
});
}
return admin;
};
这是我得到的错误:
错误:无法加载默认凭据。浏览到 https://cloud.google.com/docs/authentication/getting-started 了解更多信息。 在 GoogleAuth.getApplicationDefaultAsync (/var/task/node_modules/google-auth-library/build/src/auth/googleauth.js:173:19)
起初我只是使用 credential
属性。然后我添加了 databaseURL
以查看它是否可以解决问题,但结果仍然相同。
我想我正确地初始化了 firebase-admin
。不确定这里出了什么问题。
更新: 刚刚发现这个完全相同的代码在我的本地环境(开发中)上运行良好,但在我部署它时在我的 Next.js Node.js 环境中不起作用。可能出什么问题了?
解决方法
在地狱里待了几天后,才发现我做错了什么。
我使用 new admin.firestore.v1.FirestoreAdminClient();
是因为 firebase-admin
本身不会公开任何方法让我们访问 exportDocuments()
功能。
但事实是,当您像这样实例化 FirestoreAdminClient
时,它无法访问您在 admin.initializeApp({credentials})
上使用的凭据。
因此您需要通过执行以下操作将凭据传递给客户端:
import * as admin from "firebase-admin"; // OR IMPORT IT FROM SOME SINGLETON initializeFirebaseAdmin FUNCTION
import { NextApiHandler } from "next";
import SERVICE_ACCOUNT from "some-path/serviceAccount.json";
interface CredentialBody { // COPIED THIS FROM google-auth-library > auth > credentials
client_email?: string;
private_key?: string;
}
const backupHandler: NextApiHandler = async (req,res) => {
const client = new admin.firestore.v1.FirestoreAdminClient({
credentials: SERVICE_ACCOUNT as CredentialBody // <<<<<< THIS IS THE IMPORTANT PART
});
const PROJECT_ID = getProjectId();
const DB_NAME = client.databasePath(PROJECT_ID,"(default)");
const TODAY = getToday(); // YYYY-MM-DD
const hashId = generateId().slice(0,5);
const BUCKET = `gs://${PROJECT_ID}.appspot.com`;
const FOLDER = `backup/${TODAY}-${hashId}`;
const FULL_PATH = `${BUCKET}/${FOLDER}`;
await client.exportDocuments({
name: DB_NAME,outputUriPrefix: FULL_PATH,collectionIds: [] // CAN LIST SPECIFIC COLLECTIONS
});
console.log(`Backup successfully exported`);
return res.status(200).send("Ok");
};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。