package net.curisit.securis.services; import java.io.IOException; import java.lang.reflect.Method; import java.util.List; import java.util.Set; import javax.inject.Inject; import javax.persistence.EntityManager; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.ext.Provider; import net.curisit.securis.db.User; import net.curisit.securis.utils.CacheTTL; import net.curisit.securis.utils.TokenHelper; import org.jboss.resteasy.core.ResourceMethodInvoker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Provider public class SecurityInterceptor implements javax.ws.rs.container.ContainerRequestFilter { private static final Logger log = LoggerFactory.getLogger(SecurityInterceptor.class); @Inject private TokenHelper tokenHelper; @Context private HttpServletRequest servletRequest; @Inject CacheTTL cache; @Inject com.google.inject.Provider emProvider; @Override public void filter(ContainerRequestContext containerRequestContext) throws IOException { ResourceMethodInvoker methodInvoker = (ResourceMethodInvoker) containerRequestContext.getProperty("org.jboss.resteasy.core.ResourceMethodInvoker"); Method method = methodInvoker.getMethod(); if (!method.isAnnotationPresent(Securable.class)) return; String token = servletRequest.getHeader(TokenHelper.TOKEN_HEADER_PĂ€RAM); if (token == null || !tokenHelper.isTokenValid(token)) { log.info("Access denied to '{}', Token not valid.", servletRequest.getPathInfo()); containerRequestContext.abortWith(Response.status(Status.UNAUTHORIZED).build()); } else { Securable sec = method.getAnnotation(Securable.class); // If roles == 0 we only need to validate the token if (sec.roles() != 0) { String username = tokenHelper.extractUserFromToken(token); int userRoles = getUserRoles(username); if ((sec.roles() & userRoles) == 0) { log.info("User {} has no necessary role to access url: {}", username, servletRequest.getPathInfo()); containerRequestContext.abortWith(Response.status(Status.UNAUTHORIZED).build()); } Set orgs = getUserOrganizations(username); servletRequest.setAttribute("user_orgs", orgs); } } } private Set getUserOrganizations(String username) { @SuppressWarnings("unchecked") Set userOrgs = cache.get("orgs_" + username, Set.class); if (userOrgs == null) { // Theorically this shouldn't be never null, but just in case... EntityManager em = emProvider.get(); User user = em.find(User.class, username); if (user != null) { userOrgs = user.getAllOrgsIds(); // We store user orgs in cache only for one hour cache.set("orgs_" + username, userOrgs, 3600); } } return userOrgs; } private int getUserRoles(String username) { if (username == null) return 0; Integer userRoles = cache.get("roles_" + username, Integer.class); if (userRoles == null) { EntityManager em = emProvider.get(); User user = em.find(User.class, username); if (user != null) { userRoles = 0; List roles = user.getRoles(); for (Integer rol : roles) { userRoles += rol; } // We store user roles in cache only for one hour cache.set("roles_" + username, userRoles, 3600); cache.set("orgs_" + username, user.getOrgsIds(), 3600); } } return userRoles == null ? 0 : userRoles.intValue(); } }