This is an automated email from the git hooks/post-receive script. New commit to branch develop in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit ab7cf127187eb107639bf45fef1331fade7e83ef Author: Sylvain Bavencoff <bavencoff@codelutin.com> Date: Thu Sep 7 15:13:43 2017 +0200 réécriture des import de liste de votant (CSV et LDAP), renvoyer toute les erreurs du fichier (ref #132) --- .../FavoriteListImportExceptionMapper.java | 2 +- .../service/FavoriteListImportException.java | 19 +-- .../service/FavoriteListImportFromFile.java | 151 ++++++++++----------- .../service/FavoriteListImportFromLdap.java | 134 +++++++++++------- .../i18n/pollen-services_en_GB.properties | 12 +- .../i18n/pollen-services_fr_FR.properties | 20 +-- pollen-ui-riot-js/src/main/web/js/Session.js | 32 ++--- .../web/tag/favoriteList/ImportCsvModal.tag.html | 2 +- 8 files changed, 199 insertions(+), 173 deletions(-) diff --git a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/exceptionMappers/FavoriteListImportExceptionMapper.java b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/exceptionMappers/FavoriteListImportExceptionMapper.java index e34cdc6a..2da73212 100644 --- a/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/exceptionMappers/FavoriteListImportExceptionMapper.java +++ b/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/exceptionMappers/FavoriteListImportExceptionMapper.java @@ -15,6 +15,6 @@ public class FavoriteListImportExceptionMapper extends PollenAbstractExceptionMa @Override protected Object getEntity(FavoriteListImportException exception) { - return exception; + return exception.getErrors(); } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportException.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportException.java index 8ce6516f..c1c44a0c 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportException.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportException.java @@ -21,6 +21,8 @@ package org.chorem.pollen.services.service; * #L% */ +import java.util.List; + /** * TODO * @@ -31,20 +33,13 @@ public class FavoriteListImportException extends Exception { private static final long serialVersionUID = 1L; - private final String causeMessage; - - public FavoriteListImportException(String causeMessage, Throwable cause) { - super(cause); - this.causeMessage = causeMessage; - } + private final List<String> errors; - public FavoriteListImportException(Throwable cause) { - this(cause.getMessage(), cause); + public FavoriteListImportException(List<String> errors) { + this.errors = errors; } - /** @return the error message source from import execution. */ - public String getCauseMessage() { - return causeMessage; + public List<String> getErrors() { + return errors; } - } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromFile.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromFile.java index 9ca4939f..d66e021c 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromFile.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromFile.java @@ -22,10 +22,10 @@ package org.chorem.pollen.services.service; */ import com.google.common.base.Charsets; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.common.io.Files; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -34,7 +34,6 @@ import org.chorem.pollen.persistence.entity.FavoriteListMember; import org.chorem.pollen.services.PollenTechnicalException; import org.nuiton.util.StringUtil; -import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.util.List; @@ -80,120 +79,114 @@ public class FavoriteListImportFromFile extends PollenServiceSupport implements } } - Locale locale = serviceContext.getLocale(); - BufferedReader reader = null; + List<String> lines; try { + lines = Files.readLines(file, Charsets.UTF_8); + } catch (IOException e) { + throw new PollenTechnicalException(e); + } - reader = Files.newReader(file, Charsets.UTF_8); - String line; - int lineNumber = 0; - - while ((line = reader.readLine()) != null) { + List<String> errors = Lists.newLinkedList(); - line = line.trim(); - if (StringUtils.isBlank(line) || line.startsWith("#")) { + int lineNumber = 1; + for (String line : lines) { + if (!StringUtils.isBlank(line) && !line.startsWith("#")) { + checkLine(errors, line, lineNumber, usedEmail, usedName); + } - // comment line - continue; + lineNumber++; + } - } - lineNumber++; + if (CollectionUtils.isNotEmpty(errors)) { + throw new FavoriteListImportException(errors); + } + for (String line : lines) { + if (!StringUtils.isBlank(line) && !line.startsWith("#")) { String[] columns = line.split(";"); + String email = getCleanMail(columns[0]) ; + String memberName = columns.length >= 2 ? columns[1] : email; + double weight = columns.length >= 3 ? Double.parseDouble(columns[2]) : 1; - String email; - String memberName; - double weight; - - if (columns.length >= 1) { - - // only email - email = columns[0].trim(); - - if (columns.length >= 2) { - - memberName = columns[1].trim(); - - if (columns.length >= 3) { + FavoriteListMember member = getFavoriteListMemberDao().create(); + member.setName(memberName); + member.setEmail(email); + member.setWeight(weight); + member.setFavoriteList(favoriteList); - try { - weight = Double.parseDouble(columns[2].trim()); - } catch (NumberFormatException e) { - String error = l(locale, "pollen.error.favoriteList.import.csv.weight.notNumber", lineNumber, columns[2].trim()); - throw new FavoriteListImportException(error, null); - } + if (log.isDebugEnabled()) { + log.debug(String.format("imported member %s / %s", memberName, email)); + } + } + } - } else { + commit(); - weight = 1; + } - } - } else { - memberName = columns[0].trim(); - weight = 1; + protected void checkLine(List<String> errors, String line, int lineNumber, Set<String> usedEmail, Set<String> usedName) { - } + Locale locale = serviceContext.getLocale(); - } else { + String[] columns = line.split(";"); - continue; - - } + String email; + String memberName; + String weightString = null; - if (!usedName.add(memberName)) { - // name already exists - String error = l(locale, "pollen.error.favoriteList.import.csv.already.used.name", lineNumber, memberName); - throw new FavoriteListImportException(error, null); + if (columns.length >= 1) { - } + // only email + email = columns[0].trim(); - email = getCleanMail(email); - if (!usedEmail.add(email)) { - // email already exists - String error = l(locale, "pollen.error.favoriteList.import.csv.already.used.email", lineNumber, email); - throw new FavoriteListImportException(error, null); + if (columns.length >= 2) { - } + memberName = columns[1].trim(); - if (!StringUtil.isEmail(email)) { + if (columns.length >= 3) { - // email is not valid - String error = l(locale, "pollen.error.favoriteList.import.csv.invalid.email", lineNumber, email); - throw new FavoriteListImportException(error, null); + weightString = columns[2].trim(); } - FavoriteListMember member = getFavoriteListMemberDao().create(); - member.setName(memberName); - member.setEmail(email); - member.setWeight(weight); - member.setFavoriteList(favoriteList); + } else { - if (log.isDebugEnabled()) { - log.debug(String.format("imported member %s / %s", memberName, email)); - } + memberName = email; } - reader.close(); - - } catch (IOException e) { + email = getCleanMail(email); + if (!StringUtil.isEmail(email)) { + // email is not valid + errors.add(l(locale, "pollen.error.favoriteList.import.csv.invalid.email", lineNumber, email)); + } - // should never happens ? - throw new PollenTechnicalException(e); + if (!usedEmail.add(email)) { + // email already exists + errors.add(l(locale, "pollen.error.favoriteList.import.csv.already.used.email", lineNumber, email)); + } - } finally { + if (!usedName.add(memberName)) { + // name already exists + errors.add(l(locale, "pollen.error.favoriteList.import.csv.already.used.name", lineNumber, memberName)); + } - IOUtils.closeQuietly(reader); + if (StringUtils.isNotBlank(weightString)) { + try { + double weight = Double.parseDouble(weightString); + if (weight <= 0) { + errors.add(l(locale, "pollen.error.favoriteList.import.csv.weight.negativeOrNull", lineNumber, weightString)); + } + } catch (NumberFormatException e) { + errors.add(l(locale, "pollen.error.favoriteList.import.csv.weight.notNumber", lineNumber, weightString)); + } + } } - - commit(); - } } diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromLdap.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromLdap.java index 1b9210ca..1c242c76 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromLdap.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListImportFromLdap.java @@ -21,12 +21,15 @@ package org.chorem.pollen.services.service; * #L% */ +import com.google.common.base.Charsets; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.chorem.pollen.persistence.entity.FavoriteList; import org.chorem.pollen.persistence.entity.FavoriteListMember; +import org.chorem.pollen.persistence.entity.FavoriteListMemberImpl; import org.nuiton.util.StringUtil; import javax.naming.Context; @@ -85,91 +88,118 @@ public class FavoriteListImportFromLdap extends PollenServiceSupport implements } } - try { + List<String> errors = Lists.newLinkedList(); + List<FavoriteListMember> membersToAdd = Lists.newLinkedList(); - // Initialisation du contexte - Properties env = new Properties(); + // Initialisation du contexte + Properties env = new Properties(); - Pattern loginLdapPattern = Pattern.compile("ldaps?://(([^:]+):([^@]+)@)?.*"); - Matcher matcher = loginLdapPattern.matcher(ldap); - if (matcher.find() && matcher.group(1) != null) { - env.put(Context.SECURITY_AUTHENTICATION, "simple"); - if (matcher.group(2) != null) { - String login = URLDecoder.decode(matcher.group(2), "UTF-8"); + Pattern loginLdapPattern = Pattern.compile("ldaps?://(([^:]+):([^@]+)@)?.*"); + Matcher matcher = loginLdapPattern.matcher(ldap); + if (matcher.find() && matcher.group(1) != null) { + env.put(Context.SECURITY_AUTHENTICATION, "simple"); + if (matcher.group(2) != null) { + String login = null; + try { + login = URLDecoder.decode(matcher.group(2), Charsets.UTF_8.name()); env.put(Context.SECURITY_PRINCIPAL, "cn=" + login); + } catch (UnsupportedEncodingException e) { + errors.add(l(locale, "pollen.error.favoriteList.import.ldap.login.urlEncoding", matcher.group(2))); } - if (matcher.group(3) != null) { - String password = URLDecoder.decode(matcher.group(3), "UTF-8"); + + } + if (matcher.group(3) != null) { + String password = null; + try { + password = URLDecoder.decode(matcher.group(3), Charsets.UTF_8.name()); env.put(Context.SECURITY_CREDENTIALS, password); + } catch (UnsupportedEncodingException e) { + errors.add(l(locale, "pollen.error.favoriteList.import.ldap.password.urlEncoding", matcher.group(3))); } - ldap = ldap.replace(matcher.group(1), ""); } + ldap = ldap.replace(matcher.group(1), ""); + } - DirContext ictx = new InitialDirContext(env); + if (CollectionUtils.isEmpty(errors)) { - // Recherche en profondeur - SearchControls control = new SearchControls(); - control.setSearchScope(SearchControls.SUBTREE_SCOPE); + try { - // Création des comptes avec les résultats de la recherche - NamingEnumeration<SearchResult> e = ictx.search(ldap, null, control); + DirContext ictx = new InitialDirContext(env); - while (e.hasMore()) { + // Recherche en profondeur + SearchControls control = new SearchControls(); + control.setSearchScope(SearchControls.SUBTREE_SCOPE); - SearchResult r = e.next(); + // Création des comptes avec les résultats de la recherche + NamingEnumeration<SearchResult> e = ictx.search(ldap, null, control); - Attribute attrName = r.getAttributes().get("cn"); - Attribute attrEmail = r.getAttributes().get("mail"); + while (e.hasMore()) { - if (attrName != null && attrEmail != null) { + SearchResult r = e.next(); - String memberName = attrName.get().toString().trim(); + Attribute attrName = r.getAttributes().get("cn"); + Attribute attrEmail = r.getAttributes().get("mail"); - if (!usedName.add(memberName)) { + if (attrName != null && attrEmail != null) { - // name already exists - String error = l(locale, "pollen.error.favoriteList.import.ldap.already.used.name", memberName); - throw new FavoriteListImportException(error, null); + boolean error = false; - } + String memberName = attrName.get().toString().trim(); - String email = getCleanMail(attrEmail.get().toString()); + if (!usedName.add(memberName)) { - if (!usedEmail.add(email)) { + error = true; + // name already exists + errors.add(l(locale, "pollen.error.favoriteList.import.ldap.already.used.name", memberName)); - // email already exists - String error = l(locale, "pollen.error.favoriteList.import.ldap.already.used.email", email); - throw new FavoriteListImportException(error, null); + } - } + String email = getCleanMail(attrEmail.get().toString()); - if (!StringUtil.isEmail(email)) { + if (!usedEmail.add(email)) { - // email is not valid - String error = l(locale, "pollen.error.favoriteList.import.ldap.invalid.email", email); - throw new FavoriteListImportException(error, null); + error = true; + // email already exists + errors.add(l(locale, "pollen.error.favoriteList.import.ldap.already.used.email", email)); - } + } - FavoriteListMember member = getFavoriteListMemberDao().create(); - member.setName(memberName); - member.setEmail(email); - member.setWeight(1); - member.setFavoriteList(favoriteList); + if (!StringUtil.isEmail(email)) { - if (log.isDebugEnabled()) { - log.debug(String.format("imported member %s / %s", memberName, email)); - } + error = true; + // email is not valid + errors.add(l(locale, "pollen.error.favoriteList.import.ldap.invalid.email", email)); + } + + if (!error) { + FavoriteListMember member = new FavoriteListMemberImpl(); + member.setName(memberName); + member.setEmail(email); + member.setWeight(1); + member.setFavoriteList(favoriteList); + membersToAdd.add(member); + } + + } + } + + } catch (NamingException ex) { + errors.add(l(locale, "pollen.error.favoriteList.import.ldap.server", ex.getMessage())); } + } - } catch (NamingException ex) { + if (CollectionUtils.isNotEmpty(errors)) { + throw new FavoriteListImportException(errors); + } - throw new FavoriteListImportException("LDAP", ex); + for (FavoriteListMember member : membersToAdd) { + getFavoriteListMemberDao().create(member); - } catch (UnsupportedEncodingException e) { - throw new FavoriteListImportException("LDAP", e); + if (log.isDebugEnabled()) { + log.debug(String.format("imported member %s / %s", member.getName(), member.getEmail())); + } } commit(); 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 b19d9a81..ecca1ce1 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 @@ -56,10 +56,14 @@ pollen.error.comment.text.mandatory=text can not be empty pollen.error.favoriteList.import.csv.already.used.email=Line %s \: Email already used pollen.error.favoriteList.import.csv.already.used.name=Line %s \: Name already used pollen.error.favoriteList.import.csv.invalid.email=Line %s \: Invalid email -pollen.error.favoriteList.import.csv.weight.notNumber=Line %s \: weight is not a number -pollen.error.favoriteList.import.ldap.already.used.email= -pollen.error.favoriteList.import.ldap.already.used.name= -pollen.error.favoriteList.import.ldap.invalid.email= +pollen.error.favoriteList.import.csv.weight.negativeOrNull=Line %s \: weight (%s) must be positive +pollen.error.favoriteList.import.csv.weight.notNumber=Line %s \: weight (%s) is not a number +pollen.error.favoriteList.import.ldap.already.used.email=Email "%s" already used +pollen.error.favoriteList.import.ldap.already.used.name=Name "%s" already used +pollen.error.favoriteList.import.ldap.invalid.email=Invalid email "%s" +pollen.error.favoriteList.import.ldap.login.urlEncoding=Bad encoding for login "%s" +pollen.error.favoriteList.import.ldap.password.urlEncoding=Bad encoding for password "%s" +pollen.error.favoriteList.import.ldap.server=Error on LDAP server \: %s pollen.error.favoriteList.name.already.used=name "%s" already used by another favorite list pollen.error.favoriteList.name.empty=name can not be empty pollen.error.favoriteListMember.email.already.used=member email "%s" already used in this list 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 ab2f93c8..9c285933 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 @@ -53,18 +53,22 @@ pollen.error.choice.choiceNameExist=Le nom du choix est déjà utilisé sur ce s pollen.error.choice.choiceTypeEmpty=Le type du choix doit être défini pollen.error.comment.author.name.mandatory=Le nom est obligatoire pollen.error.comment.text.mandatory=le text est obligatoire -pollen.error.favoriteList.import.csv.already.used.email=Ligne %s \: Courriel déjà utilisé -pollen.error.favoriteList.import.csv.already.used.name=Ligne %s \: Nom déjà utilisé -pollen.error.favoriteList.import.csv.invalid.email=Ligne %s \: Courriel invalide -pollen.error.favoriteList.import.csv.weight.notNumber=Ligne %s \: Le poids n'est pas un nombre -pollen.error.favoriteList.import.ldap.already.used.email= -pollen.error.favoriteList.import.ldap.already.used.name= -pollen.error.favoriteList.import.ldap.invalid.email= +pollen.error.favoriteList.import.csv.already.used.email=Ligne %s \: Courriel « %s » est déjà utilisé +pollen.error.favoriteList.import.csv.already.used.name=Ligne %s \: Nom « %s » est déjà utilisé +pollen.error.favoriteList.import.csv.invalid.email=Ligne %s \: Courriel « %s » est invalide +pollen.error.favoriteList.import.csv.weight.negativeOrNull=Ligne %s \: Le poids (%s) doit être positif +pollen.error.favoriteList.import.csv.weight.notNumber=Ligne %s \: Le poids (%s) n'est pas un nombre +pollen.error.favoriteList.import.ldap.already.used.email=Courriel « %s » est déjà utilisé +pollen.error.favoriteList.import.ldap.already.used.name=Nom « %s » est déjà utilisé +pollen.error.favoriteList.import.ldap.invalid.email=Courriel « %s » est invalide +pollen.error.favoriteList.import.ldap.login.urlEncoding=Mauvais encodage de l'identifiant +pollen.error.favoriteList.import.ldap.password.urlEncoding=Mauvais encodage du mor de passe +pollen.error.favoriteList.import.ldap.server=Erreur sur le serveur LDAP \: %s pollen.error.favoriteList.name.already.used=Le nom « %s » est déjà utilisé par une autre liste pollen.error.favoriteList.name.empty=Le nom de la liste est obligatoire pollen.error.favoriteListMember.email.already.used=Le courriel du membre « %s » est déjà utilisé dans cette liste pollen.error.favoriteListMember.email.empty=Le courriel est obligatoire -pollen.error.favoriteListMember.email.invalid=Le courriel du membre « %s »est invalide +pollen.error.favoriteListMember.email.invalid=Le courriel du membre « %s » est invalide pollen.error.favoriteListMember.name.already.used=Le nom du membre « %s » est déjà utilisé dans cette liste pollen.error.favoriteListMember.name.empty=Le nom du membre est obligatoire pollen.error.favoriteListMember.weight.negativeOrNull=le poids du membre (%s) doit être positif diff --git a/pollen-ui-riot-js/src/main/web/js/Session.js b/pollen-ui-riot-js/src/main/web/js/Session.js index 83049c93..d11d9206 100644 --- a/pollen-ui-riot-js/src/main/web/js/Session.js +++ b/pollen-ui-riot-js/src/main/web/js/Session.js @@ -142,23 +142,23 @@ class Session { .then(auth => this.updateConnection(auth, this)); } - updateConnection(auth, session) { - logger.info("SignIn::"); - logger.info(auth); - return authService.userPromise(auth).then((user) => { - if (!user) { - logger.info("SignIn error"); - var oldUser = session.user; - session.user = null; + updateConnection(auth, session){ + logger.info("SignIn::"); + logger.info(auth); + return authService.userPromise(auth).then((user) => { + if (!user) { + logger.info("SignIn error"); + let oldUser = session.user; + session.user = null; + bus.trigger("user", session.user, oldUser); + return Promise.reject(); + } + logger.info("SignIn user::"); + logger.info(user); + pageTracker.trackLogin(); + let oldUser = session.user; + session.user = user; bus.trigger("user", session.user, oldUser); - return Promise.reject(); - } - logger.info("SignIn user::"); - logger.info(user); - pageTracker.trackLogin(); - var oldUser = session.user; - session.user = user; - bus.trigger("user", session.user, oldUser); return session.user; }); diff --git a/pollen-ui-riot-js/src/main/web/tag/favoriteList/ImportCsvModal.tag.html b/pollen-ui-riot-js/src/main/web/tag/favoriteList/ImportCsvModal.tag.html index 7707ac58..ebcb22ea 100644 --- a/pollen-ui-riot-js/src/main/web/tag/favoriteList/ImportCsvModal.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/favoriteList/ImportCsvModal.tag.html @@ -41,7 +41,7 @@ require("../popup/Modal.tag.html"); this.update(); }, errors => { this.errors = errors; - this.bus.trigger("message", errors); + this.bus.trigger("message", errors, "error"); this.update(); }); }; -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.