How do I delete a user from my admin panel using the firebase Admin SDK? I’m getting this error when trying to delete it:
Uncaught (in promise) ReferenceError: uid is not defined at eval (ManageCustomer.vue?b113:262)
What am I doing wrong?
This is my code in index.js from functions
const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp(); const db = admin.firestore(); exports.AddUserRole = functions.auth.user().onCreate(async (authUser) => { if (authUser.email) { const customClaims = { //admin: true, customer: true, }; try { var _ = await admin .auth() .setCustomUserClaims(authUser.uid, customClaims); return db .collection("roles") .doc(authUser.uid) .set({ email: authUser.email, role: customClaims, }); } catch (error) { console.log(error); } } }); exports.deleteUser = functions.https.onCall(async (data, context) => { if (!context.auth.token.admin) return try { var _ = await admin .auth() .deleteUser(uid) .then(() => { console.log("Successfully deleted user"); }) .catch((error) => { console.log("Error deleting user:", error); }); } catch (error) { console.log("error deleting user", error); } });
Here is my client side code
<template> <div class="manage-customer"> <br /> <div> <h2>Customer</h2> <br /> <section> <div class=""> <div class="column"> <div> <div class="header" style=" font-weight: bold;"> Customer Info </div> <router-link to="/admin/new-user" class="btn" href="#"> New User</router-link > <table class="table table-users" cellspacing="0"> <thead> <tr style=" text-align: center;"> <th style="background: var(--primary); color: var(--secondary); width:180px " > User Id </th> <th style="background: var(--primary); color: var(--secondary); width:180px" > Username </th> <th style="background: var(--primary); color: var(--secondary); width:120px" > Email </th> <th style="background: var(--primary); color: var(--secondary); width:150px" > Phone </th> <th style="background: var(--primary); color: var(--secondary); width:220px" > Address </th> <th style="background: var(--primary); color: var(--secondary); width:60px" > Postcode </th> <th style="background: var(--primary); color: var(--secondary); width:170px; " > Action </th> </tr> </thead> <tbody> <tr v-for="profile in profiles" :key="profile.id"> <td data-label="Id" style="width: 160px;"> {{ profile.id }} </td> <td data-label="DisplayName" style="width: 150px"> {{ profile.displayName }} </td> <td data-label="Email" style="width: 150px"> {{ profile.email }} </td> <td data-label="Phone" style="width: 100px"> {{ profile.phone }} </td> <td data-label="Address" style="width: 250px"> {{ profile.address }} </td> <td data-label="Postcode" style="width: 70px"> {{ profile.postcode }} </td> <td style="width:170px; display:inline-flex;" data-label="Action" > <button @click="editProfile(profile)" class="edit-product" style=" " > Edit </button> <button class="delete-product" @click="deleteProfile(profile)" style="" > Delete </button> </td> </tr> </tbody> </table> <br /> </div> </div> </div> </section> <modal name="profiles" style="top: 10px; margin: 0 auto;" height="80%" width="65%" :adaptive="true" > <div class="container"> <div class="modal-body-product"> <form style=" width: 90% !important; border: 0; box-shadow: none;"> <div> <span @click="hide" class="close">✖</span> </div> <!-- <h3 id="productLabel">Add Profile</h3> --> <h3 id="productLabel" style="margin-bottom: 1.5rem;"> EDIT PROFILE </h3> <div class="form-group"> <label for="">Username:</label> <input type="text" class="form-control" placeholder="Username" v-model.lazy="profile.displayName" /> </div> <div class="form-group"> <label for="">Phone:</label> <input name="description" class="form-control" placeholder="Phone" v-model.lazy="profile.phone" /> </div> <div class="form-group"> <label for="">Address:</label> <input type="text" placeholder="Address" v-model.lazy="profile.address" class="form-control" /> </div> <div class="form-group"> <label for="">Postcode:</label> <input type="text" placeholder="Postcode" v-model.lazy="profile.postcode" class="form-control" /> </div> <div class="modal-footer"> <!-- <button class="btn" type="button" @click.prevent="addProfile()" @click="hide" > Save </button> --> <br /> <button class="btn" type="button" @click="updateProfile()"> Apply changes </button> </div> </form> </div> </div> </modal> </div> <router-view></router-view> </div> </template> <script> import firebase from "firebase"; // const admin = require("firebase-admin"); // admin.initializeApp(); // const db = admin.firestore(); import Swal from "sweetalert2"; window.Swal = Swal; const Toast = Swal.mixin({ toast: true, position: "top-end", showConfirmButton: false, timer: 3000, }); window.Toast = Toast; export default { name: "Dashboard", data() { return { users: [], user: "", roles: [], profiles: [], profile: { id: null, displayName: null, phone: null, address: null, postcode: null, }, activeItem: null, }; }, firestore() { return { profiles: firebase.firestore().collection("profiles"), roles: firebase.firestore().collection("roles"), }; }, created() { var self = this; firebase.auth().onAuthStateChanged((user) => { self.user = user; }); this.users = []; firebase .firestore() .collection("roles") .get() .then((snap) => { snap.forEach((doc) => { var user = doc.data(); user.id = doc.id; console.log("🌿", doc.data()); if (!user.role.admin) this.users.push(user); }); }); }, methods: { // addNew() { // this.$router.push("/admin/new-user"); // }, hide() { this.$modal.hide("profiles"); }, editProfile(profile) { // this.modal = "edit"; this.profile = profile; this.activeItem = profile.id; this.$modal.show("profiles"); }, updateProfile() { this.$firestore.profiles.doc(this.profile.id).update(this.profile); Toast.fire({ icon: "success", title: "Profile updated successfully", }); this.$modal.hide("profiles"); }, deleteProfile(doc) { Swal.fire({ title: "Are you sure?", text: "You won't be able to revert this!", icon: "warning", showCancelButton: true, confirmButtonColor: "#3085d6", cancelButtonColor: "#d33", confirmButtonText: "Yes, delete it!", }).then((result) => { if (result.value) { this.$firestore.profiles.doc(doc.id).delete(); // console.log(doc.id); this.$firestore.roles.doc(doc.id).delete(); const uid = this.profile.id; var deleteUser = firebase.functions().httpsCallable("deleteUser"); deleteUser({ uid }) // not deleteUser(uid) .then((result) => { console.log("User delete successfully", result); }); Toast.fire({ icon: "success", title: "Deleted successfully", }); } }); }, }, }; </script>
Advertisement
Answer
You are not accessing the UID in your cloud function from the data object.
exports.deleteUser = functions.https.onCall(async (data, context) => { if (!context.auth.token.admin) return const {uid} = data; if (!uid) return {error: "Please enter an UID"} try { // return the promise from here await admin.auth().deleteUser(uid) await admin.firestore().collection("profiles").doc(uid).delete() console.log("Successfully deleted user"); return {data: "User deleted"} } catch (error) { console.log("error deleting user", error); return {error} } });
Also try passing the UID from Vue app in an object as shown in the documentation.
const uid = "uidOfUserToBeDeleted" var deleteUser = firebase.functions().httpsCallable("deleteUser"); deleteUser({uid}) // not deleteUser(uid) .then((result) => { console.log("User delete successfully", result); })
However, the issue is on your frontend. Where is uid
defined? In the example above I have hard coded it, make sure you fetch the UID from your input field if it is an admin that is trying to delete user.
Is the doc.id
the UID of user to be deleted? If yes, then you should call function like this deleteUser(doc.id)