Track all Firestore write activity in Firestore

Justin Poehnelt - Oct 24 '22 - - Dev Community

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.

Firestore Audit Logs to Collection

  1. Audit Logs are enabled for Firestore writes

Enable Firestore Audit Logs

  1. Logs are sent to a Pub/Sub topic via a sink

Create PubSub Sink

  1. 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 });
      })
    );
  });

Enter fullscreen mode Exit fullscreen mode
  1. Cloud Function writes to Firestore

User Collection Containing Activity

And that's it. I now have a /user/{userId}/activity collection!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player