Docs Menu
Docs Home
/ /
Recursos para desarrolladores de aplicaciones

Guía de permisos de sincronización de dispositivos

Esta página muestra cómo configurar los permisos de la aplicación Device Sync para los siguientes casos de uso comunes:

  • Leer y escribir datos propios

  • Escribir datos propios, leer todos los datos

  • Privilegios de administrador

  • Fuente de noticias restringida

  • Colaboración dinámica

  • Privilegios escalonados

Puede implementar rápidamente algunos de estos modelos de permisos con nuestras plantillas de aplicación de la Guía de Permisos de Sincronización de Dispositivos. Cada plantilla incluye un backend y un cliente de demostración de Node.js. El backend tiene todas las funciones, permisos y activadores configurados como se describe aquí. El cliente de demostración se conecta al backend y ejecuta un script sencillo para demostrar su funcionamiento.

Necesita una CLI de App Services autenticada para usar estas plantillas.

La CLI de App Services está disponible en npmPara instalar la CLI en su sistema, asegúrese de tener Node.js instalado y luego ejecute el siguiente comando en su shell:

npm install -g atlas-app-services-cli

Consulte la página de referencia de CLI para obtener instrucciones de inicio de sesión.

Una vez que haya iniciado sesión, puede utilizar el comando apps create con el indicador --template para crear una instancia de una plantilla.

appservices apps create --template=TEMPLATE_NAME

TEMPLATE_NAME Puede ser uno de los siguientes:

Implementar una aplicación de plantilla

Los ejemplos aquí utilizan roles predeterminados. Esto significa que las mismas reglas de permisos se aplican a todas las colecciones de la aplicación. A medida que la aplicación aumenta en complejidad, es posible que necesite roles específicos de cada colección que solo se apliquen a algunas colecciones y no a otras. En particular, si una expresión de regla en un rol predeterminado utiliza un campo consultable que no existe en los objetos de una colección determinada, puede anular las reglas de esa colección proporcionando un rol específico de la colección. Consulte Permisos basados ​​en roles para obtener más información.

En este caso, los usuarios pueden leer o escribir sus propios datos, pero no los de otros. Considere una aplicación de notas donde el usuario desea conservar y compartir notas en sus dispositivos, pero mantenerlas privadas en su cuenta.

Esta estrategia permite a un usuario crear y editar un documento si y solo si el campo owner_id de ese documento es igual al ID del usuario.

Para configurar la estrategia "Leer y escribir datos propios", siga los pasos generales:

  1. Inicie sesión en la interfaz de usuario de Realm y luego haga clic en Sync en el panel de la izquierda.

  2. En Sync Type, seleccione Flexible.

  3. Establezca el interruptor para habilitar Development Mode.

  4. Seleccione el clúster que desea sincronizar.

  5. Define a Database Name: Selecciona +Add a new database y escribe un nombre para la base de datos que Realm usará para almacenar tus objetos sincronizados. Puedes ponerle el nombre que quieras. Una estrategia común sería nombrar la base de datos como la aplicación que estás creando.

  6. Select Queryable Fields: escribe en owner_id. Esto permite que tus expresiones de permisos (que configurarás a continuación) utilicen los campos denominados owner_id.

  7. Omita Advanced Configuration y luego haga clic en Save Changes para habilitar la sincronización.

Ahora debe configurar los permisos. Vaya a la página Rules. Haga clic en el botón Default Roles and Filters para editar los roles predeterminados. Utilice el menú desplegable de plantillas para seleccionar la plantilla "Los usuarios solo pueden leer y escribir sus propios datos".

Esto llena el cuadro de expresión de reglas con lo siguiente:

{
"name": "owner-read-write",
"apply_when": {},
"document_filters": {
"read": { "owner_id": "%%user.id" },
"write": { "owner_id": "%%user.id" }
},
"read": true,
"write": true
}

Tenga en cuenta que document_filters.read document_filters.write las expresiones y utilizan el owner_id campo que marcamos como "consultable" anteriormente. También utilizan la %%user expansión para leer el ID del usuario solicitante. App Services reemplaza (o "expande") la expansión en el momento de la evaluación con el valor correspondiente; en este caso, el objeto de usuario.

Al evaluar los permisos de un documento, App Services comprueba document_filters.read y document_filters.write antes de las expresiones de nivel superior read o write correspondientes. Por ejemplo, si document_filters.write se evalúa como falso, se deniega el acceso de escritura; no se comprueban las reglas posteriores. Sin embargo, si document_filters.write se evalúa como verdadero, App Services comprueba la expresión de nivel write superior. En este caso, write es, por lo que true se concede acceso de escritura a todo el documento. Para obtener más información, consulte Permisos compatibles con la sincronización de dispositivos.

En este caso, los usuarios pueden leer todos los datos, pero solo escribir los suyos. Imagine una aplicación de recetas donde los usuarios pueden leer todas las recetas y añadir nuevas. Las recetas que añadan podrán ser vistas por todos los usuarios de la aplicación. Los usuarios solo pueden actualizar o eliminar las recetas que hayan aportado.

