Skip to content

Commit

Permalink
MGR-94
Browse files Browse the repository at this point in the history
  • Loading branch information
madness-inc committed Feb 7, 2020
1 parent f3d870c commit d72ddb8
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 50 deletions.
Expand Up @@ -61,14 +61,14 @@ public void perform(Site site, Application application, Environment environment,
try {
if (ACTION_CREATE.equals(action)) {
errorMessage = MessageConstants.SUBJECT_CREATE_ERROR;
service.createSubject(request, environment.getLocale(), valueHolder, fp);
service.createSubject(request, environment.getLocale(), valueHolder, fp, site.getPasswordPolicy());
okMessage = MessageConstants.SUBJECT_CREATED;
} else if (ACTION_UPDATE.equals(action)) {
SubjectImpl subject = valueHolder.getSubject();
subject.setId(subjectId);
okMessage = MessageConstants.SUBJECT_UPDATED;
errorMessage = MessageConstants.SUBJECT_UPDATE_ERROR;
Boolean isUpdated = service.updateSubject(request, valueHolder, fp);
Boolean isUpdated = service.updateSubject(request, valueHolder, fp, site.getPasswordPolicy());
if (isUpdated) {
String passwordMessage = request.getMessage(MessageConstants.SUBJECT_PASSWORD_UPDATED, subjectId);
fp.addOkMessage(passwordMessage);
Expand Down
29 changes: 19 additions & 10 deletions src/main/java/org/appng/application/manager/form/SubjectForm.java
Expand Up @@ -15,6 +15,7 @@
*/
package org.appng.application.manager.form;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

Expand All @@ -24,22 +25,25 @@
import org.appng.api.Environment;
import org.appng.api.FieldProcessor;
import org.appng.api.FormValidator;
import org.appng.api.MessageParam;
import org.appng.api.Options;
import org.appng.api.Request;
import org.appng.api.auth.PasswordPolicy;
import org.appng.api.auth.PasswordPolicy.ValidationResult;
import org.appng.api.model.Application;
import org.appng.api.model.Site;
import org.appng.api.model.UserType;
import org.appng.application.manager.MessageConstants;
import org.appng.core.domain.SubjectImpl;
import org.appng.xml.platform.FieldDef;
import org.appng.xml.platform.Validation;

/**
* Bindclass used for creating/updating a {@link SubjectImpl}.
*
* @author Matthias Müller
*
*/
public class SubjectForm implements FormValidator {
public class SubjectForm implements FormValidator, Serializable {
private SubjectImpl subject;
private List<Integer> groupIds = new ArrayList<Integer>();
private String password;
Expand All @@ -63,10 +67,11 @@ public void validate(Site site, Application application, Environment environment
}

String action = options.getOptionValue("action", "id");
FieldDef passwordField = fp.getField("password");
if ("create".equals(action)) {
if (null == password) {
String message = request.getMessage(MessageConstants.SUBJECT_ENTER_PASSWORD);
fp.addErrorMessage(fp.getField("password"), message);
fp.addErrorMessage(passwordField, message);
}
if (null == passwordConfirmation) {
String message = request.getMessage(MessageConstants.SUBJECT_ENTER_PASSWORD_CONFIRMATION);
Expand All @@ -76,13 +81,17 @@ public void validate(Site site, Application application, Environment environment

PasswordPolicy passwordPolicy = site.getPasswordPolicy();
if (!StringUtils.isEmpty(password)) {
if (!passwordPolicy.isValidPassword(password.toCharArray())) {
String message = request.getMessage(passwordPolicy.getErrorMessageKey());
fp.addErrorMessage(fp.getField("password"), message);
} else {
if (!StringUtils.equals(password, passwordConfirmation)) {
String message = request.getMessage(MessageConstants.SUBJECT_PASSWORDS_NO_MATCH);
fp.addErrorMessage(fp.getField("passwordConfirmation"), message);
ValidationResult validationResult = passwordPolicy.validatePassword(getSubject().getAuthName(), null,
password.toCharArray());
if (!StringUtils.equals(password, passwordConfirmation)) {
String message = request.getMessage(MessageConstants.SUBJECT_PASSWORDS_NO_MATCH);
passwordField.setValidation(new Validation());
fp.addErrorMessage(fp.getField("passwordConfirmation"), message);
} else if (!validationResult.isValid()) {
passwordField.setValidation(new Validation());
for (MessageParam m : validationResult.getMessages()) {
String errMssg = request.getMessage(m.getMessageKey(), m.getMessageArgs());
fp.addErrorMessage(passwordField, errMssg);
}
}
}
Expand Down
Expand Up @@ -53,6 +53,7 @@
import org.appng.api.RequestUtil;
import org.appng.api.Scope;
import org.appng.api.SiteProperties;
import org.appng.api.auth.PasswordPolicy;
import org.appng.api.model.Application;
import org.appng.api.model.AuthSubject.PasswordChangePolicy;
import org.appng.api.model.Group;
Expand Down Expand Up @@ -1271,8 +1272,8 @@ private NameProvider<UserType> getUserTypeNameProvider(Request request) {
return instance -> request.getMessage(UserType.class.getSimpleName() + "." + instance.name());
}

public void createSubject(Request request, Locale locale, SubjectForm form, FieldProcessor fp)
throws BusinessException {
public void createSubject(Request request, Locale locale, SubjectForm form, FieldProcessor fp,
PasswordPolicy policy) throws BusinessException {
try {
SubjectImpl subject = form.getSubject();
SubjectImpl subjectByName = getSubjectByName(subject.getName(), false);
Expand All @@ -1282,7 +1283,7 @@ public void createSubject(Request request, Locale locale, SubjectForm form, Fiel
}

if (form.isLocalUser()) {
updatePassword(form.getPassword().toCharArray(), form.getPasswordConfirmation().toCharArray(), subject);
updatePassword(policy, null, form.getPassword().toCharArray(), subject);
}
subjectRepository.save(subject);
assignGroupsToSubject(request, subject.getId(), form.getGroupIds(), fp);
Expand All @@ -1291,8 +1292,9 @@ public void createSubject(Request request, Locale locale, SubjectForm form, Fiel
}
}

public Boolean updateSubject(Request request, SubjectForm subjectForm, FieldProcessor fp) throws BusinessException {
Boolean updated = false;
public Boolean updateSubject(Request request, SubjectForm subjectForm, FieldProcessor fp, PasswordPolicy policy)
throws BusinessException {
Boolean passwordUpdated = false;
SubjectImpl subject = subjectForm.getSubject();
try {
if (subject.getId() != null) {
Expand All @@ -1302,8 +1304,7 @@ public Boolean updateSubject(Request request, SubjectForm subjectForm, FieldProc
}
if (!StringUtils.isEmpty(subjectForm.getPassword())
&& !StringUtils.isEmpty(subjectForm.getPasswordConfirmation())) {
updated = updatePassword(subjectForm.getPassword().toCharArray(),
subjectForm.getPasswordConfirmation().toCharArray(), currentSubject);
passwordUpdated = updatePassword(policy, null, subjectForm.getPassword().toCharArray(), subject).isValid();
}
assignGroupsToSubject(request, subject.getId(), subjectForm.getGroupIds(), fp);
request.setPropertyValues(subjectForm, new SubjectForm(currentSubject), fp.getMetaData());
Expand All @@ -1313,7 +1314,7 @@ public Boolean updateSubject(Request request, SubjectForm subjectForm, FieldProc
} catch (Exception e) {
request.handleException(fp, e);
}
return updated;
return passwordUpdated;
}

public void assignGroupsToSubject(Request request, Integer subjectId, List<Integer> groupIds, FieldProcessor fp)
Expand Down
Expand Up @@ -26,6 +26,7 @@
import org.appng.api.Environment;
import org.appng.api.FieldProcessor;
import org.appng.api.Request;
import org.appng.api.auth.PasswordPolicy;
import org.appng.api.model.Application;
import org.appng.api.model.Identifier;
import org.appng.api.model.Permission;
Expand Down Expand Up @@ -74,7 +75,7 @@ public interface Service {

void createSite(Request request, SiteForm sitesForm, FieldProcessor fp) throws BusinessException;

void createSubject(Request request, Locale locale, SubjectForm form, FieldProcessor fp) throws BusinessException;
void createSubject(Request request, Locale locale, SubjectForm form, FieldProcessor fp, PasswordPolicy policy) throws BusinessException;

void createProperty(Request request, PropertyForm propertyForm, Integer siteId, Integer appId, FieldProcessor fp)
throws BusinessException;
Expand Down Expand Up @@ -130,7 +131,7 @@ void updateApplication(Request request, Environment env, Application application

void updateSite(Request request, SiteForm sitesForm, FieldProcessor fp) throws BusinessException;

Boolean updateSubject(Request request, SubjectForm form, FieldProcessor fp) throws BusinessException;
Boolean updateSubject(Request request, SubjectForm form, FieldProcessor fp, PasswordPolicy policy) throws BusinessException;

void updateProperty(Request request, PropertyForm propertyForm, FieldProcessor fp) throws BusinessException;

Expand Down
Expand Up @@ -24,10 +24,8 @@
import javax.persistence.EntityManager;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.appng.api.Platform;
import org.appng.api.SiteProperties;
import org.appng.api.auth.PasswordPolicy;
import org.appng.api.model.Property;
import org.appng.api.model.SimpleProperty;
import org.appng.api.support.environment.DefaultEnvironment;
Expand All @@ -39,6 +37,7 @@
import org.appng.core.repository.RoleRepository;
import org.appng.core.repository.SiteApplicationRepository;
import org.appng.core.repository.SiteRepository;
import org.appng.core.security.ConfigurablePasswordPolicy;
import org.appng.testsupport.TestBase;
import org.appng.testsupport.validation.WritingXmlValidator;
import org.junit.Before;
Expand Down Expand Up @@ -103,20 +102,9 @@ public void setSiteId() {
((DefaultEnvironment) environment).setSubject(subject);
Mockito.when(subject.getId()).thenReturn(42);
Mockito.when(site.getId()).thenReturn(1);
Mockito.when(site.getPasswordPolicy()).thenReturn(new PasswordPolicy() {

public boolean isValidPassword(char[] password) {
return true;
}

public String getErrorMessageKey() {
return null;
}

public String generatePassword() {
return RandomStringUtils.random(6);
}
});
ConfigurablePasswordPolicy policy = new ConfigurablePasswordPolicy();
policy.configure(null);
Mockito.when(site.getPasswordPolicy()).thenReturn(policy);
}

@Override
Expand Down
Expand Up @@ -71,8 +71,9 @@ public void testCreate() throws Exception {

SubjectImpl newSubject = getSubject();
SubjectForm subjectForm = new SubjectForm(newSubject);
subjectForm.setPassword("secret");
subjectForm.setPasswordConfirmation("secret");
String password = site.getPasswordPolicy().generatePassword();
subjectForm.setPassword(password);
subjectForm.setPasswordConfirmation(password);
subjectForm.getGroupIds().add(1);
subjectForm.getGroupIds().add(2);

Expand All @@ -87,8 +88,8 @@ public void testCreate() throws Exception {
SubjectImpl anotherSubject = getSubject();
anotherSubject.setName("user");
SubjectForm anotherForm = new SubjectForm(anotherSubject);
anotherForm.setPassword("foobar");
anotherForm.setPasswordConfirmation("foobar");
anotherForm.setPassword(password);
anotherForm.setPasswordConfirmation(password);
anotherForm.getGroupIds().add(1);
callableAction = getAction(SUBJECT_EVENT, "create").withParam(FORM_ACTION, "create").getCallableAction(
anotherForm);
Expand All @@ -99,6 +100,8 @@ public void testCreate() throws Exception {
@Test
public void testCreateValidationFail() throws Exception {
SubjectForm form = new SubjectForm();
form.setPassword("§");
form.setPasswordConfirmation("§");
form.getSubject().setUserType(UserType.LOCAL_USER);
CallableAction callableAction = getAction(SUBJECT_EVENT, "create").withParam(FORM_ACTION, "create")
.getCallableAction(form);
Expand All @@ -109,8 +112,9 @@ public void testCreateValidationFail() throws Exception {
@Test
public void testCreateNameExists() throws Exception {
SubjectForm form = new SubjectForm(getSubject());
form.setPassword("foobar");
form.setPasswordConfirmation("foobar");
String password = site.getPasswordPolicy().generatePassword();
form.setPassword(password);
form.setPasswordConfirmation(password);
CallableAction callableAction = getAction(SUBJECT_EVENT, "create").withParam(FORM_ACTION, "create")
.getCallableAction(form);
callableAction.perform();
Expand Down Expand Up @@ -159,8 +163,9 @@ public void testUpdate() throws Exception {
s.setRealname("Jane Doe");
s.setTimeZone("Europe/Zurich");
SubjectForm form = new SubjectForm(s);
form.setPassword("newpassword");
form.setPasswordConfirmation("newpassword");
String password = site.getPasswordPolicy().generatePassword();
form.setPassword(password);
form.setPasswordConfirmation(password);
CallableAction callableAction = getAction(SUBJECT_EVENT, "update").withParam("userId", "1")
.withParam(FORM_ACTION, "update").getCallableAction(form);

Expand Down
12 changes: 8 additions & 4 deletions src/test/resources/xml/SubjectsTest-testCreateValidationFail.xml
Expand Up @@ -82,15 +82,19 @@
</field>
<field name="password" type="password" binding="password">
<label id="password">Password</label>
<validation />
<messages ref="password">
<message ref="password" class="ERROR">Please enter the password.</message>
<message ref="password" class="ERROR">Password must contain 1 or more lowercase letters.</message>
<message ref="password" class="ERROR">Password must contain 1 or more uppercase letters.</message>
<message ref="password" class="ERROR">Password must contain 1 or more numbers.</message>
<message ref="password" class="ERROR">Password must contain 1 or more special characters. Allowed are
!"#$%&amp;'()*+,-./:;&lt;=&gt;?@[\]^_`{|}~</message>
<message ref="password" class="ERROR">Password must be at least 8 characters long.</message>
<message ref="password" class="ERROR">Password contains illegal character: '§'</message>
</messages>
</field>
<field name="passwordConfirmation" type="password" binding="passwordConfirmation">
<label id="password.confirmation">Password confirmation</label>
<messages ref="passwordConfirmation">
<message ref="passwordConfirmation" class="ERROR">Please confirm the password.</message>
</messages>
</field>
<field name="groups" type="list:checkbox" binding="groupIds">
<label id="groups">Groups</label>
Expand Down

0 comments on commit d72ddb8

Please sign in to comment.