Control de acceso a datos automatizado con PrimeFaces (Paso a paso)

Control de acceso a datos automatizado con PrimeFaces (Paso a paso) magm 25 Febrero, 2013 - 16:08

Estimad@s,


siguiendo con los "minitutos" de PrimeFaces veremos ahora como mejorar la tabla con datos de ventas que hemos desarrollado en este tutorial y también haciendo uso del "pseudo" sistema de control de acceso que desarrollamos en este tutorial.

 

Modificando la lógica de validación

La idea general es que en base al usuario que se haya logueado se filtren los datos sin modificar la vista en absoluto. Para conseguir este objetivo comenzaremos modificando "LoginBean.java" agregando al principio de la clase el siguiente código:

public class LoginBean implements Serializable {  private static final long serialVersionUID = -2152389656664659476L;

  private static String [][] users;
  static {
    users=new String[101][2];
    users[0][0]="admin";
    users[0][1]="admin";
    for (int t=1;t<101;t++){
      users[t][0]="Cliente "+t;
      users[t][1]="Clave "+t;
    }
  }

  private static boolean usuarioValido(String nombre, String clave) {
    if(nombre == null || clave == null)
      return false;
    for(int t=0; t<users.length; t++) {
      if(users[t][0].equals(nombre) && users[t][1].equals(clave))
      return true;
    }
    return false;
  }

...

...

  public void login(ActionEvent actionEvent) {
    RequestContext context = RequestContext.getCurrentInstance();
    FacesMessage msg = null;
    if (usuarioValido(nombre,clave)) {
      logeado = true;
      msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Bienvenid@", 
nombre);

    } else {
      logeado = false;
      msg = new FacesMessage(FacesMessage.SEVERITY_WARN, "Login Error", 
"Credenciales no válidas");
    } ... ...

Bien, el código nuevo reemplaza el algoritmo de verificación de cuenta, antes solo admitía el usuario "admin" con la clave "admin", ahora sigue admitiendo al mismo usuario, pero además se crean 100 cuentas más cuyos nombres son"Cliente 1", "Cliente 2", ... , "Cliente 100" y cuyas respectivas claves son: "Clave 1", "Clave 2", ... , "Clave 100"Hay que tener en cuenta que se generan con espacios en blanco, tanto el nombre como la clave de cada uno de esos usuarios.

Algo fundamental para lo que veremos más adelante, es que los nombres de usuario generados, coinciden exactamente con los nombres de clientes que tenemos en la base de datos.
  La validación en si la derivamos a un método llamado usuarioValido(), el método es por demás sencillo. Luego reemplazamos la lógica del if(...) que se encuentra en el método login() para hacer uso del nuevo algoritmo de validación.  

Aplicando el filtrado automático

Hasta aquí no hemos hecho nada para que los datos se filtren automáticamente, a esto lo haremos en el componente que mantiene las listas de ventas en el servidor "VentasBean.java":   Lo primero es hacer que la lista ya no se genere para todos igual, para ello comentaremos el llamando en el constructor de la clase:  

public VentasBean() {
  //processList(null);
}


Lo siguiente es modificar la sentencia sql con la que se obtienen los datos para añadirle un parámetro de filtrado:

  private String sql = "SELECT year(fecha) as anio, month(fecha) as mes, zona, cliente, sum(importe*cantidad) as ventas                               FROM dw_ventasfact v INNER JOIN clientes c ON v.idCliente=c.idCliente                                                                  INNER JOIN zonas z ON z.idZona=c.idZona                                WHERE cliente like ?GROUP BY zona, cliente, anio, mes ORDER BY anio,mes,zona,cliente";
Filtramos las ventas por nombre de cliente, utilizaremos el nombre del usuario logueado para reemplazar el parámetro ?, en el caso de ser "admin" el que se loguea se utilizar se utilizará el comodín '%' lo que implica que "admin" verá la lista completa. A esto lo hace el método que encapsula la lista con las ventas getVentas() que al inicio crea la lista solo si no existe, esto mejora la respuesta, ya que solo se calcula una vez por usuario, la desventaja es que si los datos cambian, este cambio no se verá reflejado.   public List<Venta> getVentas() {
  if(ventas==null){
    HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
                                       .getExternalContext().getSession(false);     LoginBean loginBean = (LoginBean) session.getAttribute("loginBean");
    String parametroNombre=loginBean.getNombre();
    if(parametroNombre.equals("admin")){
      parametroNombre="%";
    }
    processList(new String[]{parametroNombre});
  }
  return ventas;
}

El método ahora funciona como un singleton por sesión, esto es, solo existirá una lista por sesión de usuario. Con las tres líneas que siguen obtenemos el nombre del usuario logueado:

  HttpSession session = (HttpSession) FacesContext.getCurrentInstance()                                    .getExternalContext().getSession(false);
LoginBean loginBean = (LoginBean) session.getAttribute("loginBean");
String parametroNombre=loginBean.getNombre();

Luego, si se trata de "admin" colocamos en el nombre el comodín '%', de esta manera la variable parametroNombrecontendrá el nombre del usuario logueado o, si se trata de "admin", el comodín, en otras palabras, contendrá el valor exacto que esperamos en el parámetro de la consulta. Finalmente llamamos a processList() con ese valor de parámetro.   Ahora si probamos logearnos, por ejemplo con "Cliente 3"/"Clave 3", veremos que la lista se filtra automáticamente como se ve en la siguiente figura:   Imagen eliminada.     Podemos probar con cualquier "Cliente 1" a "Cliente 100" o "admin" para ver la lista completa. El resto sigue funcionando como antes.  

Conclusión

Lo que hemos visto demuestra la potencia del encapsulamiento y la las capas de abstracción que promueven los frameworks como JSF y PrimeFaces. Aún falta mucho por recorrer y, definitivamente, muchas mejorar por implementa.

    Eso es todo, recuerden que disponen del proyecto eclipse completo en: https://github.com/magm3333/workspace-pftuto   Saludos   Mariano