es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Reglas de seguridad de Firestore: ¿Cómo crear una regla que verifique una lista de objetos?

Imagina un campo llamado specialtyList que es una lista de especialidades que almacena las especialidades de un doctor, cada doctor es un usuario de la aplicación.

doctors es la colección.

doctorId es el documentID y el ID utilizado en la autenticación de Firebase.

El documento contiene el campo specialtyList, que es una lista de objetos, como:

/doctors/{doctorId}

{
   fullName: "...",
   specialtyList: [
      {
         specialtyId: 1,
         isApproved: false
      },
      {
         specialtyId: 2,
         isApproved: false
      },
      {
         specialtyId: 3,
         isApproved: false
      }
   ]
}

Un doctor puede agregar su especialidad en la lista, pero no puede cambiar el valor de isApproved a true, solo los usuarios con el rol de “approvalManager” en la autenticación de Firebase pueden hacer eso. Por lo tanto, las reglas serían algo como:

match /doctors/{doctorId} {
      allow read: if request.auth.token.approvalManager == true ||
          request.auth.uid == doctorId;

      //problema:
      allow write: if request.auth.token.approvalManager == true || (
          request.auth.uid == doctorId &&
          request.resource.data.diff(resource.data)
                .changedKeys().hasAny([ "specialtyList" ]) == false
      );
}

El problema con mi solución es que el doctor no podría agregar una especialidad incluso si establece correctamente el valor de isApproved en false.

Entonces, mi pregunta es, ¿cómo puedo crear una regla de seguridad donde:

  • El doctor pueda agregar un objeto en specialtyList.
  • El doctor no pueda agregar un objeto con el valor de isApproved siendo true.

¡Gracias!

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para resolver este problema, podemos escribir una regla de seguridad como esta:

    match /doctors/{doctorId} {
      allow read: if request.auth.token.approvalManager == true ||
        request.auth.uid == doctorId;
    
      allow write: if request.auth.token.approvalManager == true ||
        (
          request.auth.uid == doctorId &&
          (
            "specialtyList" in request.resource.data &&
            request.resource.data.specialtyList is list &&
            request.resource.data.specialtyList.size() == request.resource.data.diff(resource.data).changedKeys().size() &&
            request.resource.data.specialtyList.hasOnly(["specialtyId", "isApproved"]) &&
            request.resource.data.specialtyList[*].isApproved is bool &&
            request.resource.data.specialtyList[?(@.isApproved == true)].size() == 0
          )
        );
    }
    

    Explicación:

    • El médico puede agregar un objeto en specialtyList si la solicitud de escritura solo contiene cambios en specialtyList.
    • El médico no puede agregar un objeto con el valor isApproved siendo true asegurando que specialtyList sea una lista, contenga solo las claves specialtyId e isApproved, y no tenga ningún objeto con isApproved siendo true.

    Al incluir estas condiciones, nos aseguramos de que los médicos solo puedan agregar especialidades con isApproved=false. Y, los encargados de aprobación pueden actualizar el valor isApproved a true.

    Nota: No olvides probar estas reglas a fondo antes de implementarlas en el entorno de producción.

Comments are closed.