i need to deleete an user from firebase auth, and then delete the document corresponding to the user.
The deletion from authentication works, but i dont know how to delete from firestore. I have this
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
admin.initializeApp();
export const deleteUser = functions.https.onRequest(async (request, response) =>{
const userEmail = request.body.userEmail;
const collection = request.body.collection;
let uid = '';
admin.auth().getUserByEmail(userEmail)
.then(userRecord => {
uid = userRecord.uid
admin.auth().deleteUser(uid)
})
.then( () => {
admin.firestore().collection(collection).doc(uid).get()
.then(queryResult => {
queryResult.ref.delete()
})
response.status(200).send('deleted')
})
.catch(error => {
response.status(500).send('Failed')
})
})
To try i used postman with
{
"userEmail": "[email protected]",
"collection" : "Users"
}
CodePudding user response:
All you have to do is get the doc ref and call the delete function. I leave error handling up to you.
try {
const userRecord = await admin.auth().getUserByEmail(userEmail)
await admin.auth().deleteUser(uid)
await admin.firestore().collection(collection).doc(uid).delete()
return response.status(200).send('deleted');
}
catch{
return response.status(500).send('Failed')
}
Read the docs: https://firebase.google.com/docs/firestore/manage-data/delete-data#web-version-8
CodePudding user response:
In addition to what @kingkong.js
mentioned in their answer (to use DocumentReference#delete()
), you also need to ensure your Promise chains are wired up correctly. If not, your function will be terminated before it makes any changes.
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";
admin.initializeApp();
async function deleteUserByEmail(userEmail, collection) {
// grabs services first to make sure they are initialized
const auth = admin.auth();
const db = admin.firestore();
// gets a user by their email, throws an error if not found
const { uid } = await auth.getUserByEmail(userEmail);
// These can be done in parallel using Promise.all()
await auth.deleteUser(uid);
await db.collection(collection)
.doc(uid)
.delete();
return uid;
}
export const deleteUser = functions.https.onRequest(async (request, response) => {
// TODO: Make sure body (it may be null!), userEmail and
// collection have values. Return HTTP 400 if not.
const userEmail = request.body.userEmail;
const collection = request.body.collection;
// IMPORTANT TODO: Make sure the calling user/admin is properly
// authorized to delete this account. Return HTTP 403 if not.
deleteUserByEmail(userEmail, collection)
.then((uid) => {
// consider the RESTful empty HTTP 204 response
response.status(200).send('deleted');
})
.catch((err) => {
if (err && err.code === "auth/user-not-found") {
// an already deleted user should be considered a success?
response.status(200).send('deleted');
return;
}
// IMPORTANT: Don't forget to log the error for debugging later
console.error("Failed to delete user by email. Error Code: " (err.code || "unknown"), err);
response.status(500).send('failed')
});
})
You may want to consider using a Callable Cloud Function (functions.https.onCall
) instead as it can handle managing the request body, response and authentication for you.