firebase - Firebase - 导入“服务帐户对象必须包含字符串“project_id”属性时出错。”
问题描述
这是我第一次使用 Firebase,如果有任何帮助,我将不胜感激!
我将代码放在一个文件中,一切正常。我试图将所有内容组织在单独的文件和文件夹中,并且第一次导入它会中断,给我一个“⚠错误:服务帐户对象必须包含字符串“project_id”属性。” 当我把一切都带回来的那一刻,一切都很好。(见下文编辑信息)
所以我不能带出任何东西,只是导入它,我尝试了几个小块。如果您在下面看到 const {signUp} = require('./handlers/users'),这会导致它中断,如果我将其注释掉(保留原始代码)就可以了。我尝试只导出 serviceAccount,同样的事情发生了。
提前致谢!
const functions = require('firebase-functions');
const admin = require("firebase-admin");
const app = require('express')()
const serviceAccount = require("./admin.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "----------------------"
});
const firebaseConfig = {
apiKey: "-------------------",
authDomain: "-----------------",
databaseURL: "-------------------",
projectId: "----------------",
storageBucket: "-------------------",
messagingSenderId: "-----------",
appId: "----------------------------",
measurementId: "----------------"
}
const db = admin.firestore()
const firebase = require('firebase')
firebase.initializeApp(firebaseConfig)
const {signUp} = require('./handlers/users')
//middleware to protect the code
const routeProtect = (req, res, next) => {
let idToken
if (req.headers.authorization && req.headers.authorization.startsWith('Bearer ')) {
idToken = req.headers.authorization.split('Bearer ')[1]
} else {
console.error('There is no token')
return res.status(403).json({error: 'Unauthorized'})
}
admin.auth().verifyIdToken(idToken)
.then(decodedToken => {
req.user = decodedToken
console.log(decodedToken)
return db.collection('users')
.where('userId', '==', req.user.uid)
.limit(1)
.get()
})
.then(data => {
req.user.handle = data.docs[0].data().handle
return next()
})
.catch(err => {
console.error('There was an error with the token', err)
return res.status(403).json(err)
})
}
app.get('/posts', (req, res) => {
db
.collection('posts')
.orderBy('createdAt', 'desc')
.get()
.then(data => {
let posts = []
data.forEach(doc => {
posts.push({
postId: doc.id,
body: doc.data().body,
userHandle: doc.data().userHandle,
createdAt: doc.data().createdAt
})
})
return res.json(posts)
})
.catch(err => console.error(err))
})
app.post('/post', routeProtect, (req, res) => {
if(req.body.body.trim() === '') {
return res.status(400).json({body: 'Boddy cannot be empty'})
}
const newPost = {
body: req.body.body,
userHandle: req.user.handle,
createdAt: new Date().toISOString()
}
db
.collection('posts')
.add(newPost)
.then(doc => {
res.json({message: `document ${doc.id} created successfully`})
})
.catch(err => {
res.status(500).json({error: 'something went wrong'})
console.error(err)
})
})
//email address validation helper functions
const isEmail = (email) => {
const emailRegEx = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
//match() matches a string against a regular expression
if (email.match(emailRegEx)) return true
else return false
}
const isEmpty = (string) => {
if (string.trim() === '') return true
else return false
}
//signup route
app.post('/signup', (req, res) => {
const newUser = {
email: req.body.email,
password: req.body.password,
confirmPassword: req.body.confirmPassword,
handle: req.body.handle,
}
let errors = {}
//validating the email address
if(isEmpty(newUser.email)) {
errors.email = 'This field cannot be empty'
} else if (!isEmail(newUser.email)) {
errors.email = 'You must enter a valid email address'
}
if(isEmpty(newUser.password)) errors.password = 'This field cannot be empty'
if(newUser.password !== newUser.confirmPassword) errors.confirmPassword = "Passwords must be the same"
if(isEmpty(newUser.handle)) errors.handle = 'This field cannot be empty'
//need to make sure the errors object is empthy
if(Object.keys(errors).length > 0) return res.status(400).json(errors)
//TODO validate data
let token, userId
db.doc(`/users/${newUser.handle}`).get()
.then(doc => {
if (doc.exists) {
return res.status(400).json({handle: 'this handle is already taken'})
}else {
return firebase.auth().createUserWithEmailAndPassword(newUser.email, newUser.password)
}
})
.then(data => {
userId = data.user.uid
return data.user.getIdToken()
})
.then(idToken => {
token = idToken
const userCredentials = {
handle: newUser.handle,
email: newUser.email,
createdAt: new Date().toISOString(),
userId
}
return db.doc(`/users/${newUser.handle}`).set(userCredentials)
})
.then(() => {
return res.status(201).json({token})
})
.catch(err => {
console.error(err)
if(err.code ==='auth/email-already-in-use') {
return res.status(400).json({email: 'Email is already in use'})
} else {
return res.status(500).json({error: err.code})
}
})
}
)
//login route
app.post('/login', (req, res) => {
const user = {
email: req.body.email,
password: req.body.password
}
let errors = {}
if(isEmpty(user.email)) errors.email = 'Cannot be empty'
if(isEmpty(user.password)) errors.password = 'Cannot be empty'
if(Object.keys(errors).length > 0) return res.status(400).json(errors)
//logging in the user
firebase.auth().signInWithEmailAndPassword(user.email, user.password)
.then(data => data.user.getIdToken())
.then(token => res.json({token}))
.catch(err => {
console.error(err)
if(err.code === 'auth/wrong-password') return res.status(403).json({general: 'Wrong credentials, try again'})
else return res.status(500).json({error: err.code})
})
})
exports.api = functions.https.onRequest(app)
我的 admin.js 包含
const admin = require("firebase-admin");
const serviceAccount = require("./admin.js");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "-------------"
});
const db = admin.firestore()
module.exports = {admin, db}
解决方案
转到应用程序的firebase控制台上的项目设置,并寻找服务帐户选项卡,而不是在底部单击“生成新私钥”,并将下载新文件“name-service-admin-account.json”
admin.initializeApp({
credential: admin.credential.cert('path/to/service-account-that-has-download-before.json'),
databaseURL: "-------------"
});
推荐阅读
- dolphindb - 使用 dolphindb python api 时出现运行时错误
- javascript - 我无法导出通过 express 模块提供的承诺中的 URL 值
- html - 具有透明背景的 HTML/CSS 徽标显示方格背景
- angular - 一种将模板中的变量转换为多种类型的方法
- c++ - 使用可变模板静态函数作为模板参数
- sql - Delete rows with certain magnitude datetime difference
- node.js - 将依赖项添加到 package.json docker
- javascript - 从将传递 jslint 的同一对象中的函数调用另一个函数的正确方法是什么?
- python - ipywidgets 可突出显示的 Textarea 或 contenteditable HTML
- ansible - Ansible regex_findall is not giving expected results with negative search