La pantalla de inicio de la aplicación está formada por tres partes, y cada una de ellas se define, de izquierda a derecha, en los ficheros menuModulos.xml, menuHerramientas.xml y menuAdministracion.xml que están en la carpeta include de la aplicación. Las tres siguen la misma sintaxis y tienen las mismas opciones, que veremos a continuación. A continuación tenemos un ejemplo:
El plugin CWPantallaEntrada, lee los tres ficheros para crear la pantalla de inicio. El objetivo de cada fichero es:
menuModulos.xml: Define la jerarquía de módulos y opciones de la aplicación, que se utilizará tanto en la pantalla principal como en el menú desplegable de las ventanas.
menuHerramientas.xml: Lista de herramientas disponibles para esta aplicación.
menuAdministracion.xml: Define las herramientas para la administración de la aplicación.
Cada uno de estos ficheros tiene una DTD con la que se define la estructura de ese bloque de menús en la pantalla entrada. La primera etiqueta que hay que definir es <menu></menu>, esta etiqueta será un bloque que englobará todo lo que definamos para ese bloque (módulos, herramientas o administración).
La aplicacion puede dividirse en módulos, etiqueta <modulo>, aunque normalmente sólo lo harán aquellas de tamaño grande; una aplicacion de tamaño mediano o pequeño constará de un sólo módulo. Dentro de cada módulo pueden aparecer tanto ramas, etiqueta <rama>, como opciones, etiqueta <opcion>; las ramas expresan submenús y las opciones son las hojas o elementos que se asocian con una acción o pantalla.
La etiqueta <controlAcceso> sirve para controlar que partes de la aplicación son visibles o no, en función del rol o de los módulos asignados al usuario (esa información se extrae de la clase IgepSession a través de la sesion). Si este nodo no aparece, cualquier usuario validado podrá acceder. Este nodo debe ser siempre el primer hijo del nodo al que quiera asociarse (NÓTESE que en el caso de opcion, debe reconvertirse la etiqueta XML y ser necesario una de apertura y otra de cierre).
A continuación se relacionan el conjunto de etiquetas utilizadas son:
La imágenes que pueden aparecer asociadas a una opción del menú se encuentran ubicadas en el directorio images/menu que debemos tener en el custom que hayamos definido para nuestra aplicación.
<menu>...</menu>
Agrupación de módulos. Sólo se pueden poner a primer nivel.
Atributos:
aplicacion: Nombre de la aplicación.
titulo: Título que aparecerá en la cabecera del bloque correspondiente.
<modulo>...</modulo>
Agrupación de opciones y ramas. Sólo se pueden poner a primer nivel.
Atributos:
titulo: Título de la opción, será la cadena presentada en el menu y en la pantalla principal.
descripcion: Se corresponde con la cadena que se muestra en el menú cuando detenemos el cursor encima.
imagen: (Opcional) Imagen
asociada en el menú. Será una ruta relativa a un fichero gráfico
en la carpeta igep/images. Si instanciamos el parámetro,
deberemos comprobar que la imagen existe. Si no especificamos la
imagen para el módulo, por defecto se utilizará la siguiente
imagen
<rama>...</rama>
Opción dentro de un módulo que contiene opciones o más ramas
Atributos:
titulo: Título de la opción, será la cadena presentada en el menu y en la pantalla principal.
descripcion: Se corresponde con la cadena que se muestra en el menú cuando detenemos el cursor encima.
imagen: (Opcional) Imagen
asociada en el menú. Será una ruta relativa a un fichero gráfico
en la carpeta igep/images. Si instanciamos el parámetro,
deberemos comprobar que la imagen existe. Si no especificamos
este parámetro por defecto se utilizará la siguiente imagen
<opcion />
Opción que ya enlazará con la ventana correspondiente. NÓTESE que en el caso de que se quiera control de acceso debe reconvertirse la etiqueta XML y ser necesario una de apertura y otra de cierre (<opcion><controlAcceso>...</controlAcceso></opcion>)
Atributos:
titulo: Título de la opción, será la cadena presentada en el menú y en la pantalla principal.
descripcion: Se corresponde con la cadena que se muestra en el menú cuando detenemos el cursor encima.
imagen: (Opcional) Imagen
asociada en el menú. Será una ruta relativa a un fichero gráfico
en la carpeta igep/images. Si instanciamos el parámetro,
deberemos comprobar que la imagen existe. Si no especificamos la
imagen para la opción por defecto se utilizará la siguiente
imagen
url: Indicaremos la clase PHP encargada de manejar la opción (se añade internamente la cadena view).
ventana: Parámetro que utilizaremos cuando queramos que la url se nos abra en una ventana diferente de la aplicación, pondremos ventana="true". Si no aparece se abrirá en la misma ventana de la aplicación.
<controlAcceso>...</controlAcceso>
Bloque para definir los roles y módulos de usuarios. Aparecerá inmediatamente después del módulo, rama u opción que haya que controlar.
<rolPermitido>
Define el rol para acceder al nodo. Se hace uso de tantas etiquetas <rolPermitido> como roles puedan acceder a ese nodo.
Atributos:
valor: Identificador del rol
<moduloPermitido>
Módulo de acceso. No tiene nada que ver con la etiqueta módulo que se ha definido antes, y que sirve para agrupar las opciones en la aplicación.
<moduloPermitido /> Pueden imitar el comportamiento de los roles o ser más restrictivos. Si sólo se especifica el módulo, los usuarios que lo tengan asignado podrán acceder.
<moduloPermitido>...</moduloPermitido> Si además se especifica una lista de valores, se comprobará si el usuario tiene asignado un módulo, y si lo tiene, el valor del mismo debe aparecer entre los especificados en la etiqueta <valorModulo> .
Atributos:
id: Identificador del módulo
<valorModulo>
Aparecerá una etiqueta por cada valor al que se le dará acceso a la opción.
Atributos:
valor: valor del módulo
<?xml version="1.0" encoding="iso-8859-1"?> <menu aplicacion="nombreAplicacion"> <modulo id="1" titulo="modulo Uno" imagen="menu.gif"> <controlAcceso> <rolPermitido valor="INFORMATICO"/> <rolPermitido valor="SUPERNENA"/> <rolPermitido valor="MIEMBROIGEP"/> <moduloPermitido id="P_TRAMITA" /> <moduloPermitido id="david"> <valorModulo valor=" " /> </moduloPermitido> <moduloPermitido id="DIASEMANA"> <valorModulo valor="LUNES" /> <valorModulo valor="MARTES" /> </moduloPermitido> </controlAcceso> <opcion imagen="menu.gif" titulo="tOpcion1.1" descripcion="dOpcion1.1" url="URLOpcion1-1.php" /> <opcion imagen="menu.gif" titulo="tOpcion1.2" descripcion="dOpcion1.1" url="URLOpcion1-1.php" /> <rama titulo="ramaL2" id="r2"> <opcion imagen="menu.gif" titulo="tOpcion2.1" descripcion="dOpcion2.1" url="URLOpcion2-1.php"> </opcion> <opcion imagen="menu.gif" titulo="tOpcion2.2" descripcion="dOpcion2.2" url="URLOpcion2-1.php"/> <rama titulo="ramaL3" id="r3"> <opcion imagen="menu.gif" titulo="tOpcion3.1" descripcion="dOpcion3.1" url="URLOpcion3-1.php" /> </opcion> </rama> </rama> <opcion imagen="menu.gif" titulo="tOpcion1.4" descripcion="dOpcion1.4" url="http://www.google.es" /> </modulo> <modulo id="2" titulo="modulo Segundo" imagen="menu.gif"> <opcion imagen="menu.gif" titulo="tOpcion1.1" descripcion="dOpcion1.1" url="URLOpcion1-1.php" /> <rama titulo="ramaL2" id="r2"> <opcion imagen="menu.gif" titulo="tOpcion2.1" descripcion="dOpcion2.1" url="URLOpcion2-1.php"> <controlAcceso> <rolPermitido id="INFORMATICO"/> <moduloPermitido id="P_TRAMITA"/> </controlAcceso> </opcion> <opcion imagen="menu.gif" titulo="tOpcion2.2" descripcion="dOpcion2.2" url="URLOpcion2-1.php" /> <rama titulo="ramaL3" id="r3"> <controlAcceso> <moduloPermitido id="COLORES"> <valorModulo valor="ROJO" /> <valorModulo valor="AZUL" /> </moduloPermitido> </controlAcceso> <opcion imagen="menu.gif" titulo="google" descripcion="Buscador" url="http://www.google.es"/> </rama> </rama> </modulo> </menu>
Ejemplo: Opción sin control de acceso.
<opcion imagen="menu.gif" titulo="tOpcion2.2" descripcion="dOpcion2.2" url="URLOpcion2-1.php" />
Ejemplo: Opción con control de acceso.
<opcion imagen="menu.gif" titulo="tOpcion2.2" descripcion="dOpcion2.2" url="URLOpcion2-1.php"> <controlAcceso> <moduloPermitido id="COLORES"> <valorModulo valor="ROJO" /> <valorModulo valor="AZUL" /> </moduloPermitido> </controlAcceso> </opcion>
En dicho nodo se incluye tanto el tratamiento de los roles de usuario como el de los módulos.
Rol: se hace uso de tantas etiquetas <rolPermitido> como roles puedan acceder a ese nodo, cada rol se identifica por el atributo valor.
Ejemplo:
<opcion imagen="menu.gif" titulo="tOpcion2.2" descripcion="dOpcion2.2" url="URLOpcion2-1.php"> <controlAcceso> <rolPermitido valor="DESARROLLO_GVHIDRA" /> </controlAcceso> </opcion>
Módulo de acceso: Pueden imitar el comportamiento de los roles o ser más restrictivos. Si sólo se especifica el módulo, los usuarios que lo tengan asignado podrán acceder. Si además se especifica una lista de valores, se comprobará si el usuario tiene asignado un módulo, y si lo tiene, el valor del mismo debe aparecer entre los especificados.
Ejemplo: Opción con lista de valores, el usuario debe tener asignado el módulo COLORES y deberá tener uno de los dos valores, ROJO o AZUL para que se permita el acceso.
<opcion imagen="menu.gif" titulo="tOpcion2.2" descripcion="dOpcion2.2" url="URLOpcion2-1.php"> <controlAcceso> <moduloPermitido id="COLORES"> <valorModulo valor="ROJO" /> <valorModulo valor="AZUL" /> </moduloPermitido> </controlAcceso> </opcion>
Opciones que pueden usarse en los ficheros xml de configuración de menús, y que están implementadas en gvHidra.
Abre una ventana emergente donde se explica el funcionamiento general de los distintos elementos de las aplicaciones realizadas con gvHIDRA. Se recomienda colocar en el menú de herramientas o de administración.
<opcion titulo="Manual Guía de Estilo" descripcion="Manual de introducción a Guía de Estilo" url="igep/doc/manualIGEP/indice/indice.html" imagen="menu/24.gif" />
También hay disponible una guía rápida:
<opcion titulo="Guía Rápida" descripcion="Guía rápida uso de aplicaciones" url="igep/custom/cit.gva.es/doc/guiaRapida/guiaRapidaUsoAplicacionesCIT.pdf" abrirVentana='true' imagen="menu/24.gif" />
Abre una ventana emergente para consultar la información generada por la aplicación. Se recomienda colocar en el menú de herramientas, y con control de acceso para que no esté accesible a usuarios.
<opcion titulo="Log Aplicación" descripcion="Log Aplicación" url="igep/_debugger.php" abrirVentana="true" imagen="menu/mensajes.gif"> <controlAcceso> ... </controlAcceso> </opcion>
Abre una ventana emergente donde podemos obtener el hash de una cadena (usados en servidores de web services). Se recomienda colocar en el menú de herramientas, y con control de acceso para que no esté accesible a usuarios.
<opcion titulo="Proteger datos usando hash" descripcion="Proteger datos usando hash" url="igep/include/igep_utils/protectdata.php" abrirVentana="true" imagen="menu/seguridad.gif"> <controlAcceso> ... </controlAcceso> </opcion>
Los módulos y roles es la forma usada para controlar el acceso a las distintas partes de un aplicación. No hay que confundir estos módulos con la etiqueta <modulo> usados a nivel de los menús para agrupar funcionalidades.
Los módulos representan permisos que un usuario tiene en una aplicación determinada. Los módulos se asignan cuando se lleva a cabo una asociación entre un usuario y una aplicación, y se cargan en el inicio de la aplicación. Cada módulo tiene un código, una descripción y opcionalmente puede tener un valor. Cada usuario puede tener asignado uno o varios módulos, y para cada uno puede modificar su valor. Algunos usos habituales de módulos son el controlar si un usuario puede acceder a una opción de menú, o si puede ver/editar un campo determinado de una pantalla, o para guardar alguna información necesaria para la aplicación (departamento del usuario, año de la contabilidad, ...).
También suelen usarse para definir variables globales para todos los usuarios, aunque en este caso es recomendable asignarlos a roles (ver apartado siguiente).
Ejemplo:
Todos los usuarios que consulten la aplicación PRESUPUESTARIO deben tener el módulo M_CONSUL_PRESUPUESTARIO, es decir, nadie que no tenga ese módulo asociado podrá acceder al apartado de listados de la aplicación
Sólo el personal de la oficina presupuestaria tendrá acceso a la manipulación de datos, es decir el módulo M_MANT_PRESUPUESTARIO
Sólo técnicos y el jefe de la oficina presupuestaria tendrán tendrán acceso a la entrada de menú "control de crédito". Pues serán aquellos usuarios que tengan el módulo M_MANT_PRESUPUESTARIO, con el valor TECNICO o el valor JEFE.
Usuarios:
Sandra (Administrativa de otro departamento que consulta la aplicación): Tiene el módulo M_CONSUL_PRESUPUESTARIO
Juan (Administrativo): Tiene el módulo M_MANT_PRESUPUESTARIO, (bien sin valor, o con el valor PERFIL_ADMD)
Pepe (Técnico): Tiene el módulo M_MANT_PRESUPUESTARIO con valor PERFIL_TECNICO
Pilar (Jefa de la oficina presupuestaria): Tiene el módulo M_MANT_PRESUPUESTARIO con valor PERFIL_JEFE
Módulos:
Nombre: M_CONSUL_PRESUPUESTARIO
Descripción: Módulos de acceso a las consultas de la aplicación de presupuestario
Valores posibles: <COMPLETAR>
Nombre: M_MANT_PRESUPUESTARIO
Descripción: Módulos de acceso a las opciones de mantenimiento de la aplicación de presupuestario
Valores posibles: PERFIL_ADMD, PERFIL_TECNICO o PERFIL_JEFE
Los roles representan el papel que el usuario desempeña en una aplicación y a diferencia de los módulos, cada usuario sólo puede tener uno y no tienen valor. ¿Entonces para que queremos los roles si podemos hacer lo mismo usando módulos sin valor? Podemos ver los módulos como los permisos básicos, y los roles como agrupaciones de módulos. Realmente los roles se utilizan para facilitar la gestión de usuarios. Si sólo usamos módulos y por ejemplo tuviéramos 30 módulos, seria muy difícil clasificar a los usuarios ya que seguramente cada uno tendría una combinación distinta de módulos, y cada vez que hubiera que dar de alta un usuario tendríamos que tener un criterio claro para saber cuales de los módulos asignar.
Con roles es más simple, ya que es sencillo ver los permisos de cualquier usuario (viendo el role suele ser suficiente), y para añadir nuevos usuarios normalmente solo necesitaremos saber su role. Para que esto sea fácil de gestionar, tendríamos que tener algún mecanismo que nos permitiera asignar módulos a roles, y que los usuarios con un rol "heredaran" estos módulos. Lo más flexible seria tener esta información en tablas aunque también se podría empezar haciéndolo directamente en PHP (o ver abajo módulos dinámicos):
if ($role == 'admin') { // combinacion 1 $modulos[] = array('borrarTodo'=>array('descrip'=>'borra todo',)); $modulos[] = array('verTodo'=>array('descrip'=>'ver todo',)); $modulos[] = array('opcion11'=>array('descrip'=>'opcion 11',)); $modulos[] = array('opcion12'=>array('descrip'=>'opcion 12',)); $modulos[] = array('opcion13'=>array('descrip'=>'opcion 13',)); ... } elseif ($role == 'gestor') { // combinacion 2 $modulos[] = array('verTodo'=>array('descrip'=>'ver todo',)); $modulos[] = array('opcion12'=>array('descrip'=>'opcion 12',)); ... } elseif ($role == '...') { ...
De esta forma, añadir un nuevo usuario de tipo administrador consistiría simplemente en indicar su role, en vez de tener que asignarle los N módulos que tienen los administradores.
La solución más flexible seria usar sólo módulos para controlar cualquier característica que pueda ser configurable por usuario, y asignar los módulos a los roles de forma centralizada (bien en base de datos o en el inicio de la aplicación). Asi el programador solo tendría que tratar con los módulos, y el analista con los módulos de cada role.
El ejemplo anterior usando roles podría ser:
módulos: M_CONSUL_PRESUPUESTARIO, M_MANT_PRESUPUESTARIO (ambos sin valor)
roles:
PERFIL_ADMD (módulo M_MANT_PRESUPUESTARIO), asignado a Juan
PERFIL_TECNICO (módulo M_MANT_PRESUPUESTARIO), asignado a Pepe
PERFIL_JEFE (módulo M_MANT_PRESUPUESTARIO), asignado a Pilar
PERFIL_OTROS (módulo M_CONSUL_PRESUPUESTARIO), asignado a Sandra
En este caso las dos soluciones tienen una complejidad similar, aunque las diferencias serán más evidentes conforme aumenten el número de módulos y usuarios. Si por ejemplo decidiéramos que ahora todos los técnicos han de tener un nuevo módulo X, sin usar roles tendríamos que añadir ese módulo a todos los usuarios que tuvieran el módulo M_MANT_PRESUPUESTARIO con valor PERFIL_TECNICO; usando roles seria simplemente añadir el módulo X al role PERFIL_TECNICO.
El primer ejemplo de uso de módulos puede encontrarse en la creación de los ficheros xml que da lugar a la pantalla de inicio de la aplicación, en dichos ficheros se utiliza la etiqueta "controlAcceso" para indicar que módulos necesita tener asignados un usuario para acceder a la opción. Por ejemplo:
<opcion titulo="Prueba del árbol" descripcion="Probando el árbol" url="phrame.php?action=IgepPruebaArbol__iniciarVentana" imagen="menu/24.gif"> <controlAcceso> <moduloPermitido id="M_INTRANET"/> </controlAcceso> </opcion>
Con el párrafo anterior de XML, se indica que la entrada de la aplicación "Prueba del árbol" sólo estará disponible para aquellos usuarios que cuenten entre sus módulos el M_INTRANET. También se puede hacer el control usando un role.
Los módulos podemos usarlos en otros sitios, y podemos acceder a ellos a través de los métodos:
Tabla 3.1. Listado de Métodos 1
método | descripción |
---|---|
IgepSession::hayModulo( <modulo> ) | Devuelve un booleano indicando si el usuario tiene asignado el módulo |
IgepSession::dameModulo( <modulo> ) | Información del módulo |
ComunSession::dameModulos() | Todos los módulos (estáticos) asignados al usuario (se recomienda usar el método con el mismo nombre de IgepSession) |
Cuando queremos usar módulos que no estén permanentemente asignados a un usuario, sino que la asignación dependa de otras circunstancias que puedan ir cambiando durante la ejecución de la aplicación, la asignación no la haremos en el inicio de la aplicación. Para poder añadir o eliminar módulos en tiempo de ejecución, y conseguir, entre otras cosas el poder hacer accesibles u ocultar opciones de menú dinámicamente, podemos además usar:
Tabla 3.2. Listado de Métodos 2
método | descripción |
---|---|
IgepSession::anyadeModuloValor( <modulo>, <valor>=null, <descripcion>=null ) | Añade un nuevo módulo al usuario |
IgepSession::quitaModuloValor( <modulo>, <valor>=null ) | Quita el módulo al usuario; si se le pasa valor, sólo lo quita si el valor del módulo coincide con el valor pasado |
IgepSession::hayModuloDinamico( <modulo> ) | Devuelve un booleano indicando si el usuario tiene asignado el módulo dinámico |
IgepSession::dameModuloDinamico( <modulo> ) | Información del módulo dinámico |
IgepSession::dameModulosDinamicos() | Todos los módulos dinámicos asignados al usuario |
IgepSession::dameModulos() | Todos los módulos asignados al usuario |
Estos módulos les llamaremos módulos dinámicos. A efectos del framework, no hay diferencia entre los módulos cargados inicialmente y los módulos dinámicos. El plugin CWPantallaEntrada ya incluye dicha funcionalidad, por lo que si en alguno de los ficheros XML aparece una opción como esta:
<opcion titulo="Prueba de módulo dinamico" descripcion="Ejemplo de activación y descativación de opciones en ejecución" url="http://www.gvpontis.gva.es" imagen="menu/24.gif"> <controlAcceso> <moduloPermitido id="MD_GVA"/> </controlAcceso> </opcion>
hasta que en algún punto de nuestro código PHP no realicemos una llamada como esta:
IgepSession::anyadeModuloValor("MD_GVA")
la opción permanecerá oculta.
Si después de habilitarla queremos volver a ocultarla, basta con ejecutar la opción:
IgepSession::quitaModuloValor("MD_GVA")
Podemos obtener el role del usuario con el método IgepSession::dameRol().
Restricciones en los menús
Para que los cambios sean efectivos de forma visual en los menús, es necesario que se reinterprete el código XML, cosa que sólo se hace cuando se pasa por la pantalla principal de la aplicación, mientras tanto NO será actualizada la visibilidad/invisibilidad de las distintas ramas, módulos y/o opciones. Por tanto, convendrá también añadir en las acciones que correspondan al menú, comprobación explícita de que se tienen los módulos/roles necesarios para el acceso.