Guía 5 – Control de acceso a registros

PHPRunner tiene muchas opciones para control de acceso e incluso, para la selección de la información de una tabla, pero para algunos requisitos de nuestras aplicaciones, no son suficientes.

 

Como vemos, podemos hacer fácilmente que el usuario sólo pueda acceder a sus datos.

La pregunta y duda, es  ¿ cómo hacemos para poder acceder a mis datos y a los datos de las personas que dependen, de forma directa o indirecta, de mí ?

En la vida real se da, bastantes veces, esta circunstancia, por ejemplo:

  • Consultar los datos salariales de mis colaboradores dependientes.
  • Consultar los fichajes de acceso al trabajo de mis colaboradores dependientes.
  • Consultar los pedidos o venta de mis colaboradores dependientes.

La solución de este tipo de preguntas no es tan sencilla, dado que PHPRunner no tiene ningún “wizard” que nos facilite este acceso a los registros de una tabla.

Objetivo

Dada una estructura de jerarquía o dependencia entre personas, la consulta de estas personas estará regida por las siguientes normas:

  • Los usuarios del grupo “administrator” podrán consultar todas las personas.
  • Los usuarios podrán consultar sus datos y los de las personas que dependan de ellos directa e indirectamente.
  • No existe límite en los niveles de dependencia.

Solución

Para la creación de la solución he utilizado la función de PHP de https://gist.github.com/ubermaniac/8834601 que  me facilita el análisis de la jerarquía de dependencia.

DEMO: https://fhumanes.com/hierarchy/

Los usuarios que actualmente están disponibles son los que se muestran en la figura.

El Login y Password tienen el mismo dato.  Os recuerdo que el login “admin” pertenece al grupo de “administrator” y es el único que podrá crear y eliminar los usuarios.

En el ejemplo se ha resuelto el problema creando una lista de códigos de usuarios “id_user”, que puede consultar el usuario y añadiendo dinámicamente en el Select de la consulta la condición de “id_user IN (1,2,3,….,7)”. Ese conjunto de “id_user” son los usuarios que puede consultar.

Lo más complejo es obtener el conjunto de “id_user” y esto se hace con este código, dejando la lista de “id’s” en una variable de sesión, para su posterior uso.

hierarcy.php

<?php
//  Create ARRAY with the data Hierarchy
function convertToHierarchy($results, $idField='user_id', $parentIdField='Boss', $childrenField='') {
      $hierarchy = array(); // -- Stores the final data
      $itemReferences = array(); // -- temporary array, storing references to all items in a single-dimention
      foreach ( $results as $item ) {
            $id       = $item[$idField];
            $parentId = $item[$parentIdField];
            if (isset($itemReferences[$parentId])) { // parent exists
                  $itemReferences[$parentId][$childrenField][$id] = $item; // assign item to parent
                  $itemReferences[$id] =& $itemReferences[$parentId][$childrenField][$id]; // reference parent's item in single-dimentional array
            } elseif (!$parentId || !isset($hierarchy[$parentId])) { // -- parent Id empty or does not exist. Add it to the root
                  $hierarchy[$id] = $item;
                  $itemReferences[$id] =& $hierarchy[$id];
            }
      }
      unset($results, $item, $id, $parentId);
      // -- Run through the root one more time. If any child got added before it's parent, fix it.
      foreach ( $hierarchy as $id => &$item ) {
            $parentId = $item[$parentIdField];
            if ( isset($itemReferences[$parentId] ) ) { // -- parent DOES exist
                  $itemReferences[$parentId][$childrenField][$id] = $item; // -- assign it to the parent's list of children
                  unset($hierarchy[$id]); // -- remove it from the root of the hierarchy
            }
      }
      unset($itemReferences, $id, $item, $parentId);
      return $hierarchy;
}
// Search the data of the connected user
function findUser($hierarchy, $id_user) {
        foreach ($hierarchy as $v) {
        if ($v['id_user'] == $id_user){ // Find the id of the connected user
                return $v;
            }    
        if (!empty($v['children'])) { // Recursive find
           $w = findUser($v['children'], $id_user);
                                    if (!empty($w)) { //  User has already been found
                                                return $w;
                                    }                                    
        }
    }
 return [];
}
$_SESSION['user_dependence'] = '0'; // Initialization
// Create list of dependent users
function listChildrenUser($hierarchy,$list) {
    foreach ($hierarchy as $v) {
        $list .= $v['id_user'].',';
        if (!empty($v['children'])) { // Recursive find
            $list = listChildrenUser($v['children'], $list); 
        }     
    }
 return $list;
}
global $conn;
// Create auxiliary Sorting tables
$results = array();
$sql = "SELECT id_user , ifnull(Boss,'') id_parent, Name FROM hierarchy_users";
if ($resql = db_query($sql,$conn)) {
    /* get associative array */
    while ($row = db_fetch_array($resql)) {
        $results[] = $row;
    }
$Hierarchy = convertToHierarchy($results,'id_user','id_parent','children'); // Create hierarchy from data
$user = $_SESSION["id_user"] ; // id User connect
$Hierarchy2 = array();
$list = '';
$Hierarchy2[] = findUser($Hierarchy, $user); // Create List of dependent User id
$list = listChildrenUser($Hierarchy2,$list);
$_SESSION['user_dependence'] = substr($list, 0,strlen($list)-1); // remove last comma
}
?>

Como siempre, podréis contactar conmigo, para cualquier necesidad en [email protected]

También, como es habitual, os dejo todos los ficheros que necesitáis para que instaléis el ejemplo en vuestros equipos.

Adjuntos

Archivo Tamaño de archivo Descargas
zip Backup de la Base de Datos 1 KB 484
zip Proyecto PHPRunner 10.2 1 MB 467

Blog personal para facilitar soporte gratuito a usuarios de React y PHPRunner