diff --git a/cspi-installation/src/main/java/org/collectionspace/chain/installation/ServiceBindingsGeneration.java b/cspi-installation/src/main/java/org/collectionspace/chain/installation/ServiceBindingsGeneration.java index c5d53e2a12..8ec50699cc 100644 --- a/cspi-installation/src/main/java/org/collectionspace/chain/installation/ServiceBindingsGeneration.java +++ b/cspi-installation/src/main/java/org/collectionspace/chain/installation/ServiceBindingsGeneration.java @@ -7,6 +7,7 @@ import java.util.Arrays; import java.util.Set; +import org.apache.commons.io.FileUtils; import org.collectionspace.chain.csp.persistence.services.TenantSpec; import org.collectionspace.chain.csp.persistence.services.TenantSpec.RemoteClient; import org.collectionspace.chain.csp.schema.EmailData; @@ -16,6 +17,7 @@ import org.collectionspace.chain.csp.schema.Group; import org.collectionspace.chain.csp.schema.Instance; import org.collectionspace.chain.csp.schema.Option; +import org.collectionspace.chain.csp.schema.PasswordComplexityData; import org.collectionspace.chain.csp.schema.Record; import org.collectionspace.chain.csp.schema.Repeat; import org.collectionspace.chain.csp.schema.Spec; @@ -31,7 +33,6 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.commons.io.FileUtils; public class ServiceBindingsGeneration { private static final Logger log = LoggerFactory.getLogger(ServiceBindingsGeneration.class); @@ -200,6 +201,8 @@ private String doServiceBindingsCommon(String serviceBindingVersion) { // Set the bindings for email notifications makeEmailBindings(ele); + makePasswordComplexityBindings(ele); + makeUiBindings(ele); // add in if required @@ -452,7 +455,6 @@ private void makeEmailBindings(Element tenantBindingElement) { // into seconds; otherwise, ignore the 'daysvalid' field and use the configured 'tokenExpirationSeconds' value. // Element ele = passwordResetElement.addElement(new QName("tokenExpirationSeconds", nstenant)); - Integer secondsValid = emailData.getTokenExpirationDays() * 60 * 60 * 24; // Convert days into seconds ele.addText(emailData.getTokenExpirationSeconds().toString()); } @@ -473,6 +475,39 @@ private void makeEmailBindings(Element tenantBindingElement) { } } + private void makePasswordComplexityBindings(Element tenantBindings) { + PasswordComplexityData passwordComplexityData = spec.getPasswordComplexityData(); + if (passwordComplexityData != null && passwordComplexityData.isEnabled()) { + final var root = tenantBindings.addElement(new QName("passwordRequirementConfig", nstenant)); + + // passwordComplexity/enabled + root.addElement(new QName("enabled", nstenant)) + .addText(String.valueOf(passwordComplexityData.isEnabled())); + + // passwordComplexity/minLength + passwordComplexityData.getMinLength().ifPresent(minLength -> + root.addElement(new QName("minLength", nstenant)) + .addText(String.valueOf(minLength)) + ); + + // passwordComplexity/requireLowerCase + root.addElement(new QName("requireLowerCase", nstenant)) + .addText(String.valueOf(passwordComplexityData.requireLowerCase())); + + // passwordComplexity/requireUpperCase + root.addElement(new QName("requireUpperCase", nstenant)) + .addText(String.valueOf(passwordComplexityData.requireUpperCase())); + + // passwordComplexity/requireDigit + root.addElement(new QName("requireDigit", nstenant)) + .addText(String.valueOf(passwordComplexityData.requireDigit())); + + // passwordComplexity/requireLowerCase + root.addElement(new QName("requireSpecial", nstenant)) + .addText(String.valueOf(passwordComplexityData.requireSpecial())); + } + } + private void makeUiBindings(Element tenantBindingElement) { UiData uiData = spec.getUiData(); String baseUrl = (uiData != null) ? uiData.getBaseURL() : null; diff --git a/cspi-schema/logs/cspace-app-perflog.csv b/cspi-schema/logs/cspace-app-perflog.csv new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/PasswordComplexityData.java b/cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/PasswordComplexityData.java new file mode 100644 index 0000000000..db66881cd9 --- /dev/null +++ b/cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/PasswordComplexityData.java @@ -0,0 +1,58 @@ +package org.collectionspace.chain.csp.schema; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import org.collectionspace.chain.csp.config.ReadOnlySection; + +public class PasswordComplexityData { + final boolean enabled; + + final Integer minLength; + final boolean requireLowerCase; + final boolean requireUpperCase; + final boolean requireDigit; + final boolean requireSpecial; + + public PasswordComplexityData(ReadOnlySection section) { + enabled = Boolean.parseBoolean((String) section.getValue("/enabled")); + + minLength = parseIntFromSection(section, "/min-length"); + requireLowerCase = Boolean.parseBoolean((String) section.getValue("/require-lower-case")); + requireUpperCase = Boolean.parseBoolean((String) section.getValue("/require-upper-case")); + requireDigit = Boolean.parseBoolean((String) section.getValue("/require-digit")); + requireSpecial = Boolean.parseBoolean((String) section.getValue("/require-special")); + } + + private Integer parseIntFromSection(ReadOnlySection section, String path) { + final var asString = (String) section.getValue(path); + return asString == null ? null : Integer.parseInt(asString); + } + + public boolean isEnabled() { + return enabled; + } + + public boolean requireLowerCase() { + return requireLowerCase; + } + + public boolean requireUpperCase() { + return requireUpperCase; + } + + public boolean requireDigit() { + return requireDigit; + } + + public boolean requireSpecial() { + return requireSpecial; + } + + public Optional getMinLength() { + return Optional.ofNullable(minLength); + } + +} diff --git a/cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/Spec.java b/cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/Spec.java index e12a18aa56..863a401284 100644 --- a/cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/Spec.java +++ b/cspi-schema/src/main/java/org/collectionspace/chain/csp/schema/Spec.java @@ -62,6 +62,7 @@ public class Spec implements CSP, Configurable { private EmailData ed; private AdminData adminData; private UiData uiData; + private PasswordComplexityData passwordComplexityData; @Override public String getName() { return "schema"; } @@ -114,6 +115,16 @@ public Object populate(Object parent, ReadOnlySection section) { } }); + rules.addRule(SECTIONED, new String[] {"password-complexity"}, SECTION_PREFIX + "password-complexity", null, + new RuleTarget() { + @Override + public Object populate(Object parent, ReadOnlySection section) { + passwordComplexityData = new PasswordComplexityData(section); + return this; + } + }); + + rules.addRule(SECTIONED,new String[]{"ui"},SECTION_PREFIX+"ui",null,new RuleTarget(){ @Override public Object populate(Object parent, ReadOnlySection section) { @@ -445,6 +456,10 @@ public Object populate(Object parent, ReadOnlySection section) { } + public PasswordComplexityData getPasswordComplexityData() { + return passwordComplexityData; + } + public EmailData getEmailData() { return ed.getEmailData(); } public UiData getUiData() { return uiData != null ? uiData.getUiData() : null; } public AdminData getAdminData() { return adminData.getAdminData(); } diff --git a/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/ServicesStorageGenerator.java b/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/ServicesStorageGenerator.java index a2ccae55c2..fe7f613209 100644 --- a/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/ServicesStorageGenerator.java +++ b/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/ServicesStorageGenerator.java @@ -155,7 +155,7 @@ public Object populate(Object parent, ReadOnlySection milestone) throws Exceptio String tenantId = (String)milestone.getValue("/tenantId"); String tenantName = (String)milestone.getValue("/tenantName"); - RemoteClient remoteClient = tenantSpec.new RemoteClient(name, url, username, password, ssl, auth, tenantId, tenantName); + RemoteClient remoteClient = new TenantSpec.RemoteClient(name, url, username, password, ssl, auth, tenantId, tenantName); tenantSpec.addRemoteClient(remoteClient); return this; diff --git a/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/TenantSpec.java b/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/TenantSpec.java index 45d70b0dbc..55ec998d9f 100644 --- a/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/TenantSpec.java +++ b/cspi-services/src/main/java/org/collectionspace/chain/csp/persistence/services/TenantSpec.java @@ -51,7 +51,7 @@ public class TenantSpec { private Set defaultlanguages = new LinkedHashSet(); private Set defaultdateformats = new LinkedHashSet(); - public class RemoteClient { + public static class RemoteClient { private String name; private String url; private String user; diff --git a/pom.xml b/pom.xml index f49616a8dc..3a0452da9b 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ 9.0.0-SNAPSHOT ${revision} - 17 + 21 ${basedir}/tmp csmake UTF-8 @@ -283,33 +283,6 @@ - - maven-antrun-plugin - 1.8 - - - check-environment-vars - validate - - run - - - - - - - - - - - - - - - - - org.apache.maven.plugins diff --git a/tomcat-main/src/main/resources/defaults/settings.xml b/tomcat-main/src/main/resources/defaults/settings.xml index aa810625da..1122fe667e 100644 --- a/tomcat-main/src/main/resources/defaults/settings.xml +++ b/tomcat-main/src/main/resources/defaults/settings.xml @@ -4,23 +4,23 @@ Administrator 1 core - 60 - + 60 + 2592000 2592000 2592000 - + 2592000 2592000 2592000 2592000 - 2592000 - - 2592000 - + 2592000 + + 2592000 + 2592000 @@ -43,14 +43,22 @@ CollectionSpace Password reset request Hello {{greeting}},\n\r\n\rYou've started the process to reset your CollectionSpace account password. To finish resetting your password, go to the Reset Password page {{link}} on CollectionSpace.\n\r\n\rIf clicking the link doesn't work, copy and paste the following link into your browser address bar and click Go.\n\r\n\r{{link}}\n\r Thanks,\n\r\n\r CollectionSpace Administrator\n\r\n\rPlease do not reply to this email. This mailbox is not monitored and you will not receive a response. For assistance, contact your CollectionSpace Administrator directly. - + + + true + 6 + true + true + true + true + http://localhost:@JEE_PORT@/cspace-services - - - /collectionspace/tenant/core/ + + + /collectionspace/tenant/core/