Para configurar la estrategia "Escribir datos propios, leer todos los datos", siga estos pasos generales:

  1. Inicie sesión en la interfaz de usuario de Realm y haga clic en Sync en el panel de la izquierda.

  2. En Sync Type, seleccione Flexible.

  3. Establezca el interruptor para habilitar Development Mode.

  4. Seleccione el clúster que desea sincronizar.

  5. Define a Database Name: Selecciona +Add a new database y escribe un nombre para la base de datos que Realm usará para almacenar tus objetos sincronizados. Puedes ponerle el nombre que quieras. Una estrategia común sería nombrar la base de datos como la aplicación que estás creando.

  6. Select Queryable Fields: escribe en owner_id. Esto permite que tus expresiones de permisos (que configurarás a continuación) utilicen los campos denominados owner_id.

  7. Omita Advanced Configuration y luego haga clic en Save Changes para habilitar la sincronización.

Ahora debe configurar los permisos. Vaya a la página Rules. Haga clic en el botón Default Roles and Filters para editar los roles predeterminados. Utilice el menú desplegable de plantillas para seleccionar la plantilla "Los usuarios pueden leer todos los datos, pero solo escribir los suyos".

Esto llena el cuadro de expresión de reglas con lo siguiente:

{
"name": "owner-write",
"apply_when": {},
"document_filters": {
"read": true,
"write": { "owner_id": "%%user.id" }
},
"read": true,
"write": true
}

Tenga en cuenta que la document_filters.read expresión se establece true en, lo que indica que, independientemente del usuario autenticado, puede leer todos los datos. La document_filters.write expresión utiliza el campo que marcamos owner_id como "consultable" anteriormente y usa la %%user expansión para comparar con el ID del usuario solicitante. App Services reemplaza ("expande") la expansión en el momento de la evaluación con el valor correspondiente; en este caso, el objeto de usuario.

Si, y solo si,document_filters.write se evalúa como verdadero, App Services comprobará la expresión de nivel write superior. Si document_filters.write se evalúa como falso, se deniega el acceso de escritura, independientemente de lo que indique la expresión de nivel write superior. Para obtener más información, consulte Permisos compatibles con la sincronización de dispositivos.

En esta estrategia de permisos, los usuarios con un rol de administrador específico pueden leer y escribir cualquier documento. Los usuarios sin dicho rol solo pueden leer y escribir sus propios datos. Para que esta estrategia funcione, primero debe definir qué usuarios tienen permisos de administrador.

Las aplicaciones Atlas permiten asociar datos de usuario personalizados en el clúster con los usuarios de la aplicación. Con esta función, se puede crear un documento con un campo que indica si el usuario tiene privilegios administrativos. Si bien existen varias maneras de configurarlo, una consiste en agregar una propiedad booleana llamada isGlobalAdmin, que se establece en true para los usuarios con permisos elevados. Otra opción consiste en crear un campo de cadena llamado role, en el que uno de los valores esperados podría ser "admin".

En el siguiente ejemplo, el objeto de usuario personalizado que crearemos tiene un campo _id, que corresponde al ID del usuario, y 3 campos adicionales: firstName, lastName y isGlobalAdmin:

{
"_id" : "1234",
"firstName": "Lily",
"lastName": "Realmster",
"isGlobalAdmin": true
}

Nota

Al usar datos de usuario personalizados para permisos, nunca permita que el cliente escriba el objeto de datos de usuario personalizado. Esto permitiría que cualquier usuario se autoconceda cualquier permiso. En su lugar, utilice las funciones del sistema del servidor para actualizar el objeto de datos de usuario personalizado.

Atlas App Services almacena documentos MongoDB correspondientes a datos de usuario personalizados en un clúster de MongoDB Atlas vinculado. Al configurar datos de usuario personalizados para su aplicación, especifique el clúster, la base de datos, la colección y, finalmente, un campo de ID de usuario, que asigna un documento de datos de usuario personalizado al ID de un usuario autenticado.

Para habilitar datos de usuario personalizados en la interfaz de usuario de App Services, siga estos pasos:

  1. Haga clic en App Users en el panel de la izquierda.

  2. Seleccione la pestaña User Settings y busque la sección Custom User Data.

  3. Establece el interruptor Enable Custom User Data en On.

  4. Especifique los siguientes valores:

    • Cluster Name:El nombre de un clúster MongoDB vinculado que contendrá la base de datos de datos de usuario personalizada.

    • Database Name:El nombre de la base de datos MongoDB que contendrá la recopilación de datos de usuario personalizados.

    • Collection Name: El nombre de la colección de MongoDB que contendrá los datos personalizados del usuario.

  5. Especifique el campo ID de usuario. Cada documento de la colección de datos de usuario personalizada debe tener un campo asignado a un usuario específico. Este campo debe estar presente en todos los documentos asignados a un usuario y debe contener el ID del usuario como una cadena. Recomendamos usar el _id campo estándar para almacenar el ID de usuario. MongoDB aplica automáticamente una restricción al _id campo para garantizar la unicidad.

    Nota

    Si dos documentos de esta colección contienen el mismo valor de ID de usuario, App Services utiliza el primer documento que coincide, lo que genera resultados inesperados.

  6. Guarda e implementa los cambios.

    Nota

    Reiniciar la sesión de sincronización después de actualizar los datos de usuario personalizados

    El servidor de sincronización almacena en caché los datos de usuario personalizados durante la sesión. Por lo tanto, debe reiniciar la sesión de sincronización después de actualizar los datos de usuario personalizados para evitar un error de escritura compensatorio. Para reiniciar la sesión de sincronización, pause y reanude todas las sesiones de sincronización abiertas en la aplicación cliente. Para obtener más información sobre cómo pausar y reanudar la sincronización desde los SDK del cliente, consulte su SDK preferido:

