Partager via


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.

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 principalobjectaccesstable (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 Createde , 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>