28/9/15

Obtener roles y privilegios de un usuario con FetchXml

Los datos que muestran los informes en CRM están filtrados por el perfil de seguridad del usuario que los ejecuta. Hasta aquí, todo bien: nuestros informes no serán un hueco de seguridad, siempre que usemos las vistas Filtered de la base de datos como fuente. En CRM Online (o On-Premise con Claims Authentication) la cosa cambia: la consulta se escribe como una expresión FetchXml que igualmente está filtrada según los privilegios. El problema viene cuando un usuario no tiene el permiso mínimo de lectura a nivel usuario. En este caso el informe simplemente lanzará una excepción, cuando tal vez lo que esperaríamos es que mostrara una lista vacía. Para evitar esto no queda más remedio que hacer un pequen˜o rodeo:
  1. Crear un informe principal que obtiene información de seguridad del usuario actual.
  2. Crear un informe secundario con los datos que realmente queremos mostrar.
  3. En el informe principal, comprobar si el usuario tiene permisos de lectura en la entidad y, en caso afirmativo, mostrar el informe secundario.
¿Y cómo obtenemos la información de seguridad (roles y privilegios) de un usuario? De eso va esta entrada. Empezamos por anadir el parámetro estándar CRM_FullName y llenando un DataSet con la información siguiente:

Para obtener los roles de seguridad del usuario actual:

<fetch>
  <entity name="systemuserroles">
    <link-entity alias="u" from="systemuserid" name="systemuser" to="systemuserid">
      <filter>
        <condition attribute="fullname" operator="eq" value="@CRM_FullName" />
      </filter>
    </link-entity>
    <link-entity alias="r" from="roleid" name="role" to="roleid">
      <attribute name="name" />
    </link-entity>
  </entity>
</fetch>

Para obtener los privilegios de lectura del usuario actual:

<fetch>
  <entity name="systemuserroles">
  <link-entity alias="u" from="systemuserid" name="systemuser" to="systemuserid">
    <filter>
      <condition attribute="fullname" operator="eq" value="@CRM_FullName">
    </condition></filter>
  </link-entity>
  <link-entity alias="_r" from="roleid" name="role" to="roleid">
    <link-entity alias="r" from="roleid" name="role" to="parentrootroleid">
      <link-entity alias="rp" from="roleid" name="roleprivileges" to="roleid">
        <attribute name="privilegedepthmask">
        <link-entity alias="p" from="privilegeid" name="privilege" to="privilegeid">
          <attribute name="name">
            <filter>
              <condition attribute="name" operator="like" value="prvRead%">
            </condition></filter>          
        </attribute></link-entity>
      </attribute></link-entity>
    </link-entity>
  </link-entity>
 </entity>
</fetch>

Una vez creado el DataSet (lo he llamdo Privileges), controlamos la visibilidad del subinforme con una expresión similar a lo siguiente:

=Lookup("prvReadaccount",Fields!p_name.Value,Fields!rp_privilegedepthmaskValue.Value,"Privileges")

Que básicamente busca en el DataSet a través de la función Lookup un privilegio de nombre prvReadaccount. En el valor de esta expresión obtenemos un 1 si el privilegio es nivel usuario, un 2 si es de unidad de negocio, 4 si es "deep" y 8 si es global.

No hay comentarios: