diff --git a/docs/source/demos/mds/mds_with_code.rst b/docs/source/demos/mds/mds_with_code.rst index 7949ff5900..76f4640d20 100644 --- a/docs/source/demos/mds/mds_with_code.rst +++ b/docs/source/demos/mds/mds_with_code.rst @@ -60,7 +60,7 @@ Defining an entity in MDS is as simple as writing a Java class and defining a fe import org.motechproject.mds.annotations.Field; import org.motechproject.mds.annotations.UIDisplayable; - import org.apache.commons.lang.ObjectUtils; + import org.apache.commons.lang3.ObjectUtils; import org.joda.time.DateTime; import java.util.List; import java.util.Objects; @@ -433,7 +433,7 @@ Let's take a look at Patient. Here is how we might specify the entity: import org.motechproject.mds.annotations.Field; import org.motechproject.mds.annotations.Cascade; - import org.apache.commons.lang.ObjectUtils; + import org.apache.commons.lang3.ObjectUtils; import java.util.List; import java.util.Objects; @@ -476,7 +476,7 @@ The domain object for Provider is similar: import org.motechproject.mds.annotations.Field; import org.motechproject.mds.annotations.Cascade; - import org.apache.commons.lang.ObjectUtils; + import org.apache.commons.lang3.ObjectUtils; import java.util.List; import java.util.Objects; @@ -523,7 +523,7 @@ At the very least, a Concept in a concept dictionary requires a name and a data import org.motechproject.mds.annotations.UIDisplayable; import javax.jdo.annotations.Unique; - import org.apache.commons.lang.ObjectUtils; + import org.apache.commons.lang3.ObjectUtils; import java.util.List; import java.util.Objects; @@ -577,7 +577,7 @@ Hence, our Observation entity look like this: import org.motechproject.mds.annotations.Field; import javax.jdo.annotations.Persistent; - import org.apache.commons.lang.ObjectUtils; + import org.apache.commons.lang3.ObjectUtils; import java.util.List; import java.util.Objects; import java.util.Date; @@ -635,7 +635,7 @@ Because an Encounter may (and typically will) include numerous Observations abou import org.motechproject.mds.annotations.Entity; import org.motechproject.mds.annotations.Field; - import org.apache.commons.lang.ObjectUtils; + import org.apache.commons.lang3.ObjectUtils; import java.util.Objects; import java.util.Date; import java.util.Set; diff --git a/docs/source/deployment/felix_webconsole.rst b/docs/source/deployment/felix_webconsole.rst new file mode 100644 index 0000000000..6bc411af6a --- /dev/null +++ b/docs/source/deployment/felix_webconsole.rst @@ -0,0 +1,32 @@ +=================================== +Using Felix Web Console with MOTECH +=================================== + +.. contents:: Table of Contents + :depth: 2 + +Overview +======== + +MOTECH is built on top of the `Felix OSGi Framework `_. Thanks to this, users can install the Felix Web Console +on their installations and then use it for monitoring the server. + +Benefits of using the Web Console +================================= + +The Felix Web Console allows viewing details of all bundles installed in the system. It also allows installing and +uninstalling modules. Generally speaking the only benefit of using the web console over the MOTECH Admin module +is that it gives access to bundles that are not MOTECH modules - for example third party libraries such as Spring. +More information on the Web Console can be found in the `Web Console Documentation `_. + +Installation +============ + +The Web Console can be installed by simply downloading it from the `Felix Downloads Page`_ into the +*~/.motech/bundles* directory belonging to the user running MOTECH. The console should become active after starting MOTECH. + +Accessing the Console +===================== + +The console should be available after appending *module/system/console* to your MOTECH server url. The default login +is admin/admin. Refer to the `Web Console Documentation `_ for ways to change it. diff --git a/docs/source/deployment/index.rst b/docs/source/deployment/index.rst index f11b84806b..53888e4a48 100644 --- a/docs/source/deployment/index.rst +++ b/docs/source/deployment/index.rst @@ -6,4 +6,5 @@ Deployment :maxdepth: 1 sticky_session_apache - multibyte_characters \ No newline at end of file + multibyte_characters + felix_webconsole \ No newline at end of file diff --git a/docs/source/development/external_bundles.rst b/docs/source/development/external_bundles.rst index 182c618085..a048cb6e57 100644 --- a/docs/source/development/external_bundles.rst +++ b/docs/source/development/external_bundles.rst @@ -128,7 +128,7 @@ pom.xml file for creating a bundle from org.example.example-artifact, version 1. org.apache.felix maven-bundle-plugin - 2.3.4 + 3.5.1 true diff --git a/docs/source/get_started/model_data/model_data.rst b/docs/source/get_started/model_data/model_data.rst index 3bfa4dd259..3ac3da47e7 100644 --- a/docs/source/get_started/model_data/model_data.rst +++ b/docs/source/get_started/model_data/model_data.rst @@ -870,6 +870,49 @@ lookup field, the customOperator field of the @LookupField annotation has to be The list of standard JDO operators that can be used in lookups is defined as constants in the class **org.motechproject.mds.util.Constants.Operators**. +Defining editable lookups for DDE entities +########################################## + +One way to define lookups for DDE entities is to include a :code:`mds-lookups.json` file in module resource directory. +The file should be a valid array of :code:`EntityLookups` class objects. Every lookup defined in the file will be added +only once, so even after user had deleted lookup it won't be recreated during module or MOTECH restart. This gives the +user complete control over those lookups without any restrictions. The unique identifier of every lookup is its +entity class name and lookup name combination. This is intended way for modules to define lookups that should be made +editable by the end user. Backend code should not depend on these lookups. + +Example :code:`mds-lookups.json` file. + +.. code-block:: json + + [ + { + "entityClassName" : "org.motechproject.tasks.domain.Task", + "lookups" : [ + { + "lookupName" : "Find Task by Owner", + "singleObjectReturn" : false, + "exposedViaRest" : false, + "lookupFields" : [ + { + "name" : "owner", + "type" : "VALUE", + "customOperator" : "\u003d\u003d", + "useGenericParam" : false + } + ], + "readOnly" : false, + "methodName" : "findTaskByOwner", + "fieldsOrder" : [ + "owner" + ] + } + ] + } + ] + +Including the example json in Tasks module will result in adding lookup for Task entity that will return all tasks that +are owned by the specified user. + Programmatic usage of DDE entities ################################## diff --git a/modules/admin/pom.xml b/modules/admin/pom.xml index 7a46c3f47f..9262399da3 100644 --- a/modules/admin/pom.xml +++ b/modules/admin/pom.xml @@ -3,13 +3,13 @@ motech org.motechproject - 0.27-SNAPSHOT + 0.27.8 ../../ 4.0.0 motech-admin - 0.27-SNAPSHOT + 0.27.8 MOTECH Admin bundle @@ -65,29 +65,33 @@ org.apache.activemq org.motechproject.org.apache.activemq - + + + com.fasterxml.jackson.core + jackson-databind org.apache.servicemix.bundles org.apache.servicemix.bundles.cglib - + - - org.springframework - spring-test-mvc + + org.sonatype.aether org.motechproject.aether-api @@ -154,7 +158,7 @@ org.apache.felix maven-bundle-plugin - 2.3.4 + 3.5.1 true @@ -177,6 +181,12 @@ org.springframework.web.servlet.config, org.eclipse.gemini.blueprint.config, org.springframework.security.config, + org.datanucleus.enhancement, + org.springframework.validation.beanvalidation, + org.springframework.core, + org.springframework.cglib.proxy, + org.springframework.cglib.core, + org.springframework.cglib.reflect, * diff --git a/modules/admin/src/main/java/org/motechproject/admin/bundles/DefaultBundleFilter.java b/modules/admin/src/main/java/org/motechproject/admin/bundles/DefaultBundleFilter.java index 893fd284f8..8bbb44d389 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/bundles/DefaultBundleFilter.java +++ b/modules/admin/src/main/java/org/motechproject/admin/bundles/DefaultBundleFilter.java @@ -1,6 +1,6 @@ package org.motechproject.admin.bundles; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.springframework.beans.factory.annotation.Autowired; diff --git a/modules/admin/src/main/java/org/motechproject/admin/bundles/ExtendedBundleInformation.java b/modules/admin/src/main/java/org/motechproject/admin/bundles/ExtendedBundleInformation.java index 4d5daf30bf..09bc159e81 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/bundles/ExtendedBundleInformation.java +++ b/modules/admin/src/main/java/org/motechproject/admin/bundles/ExtendedBundleInformation.java @@ -1,6 +1,6 @@ package org.motechproject.admin.bundles; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.motechproject.server.api.BundleInformation; import org.osgi.framework.Bundle; diff --git a/modules/admin/src/main/java/org/motechproject/admin/bundles/ImportExportResolver.java b/modules/admin/src/main/java/org/motechproject/admin/bundles/ImportExportResolver.java index 15b28a3af8..0692304111 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/bundles/ImportExportResolver.java +++ b/modules/admin/src/main/java/org/motechproject/admin/bundles/ImportExportResolver.java @@ -1,6 +1,6 @@ package org.motechproject.admin.bundles; -import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang3.ArrayUtils; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.service.packageadmin.ExportedPackage; diff --git a/modules/admin/src/main/java/org/motechproject/admin/domain/NotificationRule.java b/modules/admin/src/main/java/org/motechproject/admin/domain/NotificationRule.java index 626ba861ce..110113c6c6 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/domain/NotificationRule.java +++ b/modules/admin/src/main/java/org/motechproject/admin/domain/NotificationRule.java @@ -1,6 +1,6 @@ package org.motechproject.admin.domain; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.motechproject.admin.messages.ActionType; import org.motechproject.admin.messages.Level; import org.motechproject.mds.annotations.Access; @@ -21,6 +21,8 @@ @Entity(recordHistory = true) @Access(value = SecurityMode.PERMISSIONS, members = {"manageMessages"}) public class NotificationRule { + + @Field private Long id; @Field(required = true) diff --git a/modules/admin/src/main/java/org/motechproject/admin/domain/StatusMessage.java b/modules/admin/src/main/java/org/motechproject/admin/domain/StatusMessage.java index 454a4f5e48..a7defcac15 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/domain/StatusMessage.java +++ b/modules/admin/src/main/java/org/motechproject/admin/domain/StatusMessage.java @@ -18,6 +18,7 @@ @Entity(nonEditable = true) @Access(value = SecurityMode.PERMISSIONS, members = {"manageMessages"}) public class StatusMessage { + @Field(required = true) private String text; diff --git a/modules/admin/src/main/java/org/motechproject/admin/internal/service/impl/ModuleAdminServiceImpl.java b/modules/admin/src/main/java/org/motechproject/admin/internal/service/impl/ModuleAdminServiceImpl.java index 959098e99f..d26c3503d8 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/internal/service/impl/ModuleAdminServiceImpl.java +++ b/modules/admin/src/main/java/org/motechproject/admin/internal/service/impl/ModuleAdminServiceImpl.java @@ -2,7 +2,7 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.maven.wagon.ConnectionException; import org.apache.maven.wagon.Wagon; import org.apache.maven.wagon.authentication.AuthenticationException; @@ -24,12 +24,14 @@ import org.motechproject.server.api.BundleIcon; import org.motechproject.server.api.BundleInformation; import org.motechproject.server.api.JarInformation; +import org.motechproject.server.api.PomInformation; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.Constants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.sonatype.aether.RepositoryException; import org.sonatype.aether.RepositorySystem; import org.sonatype.aether.artifact.Artifact; import org.sonatype.aether.collection.CollectRequest; @@ -38,6 +40,8 @@ import org.sonatype.aether.graph.Dependency; import org.sonatype.aether.repository.LocalRepository; import org.sonatype.aether.repository.RemoteRepository; +import org.sonatype.aether.resolution.ArtifactRequest; +import org.sonatype.aether.resolution.ArtifactResolutionException; import org.sonatype.aether.resolution.ArtifactResult; import org.sonatype.aether.resolution.DependencyRequest; import org.sonatype.aether.resolution.DependencyResolutionException; @@ -57,10 +61,15 @@ import java.net.URLConnection; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Properties; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; -import static org.apache.commons.lang.StringUtils.isNotBlank; +import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.motechproject.config.core.constants.ConfigurationConstants.FILE_CHANGED_EVENT_SUBJECT; import static org.motechproject.server.api.BundleIcon.ICON_LOCATIONS; import static org.springframework.util.CollectionUtils.isEmpty; @@ -199,7 +208,7 @@ public BundleIcon getBundleIcon(long bundleId) { public BundleInformation installBundleFromRepository(String moduleId, boolean startBundle) { try { return installFromRepository(new Dependency(new DefaultArtifact(moduleId), JavaScopes.RUNTIME), startBundle); - } catch (DependencyResolutionException | IOException | BundleException e) { + } catch (RepositoryException | IOException | BundleException e) { throw new MotechException("Unable to install module from repository " + moduleId, e); } } @@ -229,7 +238,7 @@ public ExtendedBundleInformation getBundleDetails(long bundleId) { return bundleInfo; } - private List resolveDependencies(Dependency dependency, List remoteRepositories) throws DependencyResolutionException { + private List resolveDependencies(Dependency dependency, PomInformation pomInformation) throws RepositoryException { LOGGER.info("Resolving dependencies for {}", dependency); org.apache.maven.repository.internal.DefaultServiceLocator locator = new org.apache.maven.repository.internal.DefaultServiceLocator(); @@ -244,15 +253,28 @@ private List resolveDependencies(Dependency dependency, List resolveDependencies(Dependency dependency, List properties = getPropertiesFromString(version); + + for (String propertyName : properties) { + String parsedProperty = getPropertyFromPom(parsePropertyName(propertyName), mvnRepository, system, + remoteRepository, pomInformation); + + if (parsedProperty == null) { + LOGGER.error("The property: {} used in dependency: {} cannot be found in pom " + + "and its parents. For this dependency the latest version will be used", + propertyName, dependency.getArtifact().getArtifactId()); + version = "[0,)"; + break; + } + + version = StringUtils.replace(version, propertyName, parsedProperty); + } + + parsedVersion = version; + } + + return parsedVersion; + } + + private String parseDependencyGroupId(Dependency dependency, MavenRepositorySystemSession mvnRepository, RepositorySystem system, + RemoteRepository remoteRepository, PomInformation pomInformation) throws ArtifactResolutionException { + String parsedGroupId; + String groupId = dependency.getArtifact().getGroupId(); + + Set properties = getPropertiesFromString(groupId); + + for (String propertyName : properties) { + String parsedProperty = getPropertyFromPom(parsePropertyName(propertyName), mvnRepository, system, + remoteRepository, pomInformation); + + if (parsedProperty == null) { + throw new MotechException(String.format("The property: %s used for groupId in dependency: %s cannot be found in pom and its parents.", + propertyName, dependency.getArtifact().getArtifactId())); + } + + groupId = StringUtils.replace(groupId, propertyName, parsedProperty); + } + + parsedGroupId = groupId; + + return parsedGroupId; + } + + private Set getPropertiesFromString(String input) { + Set properties = new HashSet<>(); + + // Seeking properties like '${something}' in the input + Pattern p = Pattern.compile("\\$\\{\\S+?\\}"); + Matcher matcher = p.matcher(input); + while (matcher.find()) { + properties.add(matcher.group()); + } + + return properties; + } + + private String parsePropertyName(String property) { + String parsedPropertyName = StringUtils.remove(property, "${"); + return StringUtils.remove(parsedPropertyName, "}"); + } + + private String getPropertyFromPom(String propertyName, MavenRepositorySystemSession mvnRepository, RepositorySystem system, + RemoteRepository remoteRepository, PomInformation pomInformation) throws ArtifactResolutionException { + Properties properties = pomInformation.getProperties(); + String property = properties.getProperty(propertyName); + + if (property == null) { + if (pomInformation.getParentPomInformation() == null) { + if (pomInformation.getParent() != null) { + Artifact artifact = new DefaultArtifact(pomInformation.getParent().getGroupId(), + pomInformation.getParent().getArtifactId(), "pom", pomInformation.getParent().getVersion()); + + ArtifactRequest artifactRequest = new ArtifactRequest(); + artifactRequest.setArtifact(artifact); + + if (pomInformation.getRepositories() != null) { + for (RemoteRepository repository : pomInformation.getRepositories()) { + artifactRequest.addRepository(repository); + } + } + artifactRequest.addRepository(remoteRepository); + + ArtifactResult artifactResult = system.resolveArtifact(mvnRepository, artifactRequest); + File parentPOM = artifactResult.getArtifact().getFile(); + pomInformation.parseParentPom(parentPOM); + + return getPropertyFromPom(propertyName, mvnRepository, system, remoteRepository, pomInformation.getParentPomInformation()); + } else { + return null; + } + } else { + return getPropertyFromPom(propertyName, mvnRepository, system, remoteRepository, pomInformation.getParentPomInformation()); + } + } else { + return property; + } + } + private BundleInformation installWithDependenciesFromFile(File bundleFile, boolean startBundle) throws IOException { JarInformation jarInformation = getJarInformations(bundleFile); List bundlesInstalled = new ArrayList<>(); @@ -276,8 +408,8 @@ private BundleInformation installWithDependenciesFromFile(File bundleFile, boole List artifactResults = new LinkedList<>(); bundleWatcherSuspensionService.suspendBundleProcessing(); - for (Dependency dependency : jarInformation.getDependencies()) { - artifactResults.addAll(resolveDependencies(dependency, jarInformation.getRepositories())); + for (Dependency dependency : jarInformation.getPomInformation().getDependencies()) { + artifactResults.addAll(resolveDependencies(dependency, jarInformation.getPomInformation())); } artifactResults = removeDuplicatedArtifacts(artifactResults); @@ -294,7 +426,7 @@ private BundleInformation installWithDependenciesFromFile(File bundleFile, boole } else { bundleInformation = new BundleInformation(null); } - } catch (BundleException | DependencyResolutionException e) { + } catch (BundleException | RepositoryException e) { throw new MotechException("Error while installing bundle and dependencies.", e); } finally { bundleWatcherSuspensionService.restoreBundleProcessing(); @@ -451,7 +583,7 @@ private Bundle findMatchingBundle(JarInformation jarInformation) { } private BundleInformation installFromRepository(Dependency dependency, boolean start) - throws DependencyResolutionException, IOException, BundleException { + throws RepositoryException, IOException, BundleException { LOGGER.info("Installing {} from repository", dependency); final String featureStrNoVersion = buildFeatureStrNoVersion(dependency); diff --git a/modules/admin/src/main/java/org/motechproject/admin/internal/service/impl/SettingsServiceImpl.java b/modules/admin/src/main/java/org/motechproject/admin/internal/service/impl/SettingsServiceImpl.java index 8e12052454..53a1482114 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/internal/service/impl/SettingsServiceImpl.java +++ b/modules/admin/src/main/java/org/motechproject/admin/internal/service/impl/SettingsServiceImpl.java @@ -85,6 +85,12 @@ public AdminSettings getSettings() { securityOptions.add(minPasswordLengthOption); SettingsOption passwordValidatorOption = ParamParser.parseParam(ConfigurationConstants.PASSWORD_VALIDATOR, motechSettings.getPasswordValidator()); securityOptions.add(passwordValidatorOption); + SettingsOption passwordResetOption = ParamParser.parseParam(ConfigurationConstants.PASSWORD_RESET_DAYS, motechSettings.getNumberOfDaysToChangePassword()); + securityOptions.add(passwordResetOption); + SettingsOption passwordReminderOption = ParamParser.parseParam(ConfigurationConstants.PASSWORD_REMINDER, motechSettings.isPasswordResetReminderEnabled()); + securityOptions.add(passwordReminderOption); + SettingsOption passwordRemindDaysOption = ParamParser.parseParam(ConfigurationConstants.PASSWORD_REMINDER_DAYS, motechSettings.getNumberOfDaysForReminder()); + securityOptions.add(passwordRemindDaysOption); SettingsOption jmxUrlOption = ParamParser.parseParam(ConfigurationConstants.JMX_HOST, motechSettings.getJmxHost()); jmxOptions.add(jmxUrlOption); diff --git a/modules/admin/src/main/java/org/motechproject/admin/jmx/MotechMBeanServer.java b/modules/admin/src/main/java/org/motechproject/admin/jmx/MotechMBeanServer.java index 0ce3266006..e02b43770b 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/jmx/MotechMBeanServer.java +++ b/modules/admin/src/main/java/org/motechproject/admin/jmx/MotechMBeanServer.java @@ -17,7 +17,7 @@ import javax.management.remote.JMXServiceURL; import java.io.IOException; -import static org.apache.commons.lang.StringUtils.isNotBlank; +import static org.apache.commons.lang3.StringUtils.isNotBlank; /** * The MBean server providing access to ActiveMQ MBeans. Uses a JMX connection. diff --git a/modules/admin/src/main/java/org/motechproject/admin/listener/MessageHandler.java b/modules/admin/src/main/java/org/motechproject/admin/listener/MessageHandler.java index 3d5f457510..1936747fcd 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/listener/MessageHandler.java +++ b/modules/admin/src/main/java/org/motechproject/admin/listener/MessageHandler.java @@ -1,6 +1,6 @@ package org.motechproject.admin.listener; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.motechproject.admin.events.EventKeys; import org.motechproject.admin.events.EventSubjects; diff --git a/modules/admin/src/main/java/org/motechproject/admin/messages/Level.java b/modules/admin/src/main/java/org/motechproject/admin/messages/Level.java index 0e35bf9564..73286161a8 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/messages/Level.java +++ b/modules/admin/src/main/java/org/motechproject/admin/messages/Level.java @@ -1,6 +1,6 @@ package org.motechproject.admin.messages; -import org.codehaus.jackson.annotate.JsonValue; +import com.fasterxml.jackson.annotation.JsonValue; /** * Represents the level of a {@link org.motechproject.admin.domain.StatusMessage}, which is reflected on the UI. diff --git a/modules/admin/src/main/java/org/motechproject/admin/notification/EmailNotifier.java b/modules/admin/src/main/java/org/motechproject/admin/notification/EmailNotifier.java index 8e77e58ff4..533b9782d7 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/notification/EmailNotifier.java +++ b/modules/admin/src/main/java/org/motechproject/admin/notification/EmailNotifier.java @@ -1,6 +1,6 @@ package org.motechproject.admin.notification; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.velocity.app.VelocityEngine; import org.joda.time.format.DateTimeFormat; import org.motechproject.admin.domain.StatusMessage; diff --git a/modules/admin/src/main/java/org/motechproject/admin/security/SecurityConstants.java b/modules/admin/src/main/java/org/motechproject/admin/security/SecurityConstants.java index 1118d73eda..0fcdd54626 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/security/SecurityConstants.java +++ b/modules/admin/src/main/java/org/motechproject/admin/security/SecurityConstants.java @@ -5,11 +5,11 @@ */ public final class SecurityConstants { - public static final String MANAGE_MESSAGES = "hasRole('manageMessages')"; - public static final String MANAGE_BUNDLES = "hasRole('manageBundles')"; - public static final String MANAGE_LOGS = "hasRole('manageLogs')"; - public static final String MANAGE_ACTIVEMQ = "hasRole('manageActivemq')"; - public static final String MANAGE_SETTINGS = "hasRole('manageSettings')"; + public static final String MANAGE_MESSAGES = "hasAuthority('manageMessages')"; + public static final String MANAGE_BUNDLES = "hasAuthority('manageBundles')"; + public static final String MANAGE_LOGS = "hasAuthority('manageLogs')"; + public static final String MANAGE_ACTIVEMQ = "hasAuthority('manageActivemq')"; + public static final String MANAGE_SETTINGS = "hasAuthority('manageSettings')"; private SecurityConstants() { } diff --git a/modules/admin/src/main/java/org/motechproject/admin/service/impl/StatusMessageServiceImpl.java b/modules/admin/src/main/java/org/motechproject/admin/service/impl/StatusMessageServiceImpl.java index a142305af2..df6842328f 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/service/impl/StatusMessageServiceImpl.java +++ b/modules/admin/src/main/java/org/motechproject/admin/service/impl/StatusMessageServiceImpl.java @@ -1,6 +1,6 @@ package org.motechproject.admin.service.impl; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.motechproject.admin.domain.NotificationRule; import org.motechproject.admin.domain.StatusMessage; diff --git a/modules/admin/src/main/java/org/motechproject/admin/web/controller/BundleAdminController.java b/modules/admin/src/main/java/org/motechproject/admin/web/controller/BundleAdminController.java index 8280877f3d..fc92324610 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/web/controller/BundleAdminController.java +++ b/modules/admin/src/main/java/org/motechproject/admin/web/controller/BundleAdminController.java @@ -1,7 +1,7 @@ package org.motechproject.admin.web.controller; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.exception.ExceptionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.motechproject.admin.bundles.ExtendedBundleInformation; import org.motechproject.admin.internal.service.ModuleAdminService; import org.motechproject.admin.service.StatusMessageService; @@ -29,7 +29,7 @@ import java.io.Writer; import java.util.List; -import static org.apache.commons.lang.StringUtils.isBlank; +import static org.apache.commons.lang3.StringUtils.isBlank; /** * The Spring controller responsible for operations on bundles (modules). It allows diff --git a/modules/admin/src/main/java/org/motechproject/admin/web/controller/ServerLogController.java b/modules/admin/src/main/java/org/motechproject/admin/web/controller/ServerLogController.java index 22117b87b5..f597f46ea5 100644 --- a/modules/admin/src/main/java/org/motechproject/admin/web/controller/ServerLogController.java +++ b/modules/admin/src/main/java/org/motechproject/admin/web/controller/ServerLogController.java @@ -57,7 +57,7 @@ public void getServerLog(HttpServletResponse response) throws IOException { if (!logFile.exists()) { writer.write("server.tomcat.error.logFileNotFound"); } else { - long readSize = FileUtils.ONE_MB; + long readSize = FileUtils.ONE_KB * 200; long fileSize = logFile.length(); try (InputStream in = new FileInputStream(logFile)) { diff --git a/modules/admin/src/main/resources/META-INF/motech/applicationAdmin.xml b/modules/admin/src/main/resources/META-INF/motech/applicationAdmin.xml index 9596676ad1..46af412629 100644 --- a/modules/admin/src/main/resources/META-INF/motech/applicationAdmin.xml +++ b/modules/admin/src/main/resources/META-INF/motech/applicationAdmin.xml @@ -4,10 +4,10 @@ xmlns:context="http://www.springframework.org/schema/context" xmlns:security="http://www.springframework.org/schema/security" xmlns:mvc="http://www.springframework.org/schema/mvc" - xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd - http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd - http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd - http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd + http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd + http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd"> diff --git a/modules/admin/src/main/resources/META-INF/spring/blueprint.xml b/modules/admin/src/main/resources/META-INF/spring/blueprint.xml index 3e9a9f75cd..76f0f46f0b 100644 --- a/modules/admin/src/main/resources/META-INF/spring/blueprint.xml +++ b/modules/admin/src/main/resources/META-INF/spring/blueprint.xml @@ -2,7 +2,7 @@ diff --git a/modules/admin/src/main/resources/webapp/js/controllers.js b/modules/admin/src/main/resources/webapp/js/controllers.js index e786c41d3b..e17eb55319 100644 --- a/modules/admin/src/main/resources/webapp/js/controllers.js +++ b/modules/admin/src/main/resources/webapp/js/controllers.js @@ -688,7 +688,7 @@ if (data === 'server.tomcat.error.logFileNotFound') { $('#logContent').html($scope.msg(data)); } else { - $('#logContent').html(data.replace(/\r\n|\n/g, "
")); + $('#logContent').html(data); unblockUI(); } }). diff --git a/modules/admin/src/main/resources/webapp/js/directives.js b/modules/admin/src/main/resources/webapp/js/directives.js index e5cc143fc7..add7a25880 100644 --- a/modules/admin/src/main/resources/webapp/js/directives.js +++ b/modules/admin/src/main/resources/webapp/js/directives.js @@ -39,6 +39,27 @@ onSelect: function (selectedDateTime){ endDateTextBox.datetimepicker('option', 'minDate', elem.datetimepicker('getDate') ); scope.setDateTimeFilter(selectedDateTime, null); + }, + onChangeMonthYear: function (year, month, inst) { + var curDate = $(this).datepicker("getDate"); + if (curDate === null) { + return; + } + if (curDate.getFullYear() !== year || curDate.getMonth() !== month - 1) { + curDate.setYear(year); + curDate.setMonth(month - 1); + $(this).datepicker("setDate", curDate); + scope.setDateTimeFilter(curDate, null); + } + }, + onClose: function () { + var viewValue = $(this).val(); + if (viewValue === '') { + endDateTextBox.datetimepicker('option', 'minDate', null); + } else { + endDateTextBox.datepicker('option', 'minDate', elem.datepicker('getDate')); + } + scope.setDateTimeFilter(viewValue, null); } }); } @@ -60,6 +81,27 @@ onSelect: function (selectedDateTime){ startDateTextBox.datetimepicker('option', 'maxDate', elem.datetimepicker('getDate') ); scope.setDateTimeFilter(null, selectedDateTime); + }, + onChangeMonthYear: function (year, month, inst) { + var curDate = $(this).datepicker("getDate"); + if (curDate === null) { + return; + } + if (curDate.getFullYear() !== year || curDate.getMonth() !== month - 1) { + curDate.setYear(year); + curDate.setMonth(month - 1); + $(this).datepicker("setDate", curDate); + scope.setDateTimeFilter(null, curDate); + } + }, + onClose: function () { + var viewValue = $(this).val(); + if (viewValue === '') { + startDateTextBox.datetimepicker('option', 'maxDate', null); + } else { + startDateTextBox.datepicker('option', 'maxDate', elem.datepicker('getDate')); + } + scope.setDateTimeFilter(null, viewValue); } }); } diff --git a/modules/admin/src/main/resources/webapp/messages/messages.properties b/modules/admin/src/main/resources/webapp/messages/messages.properties index f02f822d3f..ed7307ec9d 100644 --- a/modules/admin/src/main/resources/webapp/messages/messages.properties +++ b/modules/admin/src/main/resources/webapp/messages/messages.properties @@ -164,6 +164,9 @@ admin.settings.security.required.email=Require e-mail admin.settings.security.session.timeout=Session timeout admin.settings.security.password.minlength=Minimal length admin.settings.security.password.validator=Validator +admin.settings.security.password.reset.days=Days to reset +admin.settings.security.password.reminder.sendReminder=Enable reminder +admin.settings.security.password.reminder.daysBeforeExpiration=Days before password expiration to send the reminder admin.settings.jmx.broker=Broker name admin.settings.jmx.host=Broker host @@ -176,6 +179,9 @@ admin.settings.tooltip.security.required.email=Indicates whether you must provid admin.settings.tooltip.security.session.timeout=The session timeout in seconds, default 30 minutes. After this time of inactivity, the session will be closed. admin.settings.tooltip.security.password.minlength=The minimum length of the password, default 0. if the value is 0 then length checking is disabled. admin.settings.tooltip.security.password.validator=The password validator, it specifies password rules e.g. 1 number, 1 special character. Default none validator is used. +admin.settings.tooltip.security.password.reset.days=The number of days after which the user will have to change password. +admin.settings.tooltip.security.password.reminder.sendReminder=Indicates whether to send a reminder about password expiration to the user. +admin.settings.tooltip.security.password.reminder.daysBeforeExpiration=The number of days before password expiration to send the reminder at, 0 meaning after expiration. admin.settings.tooltip.jmx.broker=JMX broker name. admin.settings.tooltip.jmx.host=The host that the JMX connector will use. diff --git a/modules/admin/src/main/resources/webapp/partials/log.html b/modules/admin/src/main/resources/webapp/partials/log.html index aa93c749ef..e03e5f93b4 100644 --- a/modules/admin/src/main/resources/webapp/partials/log.html +++ b/modules/admin/src/main/resources/webapp/partials/log.html @@ -12,7 +12,7 @@
-
+