This is an automated email from the git hooks/post-receive script. New commit to branch feature/151_desinscription in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 17348adb627161ed79d7613d5da7cce332e65d87 Author: Kevin Morin <morin@codelutin.com> Date: Tue Oct 3 10:57:21 2017 +0200 fixes #151 I cannot delete my account --- .../org/chorem/pollen/rest/api/v1/AuthApi.java | 9 +------ .../chorem/pollen/rest/api/v1/PollenUserApi.java | 14 +++++++++-- .../pollen/services/service/PollenUserService.java | 28 +++++++++++++++------- .../services/service/security/SecurityService.java | 2 ++ pollen-ui-riot-js/src/main/web/i18n/en.json | 1 + pollen-ui-riot-js/src/main/web/i18n/fr.json | 1 + .../src/main/web/tag/PollenHeader.tag.html | 2 +- .../src/main/web/tag/UserProfile.tag.html | 16 +++++++++++++ .../src/main/web/tag/popup/ConfirmPopup.tag.html | 23 +++++++++++++++--- 9 files changed, 73 insertions(+), 23 deletions(-) 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 04dc258e..30fcfbc4 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 @@ -227,19 +227,12 @@ public class AuthApi { return getLoginResponseFromPollenUser(serviceContext, securityService, securityContext, userPollenEntityRef); } - //FIXME post ou put et pas get @Path("/logout") @DELETE - public Response logout(@Context SecurityService securityService, - @Context PollenSecurityContext securityContext) { + public Response logout(@Context SecurityService securityService) { securityService.logout(); - - // Remove the session token from security context - securityContext.setSessionToken(null); - return removeAuthCookie(Response.status(Response.Status.NO_CONTENT)).build(); - } @Path("/lostpassword") diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java index d3740082..04fca78e 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserApi.java @@ -40,6 +40,7 @@ import org.chorem.pollen.services.service.PollenUserService; import org.chorem.pollen.services.service.SocialAuthService; import org.chorem.pollen.services.service.security.PollenInvalidEmailActivationTokenException; import org.chorem.pollen.services.service.security.PollenSecurityContext; +import org.chorem.pollen.services.service.security.SecurityService; import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; import javax.servlet.http.HttpServletRequest; @@ -113,11 +114,20 @@ public class PollenUserApi { @Path("/users/{userId}") @DELETE - public void deleteUser(@Context PollenUserService pollenUserService, + public Response deleteUser(@Context PollenUserService pollenUserService, + @Context SecurityService securityService, @PathParam("userId") PollenEntityId<PollenUser> userId, @QueryParam("anonymize") boolean anonymize) { - pollenUserService.deleteUser(userId.getEntityId(), anonymize); + boolean selfDeletion = pollenUserService.deleteUser(userId.getEntityId(), anonymize); + Response.ResponseBuilder responseBuilder; + if (selfDeletion) { + securityService.logout(); + responseBuilder = AuthApi.removeAuthCookie(Response.status(Response.Status.NO_CONTENT)); + } else { + responseBuilder = Response.status(Response.Status.NO_CONTENT); + } + return responseBuilder.build(); } @Path("/users/{userId}") diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java index 9b94f51b..222733b8 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java @@ -49,8 +49,6 @@ import org.nuiton.util.pagination.PaginationOrder; import org.nuiton.util.pagination.PaginationParameter; import org.nuiton.util.pagination.PaginationResult; -import java.io.IOException; -import java.sql.SQLException; import java.util.Date; import java.util.List; import java.util.Objects; @@ -156,10 +154,7 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer checkNotNull(user); checkIsPersisted(user); - PollenUser connectedUser = checkAndGetConnectedUser(); - if (!connectedUser.getTopiaId().equals(user.getEntityId())) { - checkIsAdmin(); - } + checkConnectedUserOrAdmin(user.getEntityId()); ErrorMap errorMap = checkPollenUser(user); errorMap.failIfNotEmpty(); @@ -173,10 +168,9 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer } - public void deleteUser(String userId, boolean anonymize) { + public boolean deleteUser(String userId, boolean anonymize) { - checkNotNull(userId); - checkIsAdmin(); + boolean selfDeletion = checkConnectedUserOrAdmin(userId); PollenUser user = getUser0(userId); @@ -190,6 +184,8 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer getNotificationService().onUserDeleted(user); + return selfDeletion; + } public void changePassword(String oldPassword, @@ -462,4 +458,18 @@ public class PollenUserService extends PollenServiceSupport implements PollenSer protected boolean isPremium(Date premiumTo) { return premiumTo != null && premiumTo.after(getNow()); } + + /** + * @param userId + * @return true if the user id is the one of the connected user + */ + protected boolean checkConnectedUserOrAdmin(String userId) { + checkNotNull(userId); + PollenUser connectedUser = checkAndGetConnectedUser(); + boolean result = connectedUser.getTopiaId().equals(userId); + if (!result) { + checkIsAdmin(); + } + return result; + } } 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 78b2893a..752e606b 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 @@ -199,6 +199,8 @@ public class SecurityService extends PollenServiceSupport { commit(); } + // Remove the session token from security context + getSecurityContext().setSessionToken(null); } public void lostPassword(String login) throws PollenEmailNotValidatedException { diff --git a/pollen-ui-riot-js/src/main/web/i18n/en.json b/pollen-ui-riot-js/src/main/web/i18n/en.json index f3cee7e5..30336511 100644 --- a/pollen-ui-riot-js/src/main/web/i18n/en.json +++ b/pollen-ui-riot-js/src/main/web/i18n/en.json @@ -420,6 +420,7 @@ "userProfile_deleteAvatarMessage": "Remove your avatar?", "userProfile_fileSizeMax_message": "File \"{0}\" for size {1} can't be over {2}.", "userProfile_fileNotImage_message": "The file \"{0}\" is not an image.", + "userProfile_deleteUserMessage": "Delete your account? All the polls you created will be deleted; your votes and comments will be anonymized.", "choice_description_placeholder": "You can enter a description for this choice", "date-picker_today": "Today", "date-picker_dateplaceholder": "Date", diff --git a/pollen-ui-riot-js/src/main/web/i18n/fr.json b/pollen-ui-riot-js/src/main/web/i18n/fr.json index a0073578..630120cc 100644 --- a/pollen-ui-riot-js/src/main/web/i18n/fr.json +++ b/pollen-ui-riot-js/src/main/web/i18n/fr.json @@ -422,6 +422,7 @@ "userProfile_getProviderAvatar": "ou utiliser votre avatar d'un service tiers", "userProfile_fileSizeMax_message": "Le fichier « {0} » de taille de {1} ne doit pas dépasser {2}.", "userProfile_fileNotImage_message": "Le fichier « {0} » n'est pas une image.", + "userProfile_deleteUserMessage": "Supprimer votre compte ? Tous les sondages que vous avez créés seront supprimés ; vos votes et commentaires seront anonymisés.", "choice_description_placeholder": "Vous pouvez saisir une description pour ce choix", "date-picker_today": "Aujourd'hui", "date-picker_dateplaceholder": "Date", diff --git a/pollen-ui-riot-js/src/main/web/tag/PollenHeader.tag.html b/pollen-ui-riot-js/src/main/web/tag/PollenHeader.tag.html index 7b98efef..5a0c56d2 100644 --- a/pollen-ui-riot-js/src/main/web/tag/PollenHeader.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/PollenHeader.tag.html @@ -95,7 +95,7 @@ require("./components/Avatar.tag.html"); this.user = session.getUser(); - this.admin = this.usser && this.user.administrator; + this.admin = this.user && this.user.administrator; this.onUserChange = user => { this.user = user; diff --git a/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html b/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html index a1e2950f..f4cc3cb6 100644 --- a/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/UserProfile.tag.html @@ -200,11 +200,16 @@ require("./components/LetterAvatar.tag.html"); </div> </div> </div> + <div> + <h3 class="c-heading"><i class="fa fa-sign-in"/> {__.avatar}</h3> + <button class="c-button c-button--error" onclick="{deleteAccount}">desinscription</button> + </div> </div> </div> <script type="es6"> this.loaded = false; + let route = require("riot-route"); this.session = require("../js/Session"); this.installBundle(this.session, "userProfile"); this.errors = {}; @@ -350,6 +355,17 @@ require("./components/LetterAvatar.tag.html"); } }; + this.deleteAccount = e => { + this.confirm(this.__.deleteUserMessage, null, null, 10).then((confirm) => { + if (confirm) { + userService.deleteUser(this.user.id).then(() => { + this.bus.trigger("user", null); + route("home"); + }); + } + }); + }; + this.listen("user", this.onUserChange); </script> diff --git a/pollen-ui-riot-js/src/main/web/tag/popup/ConfirmPopup.tag.html b/pollen-ui-riot-js/src/main/web/tag/popup/ConfirmPopup.tag.html index 4b2a23bc..e64c9a12 100644 --- a/pollen-ui-riot-js/src/main/web/tag/popup/ConfirmPopup.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/popup/ConfirmPopup.tag.html @@ -37,8 +37,9 @@ </button> <button type="button" class="c-button c-button--block c-button--{type}" - onclick={confirm}> - {label} + onclick={confirm} + disabled="{timeout}"> + {label} <span if="{timeout}">({timeout})</span> </button> </div> </footer> @@ -51,11 +52,25 @@ this.installBundle(session, "confirm"); this.openModal = false; + this.timeout = null; + this.timer = null; - this.open = (message, label, type) => { + this.open = (message, label, type, timeout) => { this.message = message; this.label = label || this.__.delete; this.type = type || "error"; + + this.timeout = timeout; + if (this.timeout) { + this.timer = setInterval(() => { + this.timeout--; + if (this.timeout == 0) { + clearInterval(this.timer); + } + this.update(); + }, 1000); + } + this.openModal = true; this.modalPromise = new Promise((resolve, reject) => { this.modalResolve = resolve; @@ -66,6 +81,8 @@ }; this.close = (value) => { + this.timeout = null; + clearInterval(this.timer); if (this.openModal) { this.openModal = false; this.modalResolve(value); -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.