/*
* Copyright 2013 GiavaCms.org.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.giavacms.common.controller;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.faces.application.ConfigurableNavigationHandler;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import org.giavacms.common.module.ModuleProvider;
import org.giavacms.common.module.ModuleRegistry;
import org.giavacms.common.util.BeanUtils;
import org.giavacms.common.util.FileUtils;
import org.giavacms.common.util.JSFUtils;
import org.jboss.logging.Logger;
public abstract class AbstractPermissionController
{
@Inject
// protected Logger logger =
// Logger.getLogger(getClass().getCanonicalName());
protected Logger logger;
// - VARIABILI MEMBRO
// ---------------------------------------------------------------
/**
* variabile per discriminare comportamenti che non devono succedere in produzione
*
* inoltre
*
* if ( development == true ) un alias uguale al nome del ruolo dà accesso al ruolo stesso
*
* development deve essere passato come context param in web.xml
*/
private Boolean development = null;
/**
* url dove redirigere accessi non autorizzati
*
* redirectUrl deve essere passato come context param in web.xml
*/
private String redirectUrl = null;
/**
* percorso sotto META-INF dove trovare il file della ACL
*
* aclPath deve essere passato come context param in web.xml
*/
private String aclPath = null;
/**
* file nel percorso sotto META-INF dove trovare la ACL
*
* aclFile deve essere passato come context param in web.xml
*/
private String aclFile = null;
/**
* questa mappa viene caricata dalla classe che estende PermController in ciascun progetto e che è configurata come
* bean jsf con scope di session
*/
protected Map<String, List<String>> permissions = null;
// - GETTER/SETTER E INIZIALIZZAZIONE VARIABILI MEMBRO
// ------------------------------------------------------------------------
public boolean isDevelopment()
{
return getDevelopment();
}
public boolean getDevelopment()
{
if (development == null)
{
try
{
development = Boolean.parseBoolean(JSFUtils
.getContextParam("development"));
}
catch (Exception e)
{
development = false;
}
}
return development;
}
public String getRedirectUrl()
{
if (redirectUrl == null)
{
redirectUrl = JSFUtils.getContextParam("redirectUrl");
}
return redirectUrl == null ? "error.jsp" : redirectUrl;
}
public Map<String, List<String>> getPermissions()
{
if (permissions == null)
initPermissions();
return permissions;
}
public String getAclPath()
{
if (aclPath == null)
{
try
{
aclPath = (JSFUtils.getContextParam("aclPath"));
}
catch (Exception e)
{
logger.error(e.getMessage(), e);
}
}
return aclPath;
}
public String getAclFile()
{
if (aclFile == null)
{
try
{
aclFile = JSFUtils.getContextParam("aclFile");
}
catch (Exception e)
{
logger.error(e.getMessage(), e);
}
}
return aclFile;
}
public boolean checkACL(List<String> roles)
{
if (roles == null)
return false;
for (String role : roles)
{
if (isUserInRole(role))
{
return true;
}
}
// ultima chance...
if (getDevelopment())
{
for (String role : roles)
if (getLoginAlias() != null && getLoginAlias().equals(role))
return true;
}
return false;
}
// - METODI CHE E' POSSIBILE SOVRASCRIVERE E/O IMPLEMENTARE IN UN BEAN JSF
// CON SCOPE DI SESSIONE CHE ESTENDE QUESTA CLASSE -------------
/**
* l'implementazione di questo metodo permette di valorizzare la mappa, ad esempio leggendo l'ACL da file
*/
public void initPermissions()
{
permissions = new HashMap<String, List<String>>();
Properties p = new Properties();
try
{
p.load(new FileInputStream(FileUtils
.getAbsoluteConfigurationFilename(getClass()
.getClassLoader(), getAclPath(), getAclFile())));
for (Object o : p.keySet())
{
// permissions.put(o.toString(), Arrays.asList(
// p.getProperty(o.toString()).split(",") ) );
List<String> acl = new ArrayList<String>();
for (String ac : p.getProperty(o.toString()).split(","))
{
acl.add(ac.trim());
}
permissions.put(o.toString(), acl);
}
}
catch (Exception e)
{
logger.warn("Error loading permissions: " + e.getMessage());
}
try
{
ModuleRegistry appRegistry = BeanUtils.getBean(ModuleRegistry.class);
if (appRegistry != null)
{
for (ModuleProvider module : appRegistry.getModules())
{
Map<String, String> map = module.getPermissions();
for (String o : map.keySet())
{
List<String> acl = new ArrayList<String>();
for (String ac : map.get(o).split(","))
{
acl.add(ac.trim());
}
permissions.put(o.toString(), acl);
}
}
}
}
catch (Exception e)
{
logger.warn("Error loading module permissions: " + e.getMessage());
}
}
/**
* La sovrascrittura di questo metodo permette di risolvere applicazione per applicazione l'esatto oggetto dove è
* mantenuto
*
* (es: loginController.getReferente().getAlias() )
*
*/
public String getLoginAlias()
{
HttpServletRequest req = (HttpServletRequest) FacesContext
.getCurrentInstance().getExternalContext().getRequest();
return req.getUserPrincipal().getName();
}
/**
* La sovrascrittura di questo metodo permette di risolvere applicazione per applicazione l'esatto oggetto dove è
* mantenuto
*
* (es: loginController.getReferente().getRoles().contains(role) )
*
*/
public boolean isUserInRole(String role)
{
HttpServletRequest req = (HttpServletRequest) FacesContext
.getCurrentInstance().getExternalContext().getRequest();
return req.isUserInRole(role);
}
// -----------------------------------------------------------------------------------------------------
public void checkRoles(ComponentSystemEvent event)
{
String acl = "" + event.getComponent().getAttributes().get("roles");
for (String a : acl.split(","))
{
if (checkACL(getPermissions().get(a.trim())))
return;
}
try
{
// ExternalContext extCtx = FacesContext.getCurrentInstance()
// .getExternalContext();
// extCtx.redirect(extCtx.encodeActionURL(JSFUtils.getAbsolutePath()
// + "/" + getRedirectUrl()));
FacesContext context = FacesContext.getCurrentInstance();
ConfigurableNavigationHandler handler = (ConfigurableNavigationHandler) context
.getApplication().getNavigationHandler();
handler.performNavigation("forbidden");
}
catch (Exception e)
{
e.printStackTrace();
// Se siamo qui il redirect è fallito.
// A questo punto, piuttosto che lasciare andare l'utente dove
// non deve.. runtime exception!
throw new RuntimeException("Accesso non consentito");
}
}
public String reloadPermissions()
{
initPermissions();
return null;
}
}