Reputation: 195
I'm trying to implement a role-based authentication using Firebase auth and Firebase functions. Right now I have a registration form that is working as supposed and now I'm trying to add a form that you submit an email that calls the Firebase function that will attach a custom claim to a user. I already added my function to Firebase via the terminal and I'm calling functions on my project but whenever I submit the form with the email I get a httpsCallable is not a function
error.
Here are my files:
index.js inside functions folder
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.addAdminRole = functions.https.onCall((data, context) => {
//get user and add custom claim (admin)
return admin
.auth()
.getUserByEmail(data.email)
.then(user => {
return admin.auth().setCustomUserClaims(user.uid, {
admin: true
});
})
.then(() => {
return {
message: `Success! ${data.email} has been made admin`
};
})
.catch(err => {
return err;
});
});
My firebaseInit.js config file where I call everything firebase related
import firebase from "firebase/app";
import "firebase/firestore";
import "@firebase/functions";
import firebaseConfig from "./firebaseConfig";
const firebaseApp = firebase.initializeApp(firebaseConfig);
export const fc = firebase.functions();
export const db = firebase.firestore();
export const fv = firebase.firestore.FieldValue;
export default firebaseApp.firestore();
And my Vue component where the form is
<template>
<div class="home">
<h3>Welcome to Site</h3>
<h3>Add user to admin</h3>
<div class="row">
<form @submit.prevent="addAdmin()" class="col s12">
<div class="row">
<div class="input-field col s12">
<input id="email" type="email" class="validate" v-model="email" />
<label for="email">Email</label>
</div>
</div>
<button type="submit" class="btn">Submit</button>
<router-link to="/members" class="btn grey">Cancel</router-link>
</form>
</div>
</div>
</template>
<script>
import firebase from "firebase/app";
import fc from "../data/firebaseInit";
export default {
name: "home",
data() {
return {
email: ""
};
},
methods: {
addAdmin() {
const addAdminRole = fc.httpsCallable("addAdminRole");
addAdminRole(this.email).then(result => {
console.log(result);
});
}
}
};
</script>
Can someone shed a light on why I'm getting this error? Am I forgetting to import something firebase related?
Upvotes: 3
Views: 3969
Reputation: 436
I could solve this problem in a different way. I am working with Vue 2.6. In my component I just need:
import firebase from "firebase/app";
const functions = firebase.functions();
var addMessage = functions.httpsCallable("addMessage");
In my main.js file I have:
import Vue from "vue";
import App from "./App.vue";
import vuetify from "./plugins/vuetify";
import router from "./router";
import firebase from "firebase/app";
import "firebase/functions";
import store from "./store";
Vue.config.productionTip = false;
Vue.config.devtools = true;
Vue.prototype.$firebase = firebase;
// Your web app's Firebase configuration
const firebaseConfig = {
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
let app;
firebase.auth().onAuthStateChanged(user => {
if (!app) {
app = new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
}
And in the dependencies:
"dependencies": {
"core-js": "^3.6.5",
"firebase": "^8.0.2",
"firebase-functions": "^3.13.2",
...
}
This is basically the instructions of the documentation https://firebase.google.com/docs/functions/callable applied to Vue.js
Upvotes: 1
Reputation: 83163
Your problem comes from the fact that by doing
export const fc = firebase.functions();
export const db = firebase.firestore();
export const fv = firebase.firestore.FieldValue;
export default firebaseApp.firestore();
in your firebaseInit.js
file, you aren't exporting fc
(nor fv
by the way)
The following should work
import firebase from "firebase/app";
import "firebase/firestore";
import "firebase/functions"; // <-- Note that the @ was removed
import firebaseConfig from "./firebaseConfig";
const firebaseApp = firebase.initializeApp(firebaseConfig);
const fc = firebase.functions();
const db = firebase.firestore();
const fv = firebase.firestore.FieldValue;
export { fc, db, fv };
Then, in your component you do:
import {fc, db, fv} from "../data/firebaseInit";
//....
Or the following it you only need fc
and db
, for example:
import {fc, db} from "../data/firebaseInit";
//....
Upvotes: 8