From d7a35d13cd691e6821f774b624e4203a404e67d9 Mon Sep 17 00:00:00 2001
From: Roberto Sánchez <roberto.sanchez@curisit.net>
Date: Tue, 21 Jan 2014 10:16:13 +0000
Subject: [PATCH] #396 feature - Added authorization management

---
 /dev/null                                                                    |  108 -------------
 securis/src/main/java/net/curisit/securis/db/User.java                       |    4 
 securis/src/main/java/net/curisit/securis/db/Application.java                |    3 
 securis/src/main/java/net/curisit/securis/db/Organization.java               |    6 
 securis/src/main/java/net/curisit/securis/services/UserResource.java         |    4 
 securis/src/main/java/net/curisit/securis/security/Securable.java            |    2 
 securis/src/main/java/net/curisit/securis/utils/CacheTTL.java                |   13 +
 securis/src/main/java/net/curisit/securis/security/BasicSecurityContext.java |   92 +++++++++++
 securis/src/main/java/net/curisit/securis/ioc/RequestsModule.java            |    6 
 securis/src/main/java/net/curisit/securis/services/BasicServices.java        |    1 
 securis/src/main/java/net/curisit/securis/services/OrganizationResource.java |   43 ++++
 securis/src/main/java/net/curisit/securis/security/SecurityInterceptor.java  |  144 ++++++++++++++++++
 12 files changed, 299 insertions(+), 127 deletions(-)

diff --git a/securis/src/main/java/net/curisit/securis/db/Application.java b/securis/src/main/java/net/curisit/securis/db/Application.java
index eb26cde..2273e91 100644
--- a/securis/src/main/java/net/curisit/securis/db/Application.java
+++ b/securis/src/main/java/net/curisit/securis/db/Application.java
@@ -6,6 +6,7 @@
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
 import javax.persistence.NamedQueries;
@@ -43,7 +44,7 @@
 
 	@JsonIgnore
 	// We don't include the referenced entities to limit the size of each row at the listing
