Skip to content

debug() statement in firestore rules does not write out to firestore-debug.log #8407

Closed
@Turburlar

Description

@Turburlar

[REQUIRED] Environment info

Firebase CLI 13.31.2

Running on Flutter web in Chrome
cloud_firestore: ^5.6.6

Framework • revision c236373904 (3 weeks ago) • 2025-03-13 16:17:06 -0400
Engine • revision 18b71d647a
Tools • Dart 3.7.2 • DevTools 2.42.3

[REQUIRED] Test case

To reproduce, run the following flutter app main...

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';

void main() async {
  await Firebase.initializeApp(
    options: const FirebaseOptions(
      apiKey: "your-cred",
      projectId: "your-cred",
      storageBucket: "your-cred",
      messagingSenderId: "your-cred",
      appId: "your-cred",
    ),
  );
  FirebaseFirestore.instance.useFirestoreEmulator('localhost', 8080);
  await FirebaseAuth.instance.useAuthEmulator('localhost', 9099);
  final querySnapshot = await (FirebaseFirestore.instance.collection('invites').where('recipientUid', isEqualTo: "anything")).get();
}

With the following rules...

service cloud.firestore {
  match /databases/{database}/documents {
    // Default deny all
    match /{document=**} {
      allow read, write: if false;
    }
    
    // Check if user is authenticated
    function isAuthenticated() {
      return request.auth != null;
    }
    
    // Check if user is accessing their own data
    function isOwner(userId) {
      return request.auth.uid == userId;
    }
    
    // Public user data collection
    match /publicUserData/{userId} {
      allow read: if isAuthenticated();
      allow create: if isAuthenticated() && isOwner(userId);
      allow update, delete: if isAuthenticated() && isOwner(userId);
    }
    
    // Sports leagues
    match /sportsLeagues/{leagueId} {
      allow read: if isAuthenticated();
      allow write: if isAuthenticated() && isAdmin();
      
      match /teams/{teamId} {
        allow read: if isAuthenticated();
        allow write: if isAuthenticated() && isAdmin();
      }
    }

    // Memberships collection
    match /memberships/{membershipId} {
      allow read: if isAuthenticated();
      allow create, update: if isAuthenticated() && request.resource.data.uid == request.auth.uid;
      allow delete: if false;
    }

    // Invites collection
    match /invites/{inviteId} {
      allow read, delete: if isAuthenticated() && 
       debug(/databases/$(database)/documents/memberships/$(inviteId));
      allow create: if isAuthenticated() && isPickGroupAdmin(buildMembershipIdFromInvite(request));
      allow update: if false;
    }

    function isInviteRecipient(request) {
      return request.auth.uid == request.resource.data.recipientUid;
    }

    function buildMembershipIdFromInvite(request) {
      return request.resource.data.senderUid+'-'+request.resource.data.groupId;
    }

    // Pick groups collection
    match /pickGroups/{groupId} {
      allow read: if isAuthenticated(); // this cannot be made more strict as long as PickGroupService checks if name is unique
      allow create: if isAuthenticated();
      allow update: if isAuthenticated() && isPickGroupAdmin(request.auth.uid+'-'+request.resource.data.groupId);
      allow delete: if false;
    }

    function isPickGroupAdmin(id) {
      return exists(/databases/$(database)/documents/memberships/$(id)) &&
        get(/databases/$(database)/documents/memberships/$(id)).data.role == 'admin';
    }

    function isAdmin() {
      return exists(/databases/$(database)/documents/admins/$(request.auth.uid));
    }
  }
}

In this case the expected behaviour is that the path object would be written out in the firestore-debug.log.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions