diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/WritePlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/WritePlatformService.java deleted file mode 100644 index 0ff74c092..000000000 --- a/mifosng-provider/src/main/java/org/mifosng/platform/WritePlatformService.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.mifosng.platform; - -import org.mifosng.data.command.UpdateUsernamePasswordCommand; - -public interface WritePlatformService { - - void updateUsernamePasswordOnFirstTimeLogin(UpdateUsernamePasswordCommand command); -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/WritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/WritePlatformServiceJpaRepositoryImpl.java deleted file mode 100644 index 7a63d3b6f..000000000 --- a/mifosng-provider/src/main/java/org/mifosng/platform/WritePlatformServiceJpaRepositoryImpl.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.mifosng.platform; - -import static org.mifosng.platform.Specifications.usersThatMatch; - -import org.mifosng.data.command.UpdateUsernamePasswordCommand; -import org.mifosng.platform.exceptions.UnAuthenticatedUserException; -import org.mifosng.platform.infrastructure.BasicPasswordEncodablePlatformUser; -import org.mifosng.platform.infrastructure.PlatformPasswordEncoder; -import org.mifosng.platform.infrastructure.PlatformUser; -import org.mifosng.platform.infrastructure.UsernameAlreadyExistsException; -import org.mifosng.platform.user.domain.AppUser; -import org.mifosng.platform.user.domain.AppUserRepository; -import org.mifosng.platform.user.domain.PlatformUserRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -@Service -public class WritePlatformServiceJpaRepositoryImpl implements WritePlatformService { - - private final PlatformUserRepository platformUserRepository; - private final PlatformPasswordEncoder platformPasswordEncoder; - - @Autowired - public WritePlatformServiceJpaRepositoryImpl( - final PlatformUserRepository platformUserRepository, - final PlatformPasswordEncoder platformPasswordEncoder - ) { - this.platformUserRepository = platformUserRepository; - this.platformPasswordEncoder = platformPasswordEncoder; - } - - @Transactional - @Override - public void updateUsernamePasswordOnFirstTimeLogin(final UpdateUsernamePasswordCommand command) { - - AppUser currentUser = extractAuthenticatedUser(); - - try { - PlatformUser platformUser = ((AppUserRepository) this.platformUserRepository).findOne(usersThatMatch(currentUser.getOrganisation(), command.getOldUsername())); - - PlatformUser dummyPlatformUser = new BasicPasswordEncodablePlatformUser( - ((AppUser) platformUser).getId(), - platformUser.getUsername(), command.getPassword()); - - String encodePassword = this.platformPasswordEncoder.encode(dummyPlatformUser); - - if (command.isUsernameToBeChanged()) { - platformUser.updateUsernamePasswordOnFirstTimeLogin( - command.getUsername(), encodePassword); - } else { - platformUser.updatePasswordOnFirstTimeLogin(encodePassword); - } - - ((AppUserRepository) this.platformUserRepository).save((AppUser) platformUser); - } catch (DataIntegrityViolationException e) { - throw new UsernameAlreadyExistsException(e); - } - } - - private AppUser extractAuthenticatedUser() { - AppUser currentUser = null; - SecurityContext context = SecurityContextHolder.getContext(); - if (context != null) { - Authentication auth = context.getAuthentication(); - if (auth != null) { - currentUser = (AppUser) auth.getPrincipal(); - } - } - - if (currentUser == null) { - throw new UnAuthenticatedUserException(); - } - - return currentUser; - } -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java index 8ae40a61a..3e1ecacd6 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java @@ -16,4 +16,6 @@ public interface ApiDataConversionService { Locale clientApplicationLocale); Locale localeFromString(String locale); + + Locale localeFrom(String languageCode, String courntryCode, String variantCode); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java index 9c46532c8..555a17d97 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java @@ -1,9 +1,12 @@ package org.mifosng.platform.api.infrastructure; import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.text.ParseException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Locale; @@ -13,6 +16,7 @@ import org.joda.time.format.DateTimeFormat; import org.mifosng.platform.api.data.ApiParameterError; import org.mifosng.platform.exceptions.PlatformApiDataValidationException; import org.springframework.context.i18n.LocaleContextHolder; +import org.springframework.format.number.NumberFormatter; import org.springframework.stereotype.Service; @Service @@ -55,9 +59,33 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { Integer number = null; if (StringUtils.isNotBlank(numericalValueFormatted)) { - String sourceWithoutSpaces = numericalValueFormatted.replaceAll(" ", ""); - NumberFormat format = NumberFormat.getNumberInstance(clientApplicationLocale); - Number parsedNumber = format.parse(sourceWithoutSpaces); + + String source = numericalValueFormatted.trim(); + + NumberFormat format = NumberFormat.getInstance(clientApplicationLocale); + DecimalFormat df = (DecimalFormat) format; + DecimalFormatSymbols symbols = df.getDecimalFormatSymbols(); + df.setParseBigDecimal(true); + + // http://bugs.sun.com/view_bug.do?bug_id=4510618 + char groupingSeparator = symbols.getGroupingSeparator(); + if (groupingSeparator == '\u00a0') { + source = source.replaceAll(" ", Character.toString('\u00a0')); + } + + Number parsedNumber = df.parse(source); + + double parsedNumberDouble = parsedNumber.doubleValue(); + int parsedNumberInteger = parsedNumber.intValue(); + + if (source.contains(Character.toString(symbols.getDecimalSeparator()))) { + throw new ParseException(source, 0); + } + + if (!Double.valueOf(parsedNumberDouble).equals(Double.valueOf(Integer.valueOf(parsedNumberInteger)))) { + throw new ParseException(source, 0); + } + number = parsedNumber.intValue(); } @@ -66,9 +94,9 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { List dataValidationErrors = new ArrayList(); ApiParameterError error = ApiParameterError.parameterError( - "validation.msg.invalid.number.format", "The parameter " - + parameterName + " is invalid for provided locale" - + clientApplicationLocale.toString() + ".", + "validation.msg.invalid.integer.format", "The parameter " + + parameterName + " has value: " + numericalValueFormatted + " which is invalid integer value for provided locale of [" + + clientApplicationLocale.toString() + "].", parameterName, numericalValueFormatted, clientApplicationLocale); dataValidationErrors.add(error); @@ -80,20 +108,27 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { } @Override - public BigDecimal convertFrom(String numericalValueFormatted, - String parameterName, Locale clientApplicationLocale) { + public BigDecimal convertFrom(final String numericalValueFormatted, final String parameterName, final Locale clientApplicationLocale) { try { BigDecimal number = null; - + if (StringUtils.isNotBlank(numericalValueFormatted)) { - String sourceWithoutSpaces = numericalValueFormatted - .replaceAll(" ", ""); - NumberFormat format = NumberFormat - .getNumberInstance(clientApplicationLocale); - Number parsedNumber = format.parse(sourceWithoutSpaces); - number = BigDecimal.valueOf(Double.valueOf(parsedNumber - .doubleValue())); + + String source = numericalValueFormatted.trim(); + + NumberFormat format = NumberFormat.getNumberInstance(clientApplicationLocale); + DecimalFormat df = (DecimalFormat) format; + DecimalFormatSymbols symbols = df.getDecimalFormatSymbols(); + // http://bugs.sun.com/view_bug.do?bug_id=4510618 + char groupingSeparator = symbols.getGroupingSeparator(); + if (groupingSeparator == '\u00a0') { + source = source.replaceAll(" ", Character.toString('\u00a0')); + } + + NumberFormatter numberFormatter = new NumberFormatter(); + Number parsedNumber = numberFormatter.parse(source, clientApplicationLocale); + number = BigDecimal.valueOf(Double.valueOf(parsedNumber.doubleValue())); } return number; @@ -101,9 +136,9 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { List dataValidationErrors = new ArrayList(); ApiParameterError error = ApiParameterError.parameterError( - "validation.msg.invalid.number.format", "The parameter " - + parameterName + " is invalid for provided locale" - + clientApplicationLocale.toString() + ".", + "validation.msg.invalid.decimal.format", "The parameter " + + parameterName + " has value: " + numericalValueFormatted + " which is invalid decimal value for provided locale of [" + + clientApplicationLocale.toString() + "].", parameterName, numericalValueFormatted, clientApplicationLocale); dataValidationErrors.add(error); @@ -117,33 +152,65 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { @Override public Locale localeFromString(final String localeAsString) { - Locale locale = Locale.getDefault(); + if (StringUtils.isBlank(localeAsString)) { + List dataValidationErrors = new ArrayList(); + ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format", "The parameter locale is invalid. It cannot be blank.", "locale"); + dataValidationErrors.add(error); - if (StringUtils.isNotBlank(localeAsString)) { - String[] localeParts = localeAsString.split("_"); - - String language = "en"; - String country = "GB"; - String variant = ""; - if (localeParts != null && localeParts.length == 1) { - language = localeParts[0]; - locale = new Locale(language); - } - - if (localeParts != null && localeParts.length == 2) { - language = localeParts[0]; - country = localeParts[1]; - locale = new Locale(language, country); - } - - if (localeParts != null && localeParts.length == 3) { - language = localeParts[0]; - country = localeParts[1]; - variant = localeParts[2]; - locale = new Locale(language, country, variant); + throw new PlatformApiDataValidationException( + "validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); + } + + String languageCode = ""; + String courntryCode = ""; + String variantCode = ""; + + String[] localeParts = localeAsString.split("_"); + + if (localeParts != null && localeParts.length == 1) { + languageCode = localeParts[0]; + } + + if (localeParts != null && localeParts.length == 2) { + languageCode = localeParts[0]; + courntryCode = localeParts[1]; + } + + if (localeParts != null && localeParts.length == 3) { + languageCode = localeParts[0]; + courntryCode = localeParts[1]; + variantCode = localeParts[2]; + } + + return localeFrom(languageCode, courntryCode, variantCode); + } + + @Override + public Locale localeFrom(final String languageCode, final String courntryCode, final String variantCode) { + + List dataValidationErrors = new ArrayList(); + + List allowedLanguages = Arrays.asList(Locale.getISOLanguages()); + if (!allowedLanguages.contains(languageCode.toLowerCase())) { + ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format", "The parameter locale has an invalid language value " + languageCode + " .", "locale", languageCode); + dataValidationErrors.add(error); + } + + if (StringUtils.isNotBlank(courntryCode.toUpperCase())) { + List allowedCountries = Arrays.asList(Locale.getISOCountries()); + if (!allowedCountries.contains(courntryCode)) { + ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.locale.format", "The parameter locale has an invalid country value " + courntryCode + " .", "locale", courntryCode); + dataValidationErrors.add(error); } } - return locale; + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException( + "validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); + } + + return new Locale(languageCode.toLowerCase(), courntryCode.toUpperCase(), variantCode); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java index 8dc02c6bf..3f93935b3 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java @@ -128,6 +128,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP AppUser currentUser = context.authenticatedUser(); + // FIXME - check client id matches. Note noteForUpdate = this.noteRepository.findOne(notesThatMatch(currentUser.getOrganisation(), command.getId())); if (noteForUpdate == null) { throw new NoteNotFoundException(command.getClientId());