Compartir a través de


Cómo limpiar el acceso heredado

En este artículo se presenta cómo quitar el acceso heredado para los registros cuando cambia la configuración en cascada de una tabla en Microsoft Dataverse.

Síntomas

Después de cambiar el comportamiento en cascada de una relación de tabla para la acción Reparent o Share a No Cascade, seguirá teniendo acceso a los registros relacionados que se deben quitar.

Los usuarios pueden informar de que tienen acceso inesperado a los registros. Hay dos maneras de comprobar el acceso a los registros relacionados: mediante la característica Comprobar acceso o el RetrieveAccessOrigin mensaje.

Uso de la característica Comprobar acceso

Use la característica Comprobar acceso en aplicaciones controladas por modelos para comprobar quién tiene acceso a un registro. Los administradores pueden usar esta característica para comprobar usuarios individuales o todos los usuarios que tienen acceso a un registro.

Al usar el comprobador de acceso, verá una lista de motivos por los que un usuario tiene acceso. Algunas de estas razones indican que se concedió el uso compartido debido al acceso a un registro relacionado. Por ejemplo:

  • El registro se compartió conmigo porque tengo acceso al registro relacionado.
  • El registro se compartió con los equipos de los que soy miembro porque el equipo tiene acceso a un registro relacionado.

Usar el mensaje RetrieveAccessOrigin

Los desarrolladores pueden usar el RetrieveAccessOrigin mensaje para detectar qué usuarios tienen acceso a un registro. Este mensaje devuelve una frase que describe por qué el usuario tiene acceso. Cualquiera de los siguientes resultados indica que se concedió el acceso debido al uso compartido de un registro relacionado:

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>)

Para obtener más información, consulte Determinar por qué un usuario tiene acceso con código.

Causa

Cuando cambia el comportamiento en cascada de una relación de tabla, Dataverse inicia un trabajo asincrónico para quitar los usuarios de acceso concedidos anteriormente. Sin embargo, este trabajo puede producir un error, lo que provoca que los usuarios conserven el acceso.

Solución

El primer paso para resolver este problema es volver a crear el trabajo del sistema para quitar el acceso. Si se produce un error en el trabajo, un desarrollador puede usar el ResetInheritedAccess mensaje para aplicar el cambio a un conjunto especificado de registros.

Volver a crear el trabajo del sistema para quitar el acceso

Los desarrolladores pueden usar el CreateAsyncJobToRevokeInheritedAccess mensaje para intentar volver a crear un trabajo asincrónico.

Use la clase 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);
}

Más información sobre usar mensajes con SDK para .NET.

La CreateAsyncJobToRevokeInheritedAccess acción crea un nuevo trabajo asincrónico denominado RevokeInheritedAccess. Puede supervisar el éxito de este trabajo. Para obtener más información, consulte Supervisión de trabajos del sistema o administración de trabajos del sistema con código.

Restablecer el acceso heredado

Si se produce un error al volver a crear el trabajo del sistema para quitar el acceso , un desarrollador con privilegios de administrador del sistema o personalizador del sistema puede usar el ResetInheritedAccess mensaje para establecer como destino un subconjunto de registros coincidentes. Es posible que tenga que usar este mensaje varias veces para quitar el acceso a todos los registros.

/// <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"]);
}

Más información sobre usar mensajes con SDK para .NET.

El ResetInheritedAccess mensaje intenta ejecutarse sincrónicamente cuando no hay muchos registros coincidentes. A continuación, el ResetInheritedAccessResponse valor finaliza con ExecutionMode : Sync. Si hay muchos registros coincidentes, la operación tarda más y el valor finaliza con ExecutionMode : Async. Se crea un trabajo del sistema denominado Denormalization_PrincipalObjectAccess_principalobjectaccess:<caller ID> y puede supervisar el éxito de ese trabajo. Para obtener más información, consulte Supervisión de trabajos del sistema o administración de trabajos del sistema con código.

