Merge branch 'MIFOSX-1875' of git://github.com/Musoni/mifosx into Musoni-MIFOSX-1875
Conflicts: mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java
This commit is contained in:
@@ -2032,6 +2032,14 @@
|
|||||||
<td><a href="#permissions_update">Enable/Disable Permissions for Maker Checker</a></td>
|
<td><a href="#permissions_update">Enable/Disable Permissions for Maker Checker</a></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="#password_validation_policy">Password Validation Policy</a></td>
|
||||||
|
<td>paswordValidationPolicy</td>
|
||||||
|
<td><a href=""></a></td>
|
||||||
|
<td><a href="#password_validation_policy_list">List validation Policy</a></td>
|
||||||
|
<td><a href="#password_validation_policy_update">Activate policy</a></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -30853,7 +30861,70 @@ Request Body:
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- start of password validation policy api docs -->
|
||||||
|
<a id="password_validation_policy" name="passwordValidationPolicy" class="old-syle-anchor"> </a>
|
||||||
|
<div class="method-section">
|
||||||
|
<div class="method-description">
|
||||||
|
<h3>Password validation policy</h3>
|
||||||
|
<p>An API capability to support management of application password validation policy for user administration.</p>
|
||||||
|
<p>There is no Mifos X functionality for creating or validation policy. The validation policies come pre-installed.</p>
|
||||||
|
<p>Validation policies are not updated, except in the case of enabling them</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a id="password_validation_policy_list" name="passwordValidationPolicy_list"
|
||||||
|
class="old-syle-anchor"> </a>
|
||||||
|
<div class="method-section">
|
||||||
|
<div class="method-description">
|
||||||
|
<h4>List Application Password validation policies</h4>
|
||||||
|
<h5>Arguments</h5>
|
||||||
|
<dl class="argument-list">
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<p>Example Requests:</p>
|
||||||
|
<div class=apiClick>passwordValidationPolicy</div><br><br>
|
||||||
|
</div>
|
||||||
|
<div class="method-example">
|
||||||
|
<code class="method-declaration">
|
||||||
|
GET https://DomainName/api/v1/passwordValidationPolicy
|
||||||
|
</code>
|
||||||
|
<code class="method-response">
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"description": "Password most be at least 1 character and not more that 50 characters long",
|
||||||
|
"active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"description": "Password must be at least 6 characters, no more than 50 characters long, must include at least one upper case letter, one lower case letter, one numeric digit and no space",
|
||||||
|
"active": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a id="password_validation_policy_update" name="passwordValidationPolicy_update" class="old-syle-anchor"> </a>
|
||||||
|
<div class="method-section">
|
||||||
|
<div class="method-description">
|
||||||
|
<h4>Enable Password validation policy</h4>
|
||||||
|
</div>
|
||||||
|
<div class="method-example">
|
||||||
|
<code class="method-declaration">
|
||||||
|
PUT https://DomainName/api/v1/passwordValidationPolicy/{validationPolicyId}
|
||||||
|
</code>
|
||||||
|
<code class="method-request">
|
||||||
|
PUT passwordValidationPolicy
|
||||||
|
Content-Type: application/json
|
||||||
|
Request Body:
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<!-- start of accounting api docs -->
|
<!-- start of accounting api docs -->
|
||||||
<a id="glaccounts" name="glaccounts" class="old-syle-anchor"> </a>
|
<a id="glaccounts" name="glaccounts" class="old-syle-anchor"> </a>
|
||||||
<div class="method-section">
|
<div class="method-section">
|
||||||
|
|||||||
@@ -1022,4 +1022,8 @@ public class CommandWrapper {
|
|||||||
return this.entityName.equalsIgnoreCase("WORKINGDAYS");
|
return this.entityName.equalsIgnoreCase("WORKINGDAYS");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPasswordValidationPolicyResource() {
|
||||||
|
return this.entityName.equalsIgnoreCase("PASSWORD_VALIDATION_POLICY");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+8
@@ -2361,4 +2361,12 @@ public class CommandWrapperBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CommandWrapperBuilder activatePasswordValidationPolicy(final Long validationPolicyId) {
|
||||||
|
this.actionName = "UPDATE";
|
||||||
|
this.entityName = "PASSWORD_VALIDATION_POLICY";
|
||||||
|
this.entityId = validationPolicyId;
|
||||||
|
this.href = "/passwordValidationPolicy/" + validationPolicyId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+11
-4
@@ -923,10 +923,17 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
|||||||
} else {
|
} else {
|
||||||
throw new UnsupportedCommandException(wrapper.commandName());
|
throw new UnsupportedCommandException(wrapper.commandName());
|
||||||
}
|
}
|
||||||
} else if(wrapper.isWorkingDaysResource()) {
|
} else if (wrapper.isWorkingDaysResource()) {
|
||||||
if(wrapper.isUpdate()){
|
if (wrapper.isUpdate()) {
|
||||||
handler = this.applicationContext.getBean("updateWorkingDaysCommandHandler",NewCommandSourceHandler.class);
|
handler = this.applicationContext.getBean("updateWorkingDaysCommandHandler", NewCommandSourceHandler.class);
|
||||||
}else {
|
} else {
|
||||||
|
throw new UnsupportedCommandException(wrapper.commandName());
|
||||||
|
}
|
||||||
|
} else if (wrapper.isPasswordValidationPolicyResource()) {
|
||||||
|
if (wrapper.isUpdate()) {
|
||||||
|
handler = this.applicationContext.getBean("updatePasswordValidationPolicyCommandHandler", NewCommandSourceHandler.class);
|
||||||
|
|
||||||
|
} else {
|
||||||
throw new UnsupportedCommandException(wrapper.commandName());
|
throw new UnsupportedCommandException(wrapper.commandName());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+25
-10
@@ -5,6 +5,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.infrastructure.core.data;
|
package org.mifosplatform.infrastructure.core.data;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import net.fortuna.ical4j.model.ValidationException;
|
||||||
|
import net.fortuna.ical4j.model.property.RRule;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
|
import org.quartz.CronExpression;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -12,16 +20,6 @@ import java.util.List;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import net.fortuna.ical4j.model.ValidationException;
|
|
||||||
import net.fortuna.ical4j.model.property.RRule;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.joda.time.LocalDate;
|
|
||||||
import org.quartz.CronExpression;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
|
||||||
|
|
||||||
public class DataValidatorBuilder {
|
public class DataValidatorBuilder {
|
||||||
|
|
||||||
public static final String VALID_INPUT_SEPERATOR = "_";
|
public static final String VALID_INPUT_SEPERATOR = "_";
|
||||||
@@ -725,6 +723,23 @@ public class DataValidatorBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DataValidatorBuilder matchesRegularExpression(final String expression, final String Message) {
|
||||||
|
if (this.value == null && this.ignoreNullValue) { return this; }
|
||||||
|
|
||||||
|
if (this.value != null && !this.value.toString().matches(expression)) {
|
||||||
|
final StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append(this.resource).append(".")
|
||||||
|
.append(this.parameter).append(".does.not.match.regexp");
|
||||||
|
final StringBuilder defaultEnglishMessage = new StringBuilder(Message);
|
||||||
|
|
||||||
|
final ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(),
|
||||||
|
defaultEnglishMessage.toString(), this.parameter, this.value, expression);
|
||||||
|
|
||||||
|
this.dataValidationErrors.add(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private DataValidatorBuilder validateStringFor(final String validInputs) {
|
private DataValidatorBuilder validateStringFor(final String validInputs) {
|
||||||
if (this.value == null && this.ignoreNullValue) { return this; }
|
if (this.value == null && this.ignoreNullValue) { return this; }
|
||||||
final String[] inputs = validInputs.split(VALID_INPUT_SEPERATOR);
|
final String[] inputs = validInputs.split(VALID_INPUT_SEPERATOR);
|
||||||
|
|||||||
+96
@@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.useradministration.api;
|
||||||
|
|
||||||
|
import org.mifosplatform.commands.domain.CommandWrapper;
|
||||||
|
import org.mifosplatform.commands.service.CommandWrapperBuilder;
|
||||||
|
import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||||
|
import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||||
|
import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||||
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
|
import org.mifosplatform.useradministration.data.PasswordValidationPolicyData;
|
||||||
|
import org.mifosplatform.useradministration.data.RoleData;
|
||||||
|
import org.mifosplatform.useradministration.data.RolePermissionsData;
|
||||||
|
import org.mifosplatform.useradministration.service.PasswordValidationPolicyReadPlatformService;
|
||||||
|
import org.mifosplatform.useradministration.service.PermissionReadPlatformService;
|
||||||
|
import org.mifosplatform.useradministration.service.RoleReadPlatformService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.ws.rs.*;
|
||||||
|
import javax.ws.rs.core.Context;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Path("/passwordValidationPolicy")
|
||||||
|
@Component
|
||||||
|
@Scope("singleton")
|
||||||
|
public class PasswordValidationPolicyApiResource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set of parameters that are supported in response for {@link org.mifosplatform.useradministration.data.RoleData}
|
||||||
|
*/
|
||||||
|
private final Set<String> RESPONSE_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "description",
|
||||||
|
"active"));
|
||||||
|
|
||||||
|
|
||||||
|
private final String resourceNameForPermissions = "Password_Validation_Policy";
|
||||||
|
|
||||||
|
private final PlatformSecurityContext context;
|
||||||
|
private final PasswordValidationPolicyReadPlatformService passwordValidationPolicyReadPlatformService;
|
||||||
|
private final DefaultToApiJsonSerializer<PasswordValidationPolicyData> toApiJsonSerializer;
|
||||||
|
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||||
|
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public PasswordValidationPolicyApiResource(final PlatformSecurityContext context, final PasswordValidationPolicyReadPlatformService readPlatformService,
|
||||||
|
final DefaultToApiJsonSerializer<PasswordValidationPolicyData> toApiJsonSerializer,
|
||||||
|
final ApiRequestParameterHelper apiRequestParameterHelper,
|
||||||
|
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) {
|
||||||
|
this.context = context;
|
||||||
|
this.passwordValidationPolicyReadPlatformService = readPlatformService;
|
||||||
|
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||||
|
this.apiRequestParameterHelper = apiRequestParameterHelper;
|
||||||
|
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
public String retrieveAllPolicy(@Context final UriInfo uriInfo) {
|
||||||
|
|
||||||
|
this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions);
|
||||||
|
|
||||||
|
final Collection<PasswordValidationPolicyData> validationPolicies = this.passwordValidationPolicyReadPlatformService.retrieveAll();
|
||||||
|
|
||||||
|
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||||
|
return this.toApiJsonSerializer.serialize( settings,validationPolicies ,this.RESPONSE_DATA_PARAMETERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("{validationPolicyId}")
|
||||||
|
@Consumes({ MediaType.APPLICATION_JSON })
|
||||||
|
@Produces({ MediaType.APPLICATION_JSON })
|
||||||
|
public String activate(@PathParam("validationPolicyId") final Long validationPolicyId, final String apiRequestBodyAsJson) {
|
||||||
|
|
||||||
|
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
|
||||||
|
.activatePasswordValidationPolicy(validationPolicyId) //
|
||||||
|
.withJson(apiRequestBodyAsJson) //
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||||
|
|
||||||
|
return this.toApiJsonSerializer.serialize(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.useradministration.data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immutable data object for role data.
|
||||||
|
*/
|
||||||
|
public class PasswordValidationPolicyData implements Serializable {
|
||||||
|
|
||||||
|
private final Long id;
|
||||||
|
private final String description;
|
||||||
|
private final boolean active;
|
||||||
|
|
||||||
|
|
||||||
|
public PasswordValidationPolicyData(final Long id, final Boolean active, final String description) {
|
||||||
|
this.id = id;
|
||||||
|
this.active = active;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+81
@@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.useradministration.domain;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "m_password_validation_policy")
|
||||||
|
public class PasswordValidationPolicy extends AbstractPersistable<Long> {
|
||||||
|
|
||||||
|
private final static Logger logger = LoggerFactory.getLogger(PasswordValidationPolicy.class);
|
||||||
|
|
||||||
|
@Column(name = "regex", nullable = false)
|
||||||
|
private String regex;
|
||||||
|
|
||||||
|
@Column(name = "description", nullable = false)
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Column(name = "active", nullable = false)
|
||||||
|
private boolean active ;
|
||||||
|
|
||||||
|
public PasswordValidationPolicy(final String regex, final String description, final boolean active ) {
|
||||||
|
this.description = description;
|
||||||
|
this.regex = regex;
|
||||||
|
this.active = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PasswordValidationPolicy(){
|
||||||
|
this.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRegex() {
|
||||||
|
return regex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getActive() {
|
||||||
|
return this.active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> active(){
|
||||||
|
final Map<String, Object> actualChanges = new LinkedHashMap<>(1);
|
||||||
|
|
||||||
|
final String active = "active";
|
||||||
|
|
||||||
|
if(!this.active){
|
||||||
|
|
||||||
|
actualChanges.put(active, true);
|
||||||
|
this.active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return actualChanges;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isActive(){
|
||||||
|
return this.active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deActive(){
|
||||||
|
this.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.useradministration.domain;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
|
||||||
|
public interface PasswordValidationPolicyRepository extends JpaRepository<PasswordValidationPolicy, Long>,
|
||||||
|
JpaSpecificationExecutor<PasswordValidationPolicy> {
|
||||||
|
|
||||||
|
@Query("from PasswordValidationPolicy PVP WHERE PVP.active = 1")
|
||||||
|
public PasswordValidationPolicy findActivePasswordValidationPolicy();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.useradministration.exception;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link RuntimeException} thrown when role resources are not found.
|
||||||
|
*/
|
||||||
|
public class PasswordValidationPolicyNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||||
|
|
||||||
|
public PasswordValidationPolicyNotFoundException(final Long id) {
|
||||||
|
super("error.msg.validation.policy.id.invalid", "Password Validation Policy with identifier " + id + " does not exist", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.useradministration.handler;
|
||||||
|
|
||||||
|
import org.mifosplatform.commands.handler.NewCommandSourceHandler;
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.mifosplatform.useradministration.service.PasswordValidationPolicyWritePlatformService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class UpdatePasswordValidationPolicyCommandHandler implements NewCommandSourceHandler {
|
||||||
|
|
||||||
|
private final PasswordValidationPolicyWritePlatformService writePlatformService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public UpdatePasswordValidationPolicyCommandHandler(final PasswordValidationPolicyWritePlatformService writePlatformService) {
|
||||||
|
this.writePlatformService = writePlatformService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||||
|
|
||||||
|
final Long validationPolicyId = command.entityId();
|
||||||
|
return this.writePlatformService.activate(validationPolicyId, command);
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.useradministration.service;
|
||||||
|
|
||||||
|
import org.mifosplatform.useradministration.data.PasswordValidationPolicyData;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public interface PasswordValidationPolicyReadPlatformService {
|
||||||
|
|
||||||
|
Collection<PasswordValidationPolicyData> retrieveAll();
|
||||||
|
|
||||||
|
}
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.useradministration.service;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||||
|
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
|
||||||
|
import org.mifosplatform.useradministration.data.PasswordValidationPolicyData;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class PasswordValidationPolicyReadPlatformServiceImpl implements PasswordValidationPolicyReadPlatformService {
|
||||||
|
|
||||||
|
private final JdbcTemplate jdbcTemplate;
|
||||||
|
private final PasswordValidationPolicyMapper passwordValidationPolicyMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public PasswordValidationPolicyReadPlatformServiceImpl(final RoutingDataSource dataSource) {
|
||||||
|
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||||
|
this.passwordValidationPolicyMapper = new PasswordValidationPolicyMapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<PasswordValidationPolicyData> retrieveAll() {
|
||||||
|
final String sql = "select " + this.passwordValidationPolicyMapper.schema() + " order by pvp.id";
|
||||||
|
|
||||||
|
return this.jdbcTemplate.query(sql, this.passwordValidationPolicyMapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected static final class PasswordValidationPolicyMapper implements RowMapper<PasswordValidationPolicyData> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PasswordValidationPolicyData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||||
|
|
||||||
|
final Long id = JdbcSupport.getLong(rs, "id");
|
||||||
|
final Boolean active = rs.getBoolean("active");
|
||||||
|
final String description = rs.getString("description");
|
||||||
|
|
||||||
|
return new PasswordValidationPolicyData(id, active, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String schema() {
|
||||||
|
return " pvp.id as id, pvp.active as active, pvp.description as description from m_password_validation_policy pvp";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.useradministration.service;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
|
||||||
|
public interface PasswordValidationPolicyWritePlatformService {
|
||||||
|
|
||||||
|
|
||||||
|
CommandProcessingResult activate(Long validationPolicyId, JsonCommand command);
|
||||||
|
|
||||||
|
}
|
||||||
+109
@@ -0,0 +1,109 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.useradministration.service;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
|
||||||
|
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||||
|
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||||
|
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||||
|
import org.mifosplatform.useradministration.domain.PasswordValidationPolicy;
|
||||||
|
import org.mifosplatform.useradministration.domain.PasswordValidationPolicyRepository;
|
||||||
|
import org.mifosplatform.useradministration.domain.PermissionRepository;
|
||||||
|
import org.mifosplatform.useradministration.exception.PasswordValidationPolicyNotFoundException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.cache.annotation.Caching;
|
||||||
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class PasswordValidationPolicyWritePlatformServiceJpaRepositoryImpl implements PasswordValidationPolicyWritePlatformService {
|
||||||
|
|
||||||
|
private final static Logger logger = LoggerFactory.getLogger(PasswordValidationPolicyWritePlatformServiceJpaRepositoryImpl.class);
|
||||||
|
private final PlatformSecurityContext context;
|
||||||
|
private final PasswordValidationPolicyRepository validationRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public PasswordValidationPolicyWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final PasswordValidationPolicyRepository validationPolicyRepository,
|
||||||
|
final PermissionRepository permissionRepository) {
|
||||||
|
this.context = context;
|
||||||
|
this.validationRepository = validationPolicyRepository;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Guaranteed to throw an exception no matter what the data integrity issue
|
||||||
|
* is.
|
||||||
|
*/
|
||||||
|
private void handleDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) {
|
||||||
|
|
||||||
|
logAsErrorUnexpectedDataIntegrityException(dve);
|
||||||
|
throw new PlatformDataIntegrityException("error.msg.role.unknown.data.integrity.issue",
|
||||||
|
"Unknown data integrity issue with resource.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logAsErrorUnexpectedDataIntegrityException(final DataIntegrityViolationException dve) {
|
||||||
|
logger.error(dve.getMessage(), dve);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public CommandProcessingResult activate(final Long validationPolicyId, final JsonCommand command) {
|
||||||
|
try {
|
||||||
|
this.context.authenticatedUser();
|
||||||
|
|
||||||
|
final List<PasswordValidationPolicy> validationPolicies = this.validationRepository.findAll();
|
||||||
|
|
||||||
|
Map<String, Object> changes = new LinkedHashMap<>(1);
|
||||||
|
|
||||||
|
boolean found = false;
|
||||||
|
|
||||||
|
for(PasswordValidationPolicy policy:validationPolicies){
|
||||||
|
|
||||||
|
if(policy.getId().equals(validationPolicyId)){
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
if(!policy.isActive()){
|
||||||
|
changes = policy.active();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(policy.isActive() && !policy.getId().equals(validationPolicyId)){
|
||||||
|
policy.deActive();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!found) { throw new PasswordValidationPolicyNotFoundException(validationPolicyId); }
|
||||||
|
|
||||||
|
if (!changes.isEmpty()) {
|
||||||
|
this.validationRepository.save(validationPolicies);
|
||||||
|
this.validationRepository.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommandProcessingResultBuilder() //
|
||||||
|
.withCommandId(command.commandId()) //
|
||||||
|
.withEntityId(validationPolicyId) //
|
||||||
|
.with(changes) //
|
||||||
|
.build();
|
||||||
|
} catch (final DataIntegrityViolationException dve) {
|
||||||
|
handleDataIntegrityIssues(command, dve);
|
||||||
|
return new CommandProcessingResultBuilder() //
|
||||||
|
.withCommandId(command.commandId()) //
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+17
-3
@@ -19,6 +19,8 @@ import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
|||||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||||
|
import org.mifosplatform.useradministration.domain.PasswordValidationPolicy;
|
||||||
|
import org.mifosplatform.useradministration.domain.PasswordValidationPolicyRepository;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -36,9 +38,12 @@ public final class UserDataValidator {
|
|||||||
|
|
||||||
private final FromJsonHelper fromApiJsonHelper;
|
private final FromJsonHelper fromApiJsonHelper;
|
||||||
|
|
||||||
|
private final PasswordValidationPolicyRepository passwordValidationPolicy;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public UserDataValidator(final FromJsonHelper fromApiJsonHelper) {
|
public UserDataValidator(final FromJsonHelper fromApiJsonHelper, final PasswordValidationPolicyRepository passwordValidationPolicy) {
|
||||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||||
|
this.passwordValidationPolicy = passwordValidationPolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void validateForCreate(final String json) {
|
public void validateForCreate(final String json) {
|
||||||
@@ -69,7 +74,11 @@ public final class UserDataValidator {
|
|||||||
} else {
|
} else {
|
||||||
final String password = this.fromApiJsonHelper.extractStringNamed("password", element);
|
final String password = this.fromApiJsonHelper.extractStringNamed("password", element);
|
||||||
final String repeatPassword = this.fromApiJsonHelper.extractStringNamed("repeatPassword", element);
|
final String repeatPassword = this.fromApiJsonHelper.extractStringNamed("repeatPassword", element);
|
||||||
baseDataValidator.reset().parameter("password").value(password).notBlank().notExceedingLengthOf(50);
|
final PasswordValidationPolicy validationPolicy = this.passwordValidationPolicy.findActivePasswordValidationPolicy();
|
||||||
|
final String regex = validationPolicy.getRegex();
|
||||||
|
final String description = validationPolicy.getDescription();
|
||||||
|
baseDataValidator.reset().parameter("password").value(password).matchesRegularExpression(regex,description);
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(password)) {
|
if (StringUtils.isNotBlank(password)) {
|
||||||
baseDataValidator.reset().parameter("password").value(password).equalToParameter("repeatPassword", repeatPassword);
|
baseDataValidator.reset().parameter("password").value(password).equalToParameter("repeatPassword", repeatPassword);
|
||||||
}
|
}
|
||||||
@@ -151,7 +160,12 @@ public final class UserDataValidator {
|
|||||||
if (this.fromApiJsonHelper.parameterExists("password", element)) {
|
if (this.fromApiJsonHelper.parameterExists("password", element)) {
|
||||||
final String password = this.fromApiJsonHelper.extractStringNamed("password", element);
|
final String password = this.fromApiJsonHelper.extractStringNamed("password", element);
|
||||||
final String repeatPassword = this.fromApiJsonHelper.extractStringNamed("repeatPassword", element);
|
final String repeatPassword = this.fromApiJsonHelper.extractStringNamed("repeatPassword", element);
|
||||||
baseDataValidator.reset().parameter("password").value(password).notBlank().notExceedingLengthOf(50);
|
|
||||||
|
final PasswordValidationPolicy validationPolicy = this.passwordValidationPolicy.findActivePasswordValidationPolicy();
|
||||||
|
final String regex = validationPolicy.getRegex();
|
||||||
|
final String description = validationPolicy.getDescription();
|
||||||
|
baseDataValidator.reset().parameter("password").value(password).matchesRegularExpression(regex,description);
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(password)) {
|
if (StringUtils.isNotBlank(password)) {
|
||||||
baseDataValidator.reset().parameter("password").value(password).equalToParameter("repeatPassword", repeatPassword);
|
baseDataValidator.reset().parameter("password").value(password).equalToParameter("repeatPassword", repeatPassword);
|
||||||
}
|
}
|
||||||
|
|||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `m_password_validation_policy` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`regex` text NOT NULL,
|
||||||
|
`description` text NOT NULL,
|
||||||
|
`active` tinyint(4) NOT NULL DEFAULT '0',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO `m_password_validation_policy` (
|
||||||
|
`id` ,
|
||||||
|
`regex` ,
|
||||||
|
`description` ,
|
||||||
|
`active`
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
NULL , '^.{1,50}$', 'Password most be at least 1 character and not more that 50 characters long', '1'
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO `m_password_validation_policy` (
|
||||||
|
`id` ,
|
||||||
|
`regex` ,
|
||||||
|
`description` ,
|
||||||
|
`active`
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
NULL , '^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\\s).{6,50}$', 'Password must be at least 6 characters, no more than 50 characters long, must include at least one upper case letter, one lower case letter, one numeric digit and no space', '0'
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||||
|
VALUE ("authorisation","READ_PASSWORD_VALIDATION_POLICY","PASSWORD_VALIDATION_POLICY","READ",0);
|
||||||
|
|
||||||
|
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||||
|
VALUE ("authorisation","UPDATE_PASSWORD_VALIDATION_POLICY","PASSWORD_VALIDATION_POLICY","UPDATE",0);
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user