Introduction
As part of a little side project, I wanted to log all Firestore writes for a user to a user specific collection that I can use to display a user’s activity. I was able to accomplish this using Audit Logs, Pub/Sub, and Cloud Functions.
Requirements
- Log all Firestore writes for a user, ignore reads
- Access the writes as an activity collection for the user,
users/{userId}/activity
Architecture
There are a few moving parts to this solution, but it’s pretty automatic.
- Audit Logs are enabled for Firestore writes
- Logs are sent to a Pub/Sub topic via a sink
- Cloud Function is triggered by Pub/Sub message
import * as firebaseAdmin from "firebase-admin"; import * as functions from "firebase-functions"; export default functions.pubsub .topic("firestore-activity") .onPublish(async (message) => { const { data } = message; const { timestamp, protoPayload } = JSON.parse( Buffer.from(data, "base64").toString() ); const uid = protoPayload.authenticationInfo.thirdPartyPrincipal.payload.user_id; const writes = protoPayload.request.writes; const activityRef = firebaseAdmin .firestore() .collection("users") .doc(uid) .collection("activity"); await Promise.all( // eslint-disable-next-line @typescript-eslint/no-explicit-any writes.map((write: any) => { activityRef.add({ write, timestamp }); }) ); });
- Cloud Function writes to Firestore
And that's it. I now have a /user/{userId}/activity
collection!
Top comments (0)