MIFOSX-1875 password validation policy
This commit is contained in:
@@ -2026,6 +2026,14 @@
|
||||
<td><a href="#permissions_update">Enable/Disable Permissions for Maker Checker</a></td>
|
||||
<td></td>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
@@ -30709,7 +30717,70 @@ Request Body:
|
||||
</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 -->
|
||||
<a id="glaccounts" name="glaccounts" class="old-syle-anchor"> </a>
|
||||
<div class="method-section">
|
||||
|
||||
@@ -31,6 +31,8 @@ public class CommandWrapper {
|
||||
@SuppressWarnings("unused")
|
||||
private Long templateId;
|
||||
|
||||
|
||||
|
||||
public static CommandWrapper wrap(final String actionName, final String entityName, final Long resourceId, final Long subresourceId) {
|
||||
return new CommandWrapper(null, actionName, entityName, resourceId, subresourceId, null, null);
|
||||
}
|
||||
@@ -1008,4 +1010,13 @@ public class CommandWrapper {
|
||||
public boolean isEnableOperation() {
|
||||
return this.actionName.equalsIgnoreCase("ENABLE");
|
||||
}
|
||||
|
||||
public boolean isPasswordValidationPolicyResource(){
|
||||
return this.entityName.equalsIgnoreCase("PASSWORD_VALIDATION_POLICY");}
|
||||
|
||||
|
||||
public boolean isActivatePasswordValidationPolicy(){
|
||||
return this.actionName.equalsIgnoreCase("UPDATE");
|
||||
}
|
||||
|
||||
}
|
||||
+8
-1
@@ -2308,7 +2308,6 @@ public class CommandWrapperBuilder {
|
||||
this.json = "{}";
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandWrapperBuilder disableRole(Long roleId) {
|
||||
this.actionName = "DISABLE";
|
||||
this.entityName = "ROLE";
|
||||
@@ -2327,4 +2326,12 @@ public class CommandWrapperBuilder {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
+14
-3
@@ -5,8 +5,6 @@
|
||||
*/
|
||||
package org.mifosplatform.commands.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.mifosplatform.commands.domain.CommandSource;
|
||||
import org.mifosplatform.commands.domain.CommandSourceRepository;
|
||||
@@ -29,6 +27,8 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class SynchronousCommandProcessingService implements CommandProcessingService {
|
||||
|
||||
@@ -910,7 +910,18 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
} else {
|
||||
|
||||
}else if (wrapper.isPasswordValidationPolicyResource()) {
|
||||
|
||||
if (wrapper.isActivatePasswordValidationPolicy()) {
|
||||
|
||||
handler = this.applicationContext.getBean("updatePasswordValidationPolicyCommandHandler", NewCommandSourceHandler.class);
|
||||
|
||||
} else {
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
throw new UnsupportedCommandException(wrapper.commandName());
|
||||
}
|
||||
|
||||
+25
-10
@@ -5,6 +5,14 @@
|
||||
*/
|
||||
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.text.ParseException;
|
||||
import java.util.Arrays;
|
||||
@@ -12,16 +20,6 @@ import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
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 static final String VALID_INPUT_SEPERATOR = "_";
|
||||
@@ -725,6 +723,23 @@ public class DataValidatorBuilder {
|
||||
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) {
|
||||
if (this.value == null && this.ignoreNullValue) { return this; }
|
||||
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.PlatformApiDataValidationException;
|
||||
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.stereotype.Component;
|
||||
|
||||
@@ -36,9 +38,12 @@ public final class UserDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
private final PasswordValidationPolicyRepository passwordValidationPolicy;
|
||||
|
||||
@Autowired
|
||||
public UserDataValidator(final FromJsonHelper fromApiJsonHelper) {
|
||||
public UserDataValidator(final FromJsonHelper fromApiJsonHelper, final PasswordValidationPolicyRepository passwordValidationPolicy) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
this.passwordValidationPolicy = passwordValidationPolicy;
|
||||
}
|
||||
|
||||
public void validateForCreate(final String json) {
|
||||
@@ -69,7 +74,11 @@ public final class UserDataValidator {
|
||||
} else {
|
||||
final String password = this.fromApiJsonHelper.extractStringNamed("password", 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)) {
|
||||
baseDataValidator.reset().parameter("password").value(password).equalToParameter("repeatPassword", repeatPassword);
|
||||
}
|
||||
@@ -145,7 +154,12 @@ public final class UserDataValidator {
|
||||
if (this.fromApiJsonHelper.parameterExists("password", element)) {
|
||||
final String password = this.fromApiJsonHelper.extractStringNamed("password", 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)) {
|
||||
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