"Encountering an error: unable to call the Firebase function as the httpsCallable is

I am currently working on implementing role-based authentication using Firebase auth and Firebase functions. I have successfully set up a registration form, but now I am facing an issue while trying to add a form that allows users to submit an email which triggers a Firebase function to assign custom claims. After adding the function to Firebase via terminal and calling it in my project, I encounter a httpsCallable is not a function error when submitting the form with the email.

Below are the relevant files:

index.js located 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 configuration file where all firebase related actions are called

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();

Lastly, here is my Vue component containing the form

<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>

I would appreciate any insights on why the error occurs. Could there be something missing or incorrectly imported related to Firebase?

Answer №1

The issue you are facing is due to the way you have structured your code in the firebaseInit.js file.

export const fc = firebase.functions();
export const db = firebase.firestore();
export const fv = firebase.firestore.FieldValue;

export default firebaseApp.firestore();

In this setup, you are not properly exporting fc (or fv).

To fix this, consider revising your code as shown below:

import firebase from "firebase/app";
import "firebase/firestore";
import "firebase/functions";   // <-- Take note of the @ being 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 };

After making these changes, you can import the necessary functions in your component like so:

import {fc, db, fv} from "../data/firebaseInit";

//....

If you only require fc and db, the following importing method can be used:

import {fc, db} from "../data/firebaseInit";

//....

Answer №2

My approach to tackling this issue is a bit unconventional. I'm currently utilizing Vue 2.6 and in my component, all I require is:

import firebase from "firebase/app";
const functions = firebase.functions();
var addMessage = functions.httpsCallable("addMessage");

Within my main.js file, the setup includes:

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;

// Firebase configuration for the web app
const firebaseConfig = {

};
// Initializing Firebase
firebase.initializeApp(firebaseConfig);

let app;

firebase.auth().onAuthStateChanged(user => {
  if (!app) {
    app = new Vue({
    router,
    store,
    render: h => h(App)
  }).$mount("#app");
}

In the dependencies section:

"dependencies": {
   "core-js": "^3.6.5",
    "firebase": "^8.0.2",
    "firebase-functions": "^3.13.2",
    ...
 }

This essentially embodies the guidelines outlined in the documentation at https://firebase.google.com/docs/functions/callable, adapted for use with Vue.js.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for displaying real-time error notifications from server-side validation using AJAX

Seeking a way to display inline error messages from my Symfony2 Backend without refreshing the page. I considered replacing the current form in the HTML with the validated form containing the error messages returned by the backend through AJAX. However, ...

The absence of a form data boundary in the content-type of the POST request header

I have encountered an issue with my file upload code in AngularJS. The boundary is not being added to the content-type property in the request header, causing my C# web-api function to fail in detecting the image. Here's the post request using angula ...

Unveiling the Evasive Final Element in a JavaScript Array

Having a Javascript array named full_range: const range1 = _.range(1, 10, 0.5); const range2 = _.range(10, 100, 5); const range3 = _.range(100, 1000, 50); const range4 = _.range(1000, 10000, 500); const range5 = _.range(10000, 105000, 5000); const full_ran ...

Tips for ensuring elements within a modal receive immediate focus when opened in Angular 2

I am relatively new to Angular JS and I am encountering some challenges with implementing a directive in Angular 2 that can manage focusing on the modal when it is opened by clicking a button. There have been similar queries in the past, with solutions pr ...

Using angularjs, populate a dropdown menu by enclosing the options in curly braces

Utilizing the curly braces syntax interpolation in AngularJS allows us to connect data from the model to the view. This technique is typically used for displaying text. Is there a way to populate a dropdown list using the {{}} syntax? ...

Ensure that there are three unique JS code blocks in a single JS file, and avoid repetition of any block if it appears more than three times on

In my HTML page, I have 3 distinct blocks of code named block-1, block-2, and block-3 located in the file script.js. This script is called three separate times within the same page. I want to ensure that each block is executed only once based on the order ...

Remove browser data in PhoneGap / Prevent PhoneGap from utilizing cookies

Currently, I am in the process of creating a login system for my mobile application. After logging in to my server, it sends back a JSESSIONID that I can utilize for further authentication. The issue I am encountering is that PhoneGap is automatically st ...

Having trouble with Firebase admin in your Next.js/Stripe webhook integration?

I've encountered an issue when using the stripe webhook in Next.js. Every time I attempt to set it up, I receive the following error: unable to detect a project id in this environment I initially tried setting it up in the app router and then trans ...

Showing the Nested Object following retrieval from the API

Greetings everyone, I am facing an issue with displaying basic data from an API service that contains a NESTED json object. The challenge I am encountering is that most tutorials only focus on displaying data from array objects, not nested ones. The str ...

Consolidate common values within a JSON object into a single grouping

Hello there, I need some help with grouping two JSON objects into a single array by common values. Here is the initial input: const json = { "2280492":[ { "ID":"2280492", "Name":"Paul ...

Access to an Express route in Node JS can only be granted upon clicking a button

Is it feasible to create an express route that can only be accessed once a button is clicked? I want to prevent users from entering the route directly in the URL bar, and instead require them to click a specific button first. I'm curious if this can b ...

Utilizing innerHTML in JavaScript along with an if/else statement for controlling a dropdown menu in Bootstrap 4

My project is almost complete, but I'm struggling to include innerHTML statements when a user fails to select an item from the two dropdown menus. While I know how to achieve this using alerts, I want the message to be displayed on the page itself if ...

React JS application experiencing issue with input fields not clearing upon submission

I'm facing an issue with uploading data to Firebase in my ReactJS project. While the data is successfully added, I also want to clear the input fields after submission. As a newcomer to React JS, I am struggling to figure out why the fields are not cl ...

What is the best way to handle subfolders?

I have a question about serving different directories in my dist folder using vercel/serve. Click here to learn more How can I set it up so that localhost/foo will serve the build from the foo directory, and localhost/bar will serve the build from the bar ...

"Implementing a feature in JavaScript that generates a child object within an array for every click event

On each button click, I aim to add an object as a child of the last existing object. This is the code snippet I currently have: const Myarray = [ { id: 1, child:[] } ] handleArrayDepth = (Myarray) => { Myarray.map(arrayitem => { let ...

The basic structure for organizing components and categories

I am working on creating a list and have designed the following Schema: new SimpleSchema({ element: { type: String, optional: true }, note: { type: String, optional: true }, order: { type: Number, optional: true } }); Now, I wan ...

What are the reasons and methods for cleaning up components in React JavaScript?

While I comprehend the necessity of tidying up our components in React to avoid memory leaks (among other reasons), as well as knowing how to utilize comonentWillUnmount (which is outdated) and the useEffect hook, my burning question remains: what exactl ...

Angular 2: Dynamically positioning content within a div overlay

I have made some customizations to a PrimeNg TabView and placed it inside a custom component to achieve the following: https://i.sstatic.net/mjWED.gif As you can see in the image, the tabview content is set to overflow-x: hidden to enhance the appearance ...

What is the best way to add bold formatting to text enclosed in parentheses using javascript/jquery?

How can I use jQuery or JavaScript to make the text inside parentheses bold? For example: "what is your Age (in Year)." I need assistance in making the text within parentheses bold using either jQuery or JavaScript. Can someone help me with this task? ...

How can you pass two distinct variables in a JavaScript function?

This is the JavaScript code for my first page: <script> function MessageDetailsById(id) { $("#active"+id).css({"color":"red"}); var http = new XMLHttpRequest(); var url = "Ajax.php"; ...