Guia de permissões de sincronização do dispositivo
Nesta página
- Usando os aplicativos de modelo
- Sobre esses exemplos
- Ler e gravar seus próprios dados
- Escreva seus próprios dados, Leia todos os dados
- Privilégios de administrador
- Habilitar e configurar dados de usuário personalizados
- Configurar privilégios de administrador
- Feed de notícias restrito
- Habilitar e configurar dados de usuário personalizados
- Criar função de trigger de autenticação
- Configurar permissões restritas
- Criar função SubscribetoUser
- Colaboração dinâmica
- Configurar permissões
- Adicionando um Colaborador
- Segurança
- Pesquisa de usuário
- Privilégios em camadas
- Habilitar e configurar dados de usuário personalizados
- Criar função de trigger de autenticação
- Criar função joinTeam
- Definir permissões
Esta página mostra como definir as permissions do seu aplicativo Device Sync para os seguintes use cases comuns:
Usando os aplicativos de modelo
Você pode colocar alguns desses modelos de permissões em funcionamento rapidamente com nossos aplicativos modelo do Device Sync Permissions Guide. Cada aplicativo de modelo vem com um backend e um cliente de demonstração do Node.js. O backend tem todas as funções, permissões e triggers configurados conforme descrito aqui. O cliente de demonstração se conecta ao backend e é executado por meio de um script simples para demonstrar como o backend funciona.
Você precisa de uma CLI autenticada do App Services para usar esses modelos.
O App Services CLI está disponível em npm
. Para instalar a CLI no seu sistema, verifique se você tem o Node.js instalado e, em seguida, execute o seguinte comando em sua shell:
npm install -g atlas-app-services-cli
Consulte a página de referência da CLI para obter instruções de login.
Após entrar, você pode utilizar o comando apps create
com a bandeira --template
para instanciar um modelo.
appservices apps create --template=TEMPLATE_NAME
TEMPLATE_NAME
pode ser um dos seguintes:
flex-sync-guides.add-collaborators
(correspondendo à colaboração dinâmica)flex-sync-guides.restricted-feed
(correspondendo ao Feed de notícias restrito)flex-sync-guides.tiered
(correspondente aos privilégios hierárquicos)
Sobre esses exemplos
Os exemplos aqui usam funções padrão. Isso significa que as mesmas regras de permissão se aplicam a todas as coleções em seu aplicativo. À medida que seu aplicativo cresce em complexidade, talvez você precise de funções específicas da coleção que se apliquem apenas a algumas coleções e não a outras. Em particular, se uma expressão de regra em uma função padrão usa um campo "consultável" que não existe em objetos em uma determinada coleção, você pode substituir as regras dessa coleção fornecendo uma função específica da coleção. Consulte Permissões baseadas em funções para obter mais informações.
Ler e gravar seus próprios dados
Nesse caso, os usuários podem ler ou gravar seus próprios dados, mas não os dados de outros usuários. Considere um aplicativo de anotações em que o usuário deseja persistir e compartilhar anotações em seus próprios dispositivos, mas mantê-las privadas em sua conta de usuário.
Esta estratégia permite que um usuário crie e edite um documento se e somente se o campo owner_id
desse documento for igual ao ID do usuário.
Para configurar a estratégia "Leia e escreva dados próprios", siga as etapas gerais:
Faça login na interface do usuário do Realm e clique em Sync no painel esquerdo.
Em Sync Type, escolha Flexible.
Defina o botão de alternância para ativar Development Mode.
Selecione o cluster que deseja sincronizar.
Define a Database Name: selecione +Add a new database e digite um nome para o banco de dados que o Realm usará para armazenar seus objetos sincronizados. Você pode nomeá-lo como quiser. Uma estratégia comum seria nomear o banco de dados com o nome do aplicativo que você está criando.
Select Queryable Fields: digite
owner_id
. Isso permite que suas expressões de permissão (que você definirá a seguir) usem qualquer campo chamadoowner_id
.Ignore Advanced Configuratione, em seguida, clique em Save Changes para ativar a Sincronização.
Agora você precisa configurar as permissões. Navegue até a página Rules. Clique no botão Default Roles and Filters para editar os papéis padrão. Use o menu suspenso do modelo para selecionar o modelo chamado "Os usuários só podem ler e escrever seus próprios dados".
Isto preenche a caixa de expressão de regra com o seguinte:
{ "name": "owner-read-write", "apply_when": {}, "document_filters": { "read": { "owner_id": "%%user.id" }, "write": { "owner_id": "%%user.id" } }, "read": true, "write": true }
Observe que as expressões document_filters.read
e document_filters.write
usam o campo owner_id
que marcamos como "pedido" acima. Ele também utiliza a expansão do %%user
para ler o ID do usuário solicitante. O App Services substitui (ou "expande") a expansão no tempo de avaliação pelo valor correspondente -- neste caso, o objeto do usuário.
Ao avaliar permissões em um determinado documento, o App Services verifica document_filters.read
e document_filters.write
antes das expressões read
ou write
de nível superior correspondentes. Por exemplo, se o document_filters.write
avaliar para falso, o acesso de gravação será negado; nenhuma regra subsequente será marcada. No entanto, se o document_filters.write
avaliar para verdadeiro, o App Services verificará a expressão de nível superior do write
. Nesse caso, write
é true
, portanto, o acesso de gravação é concedido em todo o documento. Para obter mais informações, consulte Permissões compatíveis com Device Sync.
Escreva seus próprios dados, Leia todos os dados
Nesse caso, os usuários podem ler todos os dados, mas escrever somente seus próprios dados. Considere um aplicativo de receitas onde os usuários possam ler todas as receitas e adicionar novas receitas. As receitas adicionadas podem ser visualizadas por todos que usam o aplicativo. Os usuários podem atualizar ou excluir apenas as receitas que contribuíram.
Para configurar a estratégia " Write Own Data, Read All Data ", siga estas etapas gerais:
Faça login na interface do usuário do Realm e clique em Sync no painel esquerdo.
Em Sync Type, escolha Flexible.
Defina o botão de alternância para ativar Development Mode.
Selecione o cluster que deseja sincronizar.
Define a Database Name: selecione +Add a new database e digite um nome para o banco de dados que o Realm usará para armazenar seus objetos sincronizados. Você pode nomeá-lo como quiser. Uma estratégia comum seria nomear o banco de dados com o nome do aplicativo que você está criando.
Select Queryable Fields: digite
owner_id
. Isso permite que suas expressões de permissão (que você definirá a seguir) usem qualquer campo chamadoowner_id
.Ignore Advanced Configuratione, em seguida, clique em Save Changes para ativar a Sincronização.
Agora você precisa configurar as permissões. Navegue até a página Rules. Clique no botão Default Roles and Filters para editar as funções padrão. Use o menu suspenso do modelo para selecionar o modelo chamado "Os usuários podem ler todos os dados, mas apenas escrever seus próprios dados ".
Isto preenche a caixa de expressão de regra com o seguinte:
{ "name": "owner-write", "apply_when": {}, "document_filters": { "read": true, "write": { "owner_id": "%%user.id" } }, "read": true, "write": true }
Note que a expressão document_filters.read
está configurada para true
, indicando que não importa qual usuário seja autenticado, eles podem ler todos os dados. A expressão document_filters.write
usa o campo owner_id
que marcamos como "consultável" acima e usa a expansão %%user
para fazer a correspondência com o ID do usuário solicitante. O App Services substitui ("expande") a expansão no tempo de avaliação pelo valor correspondente -- neste caso, o objeto do usuário.
Se e somente se document_filters.write
for avaliada como true os App Services verificarão a expressão write
de nível superior. Quando document_filters.write
é avaliado como falso, o acesso de gravação é negado, independentemente do que a expressão write
de nível superior diz. Para obter mais informações, consulte Permissões compatíveis com Device Sync.
Privilégios de administrador
Nessa estratégia de permissão, os usuários com uma função específica de "administrador" podem ler e escrever qualquer documento. Os usuários que não têm a função especificada só podem ler e gravar seus próprios dados. Para que essa estratégia funcione, primeiro você precisa definir quais usuários têm permissões de administrador.
Os aplicativos Atlas permitem que você associe dados de usuário personalizados em seu cluster com usuários de aplicativos. Usando esse recurso, você pode criar um documento com um campo que indica se o usuário tem privilégios administrativos. Embora haja muitas maneiras de configurar isso, uma abordagem é adicionar uma propriedade booleana chamada isGlobalAdmin
, que está definida como true
para os usuários com as permissões elevadas. Outra é criar um campo de string chamado role
, no qual um dos valores esperados pode ser "admin".
No exemplo a seguir, o objeto de usuário personalizado que criaremos tem um campo _id
, que corresponde ao ID do usuário, e 3 campos adicionais: firstName
, lastName
e isGlobalAdmin
:
{ "_id" : "1234", "firstName": "Lily", "lastName": "Realmster", "isGlobalAdmin": true }
Observação
Ao usar dados de usuário personalizados para permissões, nunca permita que o cliente escreva o objeto de dados de usuário personalizado. Isso permitiria que qualquer usuário concedesse a si mesmo qualquer permissão. Em vez disso, use funções do sistema no lado do servidor para atualizar o objeto de dados do usuário personalizado.
Habilitar e configurar dados de usuário personalizados
O Atlas App Services armazena documentos que correspondem aos dados personalizados do usuário em um cluster do MongoDB Atlas vinculado. Ao configurar dados de usuário personalizados para sua aplicação, você especifica o cluster, o banco de dados, a coleção e, finalmente, um campo de _id de usuário, que mapeia um documento de dados de usuário personalizado para um ID de usuário autenticado.
Para habilitar Dados de Usuário Personalizados na App Services UI, siga estas steps:
Clique em App Users no painel esquerdo.
Selecione a guia User Settings e encontre a seção Custom User Data.
Defina a alternância Enable Custom User Data para On.
Especifique os seguintes valores:
Cluster Name: O nome de um cluster MongoDB vinculado que conterá o banco de dados de dados de usuário personalizado.
Database Name: O nome do banco de dados MongoDB que conterá a coleta de dados personalizada do usuário.
Collection Name: O nome da coleção MongoDB que conterá dados de usuário personalizados.
Especifique o campo ID do usuário. Cada documento na coleção de dados de usuários personalizados deve ter um campo que mapeie para um usuário específico. O campo deve estar presente em todos os documentos que mapeiam para um usuário e deve conter o ID do usuário como uma cadeia de caracteres. Recomendamos que você use o campo padrão
_id
para armazenar o ID do usuário. O MongoDB coloca automaticamente uma restrição no campo_id
, garantindo exclusividade.Observação
Se dois documentos nesta coleção contiverem o mesmo valor de ID de usuário, o App Services usará o primeiro documento correspondente, o que leva a resultados inesperados.
Salve e implante as alterações.
Observação
Reinicie a sessão de sincronização após atualizar os dados personalizados do usuário
O servidor de sincronização armazena em cache dados personalizados do usuário durante a sessão. Como resultado, você deve reiniciar a sessão de sincronização depois de atualizar os dados personalizados do usuário para evitar um erro de gravação compensador. Para reiniciar a sessão de sincronização, pause e retome todas as sessões de sincronização abertas no aplicativo cliente. Para obter mais informações sobre como pausar e retomar a sincronização dos SDKs do cliente, consulte seu SDK preferido:
Pausar ou retomar uma sessão de sincronização de dispositivo - Flutter SDK
Pausar ou retomar uma sessão de sincronização de dispositivo - Kotlin SDK
Pausar ou retomar uma sessão de sincronização de dispositivo - Java SDK
Pausar ou retomar uma sessão de sincronização de dispositivo - .Net SDK
Pausar ou retomar uma sessão de sincronização de dispositivo - Reagir SDK nativo
Configurar privilégios de administrador
Depois de ativar os dados personalizados do usuário, você poderá implementar a estratégia de privilégios de administrador. Para fazer isso, siga estas etapas gerais:
Faça login na interface do usuário do Realm e clique em Sync no painel esquerdo.
Em Sync Type, escolha Flexible.
Defina o botão de alternância para ativar Development Mode.
Selecione o cluster que deseja sincronizar.
Define a Database Name: selecione +Add a new database e digite um nome para o banco de dados que o Realm usará para armazenar seus objetos sincronizados. Você pode nomeá-lo como quiser. Uma estratégia comum seria nomear o banco de dados com o nome do aplicativo que você está criando.
Select Queryable Fields: digite
owner_id
. Isso permite que suas expressões de permissão (que você definirá a seguir) usem qualquer campo chamadoowner_id
.Ignore Advanced Configuratione, em seguida, clique em Save Changes para ativar a Sincronização.
Agora você precisa configurar as permissões. Navegue até a página Rules. Clique no botão Default Roles and Filters para editar os papéis padrão. Use o menu suspenso do modelo para selecionar o modelo chamado "Os usuários podem ler e escrever seus próprios dados, os administradores podem ler e gravar todos os dados".
Isto preenche a caixa de expressão de regra com o seguinte:
[ { "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 } ]
Observação
Alterar as configurações padrão
Esta configuração tem duas funções padrão. A primeira define as permissões para um administrador. Note que a expressão gerada automaticamente pressupõe que há um campo booleano no documento de dados de usuário personalizado denominado isGlobalAdmin
. Dependendo de como você definiu seu documento de dados de usuário personalizado, talvez seja necessário alterar isso.
A segunda função padrão especifica as regras para todos os outros usuários. O padrão é restringir o acesso do usuário para ler e gravar somente seus próprios dados. Você pode alterar um ou ambos os campos para true
, permitindo que os usuários leiam e/ou escrevam todos os dados. Consulte as seções anteriores para saber mais sobre essas estratégias.
Feed de notícias restrito
Observação
Modelo disponível!
Para usar o modelo de backend e obter o cliente de demonstração, execute o seguinte comando:
appservices apps create --name=restricted-feed --template=flex-sync-guides.restricted-feed
Solução alternativa para o bug da configuração de dados personalizados do usuário: Às vezes, o gerador de modelos não copia corretamente a configuração de dados personalizados do usuário para o novo aplicativo. Você pode corrigir isto da seguinte forma: o comando appservices apps create
deve ter saída de algum JSON sobre o aplicativo que você acabou de criar. A partir deste JSON, copie o valor "url" (algo como https://services.cloud.mongodb.com/groups/...
) e visite esse URL no seu navegador. Faça login se for solicitado. No painel do aplicativo, no painel esquerdo, clique em App Users. Clique em Custom
User Data. Certifique-se de que Enable Custom User Data seja ON
. Se não estiver ativado, ative-o e insira "mongodb-atlas", "Item" e "Usuário" para Cluster Name, Database Name e Collection
Name, respectivamente. Para User ID Field, introduza _id
. Pressione Save (ou Save Draft, então implante).
Em seguida, em seu terminal, acesse o diretório do cliente, instale as dependências e execute a demonstração:
cd restricted-feed/frontend/flex-sync-guides.restricted-feed/ npm install npm run demo
Leia a saída no seu console para ver o que a demonstração está fazendo.
Nesta estratégia de permissão, os usuários podem criar seu próprio conteúdo e assinar o conteúdo de outros criadores. Assim como no cenário de Admin Privileges, usaremos uma coleção de dados de usuário personalizada para definir qual conteúdo de authors um user está subscribed para read.
O Flexible Device Sync suporta a consulta de arrays, portanto, criaremos uma array dentro de um objeto de dados do usuário. Essa array contém IDs dos autores que esse usuário está autorizado a "seguir". Em seguida, configuramos uma assinatura que diz, em essência, "Mostre-me todos os documentos em que eu seja o autor ou em que o ID do autor esteja na array de autores em meus dados de usuário personalizados."
Importante
Quando um usuário assina ou cancela a assinatura de um autor, atualizamos a array nos dados personalizados do usuário, mas as alterações não entram em vigor até que a sessão atual seja encerrada e uma nova sessão seja iniciada.
Observação
Limitações de tamanho
Neste exemplo, estamos criando uma array nos dados personalizados do usuário. O tamanho dessa array não é limitado pelos Atlas App Services, mas como os dados estão incluídos em cada solicitação, recomendamos manter o tamanho abaixo de 16 KB, o que é espaço suficiente para 1000 IDs de usuário no estilo GUID de 128 bits.
Observação
Ao usar dados de usuário personalizados para permissões, nunca permita que o cliente escreva o objeto de dados de usuário personalizado. Isso permitiria que qualquer usuário concedesse a si mesmo qualquer permissão. Em vez disso, use funções do sistema no lado do servidor para atualizar o objeto de dados do usuário personalizado.
Habilitar e configurar dados de usuário personalizados
Para habilitar Dados de Usuário Personalizados na App Services UI, siga estas steps:
Clique em App Users no painel esquerdo.
Selecione a guia User Settings e encontre a seção Custom User Data.
Defina a alternância Enable Custom User Data para On.
Especifique os seguintes valores:
Cluster Name: O nome de um cluster MongoDB vinculado que conterá o banco de dados de dados de usuário personalizado.
Database Name: O nome do banco de dados MongoDB que conterá a coleta de dados personalizada do usuário.
Collection Name: O nome da coleção MongoDB que conterá dados de usuário personalizados.
Especifique o campo ID do usuário. Cada documento na coleção de dados de usuários personalizados deve ter um campo que mapeie para um usuário específico. O campo deve estar presente em todos os documentos que mapeiam para um usuário e deve conter o ID do usuário como uma cadeia de caracteres. Recomendamos que você use o campo padrão
_id
para armazenar o ID do usuário. O MongoDB coloca automaticamente uma restrição no campo_id
, garantindo exclusividade.Observação
Se dois documentos nesta coleção contiverem o mesmo valor de ID de usuário, o App Services usará o primeiro documento correspondente, o que leva a resultados inesperados.
Salve e implante as alterações.
Observação
Reinicie a sessão de sincronização após atualizar os dados personalizados do usuário
O servidor de sincronização armazena em cache dados personalizados do usuário durante a sessão. Como resultado, você deve reiniciar a sessão de sincronização depois de atualizar os dados personalizados do usuário para evitar um erro de gravação compensador. Para reiniciar a sessão de sincronização, pause e retome todas as sessões de sincronização abertas no aplicativo cliente. Para obter mais informações sobre como pausar e retomar a sincronização dos SDKs do cliente, consulte seu SDK preferido:
Pausar ou retomar uma sessão de sincronização de dispositivo - Flutter SDK
Pausar ou retomar uma sessão de sincronização de dispositivo - Kotlin SDK
Pausar ou retomar uma sessão de sincronização de dispositivo - Java SDK
Pausar ou retomar uma sessão de sincronização de dispositivo - .Net SDK
Pausar ou retomar uma sessão de sincronização de dispositivo - Reagir SDK nativo
Criar função de trigger de autenticação
Precisamos criar uma função de trigger de autenticação que crie um objeto de usuário personalizado quando um usuário autenticar pela primeira vez. Para fazer isso, siga estas etapas:
Faça login na interface do usuário do Realm e clique em Triggers no painel esquerdo.
Clique no botão Add a Trigger.
Defina a alternância Trigger Type para Authentication.
Em Detalhes do trigger, especifique os seguintes valores:
Name: "onUserCreated"
Enbaled: Alterne para "Ligado"
Action Type: Selecione "criar"
Provider(s): Selecione "E-mail/Senha" ou qualquer provedor(s) de autenticação que você esteja usando
Select an Event Type: Selecione "função"
Function: Selecione "+Nova função" e, em seguida:
Function Name: "onUserCreated"
Function: substitua o texto do espaço reservado pela seguinte função:
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); };
Configurar permissões restritas
No objeto de dados de usuário personalizado, crie uma array que detém os valores _id de cada autor que o usuário segue. Neste exemplo, vamos chamá-lo de "assinaturas". Nosso objeto de dados do usuário se parece com o seguinte, onde Lily Realmster ("_id": "1234"
) está inscrita em todos os documentos escritos pelos usuários "456" e "789":
{ "_id" : "1234", "firstName": "Lily", "lastName": "Realmster", "user.custom_data.subscribedTo": [ "456", "789" ] }
Agora você pode implementar a estratégia de Privilégios Restritos. Para fazer isso, siga estas etapas gerais:
Faça login na interface do usuário do Realm e clique em Sync no painel esquerdo.
Em Sync Type, escolha Flexible.
Defina o botão de alternância para ativar Development Mode.
Selecione o cluster que deseja sincronizar.
Define a Database Name: selecione +Add a new database e digite um nome para o banco de dados que o Realm usará para armazenar seus objetos sincronizados. Você pode nomeá-lo como quiser. Uma estratégia comum seria nomear o banco de dados com o nome do aplicativo que você está criando.
Select Queryable Fields: digite
owner_id
. Isso permite que suas expressões de permissão (que você definirá a seguir) usem qualquer campo chamadoowner_id
.Ignore Advanced Configuratione, em seguida, clique em Save Changes para ativar a Sincronização.
Agora você precisa configurar as permissões. Navegue até a página Rules. Clique no botão Default Roles and Filters para editar os papéis padrão. Use o menu suspenso de modelos para selecionar o modelo chamado "Os usuários só podem ler e gravar seus próprios dados". Isso preenche a expressão de regra com o seguinte, que não é exatamente o que queremos, mas fornece a maior parte da lógica para nós:
{ "name": "owner-read-write", "apply_when": {}, "document_filters": { "read": { "owner_id": "%%user.id" }, "write": { "owner_id": "%%user.id" } }, "read": true, "write": true }
Observe que atualmente um usuário pode ler apenas seus próprios documentos ("read":
{"owner_id": "%%user.id"}
). Podemos alterar isso para incluir documentos cujos autores tenham IDs na array " SubscribedTo " do usuário. Para fazer isso, usamos o operador $in
. A expressão é parecida com a seguinte:
{ "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 }
Atualize a caixa de expressão da regra com esta nova lógica e salve as alterações.
Observação: alteramos a expressão document_filters.read
para mencionar apenas os autores na array AssinadoPara, mas os usuários ainda têm acesso de "leitura" aos seus próprios documentos devido à expressão document_filters.read
. Sempre que o acesso de escrita é concedido, o acesso de leitura é implicitamente concedido.
Criar função SubscribetoUser
Precisamos de uma função que inscreva um usuário em outro. Nossas permissões são configuradas para considerar um assinante "inscrito" para um autor se o ID de usuário do autor estiver na array de dados de usuário personalizados do assinante "subscribedTo". A função "subscribeToUser" pega o endereço de e-mail de um usuário, localiza o ID de usuário correspondente na coleta de dados de usuário personalizada e adiciona o ID à array "subscribedTo" do usuário solicitante.
Observe que essa função será executada em Autenticação do sistema e grava nos dados personalizados do usuário. Ao usar dados de usuário personalizados para permissões, os clientes nunca devem ser autorizados a editar diretamente os dados de usuário personalizados. Caso contrário, qualquer usuário pode conceder a si mesmo quaisquer permissões. Em vez disso, modifique os dados do usuário no backend com uma função do sistema. A função deve fazer as verificações necessárias para garantir que a solicitação do usuário para permissões seja válida.
Para criar a função, siga estas etapas:
Faça login na interface do usuário do Realm e clique em Functions no painel esquerdo.
Clique no botão Create New Function.
Especifique os seguintes valores:
Name: "subscribeToUser"
Authentication: "sistema"
Alterne para a guia Function Editor e substitua o texto do espaço reservado pelo seguinte 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()}; } };
Colaboração dinâmica
Observação
Modelo disponível!
Para usar o modelo de backend e obter o cliente de demonstração, execute o seguinte comando:
appservices apps create --name=add-collaborators --template=flex-sync-guides.add-collaborators
Em seguida, acesse o diretório do cliente, instale as dependências e execute a demonstração:
cd add-collaborators/frontend/flex-sync-guides.add-collaborators/ npm install npm run demo
Leia a saída no seu console para ver o que a demonstração está fazendo.
Na estratégia Colaboração dinâmica, os usuários podem criar documentos e adicionar outros usuários como editores desse documento.
Como a estratégia Read & Write Own Data, essa estratégia permite que um usuário crie e edite um documento se o campo owner_id
desse documento for igual ao ID do usuário. Além disso, um usuário pode editar o documento se o campo de array collaborators
do documento contiver sua ID.
Configurar permissões
Para implementar essa estratégia, siga estas etapas gerais:
Faça login na interface do usuário do Realm e clique em Sync no painel esquerdo.
Em Sync Type, escolha Flexible.
Defina o botão de alternância para ativar Development Mode.
Selecione o cluster que deseja sincronizar.
Define a Database Name: selecione +Add a new database e digite um nome para o banco de dados que o Realm usará para armazenar seus objetos sincronizados. Você pode nomeá-lo como quiser. Uma estratégia comum seria nomear o banco de dados com o nome do aplicativo que você está criando.
Select Queryable Fields: digite
owner_id
. Isso permite que suas expressões de permissão (que você definirá a seguir) usem qualquer campo chamadoowner_id
.Ignore Advanced Configuratione, em seguida, clique em Save Changes para ativar a Sincronização.
No campo Select Queryable Fields, digite também collaborators
. Esse será o campo que armazenará os IDs dos usuários que também poderão ler e escrever o documento.
Agora você precisa configurar as permissões. Em Define Permissions, use o menu suspenso do modelo para selecionar "Personalizado (começar do zero)". Cole o seguinte na caixa de expressão de regra:
{ "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 }
As expressões "write " e "read" são idênticas. Dê uma olhada em um deles. $or
usa uma variedade de opções. Temos duas condições possíveis em que um usuário pode escrever o documento:
O campo
owner_id
do documento é igual ao ID do usuárioO campo de array
collaborators
do documento contém o ID do usuário.
De um modo geral, quando um usuário recebe permissão de escrita, esse usuário obtém permissão de leitura automaticamente. No entanto, não podemos omitir a expressão document_filters.read
porque o App Services exige que document_filters.read
e document_filters.write
sejam definidos para o papel ser Compatível com sincronização.
Adicionando um Colaborador
Um usuário pode conceder acesso de escrita em seu documento a outro usuário adicionando o ID do usuário ao campo de array collaborators
em seu documento. Isso pode ser feito no lado do cliente.
Segurança
Não recomendamos usar esse modelo para dados altamente sensíveis.
Esse modelo usa o sistema de permissões para manter os documentos privados entre o criador do documento e os colaboradores que adicionam ao documento. No entanto, se um usuário tiver acesso de escrita a um documento, ele poderá escrever em qualquer campo do documento. Consequentemente, essa estratégia permite que colaboradores adicionem outros colaboradores. Também permitiria a um colaborador editar o campo owner_id
. As permissões de nível de campo devem ser literais booleanos para compatibilidade de sincronização, portanto, não podemos limitar gravações a esses campos para usuários específicos.
Pesquisa de usuário
Como exatamente obter o ID do outro usuário depende dos detalhes do seu aplicativo. Por exemplo, quando um usuário deseja adicionar outro usuário a um documento, você pode ter uma caixa de pesquisa que aceita um endereço de email. Se o endereço de email fornecido corresponder a outro usuário, o cliente poderá adicionar o ID desse usuário à array collaborators
do documento.
O Realm não tem uma maneira integrada de procurar usuários. Geralmente, o fluxo de busca de usuários é o seguinte:
Configure um trigger de autenticação para criar um documento de usuário quando um usuário se registrar. O documento do usuário contém informações que você usará para pesquisar mais tarde, como o endereço de e-mail do usuário.
Crie uma função que consulte a coleta de dados do usuário para um usuário.
Chame a função do lado do cliente quando o usuário quiser encontrar outro usuário.
Para criar um trigger de autenticação, siga estas etapas:
Faça login na interface do usuário do Realm e clique em Triggers no painel esquerdo.
Clique no botão Add a Trigger.
Defina a alternância Trigger Type para Authentication.
Em Detalhes do trigger, especifique os seguintes valores:
Name: "onUserCreated"
Enbaled: Alterne para "Ligado"
Action Type: Selecione "criar"
Provider(s): Selecione "E-mail/Senha" ou qualquer provedor(s) de autenticação que você esteja usando
Select an Event Type: Selecione "função"
Function: Selecione "+Nova função" e, em seguida:
Function Name: "onUserCreated"
Function: substitua o texto do espaço reservado pela seguinte função:
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); };
Em seguida, crie uma função de sistema chamada findUser
:
Faça login na interface do usuário do Realm, acesse seu aplicativo Realm e clique em Functions no painel esquerdo.
Clique no botão Create New Function.
Forneça um Name descritivo para a sua função.
Authentication: Selecione System. Isso permite que sua função ignore permissões em suas coleções.
Log Function Arguments: Deixe
off
.Authorization:
Can Evaluate: Deixe-o em branco.
Private: Deixe
off
.
Clique em Save. Isso leva você ao Function Editor, onde agora você pode inserir alguns para executar.
Aviso
Essa configuração permite que qualquer pessoa chame essa função. Como função do sistema, essa função ignora as regras de acesso. Suponha que qualquer cliente que chame esta função tenha intenções maliciosas.
No Function Editor, cole o seguinte código e salve:
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; };
Do seu cliente, agora você pode chamar esta função. O único argumento da função é uma sequência de endereços de e-mail. Se o e-mail corresponder a um usuário, a função retornará o ID do usuário. Caso contrário, retorna nulo.
Privilégios em camadas
Observação
Modelo disponível!
Para usar o modelo de backend e obter o cliente de demonstração, execute o seguinte comando:
appservices apps create --name=tiered --template=flex-sync-guides.tiered
Solução alternativa para o bug da configuração de dados personalizados do usuário: Às vezes, o gerador de modelos não copia corretamente a configuração de dados personalizados do usuário para o novo aplicativo. Você pode corrigir isto da seguinte forma: o comando appservices apps create
deve ter saída de algum JSON sobre o aplicativo que você acabou de criar. A partir deste JSON, copie o valor "url" (algo como https://services.cloud.mongodb.com/groups/...
) e visite esse URL no seu navegador. Faça login se for solicitado. No painel do aplicativo, no painel esquerdo, clique em App Users. Clique em Custom
User Data. Certifique-se de que Enable Custom User Data seja ON
. Se não estiver ativado, ative-o e insira "mongodb-atlas", "Item" e "Usuário" para Cluster Name, Database Name e Collection
Name, respectivamente. Para User ID Field, introduza _id
. Pressione Save (ou Save Draft, então implante).
Em seguida, em seu terminal, acesse o diretório do cliente, instale as dependências e execute a demonstração:
cd tiered/frontend/flex-sync-guides.tiered/ npm install npm run demo
Leia a saída no seu console para ver o que a demonstração está fazendo.
Nesta estratégia de permissão, adicionaremos funções especiais, bem como regras. Existem duas funções: um membro da equipe e um administrador da equipe. As regras são as seguintes:
Cada usuário é membro de uma equipe.
Um usuário pode ler e escrever seus próprios documentos.
Todos os membros da equipe podem ler todos os documentos criados pelos membros da equipe.
Cada equipe tem um administrador de equipe, que tem permissões de leitura e escrita em todos os documentos da equipe.
Para fazer isso funcionar, precisamos fazer o seguinte:
Habilitar dados de usuário personalizados
Crie uma função de trigger para criar um novo objeto de dados de usuário personalizado para cada novo usuário
Criar uma função para adicionar um usuário a uma equipe
Definir as permissões
Observação
Ao usar dados de usuário personalizados para permissões, nunca permita que o cliente escreva o objeto de dados de usuário personalizado. Isso permitiria que qualquer usuário concedesse a si mesmo qualquer permissão. Em vez disso, use funções do sistema no lado do servidor para atualizar o objeto de dados do usuário personalizado.
Habilitar e configurar dados de usuário personalizados
Para habilitar Dados de Usuário Personalizados na App Services UI, siga estas steps:
Clique em App Users no painel esquerdo.
Selecione a guia User Settings e encontre a seção Custom User Data.
Defina a alternância Enable Custom User Data para On.
Especifique os seguintes valores:
Cluster Name: O nome de um cluster MongoDB vinculado que conterá o banco de dados de dados de usuário personalizado.
Database Name: O nome do banco de dados MongoDB que conterá a coleta de dados personalizada do usuário.
Collection Name: O nome da coleção MongoDB que conterá dados de usuário personalizados.
Especifique o campo ID do usuário. Cada documento na coleção de dados de usuários personalizados deve ter um campo que mapeie para um usuário específico. O campo deve estar presente em todos os documentos que mapeiam para um usuário e deve conter o ID do usuário como uma cadeia de caracteres. Recomendamos que você use o campo padrão
_id
para armazenar o ID do usuário. O MongoDB coloca automaticamente uma restrição no campo_id
, garantindo exclusividade.Observação
Se dois documentos nesta coleção contiverem o mesmo valor de ID de usuário, o App Services usará o primeiro documento correspondente, o que leva a resultados inesperados.
Salve e implante as alterações.
Observação
Reinicie a sessão de sincronização após atualizar os dados personalizados do usuário
O servidor de sincronização armazena em cache dados personalizados do usuário durante a sessão. Como resultado, você deve reiniciar a sessão de sincronização depois de atualizar os dados personalizados do usuário para evitar um erro de gravação compensador. Para reiniciar a sessão de sincronização, pause e retome todas as sessões de sincronização abertas no aplicativo cliente. Para obter mais informações sobre como pausar e retomar a sincronização dos SDKs do cliente, consulte seu SDK preferido:
Pausar ou retomar uma sessão de sincronização de dispositivo - Flutter SDK
Pausar ou retomar uma sessão de sincronização de dispositivo - Kotlin SDK
Pausar ou retomar uma sessão de sincronização de dispositivo - Java SDK
Pausar ou retomar uma sessão de sincronização de dispositivo - .Net SDK
Pausar ou retomar uma sessão de sincronização de dispositivo - Reagir SDK nativo
Criar função de trigger de autenticação
Precisamos criar uma função de trigger de autenticação que crie um objeto de usuário personalizado quando um usuário autenticar pela primeira vez. Para fazer isso, siga estas etapas:
Faça login na interface do usuário do Realm e clique em Triggers no painel esquerdo.
Clique no botão Add a Trigger.
Defina a alternância Trigger Type para Authentication.
Em Detalhes do trigger, especifique os seguintes valores:
Name: "onUserCreated"
Enbaled: Alterne para "Ligado"
Action Type: Selecione "criar"
Provider(s): Selecione "E-mail/Senha" ou qualquer provedor(s) de autenticação que você esteja usando
Select an Event Type: Selecione "função"
Function: Selecione "+Nova função" e, em seguida:
Function Name: "onUserCreated"
Function: substitua o texto do espaço reservado pela seguinte função:
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); };
Criar função joinTeam
Agora precisamos de uma função que adicione um usuário a uma equipe. Observe que essa função será executada com a autenticação do sistema e gravará nos dados personalizados do usuário. Ele não realiza um upsert porque os dados personalizados do usuário foram criados quando o usuário foi autenticado pela primeira vez.
Para criar a função, siga estas etapas:
Faça login na interface do usuário do Realm e clique em Functions no painel esquerdo.
Clique no botão Create New Function.
Especifique os seguintes valores:
Name: "joinTeam"
Authentication: "sistema"
Alterne para a guia Function Editor e substitua o texto do espaço reservado pelo seguinte 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); };
Definir permissões
As permissões a seguir especificam duas funções:
teamAdmin se aplica somente quando os dados personalizados do usuário têm
isTeamAdmin: true
. Em caso afirmativo, o usuário pode ler e gravar todos os documentos em que o valorteam
do documento corresponda ao valorteam
do usuário.teamMember se aplica a todos os usuários. O usuário pode escrever seus próprios documentos e ler todos os documentos onde o valor
team
do documento corresponde ao valorteam
do usuário.
[ { "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 } ]
Observação
Vá mais longe
Essa estratégia pode ser expandida para dar suporte à função " GlobalAdmin ". O administrador global teria lido as permissões de leitura de & em qualquer documento criado em qualquer equipe.