首页 > 解决方案 > 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

解决方案


转到应用程序的firebase控制台上的项目设置,并寻找服务帐户选项卡,而不是在底部单击“生成新私钥”,并将下载新文件“name-service-admin-account.json”


admin.initializeApp({
    credential: admin.credential.cert('path/to/service-account-that-has-download-before.json'),
    databaseURL: "-------------"
});

推荐阅读