Comment nettoyer l’accès hérité
Cet article explique comment supprimer l’accès hérité pour les enregistrements lorsque la configuration en cascade d’une table change dans Microsoft Dataverse.
Symptômes
Une fois que le comportement en cascade d’une relation de table pour l’action Reparent ou Partager est remplacé par No Cascade, vous continuez à avoir accès aux enregistrements associés qui doivent être supprimés.
Comment vérifier l’accès aux enregistrements associés
Les utilisateurs peuvent signaler qu’ils ont un accès inattendu aux enregistrements. Il existe deux façons de vérifier l’accès aux enregistrements associés : à l’aide de la fonctionnalité Vérifier l’accès ou du RetrieveAccessOrigin
message.
Utiliser la fonctionnalité Vérifier l’accès
Utilisez la fonctionnalité Vérifier l’accès dans les applications basées sur des modèles pour vérifier qui a accès à un enregistrement. Les administrateurs peuvent utiliser cette fonctionnalité pour vérifier les utilisateurs individuels ou tous les utilisateurs qui ont accès à un enregistrement.
Lorsque vous utilisez le vérificateur d’accès, vous voyez une liste des raisons pour lesquelles un utilisateur a accès. Certaines de ces raisons indiquent que le partage a été accordé en raison de l’accès à un enregistrement associé. Par exemple :
- L’enregistrement a été partagé avec moi, car j’ai accès à un enregistrement associé.
- L’enregistrement a été partagé avec les équipes dont je suis membre, car l’équipe a accès à un enregistrement associé.
Utiliser le message RetrieveAccessOrigin
Les développeurs peuvent utiliser le RetrieveAccessOrigin
message pour détecter quels utilisateurs ont accès à un enregistrement. Ce message retourne une phrase décrivant pourquoi l’utilisateur a l’accès. Les résultats suivants indiquent que l’accès a été accordé en raison du partage d’un enregistrement associé :
PrincipalId is owner of a parent entity of object (<record ID>)
PrincipalId is member of team (<team ID>) who is owner of a parent entity of object (<record ID>)
PrincipalId is member of organization (<organization ID>) who is owner of a parent entity of object (<record ID>)
PrincipalId has access to (<parent record ID>) through hierarchy security. (<parent record ID>) is owner of a parent entity of object (<record ID>)
Pour plus d’informations, consultez Déterminer pourquoi un utilisateur a accès avec du code.
Cause
Lorsque le comportement en cascade d’une relation de table change, Dataverse démarre un travail asynchrone pour supprimer les utilisateurs d’accès précédemment accordés. Toutefois, ce travail peut échouer, ce qui entraîne la conservation de l’accès par les utilisateurs.
Résolution
La première étape pour résoudre ce problème consiste à recréer le travail système pour supprimer l’accès. Si le travail échoue, un développeur peut utiliser le ResetInheritedAccess
message pour appliquer la modification à un ensemble d’enregistrements spécifié.
Recréer le travail système pour supprimer l’accès
Les développeurs peuvent utiliser le CreateAsyncJobToRevokeInheritedAccess
message pour réessayer de créer un travail asynchrone.
Utilisez la classe Microsoft.Xrm.Sdk.Messages.CreateAsyncJobToRevokeInheritedAccessRequest.
/// <summary>
/// Creates and executes an asynchronous cleanup job to revoke inherited access granted through cascading inheritance.
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance to use.</param>
/// <param name="relationshipSchemaName">The schema name of the entity relationship.</param>
public static void CreateAsyncJobToRevokeInheritedAccessExample(IOrganizationService service, string relationshipSchemaName)
{
var request = new Microsoft.Xrm.Sdk.Messages.CreateAsyncJobToRevokeInheritedAccessRequest()
{
RelationshipSchema = relationshipSchemaName
};
service.Execute(request);
}
En savoir plus sur l’utilisation des messages avec le SDK pour .NET.
L’action CreateAsyncJobToRevokeInheritedAccess
crée un travail asynchrone nommé RevokeInheritedAccess
. Vous pouvez surveiller la réussite de ce travail. Pour plus d’informations, consultez surveillance des travaux système ou gestion des travaux système avec du code.
Réinitialiser l’accès hérité
Si la recréation du travail système pour supprimer l’accès échoue, un développeur disposant de privilèges d’administrateur système ou de personnalisateur système peut utiliser le ResetInheritedAccess
message pour cibler un sous-ensemble d’enregistrements correspondants. Vous devrez peut-être utiliser ce message plusieurs fois pour supprimer l’accès à tous les enregistrements.
/// <summary>
/// Resets the inherited access for the matching records.
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance to use.</param>
/// <param name="fetchXml">The fetchxml query.</param>
public static void OutputResetInheritedAccess(IOrganizationService service, string fetchXml)
{
var parameters = new ParameterCollection()
{
{ "FetchXml", fetchXml}
};
var request = new OrganizationRequest()
{
RequestName = "ResetInheritedAccess",
Parameters = parameters
};
var response = service.Execute(request);
Console.WriteLine(response.Results["ResetInheritedAccessResponse"]);
}
En savoir plus sur l’utilisation des messages avec le SDK pour .NET.
Le ResetInheritedAccess
message tente de s’exécuter de façon synchrone lorsqu’il n’y a pas beaucoup d’enregistrements correspondants. Ensuite, la ResetInheritedAccessResponse
valeur se termine par ExecutionMode : Sync
. S’il existe de nombreux enregistrements correspondants, l’opération prend plus de temps et la valeur se termine par ExecutionMode : Async
. Un travail système nommé Denormalization_PrincipalObjectAccess_principalobjectaccess:<caller ID>
est créé et vous pouvez surveiller la réussite de ce travail. Pour plus d’informations, consultez surveillance des travaux système ou gestion des travaux système avec du code.
Le ResetInheritedAccess
message nécessite une requête FetchXml pour identifier les enregistrements. Cette requête doit répondre aux exigences suivantes :
- Utilisez la
principalobjectaccess
table (POA). - Retourne uniquement la
principalobjectaccessid
colonne. - Ne doit pas inclure d’éléments
link-entity
. Vous ne pouvez pas ajouter de jointure à une autre table. - Filtrez uniquement sur les colonnes de la
principalobjectaccess
table.
Ce tableau est disponible pour l’API Web en tant que type d’entité principalobjectaccess. Elle n’est pas incluse dans la référence de table/d’entité Dataverse, car la table POA ne prend pas en charge un type d’opération de modification directe des données. Vous devez connaître les colonnes de cette table pour composer la requête FetchXml.
Colonnes de table POA
Vous devez composer une requête FetchXml en utilisant uniquement ces colonnes.
Nom logique | Type | Description |
---|---|---|
accessrightsmask |
Integer | Contient les valeurs de membre d’énumération AccessRights combinées pour les droits d’accès dont dispose directement le principal. |
changedon |
Date et heure | Date de dernière modification de l’accès du principal à l’enregistrement. |
inheritedaccessrightsmask |
Integer | Contient les valeurs de membre d’énumération AccessRights combinées pour les droits d’accès appliqués en raison de l’héritage. |
objectid |
Identificateur unique | ID de l’enregistrement auquel le principal a accès. |
objecttypecode |
Integer | Valeur EntityMetadata.ObjectTypeCode qui correspond à la table. Cette valeur n’est pas nécessairement la même pour différents environnements. Pour les tables personnalisées, elle est affectée en fonction de l’ordre dans lequel la table a été créée. Pour obtenir cette valeur, vous devrez peut-être afficher les métadonnées de la table. Il existe plusieurs outils communautaires pour trouver cela. Voici une solution de Microsoft : Parcourir les définitions de table dans votre environnement. |
principalid |
Identificateur unique | ID de l’utilisateur ou de l’équipe qui a accès. |
principalobjectaccessid |
Identificateur unique | Clé primaire de la table POA. |
principaltypecode |
Integer | Code de type du principal. SystemUser = 8, Team = 9. |
Les valeurs membres d’énumération AccessRights suivantes s’appliquent aux colonnes et inheritedaccessrightsmask
aux accessrightsmask
colonnes :
Type d’accès | Valeur | Description |
---|---|---|
None |
0 | Aucun accès. |
Read |
1 | Droit de lire un enregistrement. |
Write |
2 | Droit de mettre à jour un enregistrement. |
Append |
4 | Droit d’ajouter l’enregistrement spécifié à un autre enregistrement. |
AppendTo |
16 | Droit d’ajouter un autre enregistrement à l’enregistrement spécifié. |
Create |
32 | Droit de créer un enregistrement. |
Delete |
65 536 | Droit de supprimer un enregistrement. |
Share |
262,144 | Droit de partager un enregistrement. |
Assign |
524,288 | Droit d’affecter l’enregistrement spécifié à un autre utilisateur ou une autre équipe. |
Vous pouvez constater que la inheritedaccessrightsmask
valeur est généralement 135 069 719. Cette valeur inclut tous les types d’accès à l’exception Create
de , ce qui n’est pas nécessaire, car ces droits s’appliquent uniquement aux enregistrements déjà créés.
Exemples FetchXml
Cette section inclut quelques exemples de requêtes FetchXml que vous pouvez utiliser avec le ResetInheritedAccess
message. Pour plus d’informations, voir Utiliser FetchXML pour créer une requête.
Réinitialiser l’accès hérité accordé à un certain utilisateur pour un compte spécifique
<fetch>
<entity name="principalobjectaccess">
<attribute name="principalobjectaccessid"/>
<filter type="and">
<condition attribute="principalid" operator="eq" value="9b5f621b-584e-423f-99fd-4620bb00bf1f" />
<condition attribute="objectid" operator="eq" value="B52B7A48-EAFB-ED11-884B-00224809B6C7" />
</filter>
</entity>
</fetch>
Réinitialiser l’accès hérité accordé à toutes les lignes enfants pour un type d’objet spécifié
<fetch>
<entity name="principalobjectaccess">
<attribute name="principalobjectaccessid"/>
<filter type="and">
<condition attribute="objecttypecode" operator="eq" value="10042" />
</filter>
</entity>
</fetch>
Réinitialiser l’accès hérité accordé à un utilisateur spécifié pour tous les types d’objet
<fetch>
<entity name="principalobjectaccess">
<attribute name="principalobjectaccessid"/>
<filter type="and">
<condition attribute="principalid" operator="eq" value="9b5f621b-584e-423f-99fd-4620bb00bf1f" />
</filter>
</entity>
</fetch>