-	@OneToMany(mappedBy = "application")
+	@OneToMany(fetch = FetchType.LAZY, mappedBy = "application")
 	private Set<LicenseType> licenseTypes;
 
 	public int getId() {
diff --git a/securis/src/main/java/net/curisit/securis/db/Organization.java b/securis/src/main/java/net/curisit/securis/db/Organization.java
index 57e536a..a2fe5fa 100644
--- a/securis/src/main/java/net/curisit/securis/db/Organization.java
+++ b/securis/src/main/java/net/curisit/securis/db/Organization.java
@@ -9,6 +9,7 @@
 import javax.persistence.CascadeType;
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
@@ -36,7 +37,8 @@
 @Entity
 @Table(name = "organization")
 @NamedQueries(
-	{ @NamedQuery(name = "list-organizations", query = "SELECT o FROM Organization o"), @NamedQuery(name = "find-children-org", query = "SELECT o FROM Organization o where o.parentOrganization = :parentOrganization") })
+	{ @NamedQuery(name = "list-organizations", query = "SELECT o FROM Organization o"), @NamedQuery(name = "list-organizations-by-ids", query = "SELECT o FROM Organization o where id in :list_ids"),
+			@NamedQuery(name = "find-children-org", query = "SELECT o FROM Organization o where o.parentOrganization = :parentOrganization") })
 public class Organization implements Serializable {
 
 	@SuppressWarnings("unused")
@@ -73,7 +75,7 @@
 
 	@JsonIgnore
 	// We don't include the users to limit the size of each row a the listing
-	@OneToMany(mappedBy = "parentOrganization")
+	@OneToMany(fetch = FetchType.LAZY, mappedBy = "parentOrganization")
 	private Set<Organization> childOrganizations;
 
 	public int getId() {
diff --git a/securis/src/main/java/net/curisit/securis/db/User.java b/securis/src/main/java/net/curisit/securis/db/User.java
index 7f57cf8..79d2aa2 100644
--- a/securis/src/main/java/net/curisit/securis/db/User.java
+++ b/securis/src/main/java/net/curisit/securis/db/User.java
@@ -181,10 +181,10 @@
 	}
 
 	@JsonProperty("organizations_ids")
-	public List<Integer> getOrgsIds() {
+	public Set<Integer> getOrgsIds() {
 		if (organizations == null)
 			return null;
-		List<Integer> ids = new ArrayList<>();
+		Set<Integer> ids = new HashSet<>();
 		for (Organization org : organizations) {
 			ids.add(org.getId());
 		}
diff --git a/securis/src/main/java/net/curisit/securis/ioc/RequestsModule.java b/securis/src/main/java/net/curisit/securis/ioc/RequestsModule.java
index 4059219..7de70d9 100644
--- a/securis/src/main/java/net/curisit/securis/ioc/RequestsModule.java
+++ b/securis/src/main/java/net/curisit/securis/ioc/RequestsModule.java
@@ -1,5 +1,6 @@
 package net.curisit.securis.ioc;
 
+import net.curisit.securis.security.SecurityInterceptor;
 import net.curisit.securis.services.ApiResource;
 import net.curisit.securis.services.ApplicationResource;
 import net.curisit.securis.services.BasicServices;
@@ -8,7 +9,6 @@
 import net.curisit.securis.services.LicenseTypeResource;
 import net.curisit.securis.services.OrganizationResource;
 import net.curisit.securis.services.PackResource;
-import net.curisit.securis.services.SecurityInterceptor;
 import net.curisit.securis.services.UserResource;
 
 import org.eclipse.jetty.server.Authentication.User;
@@ -24,10 +24,12 @@
 	protected void configure() {
 		super.configure();
 		// TODO: Make the bind using reflection dynamically
+		bind(SecurityInterceptor.class);
+		// bind(SecurityContextWrapper.class).in(RequestScoped.class);
+
 		bind(BasicServices.class);
 		bind(LicenseServices.class);
 		bind(UserResource.class);
-		bind(SecurityInterceptor.class);
 
 		bind(ApplicationResource.class);
 		bind(LicenseTypeResource.class);
diff --git a/securis/src/main/java/net/curisit/securis/security/BasicSecurityContext.java b/securis/src/main/java/net/curisit/securis/security/BasicSecurityContext.java
new file mode 100644
index 0000000..73ef3b2
--- /dev/null
+++ b/securis/src/main/java/net/curisit/securis/security/BasicSecurityContext.java
@@ -0,0 +1,92 @@
+package net.curisit.securis.security;
+
+import java.security.Principal;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.core.SecurityContext;
+
+import net.curisit.integrity.commons.Utils;
+import net.curisit.securis.db.User;
+
+public class BasicSecurityContext implements SecurityContext {
+
+	final public static String ROL_ADVANCE = "advance";
+	final public static String ROL_ADMIN = "admin";
+
+	final static Map<String, Integer> ROLES = Utils.<String, Integer> createMap(ROL_ADVANCE, User.Rol.ADVANCE, ROL_ADMIN, User.Rol.ADMIN);
+
+	Principal user = null;
+	int roles = 0;
+	boolean secure = false;
+	Set<Integer> organizationsIds = null;
+	double ran = 0;
+
+	public BasicSecurityContext(String username, int roles, boolean secure) {
+		user = new UserPrincipal(username);
+		this.roles = roles;
+		this.secure = secure;
+		ran = Math.random();
+	}
+
+	@Override
+	public Principal getUserPrincipal() {
+		return user;
+	}
+
+	@Override
+	public boolean isUserInRole(String role) {
+		Integer introle = ROLES.get(role);
+		return introle != null && (introle & roles) != 0;
+	}
+
+	@Override
+	public boolean isSecure() {
+		return secure;
+	}
+
+	@Override
+	public String getAuthenticationScheme() {
+		return null;
+	}
+
+	@Override
+	public String toString() {
+
+		return String.format("SecurityContextWrapper(%f) %s", ran, user);
+	}
+
+	public void setOrganizationsIds(Set<Integer> orgs) {
+		this.organizationsIds = orgs;
+	}
+
+	public Set<Integer> getOrganizationsIds() {
+		return this.organizationsIds;
+	}
+
+	private class UserPrincipal implements Principal {
+
+		final String name;
+
+		public UserPrincipal(String name) {
+			this.name = name;
+		}
+
+		@Override
+		public String getName() {
+			return this.name;
+		}
+
+		@Override
+		public String toString() {
+			return String.format("[%s]", name);
+		}
+
+	}
+
+	public boolean isOrgAccesible(Integer orgid) {
+		if (organizationsIds == null || orgid == null)
+			return false;
+		return organizationsIds.contains(orgid);
+	}
+}
diff --git a/securis/src/main/java/net/curisit/securis/services/Securable.java b/securis/src/main/java/net/curisit/securis/security/Securable.java
similarity index 93%
rename from securis/src/main/java/net/curisit/securis/services/Securable.java
rename to securis/src/main/java/net/curisit/securis/security/Securable.java
index 6fcb8e3..79389e0 100644
--- a/securis/src/main/java/net/curisit/securis/services/Securable.java
+++ b/securis/src/main/java/net/curisit/securis/security/Securable.java
@@ -1,4 +1,4 @@
-package net.curisit.securis.services;
+package net.curisit.securis.security;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
diff --git a/securis/src/main/java/net/curisit/securis/security/SecurityInterceptor.java b/securis/src/main/java/net/curisit/securis/security/SecurityInterceptor.java
new file mode 100644
index 0000000..768dde2
--- /dev/null
+++ b/securis/src/main/java/net/curisit/securis/security/SecurityInterceptor.java
@@ -0,0 +1,144 @@
+package net.curisit.securis.security;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.Priority;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Priorities;
+import javax.ws.rs.WebApplicationException;
+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.Dispatcher;
+import org.jboss.resteasy.core.ResourceMethodInvoker;
+import org.jboss.resteasy.core.ServerResponse;
+import org.jboss.resteasy.spi.Failure;
+import org.jboss.resteasy.spi.HttpRequest;
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+//@Provider
+//@Priority(Priorities.AUTHENTICATION)
+//public class SecurityInterceptor implements javax.ws.rs.container.ContainerRequestFilter {
+
+@Provider
+// @ServerInterceptor
+// @Precedence("SECURITY")
+// public class SecurityInterceptor implements PreProcessInterceptor {
+// @PreMatching
+@Priority(Priorities.AUTHENTICATION)
+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;
+
+	@Context
+	Dispatcher dispatcher;
+
+	@Inject
+	com.google.inject.Provider<EntityManager> emProvider;
+
+	public void filter(ContainerRequestContext containerRequestContext) throws IOException {
+		// log.info("scw {}, {}", scw, scw.getClass());
+		log.info("MACHED res: {}", containerRequestContext.getUriInfo().getMatchedResources());
+		// dispatcher.getDefaultContextObjects().remove(SecurityContextWrapper.class);
+		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
+			String username = tokenHelper.extractUserFromToken(token);
+			int userRoles = getUserRoles(username);
+			// if (sec.roles() != 0) {
+			// 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<Integer> orgs = getUserOrganizations(username);
+
+			BasicSecurityContext scw = new BasicSecurityContext(username, userRoles, servletRequest.isSecure());
+			scw.setOrganizationsIds(orgs);
+			containerRequestContext.setSecurityContext(scw);
+			// Next line provide injection in resource methods
+			log.info("TEST context {}", ResteasyProviderFactory.getContextData(BasicSecurityContext.class));
+			ResteasyProviderFactory.pushContext(BasicSecurityContext.class, scw);
+			// log.info("{}", dispatcher.getDefaultContextObjects());
+			// dispatcher.getDefaultContextObjects().put(SecurityContextWrapper.class, secContext);
+			log.info("Added custom SecurityContext for user {}", username);
+		}
+	}
+
+	private Set<Integer> getUserOrganizations(String username) {
+		@SuppressWarnings("unchecked")
+		Set<Integer> 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<Integer> 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();
+	}
+
+	// @Override
+	public ServerResponse preProcess(HttpRequest request, ResourceMethodInvoker method) throws Failure, WebApplicationException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+}
diff --git a/securis/src/main/java/net/curisit/securis/services/BasicServices.java b/securis/src/main/java/net/curisit/securis/services/BasicServices.java
index e1a7a77..efa8907 100644
--- a/securis/src/main/java/net/curisit/securis/services/BasicServices.java
+++ b/securis/src/main/java/net/curisit/securis/services/BasicServices.java
@@ -21,6 +21,7 @@
 import javax.ws.rs.core.UriBuilder;
 
 import net.curisit.integrity.commons.Utils;
+import net.curisit.securis.security.Securable;
 import net.curisit.securis.utils.TokenHelper;
 
 import org.slf4j.Logger;
diff --git a/securis/src/main/java/net/curisit/securis/services/OrganizationResource.java b/securis/src/main/java/net/curisit/securis/services/OrganizationResource.java
index 71b5441..e13bd7b 100644
--- a/securis/src/main/java/net/curisit/securis/services/OrganizationResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/OrganizationResource.java
@@ -4,6 +4,7 @@
 import java.util.Date;
 import java.util.List;
 
+import javax.annotation.security.RolesAllowed;
 import javax.inject.Inject;
 import javax.inject.Provider;
 import javax.persistence.EntityManager;
@@ -27,8 +28,11 @@
 import net.curisit.securis.SecurisErrorHandler;
 import net.curisit.securis.db.Organization;
 import net.curisit.securis.db.User;
+import net.curisit.securis.security.BasicSecurityContext;
+import net.curisit.securis.security.Securable;
 import net.curisit.securis.utils.TokenHelper;
 
+import org.jboss.resteasy.spi.ResteasyProviderFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -45,10 +49,7 @@
 	private static final Logger log = LoggerFactory.getLogger(OrganizationResource.class);
 
 	@Inject
-	TokenHelper tokenHelper;
-
-	@Inject
-	Provider<EntityManager> emProvider;
+	private Provider<EntityManager> emProvider;
 
 	public OrganizationResource() {
 	}
@@ -61,11 +62,30 @@
 	@Path("/")
 	@Produces(
 		{ MediaType.APPLICATION_JSON })
-	public Response index() {
+	@Securable
+	// @RolesAllowed(SecurityContextWrapper.ROL_ADVANCE)
+	public Response index(@Context BasicSecurityContext bsc) {
 		log.info("Getting organizations list ");
 
+		// log.info("User orgs: {}", request.getAttribute("oser_orgs"));
+		BasicSecurityContext bsc2 = ResteasyProviderFactory.getContextData(BasicSecurityContext.class);
+		log.info("bsc: {}", bsc);
+		log.info("bsc2: {}", bsc2);
+		// log.info("securityContext: {}", scw);
+		log.info("securityContext ROL_ADMIN?: {}", bsc.isUserInRole(BasicSecurityContext.ROL_ADMIN));
 		EntityManager em = emProvider.get();
-		TypedQuery<Organization> q = em.createNamedQuery("list-organizations", Organization.class);
+		TypedQuery<Organization> q;
+		if (bsc.isUserInRole(BasicSecurityContext.ROL_ADMIN)) {
+			log.info("GEtting all orgs for user: " + bsc.getUserPrincipal());
+			q = em.createNamedQuery("list-organizations", Organization.class);
+		} else {
+			q = em.createNamedQuery("list-organizations", Organization.class);
+			// if (securityContext.getOrganizationsIds() == null)
+			// Response.ok().build();
+			// log.info("Getting only {} orgs for user: {}", securityContext.getOrganizationsIds(), securityContext.getUserPrincipal());
+			// q = em.createNamedQuery("list-organizations-by-ids", Organization.class);
+			// q.setParameter("list_ids", securityContext.getOrganizationsIds());
+		}
 
 		List<Organization> list = q.getResultList();
 
@@ -80,12 +100,17 @@
 	@Path("/{orgid}")
 	@Produces(
 		{ MediaType.APPLICATION_JSON })
+	@Securable
 	public Response get(@PathParam("orgid") String orgid, @HeaderParam(TokenHelper.TOKEN_HEADER_PÀRAM) String token) {
 		log.info("Getting organization data for id: {}: ", orgid);
 		if (orgid == null || orgid.equals("")) {
 			log.error("Organization ID is mandatory");
 			return Response.status(Status.NOT_FOUND).build();
 		}
+		// if (!securityContext.isOrgAccesible(Integer.parseInt(orgid))) {
+		// log.error("Organization with id {} not accessible for user: {}", orgid, securityContext.getUserPrincipal());
+		// return Response.status(Status.UNAUTHORIZED).build();
+		// }
 
 		EntityManager em = emProvider.get();
 		Organization lt = em.find(Organization.class, Integer.parseInt(orgid));
@@ -111,6 +136,8 @@
 	@Produces(
 		{ MediaType.APPLICATION_JSON })
 	@Transactional
+	@Securable
+	@RolesAllowed(BasicSecurityContext.ROL_ADMIN)
 	public Response create(Organization org, @HeaderParam(TokenHelper.TOKEN_HEADER_PÀRAM) String token) {
 		log.info("Creating new organization");
 		EntityManager em = emProvider.get();
@@ -151,6 +178,8 @@
 	@Consumes(MediaType.APPLICATION_JSON)
 	@Produces(
 		{ MediaType.APPLICATION_JSON })
+	@Securable
+	@RolesAllowed(BasicSecurityContext.ROL_ADMIN)
 	public Response modify(Organization org, @PathParam("orgid") String orgid, @HeaderParam(TokenHelper.TOKEN_HEADER_PÀRAM) String token) {
 		log.info("Modifying organization with id: {}", orgid);
 		EntityManager em = emProvider.get();
@@ -201,6 +230,8 @@
 	@Transactional
 	@Produces(
 		{ MediaType.APPLICATION_JSON })
+	@Securable
+	@RolesAllowed(BasicSecurityContext.ROL_ADMIN)
 	public Response delete(@PathParam("orgid") String orgid, @Context HttpServletRequest request) {
 		log.info("Deleting organization with id: {}", orgid);
 		EntityManager em = emProvider.get();
diff --git a/securis/src/main/java/net/curisit/securis/services/SecurityInterceptor.java b/securis/src/main/java/net/curisit/securis/services/SecurityInterceptor.java
deleted file mode 100644
index 08c4e2e..0000000
--- a/securis/src/main/java/net/curisit/securis/services/SecurityInterceptor.java
+++ /dev/null
@@ -1,108 +0,0 @@
-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<EntityManager> 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<Integer> orgs = getUserOrganizations(username);
-				servletRequest.setAttribute("user_orgs", orgs);
-			}
-		}
-	}
-
-	private Set<Integer> getUserOrganizations(String username) {
-		@SuppressWarnings("unchecked")
-		Set<Integer> 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<Integer> 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();
-	}
-
-}
diff --git a/securis/src/main/java/net/curisit/securis/services/UserResource.java b/securis/src/main/java/net/curisit/securis/services/UserResource.java
index 014ce20..f6b4560 100644
--- a/securis/src/main/java/net/curisit/securis/services/UserResource.java
+++ b/securis/src/main/java/net/curisit/securis/services/UserResource.java
@@ -115,7 +115,7 @@
 		}
 
 		Set<Organization> orgs = null;
-		List<Integer> orgsIds = user.getOrgsIds();
+		Set<Integer> orgsIds = user.getOrgsIds();
 		if (orgsIds != null && orgsIds.size() > 0) {
 			orgs = new HashSet<>();
 			for (Integer orgId : orgsIds) {
@@ -154,7 +154,7 @@
 		}
 
 		Set<Organization> orgs = null;
-		List<Integer> orgsIds = user.getOrgsIds();
+		Set<Integer> orgsIds = user.getOrgsIds();
 		if (orgsIds != null && orgsIds.size() > 0) {
 			orgs = new HashSet<>();
 			for (Integer orgId : orgsIds) {
diff --git a/securis/src/main/java/net/curisit/securis/utils/CacheTTL.java b/securis/src/main/java/net/curisit/securis/utils/CacheTTL.java
index 51a59e4..6561517 100644
--- a/securis/src/main/java/net/curisit/securis/utils/CacheTTL.java
+++ b/securis/src/main/java/net/curisit/securis/utils/CacheTTL.java
@@ -1,7 +1,9 @@
 package net.curisit.securis.utils;
 
+import java.util.ArrayList;
 import java.util.Date;
-import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import javax.inject.Inject;
@@ -25,7 +27,7 @@
 	 */
 	private static int DEFAULT_CACHE_DURATION = 24 * 60 * 60;
 
-	private Map<String, CachedObject> data = new Hashtable<>();
+	private Map<String, CachedObject> data = new HashMap<>();
 
 	private Thread cleaningThread = null;
 
@@ -46,12 +48,17 @@
 					}
 					// log.info("Cheking expired objects " + new Date());
 					Date now = new Date();
+					List<String> keysToRemove = new ArrayList<>();
 					for (String key : CacheTTL.this.data.keySet()) {
 						CachedObject co = CacheTTL.this.data.get(key);
 						if (now.after(co.getExpireAt())) {
-							CacheTTL.this.data.remove(key);
+							keysToRemove.add(key);
 						}
 					}
+					for (String key : keysToRemove) {
+						// If we try to remove directly in the previous loop an exception is thrown java.util.ConcurrentModificationException
+						CacheTTL.this.data.remove(key);
+					}
 				}
 			}
 		});

--
Gitblit v1.3.2