Tip

Una vez habilitados los datos de usuario personalizados, puede implementar la estrategia de privilegios de administrador. Para ello, siga estos pasos generales:

  1. Inicie sesión en la interfaz de usuario de Realm y haga clic en Sync en el panel de la izquierda.

  2. En Sync Type, seleccione Flexible.

  3. Establezca el interruptor para habilitar Development Mode.

  4. Seleccione el clúster que desea sincronizar.

  5. Define a Database Name: Selecciona +Add a new database y escribe un nombre para la base de datos que Realm usará para almacenar tus objetos sincronizados. Puedes ponerle el nombre que quieras. Una estrategia común sería nombrar la base de datos como la aplicación que estás creando.

  6. Select Queryable Fields: escribe en owner_id. Esto permite que tus expresiones de permisos (que configurarás a continuación) utilicen los campos denominados owner_id.

  7. Omita Advanced Configuration y luego haga clic en Save Changes para habilitar la sincronización.

Ahora debe configurar los permisos. Vaya a la página Rules. Haga clic en el botón Default Roles and Filters para editar los roles predeterminados. Utilice el menú desplegable de plantillas para seleccionar la plantilla "Los usuarios pueden leer y escribir sus propios datos, los administradores pueden leer y escribir todos los datos".

Esto llena el cuadro de expresión de reglas con lo siguiente:

[
{
"name": "admin",
"apply_when": {
"%%user.custom_data.isGlobalAdmin": true
},
"document_filters": {
"read": true,
"write": true
},
"read": true,
"write": true
},
{
"name": "user",
"apply_when": {},
"document_filters": {
"read": { "owner_id": "%%user.id" },
"write": { "owner_id": "%%user.id" }
},
"read": true,
"write": true
}
]

Nota

Cambiar la configuración predeterminada

Esta configuración tiene dos roles predeterminados. El primero define los permisos de un administrador. Tenga en cuenta que la expresión generada automáticamente presupone que hay un campo booleano llamado isGlobalAdmin en el documento de datos de usuario personalizado. Dependiendo de cómo haya definido su documento de datos de usuario personalizado, es posible que deba cambiarlo.

El segundo rol predeterminado especifica las reglas para todos los demás usuarios. El valor predeterminado es restringir el acceso de los usuarios a la lectura y escritura únicamente de sus propios datos. Puede cambiar uno o ambos campos a true, lo que permite a los usuarios leer o escribir todos los datos. Consulte las secciones anteriores para obtener más información sobre estas estrategias.

Nota

¡Plantilla disponible!

Para utilizar la plantilla de backend y obtener el cliente de demostración, ejecute el siguiente comando:

appservices apps create --name=restricted-feed --template=flex-sync-guides.restricted-feed

