01/01: Add sessionToken remove logic
This is an automated email from the git hooks/post-receive script. unknown user pushed a commit to branch devel in repository Pollen. commit 81f36845f028bb9d71f8c1a82d62176b6c4fd2db Author: Tony CHEMIT <chemit@codelutin.com> Date: Wed May 21 15:17:30 2014 +0200 Add sessionToken remove logic --- .../persistence/entity/SessionTokenTopiaDao.java | 17 +++ pollen-persistence/src/main/xmi/pollen.properties | 5 + .../org/chorem/pollen/rest/api/v1/AuthApi.java | 14 +-- .../services/config/PollenServiceConfig.java | 6 ++ .../services/config/PollenServiceConfigOption.java | 15 ++- .../pollen/services/service/AuthService.java | 93 ----------------- .../pollen/services/service/PollService.java | 2 +- .../services/service/PollenServiceSupport.java | 4 - .../services/service/security/SecurityService.java | 115 +++++++++++++++++++-- .../i18n/pollen-services_en_GB.properties | 2 +- .../i18n/pollen-services_fr_FR.properties | 2 +- 11 files changed, 157 insertions(+), 118 deletions(-) diff --git a/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/SessionTokenTopiaDao.java b/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/SessionTokenTopiaDao.java index 0670108..b0b3168 100644 --- a/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/SessionTokenTopiaDao.java +++ b/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/SessionTokenTopiaDao.java @@ -21,6 +21,13 @@ package org.chorem.pollen.persistence.entity; * #L% */ +import com.google.common.collect.ImmutableSet; +import org.nuiton.topia.persistence.HqlAndParametersBuilder; + +import java.util.Date; +import java.util.List; +import java.util.Set; + public class SessionTokenTopiaDao extends AbstractSessionTokenTopiaDao<SessionToken> { public SessionToken findUniqueOrNullByToken(String token) { @@ -29,4 +36,14 @@ public class SessionTokenTopiaDao extends AbstractSessionTokenTopiaDao<SessionTo return sessionToken; } + + public Set<SessionToken> findAllBeforeEndDate(Date now) { + + HqlAndParametersBuilder<SessionToken> builder = newHqlAndParametersBuilder(); + builder.addLowerThan(SessionToken.PROPERTY_POLLEN_TOKEN + "." + PollenToken.PROPERTY_END_DATE, now); + + List<SessionToken> sessionTokens = findAll(builder.getHql(), builder.getHqlParameters()); + return ImmutableSet.copyOf(sessionTokens); + + } } diff --git a/pollen-persistence/src/main/xmi/pollen.properties b/pollen-persistence/src/main/xmi/pollen.properties index d57e84a..306e907 100644 --- a/pollen-persistence/src/main/xmi/pollen.properties +++ b/pollen-persistence/src/main/xmi/pollen.properties @@ -35,6 +35,11 @@ org.chorem.pollen.persistence.entity.PollenUser.attribute.favoriteList.stereotyp org.chorem.pollen.persistence.entity.FavoriteList.attribute.member.stereotype=ordered, unique org.chorem.pollen.persistence.entity.VoterList.attribute.member.stereotype=unique +# clef naturelle non modifiable sur PollenToken.token +org.chorem.pollen.persistence.entity.PollenToken.class.tagValue.naturalIdMutable=true +org.chorem.pollen.persistence.entity.PollenToken.attribute.token.stereotype=unique +org.chorem.pollen.persistence.entity.PollenToken.attribute.token.tagValue.naturalId=true + # clef naturelle non modifiable sur Poll#pollId #org.chorem.pollen.persistence.entity.Poll.class.tagValue.naturalIdMutable=true #org.chorem.pollen.persistence.entity.Poll.attribute.pollId.stereotype=unique diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java index 02ed7fd..8b8be04 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthApi.java @@ -24,8 +24,8 @@ package org.chorem.pollen.rest.api.v1; */ import org.chorem.pollen.services.bean.CreateBeanRef; -import org.chorem.pollen.services.service.AuthService; import org.chorem.pollen.services.service.security.PollenAuthenticationException; +import org.chorem.pollen.services.service.security.SecurityService; import org.debux.webmotion.server.WebMotionController; /** @@ -36,22 +36,22 @@ import org.debux.webmotion.server.WebMotionController; */ public class AuthApi extends WebMotionController { - public CreateBeanRef login(AuthService authService, String login, String password, Boolean rememberMe) throws PollenAuthenticationException { + public CreateBeanRef login(SecurityService securityService, String login, String password, Boolean rememberMe) throws PollenAuthenticationException { - CreateBeanRef principalRef = authService.login(login, password, rememberMe); + CreateBeanRef principalRef = securityService.login(login, password, rememberMe); return principalRef; } - public void logout(AuthService authService) { + public void logout(SecurityService securityService) { - authService.logout(); + securityService.logout(); } - public void lostPassword(AuthService authService, String login) { + public void lostPassword(SecurityService securityService, String login) { - authService.lostPassword(login); + securityService.lostPassword(login); } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java b/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java index 2c866ef..7fd20d9 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java @@ -164,6 +164,12 @@ public class PollenServiceConfig { return result; } + public int getSessionTimeoutDelay() { + int result = applicationConfig.getOptionAsInt( + PollenServiceConfigOption.SESSION_TIMEOUT_DELAY.key); + return result; + } + /** * @return Le nom d'hôte du serveur SMTP. */ diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfigOption.java b/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfigOption.java index f115595..89d79cd 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfigOption.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfigOption.java @@ -119,6 +119,17 @@ public enum PollenServiceConfigOption implements ConfigOptionDef { ChoiceType.TEXT.name(), ChoiceType.class), + /** + * Default poll choice type to use at a new choice creation. + * + * @since 2.0 + */ + SESSION_TIMEOUT_DELAY( + "pollen.default.sessionTimeoutDelay", + n("pollen.configuration.sessionTimeoutDelay"), + "3600", // 1 hour = 3600s + int.class), + SMTP_HOST( "pollen.smtp.host", "Nom d'hôte du serveur SMTP", @@ -138,11 +149,13 @@ public enum PollenServiceConfigOption implements ConfigOptionDef { "pollen.devMode", "Mode développement, court-circuite l'envoi de mail", "true", Boolean.class), + LOG_CONFIGURATION_FILE( "logConfigurationFile", "Chemin vers le fichier de configuration des journaux", null, - String.class),; + String.class), + ; protected final String key; diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java deleted file mode 100644 index 7ede0de..0000000 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/AuthService.java +++ /dev/null @@ -1,93 +0,0 @@ -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.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.services.bean.CreateBeanRef; -import org.chorem.pollen.services.service.security.PollenAuthenticationException; - -/** - * TODO - * - * @author tchemit <chemit@codelutin.com> - * @since 2.0 - */ -public class AuthService extends PollenServiceSupport { - - /** Logger. */ - private static final Log log = LogFactory.getLog(AuthService.class); - - public CreateBeanRef login(String login, String password, Boolean rememberMe) throws PollenAuthenticationException { - - // Log-in user - PollenUser user = getSecurityService().login(login, password, rememberMe); - - // Generate a token - PollenToken pollenToken = getSecurityService().generateNewToken(); - - // Create session Token - SessionToken sessionToken = getSessionTokenDao().create( - SessionToken.PROPERTY_POLLEN_TOKEN, pollenToken, - SessionToken.PROPERTY_POLLEN_USER, user); - commit(); - - CreateBeanRef createBeanRef = new CreateBeanRef(); - createBeanRef.fromEntity(sessionToken); - return createBeanRef; - - } - - public void logout() { - - SessionToken sessionToken = getSecurityService().logout(); - if (sessionToken != null) { - - getSessionTokenDao().delete(sessionToken); - commit(); - - } - - } - - public void lostPassword(String login) { - - Preconditions.checkNotNull(login); - - PollenUser user = getPollenUserDao().forLoginEquals(login).findUnique(); - - String newPassword = serviceContext.generatePassword(); - - getSecurityService().setUserPassword(user, newPassword); - commit(); - - getNotificationService().onUserLostPasswordAsked(user, newPassword); - - } - -} diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java index 6adebc3..1530eb1 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java @@ -343,7 +343,7 @@ public class PollService extends PollenServiceSupport { ErrorMap errors = new ErrorMap(); checkNotNull(errors, Poll.PROPERTY_POLL_TYPE, poll.getPollType(), l(getLocale(), "pollen.error.poll.pollType.mandatory")); - checkNotNull(errors, Poll.PROPERTY_COMMENT_VISIBILITY, poll.getCommentVisibility(), l(getLocale(), "pollen.error.poll.pollType.mandatory commentVisibility")); + checkNotNull(errors, Poll.PROPERTY_COMMENT_VISIBILITY, poll.getCommentVisibility(), l(getLocale(), "pollen.error.poll.commentVisibility.mandatory")); checkNotNull(errors, Poll.PROPERTY_VOTE_VISIBILITY, poll.getVoteVisibility(), l(getLocale(), "pollen.error.poll.voteVisibility.mandatory")); checkNotNull(errors, Poll.PROPERTY_RESULT_VISIBILITY, poll.getResultVisibility(), l(getLocale(), "pollen.error.poll.resultVisibility.mandatory")); checkNotNull(errors, Poll.PROPERTY_VOTE_COUNTING_TYPE, poll.getVoteCountingType(), l(getLocale(), "pollen.error.poll.voteCountingType.mandatory")); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java index 219f7b3..6e1d273 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenServiceSupport.java @@ -106,10 +106,6 @@ public abstract class PollenServiceSupport implements PollenService { // -- Services -- // - protected AuthService getAuthService() { - return newService(AuthService.class); - } - public ChoiceService getChoiceService() { return newService(ChoiceService.class); } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java index 46799f8..215eeab 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/security/SecurityService.java @@ -44,9 +44,12 @@ 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.bean.CreateBeanRef; import org.chorem.pollen.services.service.PollenServiceSupport; import org.nuiton.topia.persistence.TopiaEntity; +import java.util.Calendar; +import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -63,7 +66,7 @@ public class SecurityService extends PollenServiceSupport { /** Logger. */ private static final Log log = LogFactory.getLog(SecurityService.class); - public PollenUser login(String login, String password, Boolean rememberMe) throws PollenAuthenticationException { + public CreateBeanRef login(String login, String password, Boolean rememberMe) throws PollenAuthenticationException { Subject subject = getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(login, password); @@ -78,34 +81,77 @@ public class SecurityService extends PollenServiceSupport { } PollenUser user = getPollenUserDao().forLoginEquals(login).findUnique(); - return user; + + // Generate a token + PollenToken pollenToken = generateNewToken(); + + // Set end date (createDate + sessionTimeoutDelay) + Calendar calendar = Calendar.getInstance(); + calendar.setTime(pollenToken.getCreationDate()); + calendar.add(Calendar.SECOND, getPollenServiceConfig().getSessionTimeoutDelay()); + + Date endDate = calendar.getTime(); + pollenToken.setEndDate(endDate); + + + // Create session Token + SessionToken sessionToken = getSessionTokenDao().create( + SessionToken.PROPERTY_POLLEN_TOKEN, pollenToken, + SessionToken.PROPERTY_POLLEN_USER, user); + commit(); + + CreateBeanRef createBeanRef = new CreateBeanRef(); + createBeanRef.fromEntity(sessionToken); + return createBeanRef; } - public SessionToken logout() { + public void logout() { SessionToken sessionToken = serviceContext.getSecurityContext().getSessionToken(); if (sessionToken != null) { Subject subject = getSecurityService().getSubject(); subject.logout(); + + getSessionTokenDao().delete(sessionToken); + commit(); } - return sessionToken; + } + + public void lostPassword(String login) { + + Preconditions.checkNotNull(login); + + PollenUser user = getPollenUserDao().forLoginEquals(login).findUnique(); + + String newPassword = serviceContext.generatePassword(); + + getSecurityService().setUserPassword(user, newPassword); + commit(); + + getNotificationService().onUserLostPasswordAsked(user, newPassword); } - public PollenToken generateNewToken() { + public void deleteObsoleteSessionTokens() { - PollenTokenTopiaDao dao = getPersistenceContext().getPollenTokenDao(); + Set<SessionToken> sessionTokens = getSessionTokenDao().findAllBeforeEndDate(serviceContext.getNow()); + getSessionTokenDao().deleteAll(sessionTokens); + commit(); - // Create instance - PollenToken pollenToken = dao.create(); - pollenToken.setCreationDate(serviceContext.getNow()); + } + + public PollenToken generateNewToken() { // Generate token String token = serviceContext.generateToken(); - pollenToken.setToken(token); + + // Create instance + PollenTokenTopiaDao dao = getPersistenceContext().getPollenTokenDao(); + PollenToken pollenToken = dao.createByNaturalId(token); + pollenToken.setCreationDate(serviceContext.getNow()); return pollenToken; @@ -130,11 +176,60 @@ public class SecurityService extends PollenServiceSupport { SessionToken sessionToken = null; if (token != null) { + sessionToken = getSessionTokenDao().findUniqueOrNullByToken(token); if (sessionToken == null) { throw new PollenInvalidSessionTokenException(); } + + // check that token is still valid + Date endDate = sessionToken.getPollenToken().getEndDate(); + Date now = serviceContext.getNow(); + + if (endDate.before(now)) { + + // expired token + if (log.isDebugEnabled()) { + log.debug(String.format("SessionToken %s delete expired : %s", sessionToken.getPollenToken().getToken(), endDate)); + } + getSessionTokenDao().delete(sessionToken); + commit(); + sessionToken = null; + + } else { + + int sessionTimeout = getPollenServiceConfig().getSessionTimeoutDelay(); + + Calendar calendar = Calendar.getInstance(); + // From now + calendar.setTimeInMillis(now.getTime()); + // add session timeout delay + calendar.add(Calendar.SECOND, sessionTimeout); + // retrieve 5 minutes + calendar.add(Calendar.MINUTE, -5); + + Date minEndDateToUpdate = calendar.getTime(); + + if (minEndDateToUpdate.after(endDate)) { + + // update end date (now + sessionTimeout) + calendar.setTime(now); + calendar.add(Calendar.SECOND, sessionTimeout); + Date newEndDate = calendar.getTime(); + + if (log.isDebugEnabled()) { + log.debug(String.format("SessionToken %s update endDate : %s", sessionToken.getPollenToken().getToken(), newEndDate)); + } + sessionToken.getPollenToken().setEndDate(newEndDate); + + commit(); + + } + + } + } + return sessionToken; } diff --git a/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties b/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties index f91a7cf..15216c2 100644 --- a/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties +++ b/pollen-services/src/main/resources/i18n/pollen-services_en_GB.properties @@ -5,6 +5,7 @@ pollen.configuration.defaultPollResultVisibility=Default Result vsibility used w pollen.configuration.defaultPollType=Default Poll type used when creating a new poll pollen.configuration.defaultPollVoteVisibility=Default Poll vote visibility used when creating a new poll pollen.configuration.defaultVoteCountingType=Default vote counting type used when creating a new poll +pollen.configuration.sessionTimeoutDelay=Inactivity delay before invalidate the session of a user (in seconds) pollen.error.favoriteList.import.csv.already.used.email= pollen.error.favoriteList.import.csv.already.used.name= pollen.error.favoriteList.import.csv.invalid.email= @@ -15,7 +16,6 @@ pollen.error.poll.choice.mandatory=At least a choice is mandatory pollen.error.poll.commentVisibility.mandatory=comment visiblity is mandatory pollen.error.poll.mismatch.freePoll=cant' have a voter list for a free poll pollen.error.poll.pollType.mandatory=poll type is mandatory -pollen.error.poll.pollType.mandatory\ commentVisibility= pollen.error.poll.resultVisibility.mandatory=result visibility is mandatory pollen.error.poll.title.mandatory=title is mandatory pollen.error.poll.unique.voterList.mandatory.for.restrictedPoll=A voter list is mandatory for a restricted poll diff --git a/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties b/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties index c28b780..1d2afbe 100644 --- a/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties +++ b/pollen-services/src/main/resources/i18n/pollen-services_fr_FR.properties @@ -5,6 +5,7 @@ pollen.configuration.defaultPollResultVisibility=Visibilité des résultats par pollen.configuration.defaultPollType=Type de sondage par défaut lors de la création d'un nouveau sondage pollen.configuration.defaultPollVoteVisibility=Visibilité des votes par défaut lors de la création d'un nouveau sondage pollen.configuration.defaultVoteCountingType=Type de dépouillement par défaut lors de la création d'un nouveau sondage +pollen.configuration.sessionTimeoutDelay=Temps autorisé d'inactivité avant d'invalider une session utilisateur (en secondes) pollen.error.favoriteList.import.csv.already.used.email= pollen.error.favoriteList.import.csv.already.used.name= pollen.error.favoriteList.import.csv.invalid.email= @@ -14,7 +15,6 @@ pollen.error.favoriteList.import.ldap.invalid.email= pollen.error.poll.choice.mandatory=Au moins un choix est nécessaire pollen.error.poll.commentVisibility.mandatory=la visibilité des commentaires est obligatoire pollen.error.poll.pollType.mandatory=le type de sondage est obligatoire -pollen.error.poll.pollType.mandatory\ commentVisibility= pollen.error.poll.resultVisibility.mandatory=la visibilité des résultats est obligatoire pollen.error.poll.title.mandatory=le titre du sondage est obligatoire pollen.error.poll.unique.voterList.mandatory.for.restrictedPoll=une liste de votant est obligatoire pour un sondage restreint -- To stop receiving notification emails like this one, please contact Chorem.org SCM administrator <admin+scm@chorem.org>.
participants (1)
-
Chorem.org scm