El ResetInheritedAccess mensaje requiere una consulta FetchXml para identificar los registros. Esta consulta debe cumplir los siguientes requisitos:

  • Use la principalobjectaccesstabla (POA).
  • Devuelve solo la principalobjectaccessid columna.
  • No debe incluir ningún link-entity elemento. No se puede agregar una combinación a otra tabla.
  • Filtre solo por columnas de la principalobjectaccess tabla.

Esta tabla está disponible para la API web como el tipo de entidad principalobjectaccess. No se incluye en la referencia de entidad o tabla de Dataverse porque la tabla POA no admite ningún tipo de operación de modificación directa de datos. Debe conocer las columnas de esta tabla para redactar la consulta FetchXml.

Columnas de tabla POA

Debe crear una consulta FetchXml con solo estas columnas.

Nombre lógico Type Descripción
accessrightsmask Entero Contiene los valores de miembro de enumeración AccessRights combinados para los derechos de acceso que la entidad de seguridad tiene directamente.
changedon Fecha y hora Última fecha en la que cambió el acceso de la entidad de seguridad al registro.
inheritedaccessrightsmask Entero Contiene los valores de miembro de enumeración AccessRights combinados para los derechos de acceso que se aplican debido a la herencia.
objectid Identificador único Identificador del registro al que tiene acceso la entidad de seguridad.
objecttypecode Entero Valor EntityMetadata.ObjectTypeCode que corresponde a la tabla. Este valor no es necesariamente el mismo para entornos diferentes. En el caso de las tablas personalizadas, se asigna en función del orden en que se creó la tabla. Para obtener este valor, es posible que tenga que ver los metadatos de la tabla. Hay varias herramientas de la comunidad para encontrar esto. Esta es una solución de Microsoft: Examinar definiciones de tabla en su entorno.
principalid Identificador único Identificador del usuario o equipo que tiene acceso.
principalobjectaccessid Identificador único Clave principal de la tabla POA.
principaltypecode Entero Código de tipo de la entidad de seguridad. SystemUser = 8, Team = 9.

Los siguientes valores de miembro de enumeración AccessRights se aplican a las accessrightsmask columnas y inheritedaccessrightsmask :

Tipo de acceso Valor Descripción
None 0 No hay acceso.
Read 1 Derecho a leer un registro.
Write 2 Derecho a actualizar un registro.
Append 4 Derecho a anexar el registro especificado a otro registro.
AppendTo 16 Derecho a anexar otro registro al registro especificado.
Create 32 Derecho a crear un registro.
Delete 65 536 Derecho a eliminar un registro.
Share 262,144 Derecho a compartir un registro.
Assign 524,288 Derecho a asignar el registro especificado a otro usuario o equipo.

Es posible que vea que el inheritedaccessrightsmask valor suele ser 135 069 719. Este valor incluye todos los tipos de acceso excepto para Create, que no es necesario porque estos derechos solo se aplican a los registros ya creados.

Ejemplos de FetchXml

En esta sección se incluyen algunos ejemplos de consultas FetchXml que puede usar con el ResetInheritedAccess mensaje. Para obtener más información, vea Usar FetchXML para crear una consulta.

Restablecer el acceso heredado otorgado a un determinado usuario para una cuenta específica
<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>
Restablecer el acceso heredado otorgado a todas las filas secundarias para un tipo de objeto específico
<fetch>
    <entity name="principalobjectaccess">
        <attribute name="principalobjectaccessid"/>
        <filter type="and">
            <condition attribute="objecttypecode" operator="eq" value="10042" />
        </filter>
    </entity>
</fetch>
Restablecer el acceso heredado otorgado a un usuario específico para todos los tipos de objeto
<fetch>
    <entity name="principalobjectaccess">
        <attribute name="principalobjectaccessid"/>
        <filter type="and">
            <condition attribute="principalid" operator="eq" value="9b5f621b-584e-423f-99fd-4620bb00bf1f" />
        </filter>
    </entity>
</fetch>