Solución alternativa para el error de configuración de datos de usuario personalizados: En ocasiones, el generador de plantillas no copia correctamente la configuración de datos de usuario personalizados a la nueva aplicación. Puede solucionarlo de la siguiente manera: el appservices apps create comando debería haber generado un JSON sobre la aplicación que acaba de crear. De este JSON, copie el valor "url" (algo así https://services.cloud.mongodb.com/groups/... como) y acceda a esa URL en su navegador. Inicie sesión si se le solicita. En el panel de la aplicación, en el panel izquierdo,App Users Custom User Datahaga clic en. Haga clic en.Enable Custom User Data Asegúrese de ON que sea. Si no estaba activado, actívelo e introduzca "mongodb-atlas", "Item" y "User"Cluster Name para, Database Name Collection Namey, respectivamente. Para,User ID Field _idintroduzca. Pulse Save (o Save Draft y, a continuación,implemente).

A continuación, en su terminal, vaya al directorio del cliente, instale las dependencias y ejecute la demostración:

cd restricted-feed/frontend/flex-sync-guides.restricted-feed/
npm install
npm run demo

Lea la salida en su consola para ver qué está haciendo la demostración.

En esta estrategia de permisos, los usuarios pueden crear su propio contenido y suscribirse al de otros creadores. Al igual que en el caso de los privilegios de administrador, utilizaremos una colección de datos de usuario personalizados para definir el contenido de los autores a los que un usuario está suscrito.

Flexible Device Sync admite la consulta de matrices, por lo que crearemos una matriz dentro de un objeto de datos de usuario. Esta matriz contiene los ID de los autores que el usuario está autorizado a seguir. A continuación, configuramos una suscripción que, en esencia, indica: "Mostrarme todos los documentos donde soy el autor o cuyo ID de autor se encuentra en la matriz de autores de mis datos de usuario personalizados".

Importante

Cuando un usuario se suscribe o cancela la suscripción de un autor, actualizamos la matriz en los datos de usuario personalizados, pero los cambios no surten efecto hasta que se cierra la sesión actual y se inicia una nueva.

Nota

Limitaciones de tamaño

En este ejemplo, creamos una matriz en los datos de usuario personalizados. El tamaño de esta matriz no está limitado por App Services, pero como los datos se incluyen en cada solicitud, recomendamos mantenerla por debajo de 16KB, suficiente espacio para ID de usuario de tipo GUID de 1000 128bits.

Nota

Al usar datos de usuario personalizados para permisos, nunca permita que el cliente escriba el objeto de datos de usuario personalizado. Esto permitiría que cualquier usuario se autoconceda cualquier permiso. En su lugar, utilice las funciones del sistema del servidor para actualizar el objeto de datos de usuario personalizado.

Para habilitar datos de usuario personalizados en la interfaz de usuario de App Services, siga estos pasos:

  1. Haga clic en App Users en el panel de la izquierda.

  2. Seleccione la pestaña User Settings y busque la sección Custom User Data.

  3. Establece el interruptor Enable Custom User Data en On.

  4. Especifique los siguientes valores:

    • Cluster Name:El nombre de un clúster MongoDB vinculado que contendrá la base de datos de datos de usuario personalizada.

    • Database Name:El nombre de la base de datos MongoDB que contendrá la recopilación de datos de usuario personalizados.

    • Collection Name: El nombre de la colección de MongoDB que contendrá los datos personalizados del usuario.

  5. Especifique el campo ID de usuario. Cada documento de la colección de datos de usuario personalizada debe tener un campo asignado a un usuario específico. Este campo debe estar presente en todos los documentos asignados a un usuario y debe contener el ID del usuario como una cadena. Recomendamos usar el _id campo estándar para almacenar el ID de usuario. MongoDB aplica automáticamente una restricción al _id campo para garantizar la unicidad.

    Nota

    Si dos documentos de esta colección contienen el mismo valor de ID de usuario, App Services utiliza el primer documento que coincide, lo que genera resultados inesperados.

  6. Guarda e implementa los cambios.

    Nota

    Reiniciar la sesión de sincronización después de actualizar los datos de usuario personalizados

    El servidor de sincronización almacena en caché los datos de usuario personalizados durante la sesión. Por lo tanto, debe reiniciar la sesión de sincronización después de actualizar los datos de usuario personalizados para evitar un error de escritura compensatorio. Para reiniciar la sesión de sincronización, pause y reanude todas las sesiones de sincronización abiertas en la aplicación cliente. Para obtener más información sobre cómo pausar y reanudar la sincronización desde los SDK del cliente, consulte su SDK preferido:

Necesitamos crear una función de activación de autenticación que genere un objeto de usuario personalizado cuando un usuario se autentica por primera vez. Para ello, siga estos pasos:

  1. Inicie sesión en la interfaz de usuario de Realm y haga clic en Triggers en el panel de la izquierda.

  2. Haga clic en el botón Add a Trigger.

  3. Establece el interruptor Trigger Type en Authentication.

  4. En Detalles del activador, especifica los siguientes valores:

    • Name: "onUserCreated"

    • Enbaled: interruptor para activar la opción "On"

    • Action Type:Seleccione "Crear"

    • Provider(s): Seleccione "Correo electrónico/Contraseña" o el proveedor de autenticación que esté utilizando.

    • Select an Event Type:Seleccione "Función"

    • Function:Seleccione "+Nueva función" y luego:

      • Function Name: "onUserCreated"

      • Function:Reemplace el texto del marcador de posición con la siguiente función:

      exports = function(authEvent) {
      const user = authEvent.user;
      const collection = context.services.get("mongodb-atlas").db("Item").collection("User");
      const newDoc = {
      _id: user.id,
      email: user.data.email, // Useful for looking up user IDs by email later - assuming email/password auth is used
      team: "", // Used for tiered privileges
      isTeamAdmin: false, // Used for tiered privileges
      isGlobalAdmin: false, // Used for admin privileges
      subscribedTo: [], // Used for restricted feed
      };
      return collection.insertOne(newDoc);
      };

En el objeto de datos de usuario personalizados, crea un arreglo que contenga los valores _id de cada autor que el usuario sigue. En este ejemplo, lo llamaremos "suscripciones". Nuestro objeto de datos de usuario se parece a lo siguiente, donde Lily Realmster ("_id": "1234") está suscrita a todos los documentos escritos por los usuarios "456" y "789":

{
"_id" : "1234",
"firstName": "Lily",
"lastName": "Realmster",
"user.custom_data.subscribedTo": [
"456",
"789"
]
}

Ahora puede implementar la estrategia de privilegios restringidos. Para ello, siga estos pasos generales:

  1. Inicie sesión en la interfaz de usuario de Realm y haga clic en Sync en el panel de la izquierda.

  2. En Sync Type, seleccione Flexible.

  3. Establezca el interruptor para habilitar Development Mode.

  4. Seleccione el clúster que desea sincronizar.

  5. Define a Database Name: Selecciona +Add a new database y escribe un nombre para la base de datos que Realm usará para almacenar tus objetos sincronizados. Puedes ponerle el nombre que quieras. Una estrategia común sería nombrar la base de datos como la aplicación que estás creando.

  6. Select Queryable Fields: escribe en owner_id. Esto permite que tus expresiones de permisos (que configurarás a continuación) utilicen los campos denominados owner_id.

  7. Omita Advanced Configuration y luego haga clic en Save Changes para habilitar la sincronización.

Ahora debe configurar los permisos. Vaya a la Rules página.Default Roles and Filters Haga clic en el botón para editar los roles predeterminados. Utilice el menú desplegable de plantillas para seleccionar la plantilla "Los usuarios solo pueden leer y escribir sus propios datos". Esto rellena el cuadro de expresión de la regla con lo siguiente, que no es exactamente lo que buscamos, pero nos proporciona la mayor parte de la lógica:

{
"name": "owner-read-write",
"apply_when": {},
"document_filters": {
"read": { "owner_id": "%%user.id" },
"write": { "owner_id": "%%user.id" }
},
"read": true,
"write": true
}

Tenga en cuenta que actualmente un usuario solo puede leer sus propios documentos ("read": {"owner_id": "%%user.id"}). Podemos modificar esto para incluir documentos cuyos autores tengan ID en la matriz "subscribedTo" del usuario. Para ello, usamos el operador $in. La expresión se ve así:

{
"name": "owner-read-write",
"apply_when": {},
"document_filters": {
"read": {
"owner_id": {
"$in": "%%user.custom_data.subscribedTo"
}
},
"write": { "owner_id": "%%user.id" }
},
"read": true,
"write": true
}

Actualice el cuadro de expresión de regla con esta nueva lógica y guarde los cambios.

Nota: Cambiamos la expresión document_filters.read para que solo se mencionen los autores en la matriz subscribedTo, pero los usuarios aún tienen acceso de lectura a sus propios documentos gracias a la expresión document_filters.read. Siempre que se concede acceso de escritura, se concede implícitamente el acceso de lectura.

Necesitamos una función que suscriba a un usuario a otro. Nuestros permisos están configurados para considerar que un suscriptor está "suscrito" a un autor si el ID de usuario de este se encuentra en la matriz "subscribedTo" de datos de usuario personalizados del suscriptor. La función "subscribeToUser" toma la dirección de correo electrónico del usuario, busca el ID correspondiente en la colección de datos de usuario personalizados y lo añade a la matriz "subscribedTo" del usuario solicitante.

Ten en cuenta que esta función se ejecutará bajo la autenticación del Sistema y guarda en los datos de usuario personalizados. Cuando se utilizan datos personalizados de usuario para permisos, nunca se debe permitir a los clientes editar directamente los datos personalizados del usuario. De lo contrario, cualquier usuario podría otorgarse cualquier permiso. En su lugar, modifica los datos de usuario en el backend con una función del Sistema. La función debe realizar todas las comprobaciones necesarias para garantizar que la solicitud del usuario de permisos sea válida.

Para crear la función, siga estos pasos:

  1. Inicie sesión en la interfaz de usuario de Realm y haga clic en Functions en el panel de la izquierda.

  2. Haga clic en el botón Create New Function.

  3. Especifique los siguientes valores:

    • Name: "suscribirse al usuario"

    • Authentication: "Sistema"

  4. Cambia a la pestaña Function Editor y reemplaza el texto del marcador de posición con el siguiente código:

    exports = async function(email) {
    const collection = context.services.get("mongodb-atlas").db("Item").collection("User");
    // Look up the author object to get the user id from an email
    const author = await collection.findOne({email});
    if (author == null) {
    return {error: `Author ${email} not found`};
    }
    // Whoever called this function is the would-be subscriber
    const subscriber = context.user;
    try {
    return await collection.updateOne(
    {_id: subscriber.id},
    {$addToSet: {
    subscribedTo: author._id,
    }
    });
    } catch (error) {
    return {error: error.toString()};
    }
    };

Nota

¡Plantilla disponible!

Para utilizar la plantilla de backend y obtener el cliente de demostración, ejecute el siguiente comando:

appservices apps create --name=add-collaborators --template=flex-sync-guides.add-collaborators

A continuación, entra en el directorio del cliente, instala las dependencias y ejecuta la demo:

cd add-collaborators/frontend/flex-sync-guides.add-collaborators/
npm install
npm run demo

Lea la salida en su consola para ver qué está haciendo la demostración.

En la estrategia de colaboración dinámica, los usuarios pueden crear documentos y agregar otros usuarios como editores de ese documento.

Al igual que la estrategia de lectura y escritura de datos propios, esta estrategia permite al usuario crear y editar un documento si el campo owner_id de dicho documento coincide con su ID. Además, puede editarlo si el campo de matriz collaborators contiene su ID.

Para implementar esta estrategia, siga estos pasos generales:

  1. Inicie sesión en la interfaz de usuario de Realm y haga clic en Sync en el panel de la izquierda.

  2. En Sync Type, seleccione Flexible.

  3. Establezca el interruptor para habilitar Development Mode.

  4. Seleccione el clúster que desea sincronizar.

  5. Define a Database Name: Selecciona +Add a new database y escribe un nombre para la base de datos que Realm usará para almacenar tus objetos sincronizados. Puedes ponerle el nombre que quieras. Una estrategia común sería nombrar la base de datos como la aplicación que estás creando.

  6. Select Queryable Fields: escribe en owner_id. Esto permite que tus expresiones de permisos (que configurarás a continuación) utilicen los campos denominados owner_id.

  7. Omita Advanced Configuration y luego haga clic en Save Changes para habilitar la sincronización.

En el campo Select Queryable Fields, escribe también collaborators. Este será el campo que almacene los ID de usuarios que también pueden leer y guardar el documento.

Ahora debe configurar los permisos. En Define Permissions, utilice el menú desplegable de plantillas para seleccionar "Personalizado (empezar desde cero)". Pegue lo siguiente en el cuadro de expresión de la regla:

{
"name": "collaborator",
"apply_when": {},
"document_filters": {
"read": {
"$or": [
{
"owner_id": "%%user.id"
},
{
"collaborators": "%%user.id"
}
]
},
"write": {
"$or": [
{
"owner_id": "%%user.id"
},
{
"collaborators": "%%user.id"
}
]
}
},
"read": true,
"write": true
}

Las expresiones "write" y "read" son idénticas. Observe una de ellas. $or acepta un array de opciones. Tenemos dos posibles condiciones en las que un usuario puede escribir el documento:

  • El campo owner_id del documento equivale al ID del usuario

  • El campo de matriz collaborators del documento contiene el ID del usuario.

Generalmente, cuando a un usuario se le otorgan permisos de guardar, ese usuario automáticamente obtiene permisos de lectura. Sin embargo, no podemos omitir la expresión document_filters.read porque Servicios de aplicación requiere que tanto document_filters.read como document_filters.write estén definidos para que el rol sea compatible con sincronización.

Un usuario puede otorgar acceso de escritura a su documento a otro usuario añadiendo su ID al campo de matriz collaborators de su documento. Esto se puede hacer desde el cliente.

No recomendamos utilizar este modelo para datos altamente sensibles.

Este modelo utiliza el sistema de permisos para mantener la owner_id privacidad de los documentos entre el creador y los colaboradores que este agrega. Sin embargo, si un usuario tiene acceso de escritura a un documento, puede escribir en cualquier campo. Por lo tanto, esta estrategia permite que los colaboradores agreguen a otros colaboradores. También permitiría que un colaborador edite el campo. Los permisos a nivel de campo deben ser literales booleanos para la compatibilidad con la sincronización, por lo que no podemos limitar las escrituras en estos campos a usuarios específicos.

La forma exacta de obtener el ID de otro usuario depende de los detalles de tu aplicación. Por ejemplo, si un usuario desea agregar a otro usuario a un documento, podrías tener un cuadro de búsqueda que acepte una dirección de correo electrónico. Si la dirección de correo electrónico proporcionada corresponde a otro usuario, el cliente puede agregar el ID de ese usuario a la matriz collaborators del documento.

Realm no tiene una forma integrada de buscar usuarios. Generalmente, el proceso de búsqueda es el siguiente:

  • Configura un disparador de autenticación para crear un documento de usuario cuando este se registre. Este documento contiene información que podrás consultar posteriormente, como su dirección de correo electrónico.

  • Crea una función que consulta la recopilación de datos de un usuario.

  • Llame a la función desde el lado del cliente cuando el usuario quiera encontrar a otro usuario.

Para crear un activador de autenticación, siga estos pasos:

  1. Inicie sesión en la interfaz de usuario de Realm y haga clic en Triggers en el panel de la izquierda.

  2. Haga clic en el botón Add a Trigger.

  3. Establece el interruptor Trigger Type en Authentication.

  4. En Detalles del activador, especifica los siguientes valores:

    • Name: "onUserCreated"

    • Enbaled: interruptor para activar la opción "On"

    • Action Type:Seleccione "Crear"

    • Provider(s): Seleccione "Correo electrónico/Contraseña" o el proveedor de autenticación que esté utilizando.

    • Select an Event Type:Seleccione "Función"

    • Function:Seleccione "+Nueva función" y luego:

      • Function Name: "onUserCreated"

      • Function:Reemplace el texto del marcador de posición con la siguiente función:

      exports = function(authEvent) {
      const user = authEvent.user;
      const collection = context.services.get("mongodb-atlas").db("Item").collection("User");
      const newDoc = {
      _id: user.id,
      email: user.data.email, // Useful for looking up user IDs by email later - assuming email/password auth is used
      team: "", // Used for tiered privileges
      isTeamAdmin: false, // Used for tiered privileges
      isGlobalAdmin: false, // Used for admin privileges
      subscribedTo: [], // Used for restricted feed
      };
      return collection.insertOne(newDoc);
      };

A continuación, cree una función del sistema llamada findUser:

  • Inicie sesión en la interfaz de usuario de Realm, vaya a su aplicación Realm y luego haga clic en Functions en el panel de la izquierda.

  • Haga clic en el botón Create New Function.

  • Proporcione un Name descriptivo para su función.

  • AuthenticationSeleccione System. Esto permite que su función omita los permisos en sus colecciones.

  • Log Function Arguments:Déjalo off.

  • Authorization:

    • Can Evaluate:Dejarlo en blanco.

    • Private:Déjalo off.

  • Haga clic en Save. Esto lo llevará a Function Editor, donde ahora puede ingresar algunos datos para ejecutar.

Advertencia

Esta configuración permite que cualquiera pueda llamar esta función. Como función del sistema, esta función evita las reglas de acceso. Suponga que cualquier cliente que invoque esta función tiene intenciones maliciosas.

En el Function Editor, pegue el siguiente código y guárdelo:

exports = async function(email) {
const collection = context.services.get("mongodb-atlas")
.db("Item").collection("User");
const filter = {
email,
};
// Search for the user by email
const result = await collection.findOne(filter);
// Return corresponding user id or null
return result != null ? result._id : null;
};

Desde su cliente, ahora puede llamar a esta función. El único argumento de la función es una cadena de correo electrónico. Si el correo electrónico corresponde a un usuario, la función devuelve su ID. De lo contrario, devuelve un valor nulo.

Nota

¡Plantilla disponible!

Para utilizar la plantilla de backend y obtener el cliente de demostración, ejecute el siguiente comando:

appservices apps create --name=tiered --template=flex-sync-guides.tiered

Solución alternativa para el error de configuración de datos de usuario personalizados: En ocasiones, el generador de plantillas no copia correctamente la configuración de datos de usuario personalizados a la nueva aplicación. Puede solucionarlo de la siguiente manera: el appservices apps create comando debería haber generado un JSON sobre la aplicación que acaba de crear. De este JSON, copie el valor "url" (algo así https://services.cloud.mongodb.com/groups/... como) y acceda a esa URL en su navegador. Inicie sesión si se le solicita. En el panel de la aplicación, en el panel izquierdo,App Users Custom User Datahaga clic en. Haga clic en.Enable Custom User Data Asegúrese de ON que sea. Si no estaba activado, actívelo e introduzca "mongodb-atlas", "Item" y "User"Cluster Name para, Database Name Collection Namey, respectivamente. Para,User ID Field _idintroduzca. Pulse Save (o Save Draft y, a continuación,implemente).

A continuación, en su terminal, vaya al directorio del cliente, instale las dependencias y ejecute la demostración:

cd tiered/frontend/flex-sync-guides.tiered/
npm install
npm run demo

Lea la salida en su consola para ver qué está haciendo la demostración.

En esta estrategia de permisos, añadiremos roles especiales y reglas. Hay dos roles: miembro del equipo y administrador del equipo. Las reglas son las siguientes:

  • Cada usuario es nodo de un equipo.

  • Un usuario puede leer y escribir sus propios documentos.

  • Todos los miembros del equipo pueden leer todos los documentos creados por los miembros del equipo.

  • Cada equipo tiene un administrador del equipo, que tiene permisos de lectura y escritura en todos los documentos del equipo.

Para que esto funcione, necesitamos hacer lo siguiente:

  • Habilitar datos de usuario personalizados

  • Cree una función de activación para crear un nuevo objeto de datos de usuario personalizado para cada nuevo usuario

  • Crear una función para agregar un usuario a un equipo

  • Definir los permisos

Nota

Al usar datos de usuario personalizados para permisos, nunca permita que el cliente escriba el objeto de datos de usuario personalizado. Esto permitiría que cualquier usuario se autoconceda cualquier permiso. En su lugar, utilice las funciones del sistema del servidor para actualizar el objeto de datos de usuario personalizado.

Para habilitar datos de usuario personalizados en la interfaz de usuario de App Services, siga estos pasos:

  1. Haga clic en App Users en el panel de la izquierda.

  2. Seleccione la pestaña User Settings y busque la sección Custom User Data.

  3. Establece el interruptor Enable Custom User Data en On.

  4. Especifique los siguientes valores:

    • Cluster Name:El nombre de un clúster MongoDB vinculado que contendrá la base de datos de datos de usuario personalizada.

    • Database Name:El nombre de la base de datos MongoDB que contendrá la recopilación de datos de usuario personalizados.

    • Collection Name: El nombre de la colección de MongoDB que contendrá los datos personalizados del usuario.

  5. Especifique el campo ID de usuario. Cada documento de la colección de datos de usuario personalizada debe tener un campo asignado a un usuario específico. Este campo debe estar presente en todos los documentos asignados a un usuario y debe contener el ID del usuario como una cadena. Recomendamos usar el _id campo estándar para almacenar el ID de usuario. MongoDB aplica automáticamente una restricción al _id campo para garantizar la unicidad.

    Nota

    Si dos documentos de esta colección contienen el mismo valor de ID de usuario, App Services utiliza el primer documento que coincide, lo que genera resultados inesperados.

  6. Guarda e implementa los cambios.

    Nota

    Reiniciar la sesión de sincronización después de actualizar los datos de usuario personalizados

    El servidor de sincronización almacena en caché los datos de usuario personalizados durante la sesión. Por lo tanto, debe reiniciar la sesión de sincronización después de actualizar los datos de usuario personalizados para evitar un error de escritura compensatorio. Para reiniciar la sesión de sincronización, pause y reanude todas las sesiones de sincronización abiertas en la aplicación cliente. Para obtener más información sobre cómo pausar y reanudar la sincronización desde los SDK del cliente, consulte su SDK preferido:

Necesitamos crear una función de activación de autenticación que genere un objeto de usuario personalizado cuando un usuario se autentica por primera vez. Para ello, siga estos pasos:

  1. Inicie sesión en la interfaz de usuario de Realm y haga clic en Triggers en el panel de la izquierda.

  2. Haga clic en el botón Add a Trigger.

  3. Establece el interruptor Trigger Type en Authentication.

  4. En Detalles del activador, especifica los siguientes valores:

    • Name: "onUserCreated"

    • Enbaled: interruptor para activar la opción "On"

    • Action Type:Seleccione "Crear"

    • Provider(s): Seleccione "Correo electrónico/Contraseña" o el proveedor de autenticación que esté utilizando.

    • Select an Event Type:Seleccione "Función"

    • Function:Seleccione "+Nueva función" y luego:

      • Function Name: "onUserCreated"

      • Function:Reemplace el texto del marcador de posición con la siguiente función:

      exports = function(authEvent) {
      const user = authEvent.user;
      const collection = context.services.get("mongodb-atlas").db("Item").collection("User");
      const newDoc = {
      _id: user.id,
      email: user.data.email, // Useful for looking up user IDs by email later - assuming email/password auth is used
      team: "", // Used for tiered privileges
      isTeamAdmin: false, // Used for tiered privileges
      isGlobalAdmin: false, // Used for admin privileges
      subscribedTo: [], // Used for restricted feed
      };
      return collection.insertOne(newDoc);
      };

Ahora necesitamos una función que añada un usuario a un equipo. Tenga en cuenta que esta función se ejecutará con autenticación del sistema y escribirá en los datos personalizados del usuario. No realiza una operación de upsert, ya que los datos personalizados del usuario se crearon cuando el usuario se autenticó correctamente por primera vez.

Para crear la función, siga estos pasos:

  1. Inicie sesión en la interfaz de usuario de Realm y haga clic en Functions en el panel de la izquierda.

  2. Haga clic en el botón Create New Function.

  3. Especifique los siguientes valores:

    • Name: "unirse al equipo"

    • Authentication: "Sistema"

  4. Cambia a la pestaña Function Editor y reemplaza el texto del marcador de posición con el siguiente código:

    exports = async function(userId, teamName) {
    const collection = context.services.get("mongodb-atlas")
    .db("Item").collection("User");
    const filter = { _id: userId };
    const update = { $set: { team: teamName }};
    const options = { upsert: false };
    return collection.updateOne(filter, update, options);
    };

Los siguientes permisos especifican dos roles:

  • teamAdmin solo se aplica cuando los datos personalizados del usuario isTeamAdmin: true tienen. En ese caso, el usuario puede leer y escribir todos los documentos cuyo team valor coincida con el team valor del usuario.

  • teamMember se aplica a todos los usuarios. El usuario puede crear sus propios documentos y leer todos los documentos cuyo team valor coincida con el team valor del usuario.

[
{
"name": "admin",
"apply_when": {
"%%user.custom_data.isTeamAdmin": true
},
"document_filter": {
"read": {
"team": "%%user.custom_data.team"
},
"write": {
"team": "%%user.custom_data.team"
}
},
"read": true,
"write": true
},
{
"name": "user",
"apply_when": {},
"document_filters": {
"read": {
"team": "%%user.custom_data.team"
},
"write": {
"owner_id": "%%user.id"
}
},
"read": true,
"write": true
}
]

Nota

Llévalo más allá

Esta estrategia se puede ampliar para admitir el rol de "administrador global". El administrador global tendría permisos de lectura y escritura en cualquier documento creado en cualquier equipo.

Volver

Recursos para desarrolladores de aplicaciones