firebasegoogle-cloud-firestorefirebase-storagefirebase-security

Firebase storage security rules OR not work


I'm trying to read this image: Avisos/GUinz0Tx8RQl8GUAixwx/fondo1.jpg

the rules:

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /negocios/{negocioId}{
      match /Avisos/{avisoID}/{allPaths=**}  {
          allow read: if request.auth != null && 
          (
            isOwner(firestore.get(/databases/(default)/documents/negocios/$(negocioId)).data.uid_nagusia) ||      
            (firestore.get(/databases/(default)/documents/negocios/$(negocioId)/empleados/$(request.auth.uid)).data.avisos_leer == true) ||
            request.auth.uid in firestore.get(/databases/(default)/documents/negocios/$(negocioId)/Avisos/$(avisoID)).data.empleados
              );
          
          allow create: if request.auth != null && 
            request.resource.size < 5 * 1024 * 1024 && (
            firestore.get(/databases/(default)/documents/negocios/$(negocioId)).data.uid_nagusia == request.auth.uid ||
            firestore.get(/databases/(default)/documents/negocios/$(negocioId)/empleados/$(request.auth.uid)).data.avisos_crear == true
              );
      }
    }

    function isOwner(userId) {
      return request.auth.uid == userId
    }
  }
}

I'm trying to read like this in Angular with user SqfiHvKyXRatkE3WInm2k7XkcLL2:

const path =`negocios/3xPJtdaSnZZtJ2t1WY69/Avisos/GUinz0Tx8RQl8GUAixwx/fondo1.jpg
    const ref = this.FirebaseStorage.ref(path);
file1 = await ref.getDownloadURL().toPromise();

the document of avisos ("GUinz0Tx8RQl8GUAixwx") has this array:

empleados: ["SqfiHvKyXRatkE3WInm2k7XkcLL2"]

in this case the field "avisos_leer" is false /negocios/3xPJtdaSnZZtJ2t1WY69/empleados/SqfiHvKyXRatkE3WInm2k7XkcLL2

And in the document uid_nagusia is "BQcruUKDV8X0PSrKputY6RJGcbh2" negocios/3xPJtdaSnZZtJ2t1WY69

The user is in the array "empleados" of the document, so the last condition is true (not first and second). This not work but if i remove the first or second condition, works. It seems like 2 conditions returning "false" don't check the 3rd

Just changing the order of the conditions works. I have put the last one (The one that is true) in second position and it works. But if the user is not uid_nagusia and it is not in the array but he has "avisos_leer" true, it does not work because the third condition is not checked.


isOwner(firestore.get(/databases/(default)/documents/negocios/$(negocioId)).data.uid_nagusia) ||

request.auth.uid in firestore.get(/databases/(default)/documents/negocios/$(negocioId)/Avisos/$(avisoID)).data.empleados ||

(firestore.get(/databases/(default)/documents/negocios/$(negocioId)/empleados/$(request.auth.uid)).data.avisos_leer == true) 

Solution

  • I found the solution.

    If one of the fields does not exist, it is an "error" and not a "false". When there is an error, the next condition is not checked.

    To solve my previous case:

     (
            'avisos_leer' in  firestore.get(/databases/(default)/documents/negocios/$(negocioId)/empleados/$(request.auth.uid)).data
            ? firestore.get(/databases/(default)/documents/negocios/$(negocioId)/empleados/$(request.auth.uid)).data.avisos_leer
            : false
    )
    

    In my case "avisos_leer" did not exist in the document, I thought that returned "false", but it actually returned an error