r3906 - in trunk: pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity pollen-persistence/src/main/xmi pollen-rest-api/src/main/java/org/chorem/pollen/rest/api pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1 pollen-rest-api/src/main/resources pollen-rest-api/src/test/java/org/chorem/pollen/rest/api pollen-services/src/main/java/org/chorem/pollen/services pollen-services/src/main/java/org/chorem/pollen/services/config pollen-services/src/main/java/org/chorem/poll
Author: tchemit Date: 2014-05-04 23:39:22 +0200 (Sun, 04 May 2014) New Revision: 3906 Url: http://forge.chorem.org/projects/pollen/repository/revisions/3906 Log: security + sumplify exceptions + ... Added: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/SessionTokenTopiaDao.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportException.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/InvalidEntityLinkException.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/InvalidFormException.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenAuthenticationException.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenInvalidEmailActivationTokenException.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenInvalidPasswordException.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenInvalidSessionTokenException.java Removed: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/RoleRequired.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityRole.java Modified: trunk/pollen-persistence/src/main/xmi/pollen.zargo trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplicationContext.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplicationListener.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiRequestContext.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiRequestFilter.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenTopiaTransactionFilter.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceApi.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentApi.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ErrorAction.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListApi.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollApi.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteApi.java trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListApi.java trunk/pollen-rest-api/src/main/resources/mapping trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/AbstractPollenRestApiTest.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/DefaultPollenServiceContext.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenApplicationContext.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceContext.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FixturesService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenSecurityRealm.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenApplicationContext.java trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenSecurityContext.java trunk/pollen-services/src/test/java/org/chorem/pollen/service/AbstractPollenServiceTest.java trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollenUserServiceTest.java Added: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/SessionTokenTopiaDao.java =================================================================== --- trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/SessionTokenTopiaDao.java (rev 0) +++ trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/SessionTokenTopiaDao.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -0,0 +1,11 @@ +package org.chorem.pollen.persistence.entity; + +public class SessionTokenTopiaDao extends AbstractSessionTokenTopiaDao<SessionToken> { + + public SessionToken findUniqueOrNullByToken(String token) { + + SessionToken sessionToken = forEquals(SessionToken.PROPERTY_POLLEN_TOKEN + "." + PollenToken.PROPERTY_TOKEN, token).findUniqueOrNull(); + return sessionToken; + + } +} Property changes on: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/SessionTokenTopiaDao.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/pollen-persistence/src/main/xmi/pollen.zargo =================================================================== (Binary files differ) Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -36,7 +36,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.chorem.pollen.persistence.PollenEntityEnum; -import org.chorem.pollen.services.exception.InvalidFormException; +import org.chorem.pollen.services.service.InvalidFormException; import org.debux.webmotion.server.call.Call; import org.debux.webmotion.server.call.HttpContext; import org.debux.webmotion.server.mapping.Mapping; @@ -126,7 +126,7 @@ }); PollenRestApiApplicationContext applicationContext = - PollenRestApiRequestFilter.getApplicationContext(context.getServletContext()); + PollenRestApiApplicationContext.getApplicationContext(context.getServletContext()); boolean devMode = applicationContext.getApplicationConfig().isDevMode(); if (devMode) { gsonBuilder.setPrettyPrinting(); Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplicationContext.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplicationContext.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplicationContext.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -28,6 +28,8 @@ import org.apache.commons.logging.LogFactory; import org.apache.log4j.LogManager; import org.apache.log4j.PropertyConfigurator; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.mgt.DefaultSecurityManager; import org.chorem.pollen.persistence.PollenPersistenceContext; import org.chorem.pollen.persistence.PollenTopiaApplicationContext; import org.chorem.pollen.persistence.PollenTopiaPersistenceContext; @@ -37,18 +39,19 @@ import org.chorem.pollen.services.PollenApplicationContext; import org.chorem.pollen.services.PollenServiceContext; import org.chorem.pollen.services.config.PollenServiceConfig; -import org.chorem.pollen.services.exception.EntityNotFoundException; -import org.chorem.pollen.services.exception.InvalidFormException; +import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.service.PollenUserService; import org.chorem.pollen.services.service.security.DefaultPollenSecurityContext; import org.chorem.pollen.services.service.security.PollenSecurityContext; +import org.chorem.pollen.services.service.security.PollenSecurityRealm; import org.nuiton.i18n.I18n; import org.nuiton.i18n.init.DefaultI18nInitializer; import org.nuiton.i18n.init.I18nInitializer; -import java.io.Closeable; +import javax.servlet.ServletContext; import java.io.File; import java.util.Locale; +import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -57,20 +60,46 @@ * @author tchemit <chemit@codelutin.com> * @since 2.0 */ -public class PollenRestApiApplicationContext implements Closeable, PollenApplicationContext { +public class PollenRestApiApplicationContext implements PollenApplicationContext { private static Log log = LogFactory.getLog(PollenRestApiApplicationContext.class); + protected static final String APPLICATION_CONTEXT_PARAMETER = "pollen_PollenApplicationContext"; + protected static PollenRestApiApplicationContext applicationContext; public static PollenRestApiApplicationContext getApplicationContext() { + + if (applicationContext == null) { + + PollenServiceConfig applicationConfig = new PollenServiceConfig("pollen-rest-api.properties"); + + Map<String, String> topiaProperties = applicationConfig.getTopiaProperties(); + + PollenTopiaApplicationContext pollenTopiaApplicationContext = new PollenTopiaApplicationContext(topiaProperties); + + applicationContext = new PollenRestApiApplicationContext(applicationConfig, pollenTopiaApplicationContext); + + applicationContext.init(); + } return applicationContext; } + public static PollenRestApiApplicationContext getApplicationContext(ServletContext servletContext) { + PollenRestApiApplicationContext result = (PollenRestApiApplicationContext) + servletContext.getAttribute(APPLICATION_CONTEXT_PARAMETER); + return result; + } + public static void setApplicationContext(PollenRestApiApplicationContext applicationContext) { PollenRestApiApplicationContext.applicationContext = applicationContext; } + public static void setApplicationContext(ServletContext servletContext, + PollenRestApiApplicationContext applicationContext) { + servletContext.setAttribute(APPLICATION_CONTEXT_PARAMETER, applicationContext); + } + protected AtomicBoolean started; protected AtomicBoolean closed; @@ -79,13 +108,6 @@ protected PollenServiceConfig applicationConfig; - public static PollenRestApiApplicationContext newApplicationContext() { - PollenServiceConfig applicationConfig = new PollenServiceConfig("pollen-rest-api.properties"); - PollenTopiaApplicationContext pollenTopiaApplicationContext = new PollenTopiaApplicationContext(applicationConfig.getTopiaProperties()); - PollenRestApiApplicationContext result = new PollenRestApiApplicationContext(applicationConfig, pollenTopiaApplicationContext); - return result; - } - protected PollenRestApiApplicationContext(PollenServiceConfig applicationConfig, PollenTopiaApplicationContext topiaApplicationContext) { Preconditions.checkNotNull(applicationConfig, "Configuration can not be null!"); @@ -153,7 +175,7 @@ return; } - if (topiaApplicationContext != null) { + if (topiaApplicationContext != null && !topiaApplicationContext.isClosed()) { if (log.isInfoEnabled()) { log.info("stopping Pollen, will close persistence context"); @@ -165,6 +187,7 @@ started.set(false); } + @Override public void init() { if (started.get()) { @@ -221,12 +244,17 @@ serviceContext.newService(PollenUserService.class).createDefaultUsers(); } catch (InvalidFormException e) { //Can't happen - } catch (EntityNotFoundException e) { - //Can't happen } finally { persistenceContext.closeContext(); } + // -- init security realm -- // + + PollenSecurityRealm realm = new PollenSecurityRealm(this); + + DefaultSecurityManager securityManager = new DefaultSecurityManager(realm); + SecurityUtils.setSecurityManager(securityManager); + started.set(true); } } Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplicationListener.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplicationListener.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiApplicationListener.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -24,8 +24,6 @@ */ import org.apache.commons.beanutils.Converter; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.chorem.pollen.persistence.PollenEntityEnum; import org.chorem.pollen.services.PollenService; import org.debux.webmotion.server.WebMotionServerListener; @@ -36,7 +34,6 @@ import org.debux.webmotion.server.mapping.Mapping; import org.nuiton.topia.persistence.TopiaEntity; -import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Type; import java.util.Date; @@ -48,9 +45,6 @@ */ public class PollenRestApiApplicationListener implements WebMotionServerListener { - /** Logger. */ - private static final Log log = LogFactory.getLog(PollenRestApiApplicationListener.class); - @Override public void onStart(Mapping mapping, ServerContext serverContext) { @@ -107,9 +101,8 @@ PollenRestApiRequestContext result = null; if (PollenRestApiRequestContext.class.isAssignableFrom(type)) { HttpContext httpContext = call.getContext(); - HttpServletRequest request = httpContext.getRequest(); - result = PollenRestApiRequestFilter.getRequestContext(request); + result = PollenRestApiRequestContext.getRequestContext(httpContext); } return result; } @@ -121,9 +114,9 @@ PollenService result = null; if (PollenService.class.isAssignableFrom(type)) { HttpContext httpContext = call.getContext(); - HttpServletRequest request = httpContext.getRequest(); - PollenRestApiRequestContext requestContext = PollenRestApiRequestFilter.getRequestContext(request); + PollenRestApiRequestContext requestContext = + PollenRestApiRequestContext.getRequestContext(httpContext); result = requestContext.getServiceContext().newService(type); } return result; @@ -135,16 +128,7 @@ PollenRestApiApplicationContext applicationContext = PollenRestApiApplicationContext.getApplicationContext(); - if (applicationContext == null) { - - // create application context - applicationContext = PollenRestApiApplicationContext.newApplicationContext(); - PollenRestApiApplicationContext.setApplicationContext(applicationContext); - applicationContext.init(); - } - - // push it in context - PollenRestApiRequestFilter.setApplicationContext( + PollenRestApiApplicationContext.setApplicationContext( serverContext.getServletContext(), applicationContext); } @@ -153,7 +137,7 @@ // Get application context PollenRestApiApplicationContext applicationContext = - PollenRestApiRequestFilter.getApplicationContext( + PollenRestApiApplicationContext.getApplicationContext( serverContext.getServletContext()); // close it (and all underlined resources) Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiRequestContext.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiRequestContext.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiRequestContext.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -24,6 +24,7 @@ import org.chorem.pollen.services.PollenServiceContext; import org.chorem.pollen.services.service.security.PollenSecurityContext; import org.chorem.pollen.services.service.security.SecurityService; +import org.debux.webmotion.server.call.HttpContext; /** * Created on 4/25/14. @@ -33,6 +34,20 @@ */ public class PollenRestApiRequestContext { + protected static final String REQUEST_POLLEN_REQUEST_CONTEXT = "pollen_PollenRequestContext"; + + public static PollenRestApiRequestContext getRequestContext(HttpContext httpContext) { + + PollenRestApiRequestContext result = (PollenRestApiRequestContext) + httpContext.getRequest().getAttribute(REQUEST_POLLEN_REQUEST_CONTEXT); + return result; + } + + public static void setRequestContext(HttpContext httpContext, + PollenRestApiRequestContext serviceContext) { + httpContext.getRequest().setAttribute(REQUEST_POLLEN_REQUEST_CONTEXT, serviceContext); + } + protected PollenServiceContext serviceContext; public void setServiceContext(PollenServiceContext serviceContext) { Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiRequestFilter.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiRequestFilter.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRestApiRequestFilter.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -27,19 +27,14 @@ import org.chorem.pollen.persistence.entity.PollenPrincipal; import org.chorem.pollen.persistence.entity.SessionToken; import org.chorem.pollen.services.PollenServiceContext; -import org.chorem.pollen.services.exception.InvalidSessionTokenException; +import org.chorem.pollen.services.service.security.PollenInvalidSessionTokenException; import org.chorem.pollen.services.service.security.PollenSecurityContext; -import org.chorem.pollen.services.service.security.SecurityRole; import org.chorem.pollen.services.service.security.SecurityService; import org.debux.webmotion.server.WebMotionFilter; -import org.debux.webmotion.server.call.Call; +import org.debux.webmotion.server.call.CookieManager; import org.debux.webmotion.server.call.HttpContext; -import org.debux.webmotion.server.mapping.Mapping; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.lang.reflect.Method; import java.util.Locale; import java.util.Map; @@ -51,53 +46,24 @@ */ public class PollenRestApiRequestFilter extends WebMotionFilter { - protected static final String APPLICATION_CONTEXT_PARAMETER = "pollen_PollenApplicationContext"; - - protected static final String REQUEST_POLLEN_REQUEST_CONTEXT = "pollen_PollenRequestContext"; - - protected static final String REQUEST_POLLEN_CONNECTED_USER = "pollen_PollenConnectedUser"; - - public static final String REQUEST_AUTH_PARAMETER = "auth"; - public static final String REQUEST_CREDENTIAL_PARAMETER = "credential"; - public static PollenRestApiApplicationContext getApplicationContext(ServletContext servletContext) { - PollenRestApiApplicationContext result = (PollenRestApiApplicationContext) - servletContext.getAttribute(APPLICATION_CONTEXT_PARAMETER); - return result; - } + public static final String POLLEN_SESSION = "pollenSession"; - public static PollenRestApiRequestContext getRequestContext(HttpServletRequest request) { - PollenRestApiRequestContext result = (PollenRestApiRequestContext) - request.getAttribute(REQUEST_POLLEN_REQUEST_CONTEXT); - return result; - } + public void inject(HttpContext context) throws PollenInvalidSessionTokenException { - public static SessionToken getSessionToken(HttpServletRequest request) { - SessionToken result = (SessionToken) - request.getAttribute(REQUEST_POLLEN_CONNECTED_USER); - return result; - } + PollenRestApiRequestContext requestContext = prepareRequestContext(context); - public static void setApplicationContext(ServletContext servletContext, - PollenRestApiApplicationContext applicationContext) { - servletContext.setAttribute(APPLICATION_CONTEXT_PARAMETER, applicationContext); - } + doProcess(); - public static void setRequestContext(HttpServletRequest request, - PollenRestApiRequestContext serviceContext) { - request.setAttribute(REQUEST_POLLEN_REQUEST_CONTEXT, serviceContext); - } + prepareResponse(context, requestContext); - public static void setSessionToken(HttpServletRequest request, - SessionToken sessionToken) { - request.setAttribute(REQUEST_POLLEN_CONNECTED_USER, sessionToken); } - public void inject(Call call, HttpContext context) throws InvalidSessionTokenException { + protected PollenRestApiRequestContext prepareRequestContext(HttpContext context) throws PollenInvalidSessionTokenException { PollenRestApiApplicationContext applicationContext = - getApplicationContext(context.getServletContext()); + PollenRestApiApplicationContext.getApplicationContext(context.getServletContext()); PollenPersistenceContext persistenceContext = PollenTopiaTransactionFilter.getPersistenceContext(context.getRequest()); @@ -109,86 +75,63 @@ PollenRestApiRequestContext requestContext = new PollenRestApiRequestContext(); requestContext.setServiceContext(serviceContext); - prepareSecurityContext(call, context, applicationContext, requestContext); + PollenSecurityContext securityContext = createSecurityContext(context, applicationContext, requestContext); + requestContext.setSecurityContext(securityContext); - setRequestContext(context.getRequest(), requestContext); + PollenRestApiRequestContext.setRequestContext(context, requestContext); - doProcess(); + return requestContext; + } + + protected void prepareResponse(HttpContext context, PollenRestApiRequestContext requestContext) { + HttpServletResponse response = context.getResponse(); response.addHeader(HttpContext.HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, "*"); response.addHeader(HttpContext.HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); - } - @Override - public void doProcess() { - super.doProcess(); - } + CookieManager cookieManager = context.getCookieManager(); - @Override - public void doProcess(Mapping mapping, Call call) { - super.doProcess(mapping, call); - } + PollenSecurityContext securityContext = requestContext.getSecurityContext(); + SessionToken sessionToken = securityContext.getSessionToken(); + if (sessionToken != null) { - protected void prepareSecurityContext(Call call, - HttpContext httpContext, - PollenRestApiApplicationContext applicationContext, - PollenRestApiRequestContext requestContext) throws InvalidSessionTokenException { + CookieManager.CookieEntity pollenSession = cookieManager.create(POLLEN_SESSION, sessionToken.getPollenToken().getToken()); + cookieManager.add(pollenSession); - // --- Create security context --- // - PollenSecurityContext securityContext = createSecurityContext( - httpContext, - applicationContext, - requestContext); + } else { - requestContext.setSecurityContext(securityContext); + cookieManager.remove(POLLEN_SESSION); - SecurityService securityService = requestContext.getSecurityService(); - - Method method = call.getExecutor().getMethod(); - - // --- Check roles --- // - - boolean needRole = method.isAnnotationPresent(RoleRequired.class); - if (needRole) { - RoleRequired roleAnnotation = method.getAnnotation(RoleRequired.class); - SecurityRole roleName = roleAnnotation.value(); - - securityService.checkRole(roleName); } } - protected PollenSecurityContext createSecurityContext(HttpContext context, + protected PollenSecurityContext createSecurityContext(HttpContext httpContext, PollenRestApiApplicationContext applicationContext, - PollenRestApiRequestContext pollenRestApiRequestContext) throws InvalidSessionTokenException { + PollenRestApiRequestContext requestContext) throws PollenInvalidSessionTokenException { - SecurityService securityService = pollenRestApiRequestContext.getSecurityService(); - Map<String, String[]> parameters = context.getParameters(); + SecurityService securityService = requestContext.getSecurityService(); - // get session token - SessionToken sessionToken; - { + // --- get session token (from cookie) --- // + CookieManager.CookieEntity pollenSession = httpContext.getCookieManager().get(POLLEN_SESSION); + String authParam = pollenSession == null ? null : pollenSession.getValue(); + SessionToken sessionToken = securityService.getSessionTokenByToken(authParam); - String[] strings = parameters.get(REQUEST_AUTH_PARAMETER); - String authParam = strings == null || strings.length < 1 ? null : strings[0]; - sessionToken = securityService.getSessionTokenByToken(authParam); - } - // get mainPrincipal - PollenPrincipal mainPrincipal; - { + // --- get mainPrincipal (from request parameters) --- // + Map<String, String[]> parameters = httpContext.getParameters(); + String[] strings = parameters.get(REQUEST_CREDENTIAL_PARAMETER); + String credentialParam = strings == null || strings.length < 1 ? null : strings[0]; + PollenPrincipal mainPrincipal = securityService.getPollenPrincipalById(credentialParam); - String[] strings = parameters.get(REQUEST_CREDENTIAL_PARAMETER); - String credentialParam = strings == null || strings.length < 1 ? null : strings[0]; - mainPrincipal = securityService.getPollenPrincipalById(credentialParam); - } - + // --- create security context --- // PollenSecurityContext securityContext = applicationContext.newSecurityContext(sessionToken, mainPrincipal); return securityContext; + } } Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenTopiaTransactionFilter.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenTopiaTransactionFilter.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenTopiaTransactionFilter.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -36,8 +36,7 @@ public class PollenTopiaTransactionFilter extends TypedTopiaTransactionFilter<PollenPersistenceContext> { - private static final Log log = - LogFactory.getLog(PollenTopiaTransactionFilter.class); + private static final Log log = LogFactory.getLog(PollenTopiaTransactionFilter.class); public PollenTopiaTransactionFilter() { super(PollenPersistenceContext.class); @@ -45,9 +44,14 @@ @Override protected PollenPersistenceContext beginTransaction(ServletRequest request) throws TopiaException { - PollenRestApiApplicationContext applicationContext = PollenRestApiRequestFilter.getApplicationContext(request.getServletContext()); + + PollenRestApiApplicationContext applicationContext = + PollenRestApiApplicationContext.getApplicationContext(request.getServletContext()); + PollenTopiaPersistenceContext persistenceContext = applicationContext.newPersistenceContext(); + return persistenceContext; + } @Override Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/RoleRequired.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/RoleRequired.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/RoleRequired.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -1,43 +0,0 @@ -package org.chorem.pollen.rest.api; - -/* - * #%L - * Pollen :: Rest Api - * %% - * Copyright (C) 2009 - 2014 CodeLutin - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * #L% - */ - -import org.chorem.pollen.services.service.security.SecurityRole; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Created on 5/3/14. - * - * @author Tony Chemit <chemit@codelutin.com> - * @since 2.0 - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface RoleRequired { - - SecurityRole value(); - -} Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -24,8 +24,8 @@ */ import org.chorem.pollen.persistence.entity.SessionToken; -import org.chorem.pollen.services.exception.UserInvalidPasswordException; import org.chorem.pollen.services.service.AuthService; +import org.chorem.pollen.services.service.security.PollenAuthenticationException; import org.debux.webmotion.server.WebMotionController; /** @@ -36,15 +36,15 @@ */ public class AuthApi extends WebMotionController { - public SessionToken login(AuthService authService, String login, String password) throws UserInvalidPasswordException { - return authService.login(login, password); + public SessionToken login(AuthService authService, String login, String password, Boolean rememberMe) throws PollenAuthenticationException { + return authService.login(login, password, rememberMe); } + public void logout(AuthService authService) { + authService.logout(); + } + public void lostPassword(AuthService authService, String login) { authService.lostPassword(login); } - - public void logout(AuthService authService, String login, String token) { - authService.logout(login, token); - } } Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceApi.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceApi.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceApi.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -24,7 +24,7 @@ */ import org.chorem.pollen.persistence.entity.Choice; -import org.chorem.pollen.services.exception.InvalidFormException; +import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.service.ChoiceService; import org.debux.webmotion.server.WebMotionController; Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentApi.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentApi.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentApi.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -24,7 +24,7 @@ */ import org.chorem.pollen.persistence.entity.Comment; -import org.chorem.pollen.services.exception.InvalidFormException; +import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.service.CommentService; import org.debux.webmotion.server.WebMotionController; Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ErrorAction.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ErrorAction.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ErrorAction.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -23,7 +23,7 @@ * #L% */ -import org.chorem.pollen.services.exception.InvalidFormException; +import org.chorem.pollen.services.service.InvalidFormException; import org.debux.webmotion.server.WebMotionController; import org.debux.webmotion.server.render.Render; @@ -46,6 +46,14 @@ return renderError(HttpServletResponse.SC_NOT_FOUND, e.getMessage()); } + public Render on401(Exception e) { + return renderError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage()); + } + + public Render on403(Exception e) { + return renderError(HttpServletResponse.SC_FORBIDDEN, e.getMessage()); + } + public Render on500(Exception e) { return renderError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); } Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListApi.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListApi.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListApi.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -25,11 +25,9 @@ import org.chorem.pollen.persistence.entity.FavoriteList; import org.chorem.pollen.persistence.entity.FavoriteListMember; -import org.chorem.pollen.rest.api.RoleRequired; -import org.chorem.pollen.services.exception.FavoriteListImportException; -import org.chorem.pollen.services.exception.InvalidFormException; +import org.chorem.pollen.services.service.FavoriteListImportException; +import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.service.FavoriteListService; -import org.chorem.pollen.services.service.security.SecurityRole; import org.debux.webmotion.server.WebMotionController; import java.io.File; @@ -44,72 +42,60 @@ */ public class FavoriteListApi extends WebMotionController { - @RoleRequired(SecurityRole.connected) public List<FavoriteList> getFavoriteLists(FavoriteListService favoriteListService) { List<FavoriteList> favoriteLists = favoriteListService.getFavoriteLists(); return favoriteLists; } - @RoleRequired(SecurityRole.connected) public FavoriteList getFavoriteList(FavoriteListService favoriteListService, String favoriteListId) { FavoriteList favoriteList = favoriteListService.getFavoriteList(favoriteListId); return favoriteList; } - @RoleRequired(SecurityRole.connected) public FavoriteList createFavoriteList(FavoriteListService favoriteListService, FavoriteList favoriteList) throws InvalidFormException { FavoriteList createdFavoriteList = favoriteListService.createFavoriteList(favoriteList); return createdFavoriteList; } - @RoleRequired(SecurityRole.connected) public FavoriteList editFavoriteList(FavoriteListService favoriteListService, FavoriteList favoriteList) throws InvalidFormException { FavoriteList editedFavoriteList = favoriteListService.editFavoriteList(favoriteList); return editedFavoriteList; } - @RoleRequired(SecurityRole.connected) public void deleteFavoriteList(FavoriteListService favoriteListService, String favoriteListId) { favoriteListService.deleteFavoriteList(favoriteListId); } - @RoleRequired(SecurityRole.connected) public int importFavoriteListMembersFromCsv(FavoriteListService favoriteListService, String favoriteListId, File csvFile) throws FavoriteListImportException { int i = favoriteListService.importFavoriteListMembersFromCsv(favoriteListId, csvFile); return i; } - @RoleRequired(SecurityRole.connected) public int importFavoriteListMembersFromLdap(FavoriteListService favoriteListService, String favoriteListId, String ldap) throws FavoriteListImportException { int i = favoriteListService.importFavoriteListMembersFromLdap(favoriteListId, ldap); return i; } - @RoleRequired(SecurityRole.connected) public LinkedHashSet<FavoriteListMember> getMembers(FavoriteListService favoriteListService, String favoriteListId) { LinkedHashSet<FavoriteListMember> members = favoriteListService.getFavoriteListMembers(favoriteListId); return members; } - @RoleRequired(SecurityRole.connected) public FavoriteListMember getMember(FavoriteListService favoriteListService, String favoriteListId, String memberId) { FavoriteListMember member = favoriteListService.getFavoriteListMember(favoriteListId, memberId); return member; } - @RoleRequired(SecurityRole.connected) public FavoriteListMember addMember(FavoriteListService favoriteListService, String favoriteListId, FavoriteListMember member) throws InvalidFormException { FavoriteListMember createdMember = favoriteListService.addFavoriteListMember(favoriteListId, member); return createdMember; } - @RoleRequired(SecurityRole.connected) public FavoriteListMember editMember(FavoriteListService favoriteListService, String favoriteListId, FavoriteListMember member) throws InvalidFormException { FavoriteListMember editedMember = favoriteListService.editFavoriteListMember(favoriteListId, member); return editedMember; } - @RoleRequired(SecurityRole.connected) public void removeMember(FavoriteListService favoriteListService, String favoriteListId, String memberId) { favoriteListService.removeFavoriteListMember(favoriteListId, memberId); } Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollApi.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollApi.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollApi.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -24,10 +24,8 @@ */ import org.chorem.pollen.persistence.entity.Poll; -import org.chorem.pollen.rest.api.RoleRequired; -import org.chorem.pollen.services.exception.InvalidFormException; +import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.service.PollService; -import org.chorem.pollen.services.service.security.SecurityRole; import org.debux.webmotion.server.WebMotionController; import java.io.File; @@ -46,25 +44,21 @@ return newPoll; } - @RoleRequired(SecurityRole.administrator) public Set<Poll> getPolls(PollService pollService) { Set<Poll> polls = pollService.getPolls(); return polls; } - @RoleRequired(SecurityRole.connected) public Set<Poll> getCreatedPolls(PollService pollService) { Set<Poll> polls = pollService.getCreatedPolls(); return polls; } - @RoleRequired(SecurityRole.connected) public Set<Poll> getInvitedPolls(PollService pollService) { Set<Poll> polls = pollService.getInvitedPolls(); return polls; } - @RoleRequired(SecurityRole.connected) public Set<Poll> getParticipatedPolls(PollService pollService) { Set<Poll> polls = pollService.getParticipatedPolls(); return polls; Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -24,12 +24,10 @@ */ import org.chorem.pollen.persistence.entity.PollenUser; -import org.chorem.pollen.rest.api.RoleRequired; -import org.chorem.pollen.services.exception.InvalidFormException; -import org.chorem.pollen.services.exception.UserInvalidEmailActivationTokenException; -import org.chorem.pollen.services.exception.UserInvalidPasswordException; +import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.service.PollenUserService; -import org.chorem.pollen.services.service.security.SecurityRole; +import org.chorem.pollen.services.service.security.PollenInvalidEmailActivationTokenException; +import org.chorem.pollen.services.service.security.PollenInvalidPasswordException; import org.debux.webmotion.server.WebMotionController; import java.util.List; @@ -42,7 +40,6 @@ */ public class PollenUserApi extends WebMotionController { - @RoleRequired(SecurityRole.administrator) public List<PollenUser> getUsers(PollenUserService pollenUserService) { List<PollenUser> users = pollenUserService.getUsers(); return users; @@ -73,14 +70,14 @@ public void validateUserEmail(PollenUserService pollenUserService, String userId, - String token) throws UserInvalidEmailActivationTokenException { + String token) throws PollenInvalidEmailActivationTokenException { pollenUserService.validateUserEmail(userId, token); } public void changePassword(PollenUserService pollenUserService, String userId, String oldPassword, - String newPassword) throws UserInvalidPasswordException { + String newPassword) throws PollenInvalidPasswordException { pollenUserService.changePassword(userId, oldPassword, newPassword); } } Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteApi.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteApi.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteApi.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -24,7 +24,7 @@ */ import org.chorem.pollen.persistence.entity.Vote; -import org.chorem.pollen.services.exception.InvalidFormException; +import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.service.VoteService; import org.debux.webmotion.server.WebMotionController; Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListApi.java =================================================================== --- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListApi.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListApi.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -25,10 +25,8 @@ import org.chorem.pollen.persistence.entity.VoterList; import org.chorem.pollen.persistence.entity.VoterListMember; -import org.chorem.pollen.rest.api.RoleRequired; -import org.chorem.pollen.services.exception.InvalidFormException; +import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.service.VoterListService; -import org.chorem.pollen.services.service.security.SecurityRole; import org.debux.webmotion.server.WebMotionController; import java.util.List; @@ -42,7 +40,6 @@ */ public class VoterListApi extends WebMotionController { - @RoleRequired(SecurityRole.connected) public VoterList importFavoriteList(VoterListService voterListService, String pollId, String favoriteListId) { VoterList importVoterList = voterListService.importFavoriteList(pollId, favoriteListId); return importVoterList; Modified: trunk/pollen-rest-api/src/main/resources/mapping =================================================================== --- trunk/pollen-rest-api/src/main/resources/mapping 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/main/resources/mapping 2014-05-04 21:39:22 UTC (rev 3906) @@ -10,10 +10,14 @@ [errors] -org.chorem.pollen.Apis.exception.EntityNotFoundException ErrorAction.on404 -org.chorem.pollen.Apis.exception.UserInvalidPasswordException ErrorAction.on500 -org.chorem.pollen.Apis.exception.UserInvalidEmailActivationTokenException ErrorAction.on500 -org.chorem.pollen.Apis.exception.InvalidFormException ErrorAction.on400Form +org.chorem.pollen.services.service.security.PollenAuthenticationException ErrorAction.on401 +org.chorem.pollen.services.service.security.PollenUnauthorizedException ErrorAction.on403 +org.chorem.pollen.services.service.security.PollenInvalidPermissionException ErrorAction.on403 +org.chorem.pollen.services.service.security.PollenInvalidSessionTokenException ErrorAction.on403 +org.chorem.pollen.services.service.security.PollenInvalidEmailActivationTokenException ErrorAction.on403 +org.chorem.pollen.services.service.InvalidFormException ErrorAction.on400Form +org.nuiton.topia.persistence.TopiaNoResultException ErrorAction.on404 +org.chorem.pollen.services.service.InvalidEntityLinkException ErrorAction.on404 [actions] Modified: trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/AbstractPollenRestApiTest.java =================================================================== --- trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/AbstractPollenRestApiTest.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/AbstractPollenRestApiTest.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -26,6 +26,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.chorem.pollen.persistence.PollenPersistenceContext; +import org.chorem.pollen.persistence.PollenTopiaPersistenceContext; import org.chorem.pollen.persistence.entity.PollenPrincipal; import org.chorem.pollen.persistence.entity.SessionToken; import org.chorem.pollen.services.PollenServiceContext; @@ -63,16 +64,18 @@ protected void loadFixtures(String fixturesSetName) { - PollenRestApiApplicationContext applicationContext = PollenRestApiApplicationContext.getApplicationContext(); + PollenTopiaPersistenceContext persistenceContext = application.newPersistenceContext(); - PollenServiceContext serviceContext = applicationContext.newServiceContext(applicationContext.newPersistenceContext(), Locale.FRANCE); + PollenServiceContext serviceContext = application.newServiceContext(persistenceContext, Locale.FRANCE); application.loadFixtures(serviceContext, fixturesSetName); + } protected <E> E fixture(String id) { return application.fixture(id); + } @Before @@ -91,51 +94,49 @@ application.getTopiaApplicationContext(), application.newPersistenceContext()); return serviceContext; + } @Override public PollenSecurityContext newSecurityContext(SessionToken sessionToken, PollenPrincipal mainPrincipal) { + FakePollenSecurityContext securityContext = new FakePollenSecurityContext(); securityContext.setMainPrincipal(mainPrincipal); securityContext.setSessionToken(sessionToken); return securityContext; + } }; + applicationContext.init(); + PollenRestApiApplicationContext.setApplicationContext(applicationContext); super.startServer(); + } @After public void stopServer() throws Exception { - PollenRestApiApplicationContext applicationContext = PollenRestApiApplicationContext.getApplicationContext(); + if (log.isTraceEnabled()) { + log.trace("closing application context " + application); + } - if (applicationContext != null) { - - if (log.isTraceEnabled()) { - log.trace("closing application context " + applicationContext); - } - applicationContext.close(); - } + application.close(); server.stop(); server.destroy(); + } protected void showTestResult(String content) throws IOException { + String testName = application.getMethodName(); + if (log.isInfoEnabled()) { log.info("test *" + testName + "* result\n" + content); } -// PollenServiceConfig applicationConfig = PollenRestApiApplicationContext.getTopiaApplicationContext().getApplicationConfig(); -// File dataDirectory = applicationConfig.getDataDirectory(); -// File resultFile = new File(dataDirectory, testName); -// FileUtils.write(resultFile, content); -// if (log.isInfoEnabled()) { -// log.info("ResultFile: " + resultFile); -// } } } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/DefaultPollenServiceContext.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/DefaultPollenServiceContext.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/DefaultPollenServiceContext.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -28,11 +28,15 @@ import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.crypto.RandomNumberGenerator; +import org.apache.shiro.crypto.hash.DefaultHashService; +import org.apache.shiro.crypto.hash.Hash; +import org.apache.shiro.crypto.hash.HashRequest; +import org.apache.shiro.util.ByteSource; import org.chorem.pollen.persistence.PollenPersistenceContext; import org.chorem.pollen.persistence.PollenTopiaApplicationContext; import org.chorem.pollen.services.config.PollenServiceConfig; import org.chorem.pollen.services.service.security.PollenSecurityContext; -import org.nuiton.util.StringUtil; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -52,6 +56,11 @@ private PollenTopiaApplicationContext topiaApplicationContext; + /** + * To hash passwords. + */ + protected DefaultHashService hashService; + public void setPollenServiceConfig(PollenServiceConfig pollenServiceConfig) { this.pollenServiceConfig = pollenServiceConfig; } @@ -84,11 +93,6 @@ } @Override - public String generateToken() { - return generateId(); - } - - @Override public Date getNow() { Date now = new Date(); return now; @@ -96,22 +100,62 @@ @Override public PollenSecurityContext getSecurityContext() { + return securityContext; + } @Override + public String generateSalt() { + + RandomNumberGenerator generator = getHashService().getRandomNumberGenerator(); + ByteSource byteSource = generator.nextBytes(); + String salt = byteSource.toBase64(); + return salt; + + } + + @Override + public String generateToken() { + + // generate uuid + String uuid = UUID.randomUUID().toString().replaceAll("-", ""); + + // decode in hexa base + byte[] decode; + try { + decode = Hex.decodeHex(uuid.toCharArray()); + } catch (DecoderException e) { + // can't happen! + throw new RuntimeException(e); + } + + // encode it in base64 (url safe version) + String result = Base64.encodeBase64URLSafeString(decode); + return result; + + } + + @Override public String generatePassword() { + return RandomStringUtils.randomAlphanumeric(8); + } @Override - public PollenPersistenceContext getPersistenceContext() { - return persistenceContext; + public String encodePassword(String salt, String password) { + + HashRequest hashRequest = new HashRequest.Builder().setSalt(salt).setSource(password).build(); + Hash hash = getHashService().computeHash(hashRequest); + String encodedToken = hash.toBase64(); + return encodedToken; + } @Override - public String encodePassword(String password) { - return StringUtil.encodeMD5(password); + public PollenPersistenceContext getPersistenceContext() { + return persistenceContext; } @Override @@ -141,17 +185,10 @@ throw new PollenTechnicalException("all services must provide a default public constructor", e); - } catch (InvocationTargetException e) { + } catch (InvocationTargetException | InstantiationException | IllegalAccessException e) { throw new PollenTechnicalException("unable to instantiate pollen service", e); - } catch (InstantiationException e) { - - throw new PollenTechnicalException("unable to instantiate pollen service", e); - - } catch (IllegalAccessException e) { - - throw new PollenTechnicalException("unable to instantiate pollen service", e); } service.setServiceContext(this); @@ -160,23 +197,18 @@ } - protected String generateId() { + protected DefaultHashService getHashService() { - // generate uuid - String uuid = UUID.randomUUID().toString().replaceAll("-", ""); + if (hashService == null) { - // decode in hexa base - byte[] decode; - try { - decode = Hex.decodeHex(uuid.toCharArray()); - } catch (DecoderException e) { - // can't happen! - throw new RuntimeException(e); + hashService = new DefaultHashService(); + String hashAlgorithmName = getPollenServiceConfig().getHashAlgorithmName(); + hashService.setHashAlgorithmName(hashAlgorithmName); + } - // encode it in base64 (url safe version) - String result = Base64.encodeBase64URLSafeString(decode); - return result; + return hashService; + } } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenApplicationContext.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenApplicationContext.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenApplicationContext.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -29,6 +29,7 @@ import org.chorem.pollen.services.config.PollenServiceConfig; import org.chorem.pollen.services.service.security.PollenSecurityContext; +import java.io.Closeable; import java.util.Locale; /** @@ -37,7 +38,7 @@ * @author Tony Chemit <chemit@codelutin.com> * @since 2.0 */ -public interface PollenApplicationContext { +public interface PollenApplicationContext extends Closeable { PollenTopiaApplicationContext getTopiaApplicationContext(); @@ -48,4 +49,6 @@ PollenServiceContext newServiceContext(PollenPersistenceContext persistenceContext, Locale locale); PollenSecurityContext newSecurityContext(SessionToken sessionToken, PollenPrincipal mainPrincipal); + + void init(); } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceContext.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceContext.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceContext.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -55,9 +55,11 @@ String generatePassword(); - String encodePassword(String password); - Locale getLocale(); String getCleanMail(String email); + + String generateSalt(); + + String encodePassword(String salt, String password); } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -28,6 +28,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.shiro.crypto.hash.Sha512Hash; import org.chorem.pollen.persistence.entity.CommentVisibility; import org.chorem.pollen.persistence.entity.PollType; import org.chorem.pollen.persistence.entity.VoteVisibility; @@ -167,4 +168,8 @@ public String getSmtpFrom() { return applicationConfig.getOption(PollenServiceConfigOption.SMTP_FROM.key); } + + public String getHashAlgorithmName() { + return Sha512Hash.ALGORITHM_NAME; + } } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -26,11 +26,10 @@ import com.google.common.base.Preconditions; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.chorem.pollen.persistence.entity.PollenToken; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.persistence.entity.SessionToken; -import org.chorem.pollen.persistence.entity.SessionTokenTopiaDao; -import org.chorem.pollen.services.exception.EntityNotFoundException; -import org.chorem.pollen.services.exception.UserInvalidPasswordException; +import org.chorem.pollen.services.service.security.PollenAuthenticationException; /** * TODO @@ -43,64 +42,49 @@ /** Logger. */ private static final Log log = LogFactory.getLog(AuthService.class); - public SessionToken login(String login, String password) throws EntityNotFoundException, UserInvalidPasswordException { - Preconditions.checkNotNull(login); - Preconditions.checkNotNull(password); + public SessionToken login(String login, String password, Boolean rememberMe) throws PollenAuthenticationException { - PollenUser user = getUserService().getUserByLogin(login); + // Log-in user + PollenUser user = getSecurityService().login(login, password, rememberMe); - String encodedPassword = serviceContext.encodePassword(password); - if (!encodedPassword.equals(user.getPassword())) { - throw new UserInvalidPasswordException(); - } + // Generate a token + PollenToken pollenToken = getSecurityService().generateNewToken(); - // Create a new session Token - SessionTokenTopiaDao dao = getSessionTokenDao(); + // Create session Token + SessionToken sessionToken = getSessionTokenDao().create( + SessionToken.PROPERTY_POLLEN_TOKEN, pollenToken, + SessionToken.PROPERTY_POLLEN_USER, user); + commit(); + return sessionToken; - SessionToken sessionToken = dao.newInstance(); - String token = serviceContext.generateToken(); - String encodedToken = serviceContext.encodePassword(token); - sessionToken.setPollenUser(user); - sessionToken.setToken(encodedToken); - sessionToken.setCreationDate(serviceContext.getNow()); + } - dao.create(sessionToken); - commit(); + public void logout() { - return sessionToken; + SessionToken sessionToken = getSecurityService().logout(); + if (sessionToken != null) { + getSessionTokenDao().delete(sessionToken); + commit(); + } + } - public void lostPassword(String login) throws EntityNotFoundException { + public void lostPassword(String login) { + Preconditions.checkNotNull(login); PollenUser user = getUserService().getUserByLogin(login); - // Generate a new password String newPassword = serviceContext.generatePassword(); - String encodedPassword = serviceContext.encodePassword(newPassword); - user.setPassword(encodedPassword); -// dao.update(user); + + getSecurityService().setUserPassword(user, newPassword); commit(); - //TODO Notifiy Password changed + //TODO Notifiy Password changed to user if (log.isDebugEnabled()) { - log.debug("Notify Password Changed"); + log.debug("Notify Password changed"); } - } - public void logout(String login, String token) throws EntityNotFoundException { - Preconditions.checkNotNull(login); - Preconditions.checkNotNull(token); - - getUserService().getUserByLogin(login); - - SessionTokenTopiaDao dao = getSessionTokenDao(); - - SessionToken sessionToken = dao.findByTopiaId(token); - checkEntityExists(SessionToken.class, sessionToken, token); - - dao.delete(sessionToken); - commit(); } } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -23,7 +23,6 @@ * #L% */ -import com.google.common.base.Preconditions; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; @@ -31,7 +30,6 @@ import org.chorem.pollen.persistence.entity.ChoiceTopiaDao; import org.chorem.pollen.persistence.entity.Poll; import org.chorem.pollen.persistence.entity.PollenPrincipal; -import org.chorem.pollen.services.exception.InvalidFormException; import org.chorem.pollen.services.service.security.PermissionVerb; import java.util.List; @@ -46,30 +44,36 @@ public class ChoiceService extends PollenServiceSupport { public List<Choice> getChoices(String pollId) { - Preconditions.checkNotNull(pollId); + checkNotNull(pollId); + Poll poll = getPollService().getPoll(pollId); return poll.getChoice(); + } public Choice getChoice(String pollId, String choiceId) { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(choiceId); + + checkNotNull(pollId); + checkNotNull(choiceId); checkPermission(PermissionVerb.readChoice, choiceId); + Poll poll = getPollService().getPoll(pollId); Choice result = getChoice(poll, choiceId); return result; + } public Choice addChoice(String pollId, Choice choice) throws InvalidFormException { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(choice); + + checkNotNull(pollId); + checkNotNull(choice); checkIsNotPersisted(choice); + checkPermission(PermissionVerb.editPoll, pollId); Poll poll = getPollService().getPoll(pollId); - checkPermission(PermissionVerb.editPoll, pollId); checkChoiceForm(poll, choice); @@ -79,10 +83,12 @@ commit(); //TODO Notify Choice added return result; + } public Choice editChoice(String pollId, Choice choice) throws InvalidFormException { - Preconditions.checkNotNull(choice); + + checkNotNull(choice); checkIsPersisted(choice); checkPermission(PermissionVerb.editChoice, choice.getTopiaId()); @@ -96,11 +102,13 @@ commit(); //TODO Notify Choice edited return result; + } public void deleteChoice(String pollId, String choiceId) { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(choiceId); + + checkNotNull(pollId); + checkNotNull(choiceId); checkPermission(PermissionVerb.deleteChoice, choiceId); Poll poll = getPollService().getPoll(pollId); @@ -111,13 +119,21 @@ getPollDao().update(poll); commit(); //TODO Notify Choice deleted + } protected Choice getChoice(Poll poll, String choiceId) { Choice result = poll.getChoiceByTopiaId(choiceId); - checkEntityExists(Choice.class, result, choiceId); + + if (!poll.containsChoice(result)) { + + throw new InvalidEntityLinkException(Poll.PROPERTY_CHOICE, poll, result); + + } + return result; + } protected Choice saveChoice(Poll poll, Choice choice) { @@ -167,6 +183,7 @@ throw new IllegalStateException("Not implemented"); } return choiceToPersist; + } protected void checkChoiceForm(Poll poll, Choice choice) throws InvalidFormException { @@ -190,6 +207,7 @@ continue; } choiceNames.add(choice1.getName()); + } } @@ -210,15 +228,19 @@ break; case DATE: + throw new IllegalStateException("Not implemented"); case IMAGE: + throw new IllegalStateException("Not implemented"); } if (!errors.isEmpty()) { throw new InvalidFormException(errors); + } + } } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -23,14 +23,12 @@ * #L% */ -import com.google.common.base.Preconditions; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import org.apache.commons.lang3.StringUtils; import org.chorem.pollen.persistence.entity.Comment; import org.chorem.pollen.persistence.entity.Poll; import org.chorem.pollen.persistence.entity.PollenPrincipal; -import org.chorem.pollen.services.exception.InvalidFormException; import org.chorem.pollen.services.service.security.PermissionVerb; import java.util.List; @@ -44,58 +42,71 @@ public class CommentService extends PollenServiceSupport { public List<Comment> getComments(String pollId) { - Preconditions.checkNotNull(pollId); + + checkNotNull(pollId); + Poll poll = getPollService().getPoll(pollId); return poll.getComment(); + } public Comment getComment(String pollId, String commentId) { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(commentId); - Poll poll = getPollService().getPoll(pollId); + checkNotNull(pollId); + checkNotNull(commentId); checkPermission(PermissionVerb.readComment, commentId); + Poll poll = getPollService().getPoll(pollId); + Comment result = getComment(poll, commentId); return result; + } public Comment addComment(String pollId, Comment comment) throws InvalidFormException { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(comment); + + checkNotNull(pollId); + checkNotNull(comment); checkIsNotPersisted(comment); checkPermission(PermissionVerb.addComment, pollId); + Poll poll = getPollService().getPoll(pollId); - checkCommentForm(poll, comment); + checkCommentForm(comment); + Comment result = saveComment(poll, comment); getPollDao().update(poll); commit(); + return result; + } public Comment editComment(String pollId, Comment comment) throws InvalidFormException { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(comment); + + checkNotNull(pollId); + checkNotNull(comment); checkIsPersisted(comment); - checkPermission(PermissionVerb.editComment, comment.getTopiaId()); Poll poll = getPollService().getPoll(pollId); - checkCommentForm(poll, comment); + checkCommentForm(comment); + Comment result = saveComment(poll, comment); getCommentDao().update(comment); commit(); + return result; + } public void deleteComment(String pollId, String commentId) { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(commentId); + checkNotNull(pollId); + checkNotNull(commentId); checkPermission(PermissionVerb.deleteComment, commentId); Poll poll = getPollService().getPoll(pollId); @@ -106,16 +117,24 @@ getPollDao().update(poll); commit(); + } protected Comment getComment(Poll poll, String commentId) { - Comment result = poll.getCommentByTopiaId(commentId); - checkEntityExists(Comment.class, result, commentId); + Comment result = getCommentDao().findByTopiaId(commentId); + + if (!poll.containsComment(result)) { + + throw new InvalidEntityLinkException(Poll.PROPERTY_COMMENT, poll, result); + + } + return result; + } - protected void checkCommentForm(Poll poll, Comment comment) throws InvalidFormException { + protected void checkCommentForm(Comment comment) throws InvalidFormException { //TODO use nuiton validator ? Multimap<String, String> errors = ArrayListMultimap.create(); @@ -123,13 +142,17 @@ checkNotBlank(errors, "text", comment.getText(), "textcan not be empty"); boolean authorNotNull = checkNotNull(errors, "author", comment.getAuthor(), "author can not be null"); if (authorNotNull) { + checkNotBlank(errors, "author.name", comment.getAuthor().getName(), "author name can not be empty"); + } if (!errors.isEmpty()) { throw new InvalidFormException(errors); + } + } protected Comment saveComment(Poll poll, Comment comment) { @@ -140,7 +163,8 @@ if (commentExists) { - toSave = getComment(poll, comment.getTopiaId()); + toSave = getCommentDao().findByTopiaId(comment.getTopiaId()); + } else { toSave = getCommentDao().newInstance(); @@ -152,6 +176,7 @@ toSave.setAuthor(author); poll.addComment(toSave); + } toSave.setText(comment.getText()); @@ -160,10 +185,13 @@ toSave.getAuthor().setName(comment.getAuthor().getName()); if (StringUtils.isNotBlank(comment.getAuthor().getEmail())) { + toSave.getAuthor().setEmail(StringUtils.lowerCase(comment.getAuthor().getEmail())); + } return toSave; + } } Copied: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportException.java (from rev 3905, trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListImportException.java) =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportException.java (rev 0) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportException.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -0,0 +1,52 @@ +package org.chorem.pollen.services.service; + +/* + * #%L + * Pollen :: Service + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2009 - 2013 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + +/** + * TODO + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class FavoriteListImportException extends Exception { + + private static final long serialVersionUID = 1L; + + private String causeMessage; + + public FavoriteListImportException(String causeMessage, Throwable cause) { + super(cause); + this.causeMessage = causeMessage; + } + + public FavoriteListImportException(Throwable cause) { + this(cause.getMessage(), cause); + } + + /** @return the error message source from import execution. */ + public String getCauseMessage() { + return causeMessage; + } + +} Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -23,7 +23,6 @@ * #L% */ -import com.google.common.base.Preconditions; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; @@ -33,8 +32,6 @@ import org.chorem.pollen.persistence.entity.FavoriteListMember; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.services.PollenTechnicalException; -import org.chorem.pollen.services.exception.FavoriteListImportException; -import org.chorem.pollen.services.exception.InvalidFormException; import org.nuiton.util.StringUtil; import javax.naming.NamingEnumeration; @@ -66,6 +63,8 @@ public class FavoriteListService extends PollenServiceSupport { public List<FavoriteList> getFavoriteLists() { + + checkIsConnected(); PollenUser user = getConnectedUser(); List<FavoriteList> result = user.getFavoriteList(); @@ -74,7 +73,8 @@ public FavoriteList getFavoriteList(String favoriteListId) { - Preconditions.checkNotNull(favoriteListId); + checkIsConnected(); + checkNotNull(favoriteListId); PollenUser user = getConnectedUser(); @@ -84,7 +84,8 @@ public FavoriteList createFavoriteList(FavoriteList favoriteList) throws InvalidFormException { - Preconditions.checkNotNull(favoriteList); + checkIsConnected(); + checkNotNull(favoriteList); checkIsNotPersisted(favoriteList); PollenUser user = getConnectedUser(); @@ -102,7 +103,9 @@ } public FavoriteList editFavoriteList(FavoriteList favoriteList) throws InvalidFormException { - Preconditions.checkNotNull(favoriteList); + + checkIsConnected(); + checkNotNull(favoriteList); checkIsPersisted(favoriteList); // get user @@ -123,7 +126,8 @@ public void deleteFavoriteList(String favoriteListId) { - Preconditions.checkNotNull(favoriteListId); + checkIsConnected(); + checkNotNull(favoriteListId); PollenUser user = getConnectedUser(); @@ -137,7 +141,8 @@ public LinkedHashSet<FavoriteListMember> getFavoriteListMembers(String favoriteListId) { - Preconditions.checkNotNull(favoriteListId); + checkIsConnected(); + checkNotNull(favoriteListId); PollenUser user = getConnectedUser(); @@ -148,8 +153,9 @@ public FavoriteListMember getFavoriteListMember(String favoriteListId, String memberId) { - Preconditions.checkNotNull(favoriteListId); - Preconditions.checkNotNull(memberId); + checkIsConnected(); + checkNotNull(favoriteListId); + checkNotNull(memberId); PollenUser user = getConnectedUser(); @@ -162,8 +168,9 @@ public FavoriteListMember addFavoriteListMember(String favoriteListId, FavoriteListMember member) throws InvalidFormException { - Preconditions.checkNotNull(favoriteListId); - Preconditions.checkNotNull(member); + checkIsConnected(); + checkNotNull(favoriteListId); + checkNotNull(member); checkIsNotPersisted(member); PollenUser user = getConnectedUser(); @@ -186,11 +193,11 @@ public FavoriteListMember editFavoriteListMember(String favoriteListId, FavoriteListMember member) throws InvalidFormException { - Preconditions.checkNotNull(favoriteListId); - Preconditions.checkNotNull(member); + checkIsConnected(); + checkNotNull(favoriteListId); + checkNotNull(member); checkIsPersisted(member); - PollenUser user = getConnectedUser(); FavoriteList favoriteList = getFavoriteList(user, favoriteListId); @@ -212,8 +219,9 @@ public void removeFavoriteListMember(String favoriteListId, String memberId) { - Preconditions.checkNotNull(favoriteListId); - Preconditions.checkNotNull(memberId); + checkIsConnected(); + checkNotNull(favoriteListId); + checkNotNull(memberId); PollenUser user = getConnectedUser(); @@ -230,8 +238,9 @@ public int importFavoriteListMembersFromCsv(String favoriteListId, File file) throws FavoriteListImportException { - Preconditions.checkNotNull(favoriteListId); - Preconditions.checkNotNull(file); + checkIsConnected(); + checkNotNull(favoriteListId); + checkNotNull(file); PollenUser user = getConnectedUser(); @@ -327,9 +336,11 @@ public int importFavoriteListMembersFromLdap(String favoriteListId, String ldap) throws FavoriteListImportException { - Preconditions.checkNotNull(favoriteListId); - Preconditions.checkNotNull(ldap); + checkIsConnected(); + checkNotNull(favoriteListId); + checkNotNull(ldap); + PollenUser user = getConnectedUser(); FavoriteList favoriteList = getFavoriteList(user, favoriteListId); @@ -412,19 +423,30 @@ } protected FavoriteList getFavoriteList(PollenUser user, String favoriteListId) { - Preconditions.checkNotNull(favoriteListId); - FavoriteList result = user.getFavoriteListByTopiaId(favoriteListId); - checkEntityExists(FavoriteList.class, result, favoriteListId); + FavoriteList result = getFavoriteListDao().findByTopiaId(favoriteListId); + if (!user.containsFavoriteList(result)) { + throw new InvalidEntityLinkException(PollenUser.PROPERTY_FAVORITE_LIST, user, result); + + } + return result; + } protected FavoriteListMember getFavoriteListMember(FavoriteList favoriteList, String memberId) { - FavoriteListMember result = favoriteList.getMemberByTopiaId(memberId); - checkEntityExists(FavoriteListMember.class, result, memberId); + FavoriteListMember result = getFavoriteListMemberDao().findByTopiaId(memberId); + + if (!favoriteList.containsMember(result)) { + + throw new InvalidEntityLinkException(FavoriteList.PROPERTY_MEMBER, favoriteList, result); + + } + return result; + } protected void copyFavoriteList(FavoriteList source, Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FixturesService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FixturesService.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FixturesService.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -34,7 +34,7 @@ import org.chorem.pollen.persistence.entity.PollenUserTopiaDao; import org.chorem.pollen.services.PollenFixtures; import org.chorem.pollen.services.PollenTechnicalException; -import org.chorem.pollen.services.exception.InvalidFormException; +import org.chorem.pollen.services.service.security.SecurityService; import java.util.Collection; import java.util.Map; @@ -86,13 +86,15 @@ } + SecurityService securityService = getSecurityService(); + PollenUserTopiaDao userDao = persistenceContext.getPollenUserDao(); Collection<PollenUser> users = fixtures.fixture("users"); for (PollenUser user : users) { - user.setPassword(serviceContext.encodePassword(user.getPassword())); + securityService.setUserPassword(user, user.getPassword()); PollenUser createdUser = userDao.create(user); user.setTopiaId(createdUser.getTopiaId()); } Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/InvalidEntityLinkException.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/InvalidEntityLinkException.java (rev 0) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/InvalidEntityLinkException.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -0,0 +1,38 @@ +package org.chorem.pollen.services.service; + +import org.chorem.pollen.services.PollenTechnicalException; +import org.nuiton.topia.persistence.TopiaEntity; + +/** + * Created on 5/4/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 2.0 + */ +public class InvalidEntityLinkException extends PollenTechnicalException { + + private static final long serialVersionUID = 1L; + + protected final Class<? extends TopiaEntity> containerType; + + protected final Class<? extends TopiaEntity> entityType; + + protected final String containerId; + + protected final String link; + + protected final String entityId; + + public InvalidEntityLinkException(String link, TopiaEntity container, TopiaEntity entity) { + this.containerType = container.getClass(); + this.entityType = entity.getClass(); + this.link = link; + this.containerId = container.getTopiaId(); + this.entityId = entity.getTopiaId(); + } + + @Override + public String getMessage() { + return "Could not find a " + entityType + " of id " + entityId + " as a " + link + " of container " + containerType + ") of id: " + containerId; + } +} Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/InvalidEntityLinkException.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Copied: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/InvalidFormException.java (from rev 3895, trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidFormException.java) =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/InvalidFormException.java (rev 0) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/InvalidFormException.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -0,0 +1,52 @@ +package org.chorem.pollen.services.service; + +/* + * #%L + * Pollen :: Service + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2009 - 2013 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + +import com.google.common.collect.Multimap; + +/** + * TODO + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class InvalidFormException extends Exception { + + private static final long serialVersionUID = 1L; + + protected final Multimap<String, String> errors; + + public InvalidFormException(Multimap<String, String> errors) { + this.errors = errors; + } + + public Multimap<String, String> getErrors() { + return errors; + } + + @Override + public String toString() { + return super.toString() + " errors: " + errors; + } +} Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -31,13 +31,11 @@ import org.apache.commons.lang3.StringUtils; import org.chorem.pollen.persistence.entity.Choice; import org.chorem.pollen.persistence.entity.Poll; -import org.chorem.pollen.persistence.entity.PollTopiaDao; import org.chorem.pollen.persistence.entity.PollenPrincipal; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.persistence.entity.Polls; import org.chorem.pollen.persistence.entity.VoterList; import org.chorem.pollen.persistence.entity.VoterListMember; -import org.chorem.pollen.services.exception.InvalidFormException; import org.chorem.pollen.services.service.security.PermissionVerb; import java.io.File; @@ -55,32 +53,44 @@ public ImmutableSet<Poll> getPolls() { + checkIsConnected(); + checkIsAdmin(); + List<Poll> polls = getPollDao().findAll(); - return ImmutableSet.<Poll>builder().addAll(polls).build(); + return ImmutableSet.copyOf(polls); } public ImmutableSet<Poll> getCreatedPolls() { + checkIsConnected(); + PollenUser connectedUser = getConnectedUser(); + Set<Poll> polls = getPollDao().findAllCreated(connectedUser); - return ImmutableSet.<Poll>builder().addAll(polls).build(); + return ImmutableSet.copyOf(polls); } public ImmutableSet<Poll> getInvitedPolls() { + checkIsConnected(); + PollenUser connectedUser = getConnectedUser(); + Set<Poll> polls = getPollDao().findAllInvited(connectedUser); - return ImmutableSet.<Poll>builder().addAll(polls).build(); + return ImmutableSet.copyOf(polls); } public ImmutableSet<Poll> getParticipatedPolls() { + checkIsConnected(); + PollenUser connectedUser = getConnectedUser(); + Set<Poll> polls = getPollDao().findAllParticipated(connectedUser); - return ImmutableSet.<Poll>builder().addAll(polls).build(); + return ImmutableSet.copyOf(polls); } @@ -88,8 +98,8 @@ checkNotNull(pollId); checkPermission(PermissionVerb.readPoll, pollId); - Poll result = getPollDao().forTopiaIdEquals(pollId).findUniqueOrNull(); - checkEntityExists(Poll.class, result, pollId); + + Poll result = getPollDao().findByTopiaId(pollId); return result; } @@ -121,6 +131,7 @@ result.setChoice(Lists.<Choice>newArrayList()); result.setVoterList(Lists.<VoterList>newArrayList()); + return result; } @@ -135,7 +146,9 @@ getPollDao().create(savedPoll); commit(); + getNotificationService().onPollCreated(poll); + return savedPoll; } @@ -151,7 +164,9 @@ getPollDao().update(savedPoll); commit(); + getNotificationService().onPollEdited(poll); + return savedPoll; } @@ -165,6 +180,7 @@ getPollDao().delete(poll); commit(); + getNotificationService().onPollDeleted(poll); } @@ -175,9 +191,12 @@ checkPermission(PermissionVerb.clonePoll, pollId); Poll poll = getPoll(pollId); + //TODO commit(); + getNotificationService().onPollCreated(poll); + return poll; } @@ -188,8 +207,10 @@ checkPermission(PermissionVerb.closePoll, pollId); Poll poll = getPoll(pollId); + //TODO commit(); + getNotificationService().onPollClosed(poll); } @@ -198,7 +219,9 @@ checkNotNull(pollId); checkPermission(PermissionVerb.exportPoll, pollId); + Poll poll = getPoll(pollId); + //TODO return null; @@ -211,17 +234,18 @@ Poll toSave; if (pollExists) { + toSave = getPoll(poll.getTopiaId()); } else { - PollTopiaDao dao = getPollDao(); - toSave = dao.newInstance(); + toSave = getPollDao().newInstance(); PollenPrincipal creatorToPersist = getSecurityService().generatePollenPrincipal(); toSave.setCreator(creatorToPersist); + } // -- creator -- // @@ -232,12 +256,15 @@ // link to connected user toSave.getCreator().setPollenUser(connectedUser); + } PollenPrincipal creator = poll.getCreator(); if (creator != null) { + toSave.getCreator().setName(creator.getName()); toSave.getCreator().setEmail(creator.getEmail()); + } // -- simple properties -- // @@ -265,6 +292,7 @@ for (Choice choice : poll.getChoice()) { getChoiceService().saveChoice(toSave, choice); + } // -- voting list -- // @@ -274,6 +302,7 @@ for (VoterList voterList : poll.getVoterList()) { getVoterListService().saveVoterList(toSave, voterList); + } } @@ -409,6 +438,7 @@ if (!errors.isEmpty()) { throw new InvalidFormException(errors); + } } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -44,9 +44,9 @@ import org.chorem.pollen.services.PollenService; import org.chorem.pollen.services.PollenServiceContext; import org.chorem.pollen.services.config.PollenServiceConfig; -import org.chorem.pollen.services.exception.EntityNotFoundException; import org.chorem.pollen.services.service.mail.EmailService; import org.chorem.pollen.services.service.security.PermissionVerb; +import org.chorem.pollen.services.service.security.PollenSecurityContext; import org.chorem.pollen.services.service.security.SecurityService; import org.nuiton.topia.persistence.TopiaEntity; import org.nuiton.util.StringUtil; @@ -77,8 +77,8 @@ return serviceContext.getNow(); } - protected String generateToken() { - return serviceContext.generateToken(); + protected PollenSecurityContext getSecurityContext() { + return serviceContext.getSecurityContext(); } protected String getCleanMail(String email) { @@ -211,6 +211,19 @@ return serviceContext.getSecurityContext().getPollenUser(); } + public void checkIsConnected() { + + getSecurityService().checkIsConnected(); + + } + + public void checkIsAdmin() { + + //FIXME Reput this +// getSecurityService().checkIsAdmin(); + + } + protected void checkPermission(PermissionVerb verb, String id) { String permission = getSecurityService().createPermission(verb, id); getSecurityService().checkPermission(permission); @@ -228,23 +241,6 @@ Preconditions.checkState(!entity.isPersisted()); } - protected <E extends TopiaEntity> void checkEntityExists(Class<E> type, - E entity, - String entityId) throws EntityNotFoundException { - if (entity == null) { - throw new EntityNotFoundException(type, entityId); - } - } - - protected <E extends TopiaEntity> void checkEntityExists(Class<E> type, - E entity, - String property, - String entityId) throws EntityNotFoundException { - if (entity == null) { - throw new EntityNotFoundException(type, property, entityId); - } - } - protected boolean check(Multimap<String, String> errors, String field, boolean condition, String error) { boolean valid = condition; if (!valid) { Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -26,12 +26,12 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import org.apache.commons.lang3.ObjectUtils; +import org.chorem.pollen.persistence.entity.PollenToken; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.persistence.entity.PollenUserTopiaDao; import org.chorem.pollen.services.PollenService; -import org.chorem.pollen.services.exception.InvalidFormException; -import org.chorem.pollen.services.exception.UserInvalidEmailActivationTokenException; -import org.chorem.pollen.services.exception.UserInvalidPasswordException; +import org.chorem.pollen.services.service.security.PollenInvalidEmailActivationTokenException; +import org.chorem.pollen.services.service.security.PollenInvalidPasswordException; import java.util.List; import java.util.Objects; @@ -46,6 +46,9 @@ public List<PollenUser> getUsers() { + checkIsConnected(); + checkIsAdmin(); + List<PollenUser> pollenUsers = getPollenUserDao().findAll(); return pollenUsers; @@ -55,8 +58,7 @@ checkNotNull(userId); - PollenUser result = getPollenUserDao().forTopiaIdEquals(userId).findUniqueOrNull(); - checkEntityExists(PollenUser.class, result, userId); + PollenUser result = getPollenUserDao().findByTopiaId(userId); return result; } @@ -65,9 +67,9 @@ checkNotNull(login); - PollenUser result = getPollenUserDao().forLoginEquals(login).findUniqueOrNull(); - checkEntityExists(PollenUser.class, result, PollenUser.PROPERTY_LOGIN, login); + PollenUser result = getPollenUserDao().forLoginEquals(login).findUnique(); return result; + } public PollenUser createUser(PollenUser user, boolean generatePassword) throws InvalidFormException { @@ -80,6 +82,7 @@ getPollenUserDao().create(result); commit(); + //TODO Notify user created return result; @@ -95,6 +98,7 @@ getPollenUserDao().update(result); commit(); + //TODO Notify user edited return result; @@ -105,6 +109,7 @@ checkNotNull(userId); PollenUser user = getUser(userId); + getPollenUserDao().delete(user); commit(); @@ -112,7 +117,7 @@ public void changePassword(String userId, String oldPassword, - String newPassword) throws UserInvalidPasswordException { + String newPassword) throws PollenInvalidPasswordException { checkNotNull(userId); checkNotNull(oldPassword); @@ -120,15 +125,11 @@ PollenUser user = getUser(userId); - // check current password - String encodedPassword = serviceContext.encodePassword(user.getPassword()); - if (!encodedPassword.equals(user.getPassword())) { - throw new UserInvalidPasswordException(); - } + // check old password + getSecurityService().checkUserPassword(user, oldPassword); - // encode new password and store it in user account - String newEncodedPassword = serviceContext.encodePassword(newPassword); - user.setPassword(newEncodedPassword); + // set new password + getSecurityService().setUserPassword(user, newPassword); getPollenUserDao().update(user); commit(); @@ -137,24 +138,18 @@ } public void validateUserEmail(String userId, - String token) throws UserInvalidEmailActivationTokenException { + String token) throws PollenInvalidEmailActivationTokenException { checkNotNull(userId); checkNotNull(token); PollenUser user = getUser(userId); - boolean valid = Objects.equals( - user.getEmailActivationToken(), token); + getSecurityService().checkUserEmailValidation(user, token); - if (!valid) { - throw new UserInvalidEmailActivationTokenException(); - } - // reset token in database user.setEmailActivationToken(null); - getPollenUserDao().update(user); commit(); } @@ -171,6 +166,7 @@ user.setEmail("admin@pollen.org"); user.setPassword("admin"); createUser(user, false); + } } @@ -209,6 +205,7 @@ if (emailChanged) { check(errors, "email", !dao.emailExists(userEmail), "email already exists"); } + } else { check(errors, "email", !dao.emailExists(userEmail), "email already exists"); } @@ -217,13 +214,18 @@ if (userExists) { // check current password - String encodedPassword = serviceContext.encodePassword(user.getPassword()); - check(errors, "password", encodedPassword.equals(persisted.getPassword()), "invalid password"); + try { + getSecurityService().checkUserPassword(persisted, user.getPassword()); + } catch (PollenInvalidPasswordException e) { + check(errors, "password", false, "invalid password"); + } + } if (!errors.isEmpty()) { throw new InvalidFormException(errors); + } } @@ -232,58 +234,52 @@ boolean userExists = user.isPersisted(); + String cleanMail = getCleanMail(user.getEmail()); + PollenUser toSave; - String userEmail = getCleanMail(user.getEmail()); - - String emailValidationToken = null; - if (userExists) { toSave = getUser(user.getTopiaId()); - boolean emailChanged = ObjectUtils.notEqual(toSave.getEmail(), - userEmail); + boolean emailChanged = !Objects.equals(toSave.getEmail(), cleanMail); if (emailChanged) { - // add a new emailValidationtoken - emailValidationToken = generateToken(); + PollenToken emailActivation = getSecurityService().generateNewToken(); + toSave.setEmailActivationToken(emailActivation); - //TODO Notify email changed } + } else { - toSave = getPollenUserDao().newInstance(); - - // add a emailValidationToken - emailValidationToken = generateToken(); - String password; if (generatePassword) { - // let's generate the new password + password = serviceContext.generatePassword(); + } else { + password = user.getPassword(); + } - // encode the password - String encodedPassword = serviceContext.encodePassword(password); + PollenToken emailActivation = getSecurityService().generateNewToken(); + toSave = getPollenUserDao().newInstance(); toSave.setLogin(user.getLogin()); - toSave.setPassword(encodedPassword); + toSave.setEmailActivationToken(emailActivation); + + getSecurityService().setUserPassword(toSave, password); + } toSave.setAdministrator(user.isAdministrator()); toSave.setName(user.getName()); toSave.setLanguage(user.getLanguage()); - toSave.setEmail(userEmail); + toSave.setEmail(cleanMail); - if (emailValidationToken != null) { - toSave.setEmailActivationToken(emailValidationToken); - } - return toSave; } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -23,13 +23,11 @@ * #L% */ -import com.google.common.base.Preconditions; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import org.chorem.pollen.persistence.entity.Poll; import org.chorem.pollen.persistence.entity.Polls; import org.chorem.pollen.persistence.entity.Vote; -import org.chorem.pollen.services.exception.InvalidFormException; import org.chorem.pollen.services.service.security.PermissionVerb; import java.util.Date; @@ -44,61 +42,74 @@ public class VoteService extends PollenServiceSupport { public List<Vote> getVotes(String pollId) { - Preconditions.checkNotNull(pollId); + checkNotNull(pollId); + Poll poll = getPollService().getPoll(pollId); + List<Vote> result = poll.getVote(); return result; + } public Vote getVote(String pollId, String voteId) { - Preconditions.checkNotNull(voteId); + checkNotNull(voteId); checkPermission(PermissionVerb.readVote, voteId); + Poll poll = getPollService().getPoll(pollId); Vote result = getVote(poll, voteId); return result; + } public Vote addVote(String pollId, Vote vote) throws InvalidFormException { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(vote); + + checkNotNull(pollId); + checkNotNull(vote); checkIsNotPersisted(vote); checkPermission(PermissionVerb.addVote, pollId); Poll poll = getPollService().getPoll(pollId); + checkVoteForm(poll, vote); Vote result = saveVote(poll, vote); getPollDao().update(poll); commit(); + //TODO Notify vote added return result; + } public Vote editVote(String pollId, Vote vote) throws InvalidFormException { - Preconditions.checkNotNull(vote); + + checkNotNull(vote); checkIsPersisted(vote); checkPermission(PermissionVerb.editVote, vote.getTopiaId()); Poll poll = getPollService().getPoll(pollId); + checkVoteForm(poll, vote); Vote result = saveVote(poll, vote); getVoteDao().update(vote); commit(); + //TODO Notify vote edited return result; + } public void deleteVote(String pollId, String voteId) { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(voteId); + checkNotNull(pollId); + checkNotNull(voteId); checkPermission(PermissionVerb.deleteVote, voteId); Poll poll = getPollService().getPoll(pollId); @@ -110,6 +121,7 @@ getPollDao().update(poll); commit(); //TODO Notify vote deleted + } protected void checkVoteForm(Poll poll, Vote vote) throws InvalidFormException { @@ -132,7 +144,9 @@ if (!errors.isEmpty()) { throw new InvalidFormException(errors); + } + } protected Vote saveVote(Poll poll, Vote vote) { @@ -168,13 +182,20 @@ // } return toSave; + } protected Vote getVote(Poll poll, String voteId) { - Preconditions.checkNotNull(voteId); - Vote result = poll.getVoteByTopiaId(voteId); - checkEntityExists(Vote.class, result, voteId); + Vote result = getVoteDao().findByTopiaId(voteId); + + if (!poll.containsVote(result)) { + + throw new InvalidEntityLinkException(Poll.PROPERTY_VOTE, poll, result); + + } + return result; + } } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -23,7 +23,6 @@ * #L% */ -import com.google.common.base.Preconditions; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; @@ -35,7 +34,6 @@ import org.chorem.pollen.persistence.entity.VoterListMember; import org.chorem.pollen.persistence.entity.VoterListMemberTopiaDao; import org.chorem.pollen.persistence.entity.VoterListTopiaDao; -import org.chorem.pollen.services.exception.InvalidFormException; import java.util.List; import java.util.Set; @@ -50,9 +48,11 @@ public VoterList importFavoriteList(String pollId, String favoriteListId) { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(favoriteListId); + checkIsConnected(); + checkNotNull(pollId); + checkNotNull(favoriteListId); + Poll poll = getPollService().getPoll(pollId); FavoriteList favoriteList = getFavoriteListService().getFavoriteList(favoriteListId); @@ -78,62 +78,77 @@ getPollDao().update(poll); commit(); + return result; + } public List<VoterList> getVoterLists(String pollId) { - Preconditions.checkNotNull(pollId); + checkNotNull(pollId); + Poll poll = getPollService().getPoll(pollId); List<VoterList> result = Lists.newArrayList(poll.getVoterList()); return result; + } public VoterList getVoterList(String pollId, String voterListId) { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(voterListId); + checkNotNull(pollId); + checkNotNull(voterListId); + Poll poll = getPollService().getPoll(pollId); VoterList result = getVoterList(poll, voterListId); return result; + } public VoterList addVoterList(String pollId, VoterList voterList) throws InvalidFormException { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(voterList); + + checkNotNull(pollId); + checkNotNull(voterList); checkIsNotPersisted(voterList); Poll poll = getPollService().getPoll(pollId); - checkVoterList(poll, voterList); + checkVoterListForm(poll, voterList); + VoterList result = saveVoterList(poll, voterList); getPollDao().update(poll); commit(); + return result; + } public VoterList editVoterList(String pollId, VoterList voterList) throws InvalidFormException { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(voterList); + + checkNotNull(pollId); + checkNotNull(voterList); checkIsPersisted(voterList); Poll poll = getPollService().getPoll(pollId); - checkVoterList(poll, voterList); + checkVoterListForm(poll, voterList); + VoterList result = saveVoterList(poll, voterList); getVoterListDao().update(voterList); commit(); + return result; + } public void deleteVoterList(String pollId, String voterListId) { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(voterListId); + checkNotNull(pollId); + checkNotNull(voterListId); + Poll poll = getPollService().getPoll(pollId); VoterList voterList = getVoterList(poll, voterListId); @@ -142,98 +157,121 @@ getPollDao().update(poll); commit(); + } public Set<VoterListMember> getVoterListMembers(String pollId, String voterListId) { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(voterListId); + checkNotNull(pollId); + checkNotNull(voterListId); + VoterList voterList = getVoterList(pollId, voterListId); Set<VoterListMember> result = voterList.getMember(); return result; + } public VoterListMember getVoterListMember(String pollId, String voterListId, String memberId) { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(voterListId); - Preconditions.checkNotNull(memberId); + checkNotNull(pollId); + checkNotNull(voterListId); + checkNotNull(memberId); + VoterList voterList = getVoterList(pollId, voterListId); VoterListMember result = getVoterListMember(voterList, memberId); - checkEntityExists(VoterListMember.class, result, memberId); + return result; + } public VoterListMember addVoterListMember(String pollId, String voterListId, VoterListMember member) throws InvalidFormException { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(voterListId); - Preconditions.checkNotNull(member); + + checkNotNull(pollId); + checkNotNull(voterListId); + checkNotNull(member); checkIsNotPersisted(member); VoterList voterList = getVoterList(pollId, voterListId); - checkVoterListMember(voterList, member); + checkVoterListMemberForm(voterList, member); VoterListMember result = saveVoterListMember(voterList, member); getVoterListDao().update(voterList); commit(); + return result; + } public VoterListMember editVoterListMember(String pollId, String voterListId, VoterListMember member) throws InvalidFormException { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(voterListId); - Preconditions.checkNotNull(member); + + checkNotNull(pollId); + checkNotNull(voterListId); + checkNotNull(member); checkIsPersisted(member); VoterList voterList = getVoterList(pollId, voterListId); - checkVoterListMember(voterList, member); + checkVoterListMemberForm(voterList, member); VoterListMember result = saveVoterListMember(voterList, member); getVoterListMemberDao().update(member); commit(); + return result; + } public void deleteVoterListMember(String pollId, String voterListId, String memberId) { - Preconditions.checkNotNull(pollId); - Preconditions.checkNotNull(voterListId); - Preconditions.checkNotNull(memberId); + checkNotNull(pollId); + checkNotNull(voterListId); + checkNotNull(memberId); + VoterList voterList = getVoterList(pollId, voterListId); VoterListMember member = getVoterListMember(voterList, memberId); voterList.removeMember(member); -// getVoterListDao().merge(voterList); + commit(); - commit(); } protected VoterList getVoterList(Poll poll, String voterListId) { - VoterList result = poll.getVoterListByTopiaId(voterListId); - checkEntityExists(VoterList.class, result, voterListId); + VoterList result = getVoterListDao().findByTopiaId(voterListId); + + if (!poll.containsVoterList(result)) { + + throw new InvalidEntityLinkException(Poll.PROPERTY_VOTER_LIST, poll, result); + + } + return result; + } protected VoterListMember getVoterListMember(VoterList voterList, String memberId) { - Preconditions.checkNotNull(memberId); - VoterListMember result = voterList.getMemberByTopiaId(memberId); - checkEntityExists(VoterListMember.class, result, memberId); + VoterListMember result = getVoterListMemberDao().findByTopiaId(memberId); + + if (!voterList.containsMember(result)) { + + throw new InvalidEntityLinkException(VoterList.PROPERTY_MEMBER, voterList, result); + + } + return result; + } protected VoterList saveVoterList(Poll poll, VoterList voterList) { - boolean voterListExists = voterList.isPersisted(); VoterList toSave; @@ -241,12 +279,13 @@ if (voterListExists) { toSave = getVoterList(poll, voterList.getTopiaId()); + } else { - VoterListTopiaDao voterListDao = - getVoterListDao(); - toSave = voterListDao.newInstance(); + toSave = getVoterListDao().newInstance(); + poll.addVoterList(toSave); + } toSave.setName(voterList.getName()); @@ -255,9 +294,11 @@ for (VoterListMember voterListMember : voterList.getMember()) { saveVoterListMember(toSave, voterListMember); + } return toSave; + } protected VoterListMember saveVoterListMember(VoterList voterList, @@ -270,14 +311,13 @@ if (voterListMemberExists) { toSave = getVoterListMember(voterList, voterListMember.getTopiaId()); + } else { - VoterListMemberTopiaDao voterListMemberDao = - getVoterListMemberDao(); + toSave = getVoterListMemberDao().newInstance(); - toSave = voterListMemberDao.newInstance(); + voterList.addMember(toSave); - voterList.addMember(toSave); } toSave.setName(voterListMember.getName()); @@ -285,9 +325,10 @@ toSave.setWeight(voterListMember.getWeight()); return toSave; + } - protected void checkVoterList(Poll poll, VoterList voterList) throws InvalidFormException { + protected void checkVoterListForm(Poll poll, VoterList voterList) throws InvalidFormException { //TODO use nuiton validator ? Multimap<String, String> errors = ArrayListMultimap.create(); @@ -307,7 +348,9 @@ } voterListNames.add(voterList.getName()); + } + } checkNotBlank(errors, "name", voterList.getName(), "voterList name can not be empty"); @@ -344,16 +387,19 @@ checkValidEmail(errors, voterListMemberField + "email", voterListMemberEmail, "member email is not valid"); boolean emailAdded = voterListMemberEmails.add(voterListMemberEmail); check(errors, voterListMemberField + "email", emailAdded, "member email already used in this list"); + } } if (!errors.isEmpty()) { throw new InvalidFormException(errors); + } + } - protected void checkVoterListMember(VoterList voterList, VoterListMember voterListMember) throws InvalidFormException { + protected void checkVoterListMemberForm(VoterList voterList, VoterListMember voterListMember) throws InvalidFormException { //TODO use nuiton validator ? Multimap<String, String> errors = ArrayListMultimap.create(); @@ -375,7 +421,9 @@ voterListMemberNames.add(voterListMember.getName()); voterListMemberEmails.add(voterListMember.getEmail()); + } + } String voterListMemberName = voterListMember.getName(); boolean nameNotblank = checkNotBlank(errors, "name", voterListMemberName, "member name can not be empty"); @@ -394,11 +442,14 @@ checkValidEmail(errors, "email", voterListMemberEmail, "member email is not valid"); boolean emailAdded = voterListMemberEmails.add(voterListMemberEmail); check(errors, "email", emailAdded, "member email already used in this list"); + } if (!errors.isEmpty()) { throw new InvalidFormException(errors); + } + } } Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenAuthenticationException.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenAuthenticationException.java (rev 0) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenAuthenticationException.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -0,0 +1,16 @@ +package org.chorem.pollen.services.service.security; + +/** + * Created on 5/4/14. + * + * @author Tony Chemit <chemit@codelutin.com> + * @since 2.0 + */ +public class PollenAuthenticationException extends Exception { + + private static final long serialVersionUID = 1L; + + public PollenAuthenticationException(Exception e) { + super(e); + } +} Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenAuthenticationException.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Copied: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenInvalidEmailActivationTokenException.java (from rev 3895, trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserInvalidEmailActivationTokenException.java) =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenInvalidEmailActivationTokenException.java (rev 0) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenInvalidEmailActivationTokenException.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -0,0 +1,34 @@ +package org.chorem.pollen.services.service.security; + +/* + * #%L + * Pollen :: Service + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2009 - 2013 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + +/** + * TODO + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class PollenInvalidEmailActivationTokenException extends Exception { + private static final long serialVersionUID = 1L; +} Copied: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenInvalidPasswordException.java (from rev 3895, trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserInvalidPasswordException.java) =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenInvalidPasswordException.java (rev 0) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenInvalidPasswordException.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -0,0 +1,34 @@ +package org.chorem.pollen.services.service.security; + +/* + * #%L + * Pollen :: Service + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2009 - 2013 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + +/** + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class PollenInvalidPasswordException extends Exception { + + private static final long serialVersionUID = 1L; + +} Copied: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenInvalidSessionTokenException.java (from rev 3895, trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidSessionTokenException.java) =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenInvalidSessionTokenException.java (rev 0) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenInvalidSessionTokenException.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -0,0 +1,35 @@ +package org.chorem.pollen.services.service.security; + +/* + * #%L + * Pollen :: Service + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2009 - 2013 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ + +/** + * TODO + * + * @author tchemit <chemit@codelutin.com> + * @since 2.0 + */ +public class PollenInvalidSessionTokenException extends Exception { + + private static final long serialVersionUID = 1L; +} Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenSecurityRealm.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenSecurityRealm.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/PollenSecurityRealm.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -28,19 +28,14 @@ import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.chorem.pollen.persistence.PollenTopiaPersistenceContext; import org.chorem.pollen.services.PollenApplicationContext; -import org.chorem.pollen.services.PollenServiceContext; -import org.chorem.pollen.services.exception.EntityNotFoundException; -import org.chorem.pollen.services.exception.UserInvalidPasswordException; -import org.chorem.pollen.services.service.AuthService; -import java.util.Locale; - /** * TODO * <p/> @@ -51,10 +46,19 @@ */ public class PollenSecurityRealm extends AuthorizingRealm { - protected PollenApplicationContext applicationContext; + public static final String REALM_NAME = "pollenRealm"; - public void setApplicationContext(PollenApplicationContext applicationContext) { + protected final PollenApplicationContext applicationContext; + + public PollenSecurityRealm(PollenApplicationContext applicationContext) { + this.applicationContext = applicationContext; + + String hashAlgorithmName = applicationContext.getApplicationConfig().getHashAlgorithmName(); + HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(hashAlgorithmName); + matcher.setStoredCredentialsHexEncoded(false); + setCredentialsMatcher(matcher); + } @Override @@ -72,21 +76,20 @@ UsernamePasswordToken upToken = (UsernamePasswordToken) token; String username = upToken.getUsername(); - char[] password = upToken.getPassword(); + PollenTopiaPersistenceContext persistenceContext = applicationContext.newPersistenceContext(); try { - PollenServiceContext serviceContext = applicationContext.newServiceContext(persistenceContext, Locale.FRANCE); - AuthService authService = serviceContext.newService(AuthService.class); - try { - authService.login(username, new String(password)); - } catch (EntityNotFoundException e) { - throw new AuthenticationException(e); - } catch (UserInvalidPasswordException e) { - throw new AuthenticationException(e); + boolean loginExists = persistenceContext.getPollenUserDao().loginExists(username); + + if (!loginExists) { + throw new AuthenticationException(); } + + char[] password = upToken.getPassword(); + SimpleAuthenticationInfo result = new SimpleAuthenticationInfo(username, password, getName()); return result; Deleted: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityRole.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityRole.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityRole.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -1,33 +0,0 @@ -package org.chorem.pollen.services.service.security; - -/* - * #%L - * Pollen :: Service - * %% - * Copyright (C) 2009 - 2014 CodeLutin - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * #L% - */ - -/** - * Created on 5/1/14. - * - * @author Tony Chemit <chemit@codelutin.com> - * @since 2.0 - */ -public enum SecurityRole { - connected, - administrator -} Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -28,6 +28,8 @@ import com.google.common.collect.Sets; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.SimplePrincipalCollection; import org.apache.shiro.subject.Subject; import org.chorem.pollen.persistence.entity.Choice; @@ -36,16 +38,17 @@ import org.chorem.pollen.persistence.entity.Poll; import org.chorem.pollen.persistence.entity.PollenPrincipal; import org.chorem.pollen.persistence.entity.PollenPrincipalTopiaDao; +import org.chorem.pollen.persistence.entity.PollenToken; +import org.chorem.pollen.persistence.entity.PollenTokenTopiaDao; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.persistence.entity.SessionToken; import org.chorem.pollen.persistence.entity.Vote; -import org.chorem.pollen.services.PollenTechnicalException; -import org.chorem.pollen.services.exception.InvalidSessionTokenException; import org.chorem.pollen.services.service.PollenServiceSupport; import org.nuiton.topia.persistence.TopiaEntity; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; /** @@ -59,23 +62,79 @@ /** Logger. */ private static final Log log = LogFactory.getLog(SecurityService.class); + public PollenUser login(String login, String password, Boolean rememberMe) throws PollenAuthenticationException { + + Subject subject = getSubject(); + UsernamePasswordToken token = new UsernamePasswordToken(login, password); + token.setRememberMe(rememberMe); + + try { + subject.login(token); + } catch (AuthenticationException e) { + throw new PollenAuthenticationException(e); + } + + PollenUser user = getUserService().getUserByLogin(login); + return user; + + } + + public SessionToken logout() { + + SessionToken sessionToken = serviceContext.getSecurityContext().getSessionToken(); + + if (sessionToken != null) { + Subject subject = getSecurityService().getSubject(); + subject.logout(); + } + + return sessionToken; + + } + + public PollenToken generateNewToken() { + + PollenTokenTopiaDao dao = getPersistenceContext().getPollenTokenDao(); + + // Create instance + PollenToken pollenToken = dao.newInstance(); + pollenToken.setCreationDate(serviceContext.getNow()); + + // Generate token + String token = serviceContext.generateToken(); + pollenToken.setToken(token); + + // Persist + pollenToken = dao.create(pollenToken); + + return pollenToken; + + } + public PollenPrincipal generatePollenPrincipal() { - PollenPrincipalTopiaDao pollenPrincipalDao = getPersistenceContext().getPollenPrincipalDao(); - PollenPrincipal principal = pollenPrincipalDao.newInstance(); - principal.setCreationDate(serviceContext.getNow()); - pollenPrincipalDao.create(principal); + PollenPrincipalTopiaDao dao = getPersistenceContext().getPollenPrincipalDao(); + + // Create instance + PollenPrincipal principal = dao.newInstance(); + + // Generate token + PollenToken token = generateNewToken(); + principal.setToken(token); + + // Persist + dao.create(principal); return principal; } - public SessionToken getSessionTokenByToken(String token) throws InvalidSessionTokenException { + public SessionToken getSessionTokenByToken(String token) throws PollenInvalidSessionTokenException { SessionToken sessionToken = null; if (token != null) { - sessionToken = getSessionTokenDao().forTokenEquals(token).findUniqueOrNull(); + sessionToken = getSessionTokenDao().findUniqueOrNullByToken(token); if (sessionToken == null) { - throw new InvalidSessionTokenException(); + throw new PollenInvalidSessionTokenException(); } } return sessionToken; @@ -86,44 +145,62 @@ PollenPrincipal principal = null; if (principalId != null) { - principal = getPollenPrincipalDao().forTopiaIdEquals(principalId).findUniqueOrNull(); - checkEntityExists(PollenPrincipal.class, principal, principalId); + principal = getPollenPrincipalDao().findByTopiaId(principalId); } return principal; } + public void setUserPassword(PollenUser user, String newPassword) { + + String salt = serviceContext.generateSalt(); + + String encodedPassword = serviceContext.encodePassword(salt, newPassword); + + user.setSalt(salt); + user.setPassword(encodedPassword); + } + public String createPermission(PermissionVerb verb, String id) { return ":" + verb.name() + ":" + id; } - public void checkRole(SecurityRole roleName) { + public void checkUserPassword(PollenUser user, String password) throws PollenInvalidPasswordException { - checkNotNull(roleName); + String encodedPassword = serviceContext.encodePassword(user.getSalt(), password); + boolean valid = Objects.equals(encodedPassword, user.getPassword()); + if (!valid) { + throw new PollenInvalidPasswordException(); + } - PollenSecurityContext securityContext = serviceContext.getSecurityContext(); - switch (roleName) { + } - case connected: + public void checkUserEmailValidation(PollenUser user, String emailToken) throws PollenInvalidEmailActivationTokenException { - if (!securityContext.isConnected()) { - throw new PollenUnauthorizedException("connected"); - } - break; + boolean valid = Objects.equals(user.getEmailActivationToken().getToken(), emailToken); - case administrator: + if (!valid) { + throw new PollenInvalidEmailActivationTokenException(); + } - if (!securityContext.isAdmin()) { - throw new PollenUnauthorizedException("administrator"); - } - break; + } - default: + public void checkIsConnected() { - throw new PollenTechnicalException("can't handler security role: " + roleName); + PollenSecurityContext securityContext = getSecurityContext(); + if (!securityContext.isConnected()) { + throw new PollenUnauthorizedException("connected"); + } + } + + public void checkIsAdmin() { + + PollenSecurityContext securityContext = getSecurityContext(); + if (!securityContext.isAdmin()) { + throw new PollenUnauthorizedException("administrator"); } } @@ -146,7 +223,7 @@ protected Subject getSubject() { - PollenSecurityContext securityContext = serviceContext.getSecurityContext(); + PollenSecurityContext securityContext = getSecurityContext(); Preconditions.checkNotNull(securityContext); Subject subject = securityContext.getSubject(); @@ -162,7 +239,7 @@ // Create Subject SimplePrincipalCollection principalCollection = new SimplePrincipalCollection(); - principalCollection.addAll(permissions, "pollenRealm"); + principalCollection.addAll(permissions, PollenSecurityRealm.REALM_NAME); subject = new Subject. Builder(). authenticated(securityContext.isConnected()). Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenApplicationContext.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenApplicationContext.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenApplicationContext.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -61,41 +61,31 @@ /** Logger. */ private static final Log log = LogFactory.getLog(FakePollenApplicationContext.class); - private File testBasedir; + protected static AtomicInteger portNumberCounter = new AtomicInteger(9999); + protected File testBasedir; + protected List<PollenTopiaPersistenceContext> openedTransactions = new LinkedList<>(); - private PollenTopiaApplicationContext applicationContext; + protected PollenTopiaApplicationContext applicationContext; - private PollenServiceConfig configuration; + protected PollenServiceConfig configuration; - private final String configurationPath; - protected PollenFixtures fixtures; protected String methodName; - protected static AtomicInteger portNumberCounter = new AtomicInteger(9999); - protected int currentPortNumber; + protected final String configurationPath; + public FakePollenApplicationContext(String configurationPath) { this.configurationPath = configurationPath; } - public int getPort() { - return currentPortNumber; - } - @Override protected void starting(Description description) { - PollenSecurityRealm realm = new PollenSecurityRealm(); - realm.setApplicationContext(this); - - DefaultSecurityManager securityManager = new DefaultSecurityManager(realm); - SecurityUtils.setSecurityManager(securityManager); - currentPortNumber = portNumberCounter.getAndIncrement(); methodName = description.getMethodName(); @@ -109,20 +99,42 @@ log.debug("testBasedir: " + testBasedir); } - // create configuration + init(); + } + + @Override + public void finished(Description description) { + + close(); + } + + @Override + public void init() { + + // --- create configuration --- // + Properties defaultvalues = new Properties(); defaultvalues.put(PollenServiceConfigOption.DATA_DIRECTORY.getKey(), testBasedir.getAbsolutePath()); configuration = new PollenServiceConfig(configurationPath, defaultvalues); + // --- create topia application context --- // + Map<String, String> topiaProperties = configuration.getTopiaProperties(); applicationContext = new PollenTopiaApplicationContext(topiaProperties); + // --- create security context --- // + + PollenSecurityRealm realm = new PollenSecurityRealm(this); + + DefaultSecurityManager securityManager = new DefaultSecurityManager(realm); + SecurityUtils.setSecurityManager(securityManager); + } @Override - public void finished(Description description) { + public void close() { if (applicationContext != null && !applicationContext.isClosed()) { @@ -145,10 +157,6 @@ } } - public File getTestBasedir() { - return testBasedir; - } - @Override public PollenTopiaApplicationContext getTopiaApplicationContext() { return applicationContext; @@ -191,12 +199,22 @@ @Override public FakePollenSecurityContext newSecurityContext(SessionToken sessionToken, PollenPrincipal mainPrincipal) { + FakePollenSecurityContext securityContext = new FakePollenSecurityContext(); securityContext.setMainPrincipal(mainPrincipal); securityContext.setSessionToken(sessionToken); return securityContext; + } + public File getTestBasedir() { + return testBasedir; + } + + public int getPort() { + return currentPortNumber; + } + public String getMethodName() { return methodName; } Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenSecurityContext.java =================================================================== --- trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenSecurityContext.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/test/FakePollenSecurityContext.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -21,7 +21,6 @@ * #L% */ -import org.apache.shiro.subject.Subject; import org.chorem.pollen.services.service.security.DefaultPollenSecurityContext; /** @@ -44,9 +43,4 @@ return false; } - @Override - public void setSubject(Subject subject) { - this.subject = subject; - } - } Modified: trunk/pollen-services/src/test/java/org/chorem/pollen/service/AbstractPollenServiceTest.java =================================================================== --- trunk/pollen-services/src/test/java/org/chorem/pollen/service/AbstractPollenServiceTest.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/test/java/org/chorem/pollen/service/AbstractPollenServiceTest.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -25,7 +25,7 @@ import com.google.common.collect.Multimap; import org.chorem.pollen.services.PollenService; -import org.chorem.pollen.services.exception.InvalidFormException; +import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.test.FakePollenApplicationContext; import org.chorem.pollen.services.test.FakePollenServiceContext; import org.junit.Assert; Modified: trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java =================================================================== --- trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -29,7 +29,7 @@ import org.chorem.pollen.persistence.entity.PollType; import org.chorem.pollen.persistence.entity.VoterList; import org.chorem.pollen.persistence.entity.VoterListMember; -import org.chorem.pollen.services.exception.InvalidFormException; +import org.chorem.pollen.services.service.InvalidFormException; import org.chorem.pollen.services.service.ChoiceService; import org.chorem.pollen.services.service.PollService; import org.chorem.pollen.services.service.VoterListService; Modified: trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollenUserServiceTest.java =================================================================== --- trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollenUserServiceTest.java 2014-05-04 16:40:00 UTC (rev 3905) +++ trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollenUserServiceTest.java 2014-05-04 21:39:22 UTC (rev 3906) @@ -26,13 +26,13 @@ import org.apache.commons.collections4.CollectionUtils; import org.chorem.pollen.persistence.entity.PollenUser; import org.chorem.pollen.persistence.entity.PollenUsers; -import org.chorem.pollen.services.exception.EntityNotFoundException; -import org.chorem.pollen.services.exception.InvalidFormException; -import org.chorem.pollen.services.exception.UserInvalidEmailActivationTokenException; +import org.chorem.pollen.services.service.InvalidFormException; +import org.chorem.pollen.services.service.security.PollenInvalidEmailActivationTokenException; import org.chorem.pollen.services.service.PollenUserService; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.nuiton.topia.persistence.TopiaNoResultException; import java.text.ParseException; import java.util.Date; @@ -77,7 +77,7 @@ try { service.getUser("pollen_user_tony_" + System.nanoTime()); - } catch (EntityNotFoundException e) { + } catch (TopiaNoResultException e) { Assert.assertTrue(true); } @@ -167,7 +167,7 @@ } @Test - public void testValidateEmail() throws UserInvalidEmailActivationTokenException, InvalidFormException { + public void testValidateEmail() throws PollenInvalidEmailActivationTokenException, InvalidFormException { PollenUser user = service.getUser(this.user.getTopiaId()); Assert.assertNotNull(user); @@ -188,13 +188,13 @@ try { service.validateUserEmail(user.getTopiaId(), "fakeToken"); Assert.fail(); - } catch (UserInvalidEmailActivationTokenException e) { + } catch (PollenInvalidEmailActivationTokenException e) { Assert.assertTrue(true); } Assert.assertFalse(PollenUsers.isEmailActivated(savedUser)); - service.validateUserEmail(user.getTopiaId(), savedUser.getEmailActivationToken()); + service.validateUserEmail(user.getTopiaId(), savedUser.getEmailActivationToken().getToken()); PollenUser reloadedUser = service.getUser(this.user.getTopiaId()); Assert.assertTrue(PollenUsers.isEmailActivated(reloadedUser));
participants (1)
-
tchemit@users.chorem.org