OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

Firestore Null value error. caused by rules in emulation

  • Thread starter Thread starter Silent Sheaf
  • Start date Start date
S

Silent Sheaf

Guest
I'm trying to get my firestore rules working for certain collections in the emulator, and I have for most of them up until I want the auth'd user to be able to read users that are within the same organisation.

However, when I set up some rules that check if a user is present in an organisation, I get a very helpful "Null value error" in the console.

For what it's worth, this all works when there's no rules set other than read: true.

A user contains an of organisation ids (organisations), and an organisation contains an array of userIds (users).

here's my query function:

Code:
  async getUsersForOrganisation(organisationId: string): Promise<User[]> {
    const orgRef = doc(db, 'organisations', organisationId)

    try {
      const orgDoc = await getDoc(orgRef)

      if (!orgDoc.exists()) {
        throw new Error(`Organisation ${organisationId} not found`)
      }

      const userIds = orgDoc.data().users as string[]

      if (userIds.length === 0) {
        return []
      }

      const usersCollectionRef = collection(db, 'users')
      const usersQuery = query(usersCollectionRef, where('uid', 'in', userIds))
      const querySnapshot = await getDocs(usersQuery) 
      const users = querySnapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() })) as User[]

      return []
    } catch (error: any) {
      console.error('Error fetching users for organisation: ', error)

      throw new Error(`Failed to fetch users for organisation ${organisationId}: ${error.message}`)
    }
  }

And here's my rules, specifically hasCommonOrganisation is where it's breaking. If I return true there, it works. wrapping each variable in debug() shows that they both contain the correct ids. If I add any null checks in the function, everything breaks.

Code:
  match /users/{userId} {
      allow read: if isAuthenticated() && hasCommonOrganisation(userId); // || request.auth.uid == userId
      allow write: if isAuthenticated() && request.auth.uid == userId;
    }

    function isAuthenticated() {
      return request.auth != null;
    }

    // check if auth'd user is in same org as passed user
    function hasCommonOrganisation(userId) {
      let authUserOrgs = get(/databases/$(database)/documents/users/$(request.auth.uid)).data.organisations;
      let targetUserOrgs = get(/databases/$(database)/documents/users/$(userId)).data.organisations;

      return authUserOrgs.hasAny(targetUserOrgs);
    }

Is there anything screamingly obvious to anyone here? I'm pulling my hair out.

I've tried using debug() to print out the variables. They all look fine, and it almost feels like this is silently breaking.

<p>I'm trying to get my firestore rules working for certain collections in the emulator, and I have for most of them up until I want the auth'd user to be able to read users that are within the same organisation.</p>
<p>However, when I set up some rules that check if a user is present in an organisation, I get a very helpful "Null value error" in the console.</p>
<p>For what it's worth, this all works when there's no rules set other than <code>read: true</code>.</p>
<p>A user contains an of organisation ids (organisations), and an organisation contains an array of userIds (users).</p>
<p>here's my query function:</p>
<pre><code> async getUsersForOrganisation(organisationId: string): Promise<User[]> {
const orgRef = doc(db, 'organisations', organisationId)

try {
const orgDoc = await getDoc(orgRef)

if (!orgDoc.exists()) {
throw new Error(`Organisation ${organisationId} not found`)
}

const userIds = orgDoc.data().users as string[]

if (userIds.length === 0) {
return []
}

const usersCollectionRef = collection(db, 'users')
const usersQuery = query(usersCollectionRef, where('uid', 'in', userIds))
const querySnapshot = await getDocs(usersQuery)
const users = querySnapshot.docs.map((doc) => ({ id: doc.id, ...doc.data() })) as User[]

return []
} catch (error: any) {
console.error('Error fetching users for organisation: ', error)

throw new Error(`Failed to fetch users for organisation ${organisationId}: ${error.message}`)
}
}
</code></pre>
<p>And here's my rules, specifically <code>hasCommonOrganisation</code> is where it's breaking. If I return true there, it works. wrapping each variable in <code>debug()</code> shows that they both contain the correct ids. If I add any null checks in the function, everything breaks.</p>
<pre><code> match /users/{userId} {
allow read: if isAuthenticated() && hasCommonOrganisation(userId); // || request.auth.uid == userId
allow write: if isAuthenticated() && request.auth.uid == userId;
}

function isAuthenticated() {
return request.auth != null;
}

// check if auth'd user is in same org as passed user
function hasCommonOrganisation(userId) {
let authUserOrgs = get(/databases/$(database)/documents/users/$(request.auth.uid)).data.organisations;
let targetUserOrgs = get(/databases/$(database)/documents/users/$(userId)).data.organisations;

return authUserOrgs.hasAny(targetUserOrgs);
}
</code></pre>
<p>Is there anything screamingly obvious to anyone here? I'm pulling my hair out.</p>
<p>I've tried using debug() to print out the variables. They all look fine, and it almost feels like this is silently breaking.</p>
 

Online statistics

Members online
0
Guests online
5
Total visitors
5
Top