问题
I'm new to Firebase/Firestore and trying to create a Firebase Function that will delete all user data upon deletion of an Auth account.
My functions is successfully called on deleting an account and I'm trying to delete a collection called links for that user and then delete the user document. But I'm getting an error of linksRef.forEach is not a function.
Any guidance on how I'd do this cascading delete?
exports.deleteUserData = functions.auth.user().onDelete((event) => {
const userId = event.data.uid;
const store = admin.firestore();
store.collection('users').doc(userId).get().then(user => {
if (user.exists) {
user.collection('links').get().then(links => {
links.forEach(link => {
link.delete();
})
return;
}).catch(reason => {
console.log(reason);
});
user.delete();
return;
}
else {
// User does not exist
return;
}
}
).catch(reason => {
console.log(reason);
});
});
回答1:
Based on the comment from @Doug Stevenson regarding Promises I managed to get this working by scraping together code. Definitely not the cleanest but it works if anyone is trying to do similar.
// Delete user data when user deleted
exports.deleteUserData = functions.auth.user().onDelete((event) => {
const userId = event.data.uid;
const database = admin.firestore();
const linksRef = database.collection('users').doc(userId).collection('links');
const deleteLinks = deleteCollection(database, linksRef, BATCH_SIZE)
return Promise.all([deleteLinks]).then(() => {
return database.collection('users').doc(userId).delete();
});
});
/**
* Delete a collection, in batches of batchSize. Note that this does
* not recursively delete subcollections of documents in the collection
*/
function deleteCollection (db, collectionRef, batchSize) {
var query = collectionRef.orderBy('__name__').limit(batchSize)
return new Promise(function (resolve, reject) {
deleteQueryBatch(db, query, batchSize, resolve, reject)
})
}
function deleteQueryBatch (db, query, batchSize, resolve, reject) {
query.get()
.then((snapshot) => {
// When there are no documents left, we are done
if (snapshot.size === 0) {
return 0
}
// Delete documents in a batch
var batch = db.batch()
snapshot.docs.forEach(function (doc) {
batch.delete(doc.ref)
})
return batch.commit().then(function () {
return snapshot.size
})
}).then(function (numDeleted) {
if (numDeleted <= batchSize) {
resolve()
return
}
else {
// Recurse on the next process tick, to avoid
// exploding the stack.
return process.nextTick(function () {
deleteQueryBatch(db, query, batchSize, resolve, reject)
})
}
})
.catch(reject)
}
回答2:
Based on this official doc from Firebase, it seems that it's quite easy to set-up a clearData function.
It only supports basic Firestore structure. But in your case it should work configuring only the user_privacy.json with something like:
{
"firestore": {
"clearData": [
{"collection": "users", "doc": "UID_VARIABLE", "field": "links"},
{"collection": "users", "doc": "UID_VARIABLE"}
],
}
}
For more complex cases, the function code needs to be tweaked.
Please refer to the doc
来源:https://stackoverflow.com/questions/49367260/firestore-delete-all-user-data-on-account-delete-using-a-firebase-function