diff --git a/.gitignore b/.gitignore
index ba9cf4617..8cd3d476e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,13 +16,13 @@
*.jar
*.war
-######################
# Sonar
-######################
.sonar_lock
-# Eclipse IDE
+# Created by spring-boot-configuration-processor
+.factorypath
+# Eclipse IDE
*.pydevproject
.project
.metadata
diff --git a/MIGRATION.md b/MIGRATION.md
new file mode 100644
index 000000000..eacce864d
--- /dev/null
+++ b/MIGRATION.md
@@ -0,0 +1,9 @@
+# hawkBit Migration Guides
+## Release 0.2
+### Configuration Property changes
+- hawkbit.server.controller._ have changed to hawkbit.server.ddi._
+- info.build._ have changed to hawkbit.server.build._
+- hawkbit.server.demo._ have changed to hawkbit.server.ui.demo._
+- hawkbit.server.email.support has changed to hawkbit.server.ui.links.support
+- hawkbit.server.email.request.account has changed to hawkbit.server.ui.links.requestAccount
+- hawkbit.server.im.login.url has changed to hawkbit.server.ui.links.userManagement
diff --git a/examples/hawkbit-device-simulator/pom.xml b/examples/hawkbit-device-simulator/pom.xml
index 9a84d13f5..94749789c 100644
--- a/examples/hawkbit-device-simulator/pom.xml
+++ b/examples/hawkbit-device-simulator/pom.xml
@@ -100,7 +100,6 @@
com.google.guava
guava
- 19.0
com.netflix.feign
@@ -116,6 +115,11 @@
com.jayway.jsonpath
json-path
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
diff --git a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpProperties.java b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpProperties.java
index ff9762c5d..f9e6ab23d 100644
--- a/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpProperties.java
+++ b/examples/hawkbit-device-simulator/src/main/java/org/eclipse/hawkbit/simulator/amqp/AmqpProperties.java
@@ -9,21 +9,35 @@
package org.eclipse.hawkbit.simulator.amqp;
import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
/**
* Bean which holds the necessary properties for configuring the AMQP
* connection.
*
- *
- *
*/
+@Component
@ConfigurationProperties("hawkbit.device.simulator.amqp")
public class AmqpProperties {
+ /**
+ * Queue for receiving DMF messages from update server.
+ */
private String receiverConnectorQueueFromSp;
+
+ /**
+ * Exchange for sending DMF messages to update server.
+ */
private String senderForSpExchange;
+ /**
+ * Simulator dead letter queue.
+ */
private String deadLetterQueue;
+
+ /**
+ * Simulator dead letter exchange.
+ */
private String deadLetterExchange;
public String getReceiverConnectorQueueFromSp() {
diff --git a/examples/hawkbit-example-app/src/main/resources/application.properties b/examples/hawkbit-example-app/src/main/resources/application.properties
index 13ceca40a..d3eddeff1 100644
--- a/examples/hawkbit-example-app/src/main/resources/application.properties
+++ b/examples/hawkbit-example-app/src/main/resources/application.properties
@@ -7,23 +7,20 @@
# http://www.eclipse.org/legal/epl-v10.html
#
-# need to re-name these properties in the defaulthawkbit.properties and code!
-hawkbit.server.controller.security.authentication.anonymous.enabled=true
-hawkbit.server.controller.security.authentication.header.enabled=false
-hawkbit.server.controller.security.authentication.targettoken.enabled=false
-hawkbit.server.controller.security.authentication.gatewaytoken.enabled=false
+hawkbit.server.ddi.security.authentication.anonymous.enabled=true
+hawkbit.server.ddi.security.authentication.targettoken.enabled=false
+hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=false
spring.profiles.active=amqp
vaadin.servlet.productionMode=false
-vaadin.static.servlet.productionMode=false
## Configuration for RabbitMQ integration
-hawkbit.server.amqp.username=guest
-hawkbit.server.amqp.password=guest
-hawkbit.server.amqp.virtualHost=/
-hawkbit.server.amqp.host=localhost
-hawkbit.server.amqp.port=5672
-hawkbit.server.amqp.deadLetterQueue=sp_deadletter
-hawkbit.server.amqp.deadLetterExchange=sp.deadletter
-hawkbit.server.amqp.receiverQueue=sp_receiver
+spring.rabbitmq.username=guest
+spring.rabbitmq.password=guest
+spring.rabbitmq.virtualHost=/
+spring.rabbitmq.host=localhost
+spring.rabbitmq.port=5672
+hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter
+hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.connector.deadletter
+hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver
diff --git a/examples/hawkbit-mgmt-api-client/pom.xml b/examples/hawkbit-mgmt-api-client/pom.xml
index 6e62bfe4e..9aaf53dc6 100644
--- a/examples/hawkbit-mgmt-api-client/pom.xml
+++ b/examples/hawkbit-mgmt-api-client/pom.xml
@@ -87,5 +87,10 @@
google-collections
1.0-rc2
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
\ No newline at end of file
diff --git a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java
index 6d15bcc04..ead019247 100644
--- a/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java
+++ b/examples/hawkbit-mgmt-api-client/src/main/java/org/eclipse/hawkbit/mgmt/client/ClientConfigurationProperties.java
@@ -9,17 +9,30 @@
package org.eclipse.hawkbit.mgmt.client;
import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
/**
* Configuration bean which holds the configuration of the client e.g. the base
* URL of the hawkbit-server and the credentials to use the RESTful Management
* API.
*/
+@Component
@ConfigurationProperties(prefix = "hawkbit")
public class ClientConfigurationProperties {
+ /**
+ * Update server URI.
+ */
private String url = "localhost:8080";
+
+ /**
+ * Update server user name.
+ */
private String username = "admin";
+
+ /**
+ * Update server password.
+ */
private String password = "admin"; // NOSONAR this password is only used for
// examples
diff --git a/examples/hawkbit-mgmt-api-client/src/main/resources/application.properties b/examples/hawkbit-mgmt-api-client/src/main/resources/application.properties
index da0aa79dd..d3a3eb969 100644
--- a/examples/hawkbit-mgmt-api-client/src/main/resources/application.properties
+++ b/examples/hawkbit-mgmt-api-client/src/main/resources/application.properties
@@ -11,4 +11,4 @@ hawkbit.url=localhost:8080
hawkbit.username=admin
hawkbit.password=admin
-spring.main.banner-mode=OFF
\ No newline at end of file
+spring.main.show-banner=false
\ No newline at end of file
diff --git a/hawkbit-autoconfigure/pom.xml b/hawkbit-autoconfigure/pom.xml
index 11a106a4b..7670da406 100644
--- a/hawkbit-autoconfigure/pom.xml
+++ b/hawkbit-autoconfigure/pom.xml
@@ -72,5 +72,10 @@
org.springframework
spring-context-support
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/conf/ControllerPollAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/conf/ControllerPollAutoConfiguration.java
deleted file mode 100644
index bcbc5ec16..000000000
--- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/conf/ControllerPollAutoConfiguration.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- */
-package org.eclipse.hawkbit.autoconfigure.conf;
-
-import org.eclipse.hawkbit.ControllerPollProperties;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * Enable the Controlle Poll.
- *
- *
- *
- */
-@Configuration
-@ConditionalOnClass(ControllerPollProperties.class)
-@EnableConfigurationProperties(ControllerPollProperties.class)
-public class ControllerPollAutoConfiguration {
-
-}
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerThreadpoolProperties.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerThreadpoolProperties.java
index f7f18f1b0..35996a114 100644
--- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerThreadpoolProperties.java
+++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/AsyncConfigurerThreadpoolProperties.java
@@ -13,17 +13,29 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Properties for the async configurer.
*
- *
*/
@ConfigurationProperties("hawkbit.threadpool")
public class AsyncConfigurerThreadpoolProperties {
+ /**
+ * Max queue size for central event executor.
+ */
private Integer queuesize = 250;
+ /**
+ * Core processing threads for central event executor.
+ */
private Integer corethreads = 5;
+ /**
+ * Maximum thread pool size for central event executor.
+ */
private Integer maxthreads = 50;
+ /**
+ * When the number of threads is greater than the core, this is the maximum
+ * time that excess idle threads will wait for new tasks before terminating.
+ */
private Long idletimeout = 10000L;
public Integer getQueuesize() {
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorAutoConfiguration.java
index f8a86d1bc..43a096e7d 100644
--- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorAutoConfiguration.java
+++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/scheduling/ExecutorAutoConfiguration.java
@@ -26,10 +26,9 @@ import org.springframework.security.concurrent.DelegatingSecurityContextExecutor
import com.google.common.util.concurrent.ThreadFactoryBuilder;
/**
- *
+ * Central event processors inside update server.
*
*/
-
@Configuration
@EnableConfigurationProperties(AsyncConfigurerThreadpoolProperties.class)
public class ExecutorAutoConfiguration {
@@ -40,7 +39,7 @@ public class ExecutorAutoConfiguration {
private AsyncConfigurerThreadpoolProperties asyncConfigurerProperties;
/**
- * @return ExecutorService for general pupose multi threaded operations
+ * @return ExecutorService for general purpose multi threaded operations
*/
@Bean
@ConditionalOnMissingBean
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityAutoConfiguration.java
index 326ff4774..8a3a50ad2 100644
--- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityAutoConfiguration.java
+++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityAutoConfiguration.java
@@ -20,7 +20,7 @@ import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
import org.eclipse.hawkbit.im.authentication.UserAuthenticationFilter;
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
-import org.eclipse.hawkbit.security.SecurityProperties;
+import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger;
@@ -53,7 +53,7 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationFi
*
*/
@Configuration
-@EnableConfigurationProperties(SecurityProperties.class)
+@EnableConfigurationProperties(DdiSecurityProperties.class)
public class SecurityAutoConfiguration {
/**
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java
index ca55f1711..b27e76a28 100644
--- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java
+++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java
@@ -31,29 +31,27 @@ import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.rest.resource.RestConstants;
import org.eclipse.hawkbit.security.ControllerTenantAwareAuthenticationDetailsSource;
+import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.DosFilter;
+import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticateSecurityTokenFilter;
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedGatewaySecurityTokenFilter;
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedSecurityHeaderFilter;
import org.eclipse.hawkbit.security.HttpDownloadAuthenticationFilter;
import org.eclipse.hawkbit.security.PreAuthTokenSourceTrustAuthenticationProvider;
-import org.eclipse.hawkbit.security.SecurityProperties;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.boot.context.embedded.ServletListenerRegistrationBean;
import org.springframework.cache.Cache;
-import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
-import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -94,17 +92,11 @@ import org.vaadin.spring.security.web.authentication.VaadinUrlAuthenticationSucc
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.ASPECTJ, proxyTargetClass = true, securedEnabled = true)
@EnableWebMvcSecurity
@Order(value = Ordered.HIGHEST_PRECEDENCE)
-public class SecurityManagedConfiguration implements EnvironmentAware {
+public class SecurityManagedConfiguration {
private static final Logger LOG = LoggerFactory.getLogger(SecurityManagedConfiguration.class);
- private static final String SP_SERVER_CONFIG_PREFIX = "hawkbit.server.";
- private RelaxedPropertyResolver environment;
-
- @Override
- public void setEnvironment(final Environment environment) {
- this.environment = new RelaxedPropertyResolver(environment, SP_SERVER_CONFIG_PREFIX);
-
- }
+ @Autowired
+ private HawkbitSecurityProperties securityProperties;
/**
* {@link WebSecurityConfigurer} for the internal SP controller API.
@@ -123,7 +115,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
@Autowired
private TenantAware tenantAware;
@Autowired
- private SecurityProperties securityConfiguration;
+ private DdiSecurityProperties ddiSecurityConfiguration;
@Autowired
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
@@ -132,7 +124,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
final ControllerTenantAwareAuthenticationDetailsSource authenticationDetailsSource = new ControllerTenantAwareAuthenticationDetailsSource();
final HttpControllerPreAuthenticatedSecurityHeaderFilter securityHeaderFilter = new HttpControllerPreAuthenticatedSecurityHeaderFilter(
- securityConfiguration.getRpCnHeader(), securityConfiguration.getRpSslIssuerHashHeader(),
+ ddiSecurityConfiguration.getRp().getCnHeader(), ddiSecurityConfiguration.getRp().getSslIssuerHashHeader(),
systemManagement, tenantAware);
securityHeaderFilter.setAuthenticationManager(authenticationManager());
securityHeaderFilter.setCheckForPrincipalChanges(true);
@@ -158,7 +150,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and();
}
- if (securityConfiguration.getAnonymousEnabled()) {
+ if (ddiSecurityConfiguration.getAuthentication().getAnonymous().isEnabled()) {
LOG.info(
"******************\n** Anonymous controller security enabled, should only use for developing purposes **\n******************");
final AnonymousAuthenticationFilter anoymousFilter = new AnonymousAuthenticationFilter(
@@ -189,7 +181,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(
- new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration.getRpTrustedIPs()));
+ new PreAuthTokenSourceTrustAuthenticationProvider(ddiSecurityConfiguration.getRp().getTrustedIPs()));
}
}
@@ -204,13 +196,10 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
public FilterRegistrationBean dosFilter() {
final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
- filterRegBean
- .setFilter(
- new DosFilter(environment.getProperty("security.dos.filter.maxRead", Integer.class, 200),
- environment.getProperty("security.dos.filter.maxWrite", Integer.class, 50),
- environment.getProperty("security.dos.filter.whitelist"), environment
- .getProperty("security.clients.blacklist"),
- environment.getProperty("security.rp.remote_ip_header", String.class, "X-Forwarded-For")));
+ filterRegBean.setFilter(new DosFilter(securityProperties.getDos().getFilter().getMaxRead(),
+ securityProperties.getDos().getFilter().getMaxWrite(),
+ securityProperties.getDos().getFilter().getWhitelist(), securityProperties.getClients().getBlacklist(),
+ securityProperties.getClients().getRemoteIpHeader()));
filterRegBean.addUrlPatterns("/{tenant}/controller/v1/*", "/rest/*");
return filterRegBean;
}
@@ -310,8 +299,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
@Configuration
@Order(400)
@EnableVaadinSecurity
- public static class UISecurityConfigurationAdapter extends WebSecurityConfigurerAdapter
- implements EnvironmentAware {
+ public static class UISecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
private static final String XFRAME_OPTION_DENY = "DENY";
private static final String XFRAME_OPTION_SAMEORIGIN = "SAMEORIGIN";
@@ -320,13 +308,8 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
private VaadinSecurityContext vaadinSecurityContext;
@Autowired
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
-
- private RelaxedPropertyResolver environment;
-
- @Override
- public void setEnvironment(final Environment environment) {
- this.environment = new RelaxedPropertyResolver(environment, SP_SERVER_CONFIG_PREFIX);
- }
+ @Autowired
+ private HawkbitSecurityProperties securityProperties;
/**
* post construct for setting the authentication success handler for the
@@ -379,13 +362,13 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
protected void configure(final HttpSecurity http) throws Exception {
// configuration xframe-option
- final String confXframeOption = environment.getProperty("security.xframe.option", XFRAME_OPTION_DENY);
- final String confAllowFromUri = environment.getProperty("security.xframe.option.allowfrom");
- if (confXframeOption.equals(XFAME_OPTION_ALLOW_FROM) && confAllowFromUri == null) {
+ final String confXframeOption = securityProperties.getXframe().getOption();
+ final String confAllowFromUri = securityProperties.getXframe().getAllowfrom();
+ if (confXframeOption.equals(XFAME_OPTION_ALLOW_FROM) && confAllowFromUri.isEmpty()) {
// if allow-from option is specified but no allowFromUri throw
// exception
throw new IllegalStateException("hawkbit.server.security.xframe.option has been specified as ALLOW-FROM"
- + " but no hawkbit.server.security.xframe.option.allowfrom has been set, "
+ + " but no hawkbit.server.security.xframe.allowfrom has been set, "
+ "please ensure to set allow from URIs");
}
@@ -461,7 +444,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
public static class IdRestSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Autowired
- private SecurityProperties securityConfiguration;
+ private DdiSecurityProperties ddiSecurityConfiguration;
@Autowired
@Qualifier(CacheConstants.DOWNLOAD_ID_CACHE)
@@ -484,7 +467,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(
- new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration.getRpTrustedIPs()));
+ new PreAuthTokenSourceTrustAuthenticationProvider(ddiSecurityConfiguration.getRp().getTrustedIPs()));
}
}
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/url/PropertyHostnameResolverAutoConfiguration.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/url/PropertyHostnameResolverAutoConfiguration.java
index eb925e281..0bd4a8240 100644
--- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/url/PropertyHostnameResolverAutoConfiguration.java
+++ b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/url/PropertyHostnameResolverAutoConfiguration.java
@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.autoconfigure.url;
import java.net.MalformedURLException;
import java.net.URL;
+import org.eclipse.hawkbit.HawkbitServerProperties;
import org.eclipse.hawkbit.api.HostnameResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -27,11 +28,11 @@ import com.google.common.base.Throwables;
*
*/
@Configuration
-@EnableConfigurationProperties(ServerProperties.class)
+@EnableConfigurationProperties(HawkbitServerProperties.class)
public class PropertyHostnameResolverAutoConfiguration {
@Autowired
- private ServerProperties serverProperties;
+ private HawkbitServerProperties serverProperties;
/**
* @return the default autoconfigure hostname resolver implementation which
diff --git a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/url/ServerProperties.java b/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/url/ServerProperties.java
deleted file mode 100644
index 24c9dfb0e..000000000
--- a/hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/url/ServerProperties.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- */
-package org.eclipse.hawkbit.autoconfigure.url;
-
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-/**
- * Properties for the server e.g. the server's URL which must be configured.
- *
- *
- */
-@ConfigurationProperties("hawkbit.server")
-public class ServerProperties {
-
- private String url = "http://localhost:8080";
-
- public String getUrl() {
- return url;
- }
-
- public void setUrl(final String url) {
- this.url = url;
- }
-}
diff --git a/hawkbit-autoconfigure/src/main/resources/META-INF/spring.factories b/hawkbit-autoconfigure/src/main/resources/META-INF/spring.factories
index 5d8d005d9..335054585 100644
--- a/hawkbit-autoconfigure/src/main/resources/META-INF/spring.factories
+++ b/hawkbit-autoconfigure/src/main/resources/META-INF/spring.factories
@@ -11,5 +11,4 @@ org.eclipse.hawkbit.autoconfigure.eventbus.EventBusAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.scheduling.AsyncConfigurerAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.cache.RedisAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.scheduling.ExecutorAutoConfiguration,\
-org.eclipse.hawkbit.autoconfigure.conf.ControllerPollAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.amqp.AmqpAutoConfiguration
diff --git a/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties b/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties
index 98749a384..8f7ab288a 100644
--- a/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties
+++ b/hawkbit-autoconfigure/src/main/resources/hawkbitdefaults.properties
@@ -7,12 +7,6 @@
# http://www.eclipse.org/legal/epl-v10.html
#
-# Tomcat / Server
-server.tomcat.compression=on
-spring.http.gzip.mime-types=text/html,text/xml,text/plain,application/json,application/javascript,text/css,application/x-javascript,text/javascript,application/vnd.ms-fontobject,application/x-font-opentype,application/x-font-truetype,application/x-font-ttf,application/xml,font/eot,font/opentype,font/otf,image/svg+xml,image/vnd.microsoft.icon
-server.tomcat.compressable-mime-types=${spring.http.gzip.mime-types}
-spring.http.gzip.min-gzip-size=256
-
# JPA / Datasource
spring.jpa.eclipselink.eclipselink.weaving=false
spring.jpa.database=H2
@@ -21,7 +15,6 @@ spring.datasource.driverClassName=org.h2.Driver
# MongoDB for artifact-repository
spring.data.mongodb.uri=mongodb://localhost/artifactrepo
-spring.data.mongo.repositories.enabled=true
# Flyway DDL
flyway.enabled=true
@@ -29,15 +22,10 @@ flyway.initOnMigrate=true
flyway.sqlMigrationSuffix=${spring.jpa.database}.sql
# Vaadin Servlet
-vaadin.static.servlet.productionMode=true
vaadin.servlet.productionMode=true
vaadin.servlet.urlMapping=/UI/*
-vaadin.servlet.params.heartbeatInterval=60
-vaadin.servlet.params.closeIdleSessions=false
-
-# Spring MVC
-spring.mvc.favicon.enabled=false
-
+vaadin.servlet.heartbeatInterval=60
+vaadin.servlet.closeIdleSessions=false
# Defines the thread pool executor
hawkbit.threadpool.corethreads=5
@@ -50,6 +38,6 @@ hawkbit.controller.pollingTime=00:05:00
hawkbit.controller.pollingOverdueTime=00:05:00
## Configuration for RabbitMQ integration
-hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter
-hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.connector.deadletter
+hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_receiver_deadletter
+hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.receiver.deadletter
hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver
diff --git a/hawkbit-cache-redis/pom.xml b/hawkbit-cache-redis/pom.xml
index 99c8328b5..09567291b 100644
--- a/hawkbit-cache-redis/pom.xml
+++ b/hawkbit-cache-redis/pom.xml
@@ -37,6 +37,11 @@
redis.clients
jedis
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
diff --git a/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisConfiguration.java b/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisConfiguration.java
index acf50ad3f..edc183b17 100644
--- a/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisConfiguration.java
+++ b/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisConfiguration.java
@@ -26,8 +26,6 @@ import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer
* The spring Redis configuration which is enabled by using the profile
* {@code redis} to use a Redis server as cache.
*
- *
- *
*/
@Configuration
@EnableConfigurationProperties(RedisProperties.class)
diff --git a/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisProperties.java b/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisProperties.java
index c228cde4c..ab409bbf5 100644
--- a/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisProperties.java
+++ b/hawkbit-cache-redis/src/main/java/org/eclipse/hawkbit/cache/RedisProperties.java
@@ -14,14 +14,18 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
* Bean which holds the necessary properties for configuring the Redis
* connection.
*
- *
- *
- *
*/
@ConfigurationProperties("hawkbit.server.redis")
public class RedisProperties {
+ /**
+ * Redis server hostname.
+ */
private String host;
+
+ /**
+ * Redis server port.
+ */
private int port;
/**
diff --git a/hawkbit-core/pom.xml b/hawkbit-core/pom.xml
index b56d30075..f9e140d40 100644
--- a/hawkbit-core/pom.xml
+++ b/hawkbit-core/pom.xml
@@ -43,6 +43,11 @@
allure-junit-adaptor
test
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
\ No newline at end of file
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/ControllerPollProperties.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/ControllerPollProperties.java
index 694d5c016..4e176d258 100644
--- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/ControllerPollProperties.java
+++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/ControllerPollProperties.java
@@ -9,18 +9,26 @@
package org.eclipse.hawkbit;
import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
/**
* Defines the polling time for the controllers in HH:MM:SS notation.
*
- *
- *
*/
-
+@Component
@ConfigurationProperties(prefix = "hawkbit.controller")
public class ControllerPollProperties {
+ /**
+ * Recommended target polling time for DDI API. Final choice is up to the
+ * target.
+ */
private String pollingTime = "00:05:00";
+
+ /**
+ * Assumed time frame where the target is considered overdue when no DDI
+ * polling has been registered by the update server.
+ */
private String pollingOverdueTime = "00:05:00";
public String getPollingTime() {
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/HawkbitServerProperties.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/HawkbitServerProperties.java
new file mode 100644
index 000000000..878965102
--- /dev/null
+++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/HawkbitServerProperties.java
@@ -0,0 +1,97 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * Properties for the server e.g. the server's URL which must be configured.
+ *
+ */
+@ConfigurationProperties("hawkbit.server")
+public class HawkbitServerProperties {
+ /**
+ * Defines under which URI the update server can be reached. Used to
+ * calculate download URLs for DMF transmitted update actions.
+ */
+ private String url = "http://localhost:8080";
+
+ private final Build build = new Build();
+
+ public Build getBuild() {
+ return build;
+ }
+
+ /**
+ * Build information of the hawkBit instance. Influenced by maven.
+ *
+ */
+ public static class Build {
+ /**
+ * Project artifact ID.
+ */
+ private String artifact = "";
+
+ /**
+ * Project name.
+ */
+ private String name = "";
+
+ /**
+ * Project description.
+ */
+ private String description = "";
+
+ /**
+ * Project version.
+ */
+ private String version = "";
+
+ public String getArtifact() {
+ return artifact;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setArtifact(final String artifact) {
+ this.artifact = artifact;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ public void setVersion(final String version) {
+ this.version = version;
+ }
+
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(final String url) {
+ this.url = url;
+ }
+}
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionStatusFields.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionStatusFields.java
index 22fa42474..ef8bf3c98 100644
--- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionStatusFields.java
+++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/repository/ActionStatusFields.java
@@ -20,7 +20,12 @@ public enum ActionStatusFields implements FieldNameProvider {
/**
* The id field.
*/
- ID("id");
+ ID("id"),
+
+ /**
+ * The reportedAt field.
+ */
+ REPORTEDAT("createdAt");
private final String fieldName;
diff --git a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/TenantConfigurationKey.java b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/TenantConfigurationKey.java
index 477cd654e..ec5c5ec40 100644
--- a/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/TenantConfigurationKey.java
+++ b/hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/TenantConfigurationKey.java
@@ -22,35 +22,35 @@ public enum TenantConfigurationKey {
* boolean value {@code true} {@code false}.
*/
AUTHENTICATION_MODE_HEADER_ENABLED("authentication.header.enabled",
- "hawkbit.server.controller.security.authentication.header.enabled", Boolean.FALSE.toString()),
+ "hawkbit.server.ddi.security.authentication.header.enabled", Boolean.FALSE.toString()),
/**
*
*/
AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME("authentication.header.authority",
- "hawkbit.server.controller.security.authentication.header.authority", Boolean.FALSE.toString()),
+ "hawkbit.server.ddi.security.authentication.header.authority", Boolean.FALSE.toString()),
/**
* boolean value {@code true} {@code false}.
*/
AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED("authentication.targettoken.enabled",
- "hawkbit.server.controller.security.authentication.targettoken.enabled", Boolean.FALSE.toString()),
+ "hawkbit.server.ddi.security.authentication.targettoken.enabled", Boolean.FALSE.toString()),
/**
* boolean value {@code true} {@code false}.
*/
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_ENABLED("authentication.gatewaytoken.enabled",
- "hawkbit.server.controller.security.authentication.gatewaytoken.enabled", Boolean.FALSE.toString()),
+ "hawkbit.server.ddi.security.authentication.gatewaytoken.enabled", Boolean.FALSE.toString()),
/**
* string value which holds the name of the security token key.
*/
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_NAME("authentication.gatewaytoken.name",
- "hawkbit.server.controller.security.authentication.gatewaytoken.name", null),
+ "hawkbit.server.ddi.security.authentication.gatewaytoken.name", null),
/**
* string value which holds the actual security-key of the gateway security
* token.
*/
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY("authentication.gatewaytoken.key",
- "hawkbit.server.controller.security.authentication.gatewaytoken.key", null);
+ "hawkbit.server.ddi.security.authentication.gatewaytoken.key", null);
private final String keyName;
private final String defaultKeyName;
diff --git a/hawkbit-dmf-amqp/pom.xml b/hawkbit-dmf-amqp/pom.xml
index a7dfc5b42..2fded8559 100644
--- a/hawkbit-dmf-amqp/pom.xml
+++ b/hawkbit-dmf-amqp/pom.xml
@@ -60,6 +60,11 @@
org.slf4j
slf4j-api
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java
index 9b98cadfa..58ad38c92 100644
--- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java
+++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java
@@ -21,9 +21,9 @@ import org.eclipse.hawkbit.security.CoapAnonymousPreAuthenticatedFilter;
import org.eclipse.hawkbit.security.ControllerPreAuthenticateSecurityTokenFilter;
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedGatewaySecurityTokenFilter;
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedSecurityHeaderFilter;
+import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.PreAuthTokenSourceTrustAuthenticationProvider;
import org.eclipse.hawkbit.security.PreAuthenficationFilter;
-import org.eclipse.hawkbit.security.SecurityProperties;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -55,7 +55,7 @@ public class AmqpControllerAuthentfication {
private TenantAware tenantAware;
@Autowired
- private SecurityProperties secruityProperties;
+ private DdiSecurityProperties ddiSecruityProperties;
/**
* Constructor.
@@ -78,8 +78,8 @@ public class AmqpControllerAuthentfication {
filterChain.add(gatewaySecurityTokenFilter);
final ControllerPreAuthenticatedSecurityHeaderFilter securityHeaderFilter = new ControllerPreAuthenticatedSecurityHeaderFilter(
- secruityProperties.getRpCnHeader(), secruityProperties.getRpSslIssuerHashHeader(), systemManagement,
- tenantAware);
+ ddiSecruityProperties.getRp().getCnHeader(), ddiSecruityProperties.getRp().getSslIssuerHashHeader(),
+ systemManagement, tenantAware);
filterChain.add(securityHeaderFilter);
final ControllerPreAuthenticateSecurityTokenFilter securityTokenFilter = new ControllerPreAuthenticateSecurityTokenFilter(
@@ -134,8 +134,8 @@ public class AmqpControllerAuthentfication {
this.controllerManagement = controllerManagement;
}
- public void setSecruityProperties(final SecurityProperties secruityProperties) {
- this.secruityProperties = secruityProperties;
+ public void setSecruityProperties(final DdiSecurityProperties secruityProperties) {
+ this.ddiSecruityProperties = secruityProperties;
}
public void setSystemManagement(final SystemManagement systemManagement) {
diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java
index c3a807f48..4b33a59b8 100644
--- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java
+++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpProperties.java
@@ -8,41 +8,91 @@
*/
package org.eclipse.hawkbit.amqp;
+import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
/**
* Bean which holds the necessary properties for configuring the AMQP
* connection.
- *
+ *
*/
+@Component
@ConfigurationProperties("hawkbit.dmf.rabbitmq")
public class AmqpProperties {
-
+ /**
+ * DMF API dead letter queue.
+ */
private String deadLetterQueue = "dmf_receiver_deadletter";
+
+ /**
+ * DMF API dead letter exchange.
+ */
private String deadLetterExchange = "dmf.receiver.deadletter";
+
+ /**
+ * DMF API receiving queue.
+ */
private String receiverQueue = "dmf_receiver";
+
+ /**
+ * Missing queue fatal.
+ */
private boolean missingQueuesFatal = false;
+ /**
+ * Is missingQueuesFatal enabled
+ *
+ * @see SimpleMessageListenerContainer#setMissingQueuesFatal
+ * @return the missingQueuesFatal enabled disabled
+ */
public boolean isMissingQueuesFatal() {
return missingQueuesFatal;
}
+ /**
+ * @param missingQueuesFatal
+ * the missingQueuesFatal to set.
+ * @see SimpleMessageListenerContainer#setMissingQueuesFatal
+ */
public void setMissingQueuesFatal(final boolean missingQueuesFatal) {
this.missingQueuesFatal = missingQueuesFatal;
}
+ /**
+ * Returns the dead letter exchange.
+ *
+ * @return dead letter exchange
+ */
public String getDeadLetterExchange() {
return deadLetterExchange;
}
+ /**
+ * Sets the dead letter exchange.
+ *
+ * @param deadLetterExchange
+ * the deadLetterExchange to be set
+ */
public void setDeadLetterExchange(final String deadLetterExchange) {
this.deadLetterExchange = deadLetterExchange;
}
+ /**
+ * Returns the dead letter queue.
+ *
+ * @return the dead letter queue
+ */
public String getDeadLetterQueue() {
return deadLetterQueue;
}
+ /**
+ * Sets the dead letter queue.
+ *
+ * @param deadLetterQueue
+ * the deadLetterQueue ro be set
+ */
public void setDeadLetterQueue(final String deadLetterQueue) {
this.deadLetterQueue = deadLetterQueue;
}
diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java
index af5ce3267..501fddf81 100644
--- a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java
+++ b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthenticationTest.java
@@ -23,8 +23,9 @@ import org.eclipse.hawkbit.dmf.json.model.TenantSecruityToken;
import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.SystemManagement;
+import org.eclipse.hawkbit.security.DdiSecurityProperties;
+import org.eclipse.hawkbit.security.DdiSecurityProperties.Rp;
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
-import org.eclipse.hawkbit.security.SecurityProperties;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.junit.Before;
import org.junit.Test;
@@ -67,8 +68,11 @@ public class AmqpControllerAuthenticationTest {
authenticationManager = new AmqpControllerAuthentfication();
authenticationManager.setControllerManagement(mock(ControllerManagement.class));
- final SecurityProperties secruityProperties = mock(SecurityProperties.class);
- when(secruityProperties.getRpSslIssuerHashHeader()).thenReturn("X-Ssl-Issuer-Hash-%d");
+
+ final DdiSecurityProperties secruityProperties = mock(DdiSecurityProperties.class);
+ final Rp rp = mock(Rp.class);
+ when(secruityProperties.getRp()).thenReturn(rp);
+ when(rp.getSslIssuerHashHeader()).thenReturn("X-Ssl-Issuer-Hash-%d");
authenticationManager.setSecruityProperties(secruityProperties);
systemManagement = mock(SystemManagement.class);
authenticationManager.setSystemManagement(systemManagement);
diff --git a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/util/PropertyBasedArtifactUrlHandlerTest.java b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/util/PropertyBasedArtifactUrlHandlerTest.java
index 169a12f1e..e7ba06d19 100644
--- a/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/util/PropertyBasedArtifactUrlHandlerTest.java
+++ b/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/util/PropertyBasedArtifactUrlHandlerTest.java
@@ -56,7 +56,7 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
}
@Test
- @Description("Tests generate the http download url")
+ @Description("Tests the generation of http download url.")
public void testHttpUrl() {
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.HTTP);
assertEquals("http is build incorrect",
@@ -67,7 +67,7 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
}
@Test
- @Description("Tests generate the https download url")
+ @Description("Tests the generation of https download url.")
public void testHttpsUrl() {
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.HTTPS);
assertEquals("https is build incorrect",
@@ -78,7 +78,7 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
}
@Test
- @Description("Tests generate the coap download url")
+ @Description("Tests the generation of coap download url.")
public void testCoapUrl() {
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.COAP);
diff --git a/hawkbit-repository/pom.xml b/hawkbit-repository/pom.xml
index 981da979e..7259262de 100644
--- a/hawkbit-repository/pom.xml
+++ b/hawkbit-repository/pom.xml
@@ -99,6 +99,11 @@
org.flywaydb
flyway-core
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java
index e2d31a04c..84d1d9b60 100644
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RepositoryApplicationConfiguration.java
@@ -40,10 +40,6 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess
/**
* General configuration for the SP Repository.
*
- *
- *
- *
- *
*/
@EnableJpaRepositories(basePackages = { "org.eclipse.hawkbit.repository" })
@EnableTransactionManagement
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RolloutProperties.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RolloutProperties.java
new file mode 100644
index 000000000..63e116f47
--- /dev/null
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/RolloutProperties.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * Rollout Management properties.
+ *
+ */
+@Component
+@ConfigurationProperties("hawkbit.rollout")
+public class RolloutProperties {
+ private final Scheduler scheduler = new Scheduler();
+
+ public Scheduler getScheduler() {
+ return scheduler;
+ }
+
+ /**
+ * Rollout scheduler configuration.
+ */
+ public static class Scheduler {
+ // used by @Scheduled annotation which needs constant
+ public static final String PROP_SCHEDULER_DELAY_PLACEHOLDER = "${hawkbit.rollout.scheduler.fixedDelay:30000}";
+
+ /**
+ * Schedule where the rollout scheduler looks necessary state changes in
+ * milliseconds.
+ */
+ private long fixedDelay = 30000L;
+
+ public long getFixedDelay() {
+ return fixedDelay;
+ }
+
+ public void setFixedDelay(final long fixedDelay) {
+ this.fixedDelay = fixedDelay;
+ }
+
+ }
+
+}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ActionStatusRepository.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ActionStatusRepository.java
index 5e2800755..2705b9ac6 100644
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ActionStatusRepository.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ActionStatusRepository.java
@@ -21,45 +21,47 @@ import org.springframework.transaction.annotation.Transactional;
/**
* {@link ActionStatus} repository.
*
- *
- *
- *
*/
@Transactional(readOnly = true)
public interface ActionStatusRepository
extends BaseEntityRepository, JpaSpecificationExecutor {
/**
- * @param target
+ * Counts {@link ActionStatus} entries of given {@link Action} in
+ * repository.
+ *
* @param action
- * @return
+ * to count status entries
+ * @return number of actions in repository
*/
Long countByAction(Action action);
/**
+ * Counts {@link ActionStatus} entries of given {@link Action} with given
+ * {@link Status} in repository.
+ *
* @param action
- * @param retrieved
- * @return
+ * to count status entries
+ * @param status
+ * to filter for
+ * @return number of actions in repository
*/
- Long countByActionAndStatus(Action action, Status retrieved);
+ Long countByActionAndStatus(Action action, Status status);
/**
+ * Retrieves all {@link ActionStatus} entries from repository of given
+ * {@link Action}.
+ *
* @param pageReq
+ * parameters
* @param action
- * @return
+ * of the status entries
+ * @return pages list of {@link ActionStatus} entries
*/
Page findByAction(Pageable pageReq, Action action);
/**
- * @param pageReq
- * @param action
- * @return
- */
- Page findByActionOrderByIdDesc(Pageable pageReq, Action action);
-
- /**
- * Finds all status updates for the defined action and target order by
- * {@link ActionStatus#getId()} desc including
+ * Finds all status updates for the defined action and target including
* {@link ActionStatus#getMessages()}.
*
* @param pageReq
@@ -71,6 +73,6 @@ public interface ActionStatusRepository
* @return Page with found targets
*/
@EntityGraph(value = "ActionStatus.withMessages", type = EntityGraphType.LOAD)
- Page getByActionOrderByIdDesc(Pageable pageReq, Action action);
+ Page getByAction(Pageable pageReq, Action action);
}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java
index e4a1e5e6b..b6fbb6010 100644
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ControllerManagement.java
@@ -33,13 +33,11 @@ import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.model.Target_;
+import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.hibernate.validator.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.bind.RelaxedPropertyResolver;
-import org.springframework.context.EnvironmentAware;
-import org.springframework.core.env.Environment;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -57,7 +55,7 @@ import org.springframework.validation.annotation.Validated;
@Transactional(readOnly = true)
@Validated
@Service
-public class ControllerManagement implements EnvironmentAware {
+public class ControllerManagement {
private static final Logger LOG = LoggerFactory.getLogger(ControllerManagement.class);
private static final Logger LOG_DOS = LoggerFactory.getLogger("server-security.dos");
@@ -85,9 +83,8 @@ public class ControllerManagement implements EnvironmentAware {
@Autowired
private ActionStatusRepository actionStatusRepository;
- private Integer maxCount = 1000;
-
- private Integer maxAttributes = 100;
+ @Autowired
+ private HawkbitSecurityProperties securityProperties;
/**
* Refreshes the time of the last time the controller has been connected to
@@ -379,15 +376,16 @@ public class ControllerManagement implements EnvironmentAware {
}
private void checkForToManyStatusEntries(final Action action) {
- if (maxCount > 0) {
+ if (securityProperties.getDos().getMaxStatusEntriesPerAction() > 0) {
final Long statusCount = actionStatusRepository.countByAction(action);
- if (statusCount >= maxCount) {
+ if (statusCount >= securityProperties.getDos().getMaxStatusEntriesPerAction()) {
LOG_DOS.error(
"Potential denial of service (DOS) attack identfied. More status entries in the system than permitted ({})!",
- maxCount);
- throw new ToManyStatusEntriesException(String.valueOf(maxCount));
+ securityProperties.getDos().getMaxStatusEntriesPerAction());
+ throw new ToManyStatusEntriesException(
+ String.valueOf(securityProperties.getDos().getMaxStatusEntriesPerAction()));
}
}
}
@@ -436,10 +434,12 @@ public class ControllerManagement implements EnvironmentAware {
target.getTargetInfo().getControllerAttributes().putAll(data);
- if (target.getTargetInfo().getControllerAttributes().size() > maxAttributes) {
+ if (target.getTargetInfo().getControllerAttributes().size() > securityProperties.getDos()
+ .getMaxAttributeEntriesPerTarget()) {
LOG_DOS.info("Target tries to insert more than the allowed number of entries ({}). DOS attack anticipated!",
- maxAttributes);
- throw new ToManyAttributeEntriesException(String.valueOf(maxAttributes));
+ securityProperties.getDos().getMaxAttributeEntriesPerTarget());
+ throw new ToManyAttributeEntriesException(
+ String.valueOf(securityProperties.getDos().getMaxAttributeEntriesPerTarget()));
}
target.getTargetInfo().setLastTargetQuery(System.currentTimeMillis());
@@ -447,19 +447,6 @@ public class ControllerManagement implements EnvironmentAware {
return targetRepository.save(target);
}
- /*
- * (non-Javadoc)
- *
- * @see org.springframework.context.EnvironmentAware#setEnvironment(org.
- * springframework.core.env. Environment)
- */
- @Override
- public void setEnvironment(final Environment environment) {
- final RelaxedPropertyResolver env = new RelaxedPropertyResolver(environment, "hawkbit.server.");
- maxCount = env.getProperty("security.dos.maxStatusEntriesPerAction", Integer.class, 1000);
- maxAttributes = env.getProperty("security.dos.maxAttributeEntriesPerTarget", Integer.class, 100);
- }
-
/**
* Registers retrieved status for given {@link Target} and {@link Action} if
* it does not exist yet.
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java
index 58ce8c26d..e1976c9a6 100644
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java
@@ -925,7 +925,7 @@ public class DeploymentManagement {
/**
* retrieves all the {@link ActionStatus} entries of the given
- * {@link Action} and {@link Target} in the order latest first.
+ * {@link Action} and {@link Target}.
*
* @param pageReq
* pagination parameter
@@ -937,12 +937,12 @@ public class DeploymentManagement {
* @return the corresponding {@link Page} of {@link ActionStatus}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
- public Page findActionStatusMessagesByActionInDescOrder(final Pageable pageReq, final Action action,
+ public Page findActionStatusByAction(final Pageable pageReq, final Action action,
final boolean withMessages) {
if (withMessages) {
- return actionStatusRepository.getByActionOrderByIdDesc(pageReq, action);
+ return actionStatusRepository.getByAction(pageReq, action);
} else {
- return actionStatusRepository.findByActionOrderByIdDesc(pageReq, action);
+ return actionStatusRepository.findByAction(pageReq, action);
}
}
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ReportManagement.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ReportManagement.java
index 8f87f9209..eab926b4b 100644
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ReportManagement.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/ReportManagement.java
@@ -46,7 +46,6 @@ import org.eclipse.hawkbit.repository.model.Target_;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -55,14 +54,10 @@ import org.springframework.validation.annotation.Validated;
/**
* Service layer for generating SP reportings.
*
- *
- *
- *
*/
@Transactional(readOnly = true)
@Validated
@Service
-@ConfigurationProperties
public class ReportManagement {
@Value("${spring.jpa.database}")
diff --git a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/RolloutScheduler.java b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/RolloutScheduler.java
index b60d64cc5..24b7c2627 100644
--- a/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/RolloutScheduler.java
+++ b/hawkbit-repository/src/main/java/org/eclipse/hawkbit/repository/RolloutScheduler.java
@@ -10,14 +10,13 @@ package org.eclipse.hawkbit.repository;
import java.util.List;
+import org.eclipse.hawkbit.RolloutProperties;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Profile;
-import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@@ -31,15 +30,10 @@ import org.springframework.stereotype.Component;
// don't active the rollout scheduler in test, otherwise it is hard to test
// rolloutmanagement and leads weird side-effects maybe.
@Profile("!test")
-public class RolloutScheduler implements EnvironmentAware {
+public class RolloutScheduler {
private static final Logger logger = LoggerFactory.getLogger(RolloutScheduler.class);
- private static final String PROP_SCHEDULER_DELAY = "hawkbit.rollout.scheduler.fixedDelay";
- private static final long DEFAULT_SCHEDULER_DELAY = 30000L;
- private static final String PROP_SCHEDULER_DELAY_PLACEHOLDER = "${" + PROP_SCHEDULER_DELAY + ":"
- + DEFAULT_SCHEDULER_DELAY + "}";
-
@Autowired
private TenantAware tenantAware;
@@ -52,7 +46,8 @@ public class RolloutScheduler implements EnvironmentAware {
@Autowired
private SystemSecurityContext systemSecurityContext;
- private long fixedDelay = DEFAULT_SCHEDULER_DELAY;
+ @Autowired
+ private RolloutProperties rolloutProperties;
/**
* Scheduler method called by the spring-async mechanism. Retrieves all
@@ -60,7 +55,7 @@ public class RolloutScheduler implements EnvironmentAware {
* tenant the {@link RolloutManagement#checkRunningRollouts(long)} in the
* {@link SystemSecurityContext}.
*/
- @Scheduled(initialDelayString = PROP_SCHEDULER_DELAY_PLACEHOLDER, fixedDelayString = PROP_SCHEDULER_DELAY_PLACEHOLDER)
+ @Scheduled(initialDelayString = RolloutProperties.Scheduler.PROP_SCHEDULER_DELAY_PLACEHOLDER, fixedDelayString = RolloutProperties.Scheduler.PROP_SCHEDULER_DELAY_PLACEHOLDER)
public void rolloutScheduler() {
logger.debug("rollout schedule checker has been triggered.");
// run this code in system code privileged to have the necessary
@@ -76,16 +71,11 @@ public class RolloutScheduler implements EnvironmentAware {
logger.info("Checking rollouts for {} tenants", tenants.size());
for (final String tenant : tenants) {
tenantAware.runAsTenant(tenant, () -> {
- rolloutManagement.checkRunningRollouts(fixedDelay);
+ rolloutManagement.checkRunningRollouts(rolloutProperties.getScheduler().getFixedDelay());
return null;
});
}
return null;
});
}
-
- @Override
- public void setEnvironment(final Environment environment) {
- fixedDelay = environment.getProperty(PROP_SCHEDULER_DELAY, Long.class, DEFAULT_SCHEDULER_DELAY);
- }
}
diff --git a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/TestConfiguration.java b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/TestConfiguration.java
index 945e71c75..706cb4479 100644
--- a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/TestConfiguration.java
+++ b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/TestConfiguration.java
@@ -17,8 +17,8 @@ import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
import org.eclipse.hawkbit.repository.model.helper.EventBusHolder;
import org.eclipse.hawkbit.repository.utils.RepositoryDataGenerator;
import org.eclipse.hawkbit.repository.utils.RepositoryDataGenerator.DatabaseCleanupUtil;
+import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
-import org.eclipse.hawkbit.security.SecurityProperties;
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
@@ -47,7 +47,7 @@ import com.mongodb.MongoClientOptions;
*/
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.ASPECTJ, proxyTargetClass = true, securedEnabled = true)
-@EnableConfigurationProperties({ SecurityProperties.class, ControllerPollProperties.class })
+@EnableConfigurationProperties({ DdiSecurityProperties.class, ControllerPollProperties.class })
@Profile("test")
public class TestConfiguration implements AsyncConfigurer {
diff --git a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/ControllerManagementTest.java b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/ControllerManagementTest.java
index 41a7c7848..a3913da2b 100644
--- a/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/ControllerManagementTest.java
+++ b/hawkbit-repository/src/test/java/org/eclipse/hawkbit/repository/ControllerManagementTest.java
@@ -70,8 +70,8 @@ public class ControllerManagementTest extends AbstractIntegrationTest {
.isEqualTo(TargetUpdateStatus.IN_SYNC);
assertThat(actionStatusRepository.findAll(pageReq).getNumberOfElements()).isEqualTo(3);
- assertThat(deploymentManagement.findActionStatusMessagesByActionInDescOrder(pageReq, savedAction, false)
- .getNumberOfElements()).isEqualTo(3);
+ assertThat(deploymentManagement.findActionStatusByAction(pageReq, savedAction, false).getNumberOfElements())
+ .isEqualTo(3);
}
@Test
diff --git a/hawkbit-repository/src/test/resources/application-test.properties b/hawkbit-repository/src/test/resources/application-test.properties
index e5fb04a21..dc7549fcb 100644
--- a/hawkbit-repository/src/test/resources/application-test.properties
+++ b/hawkbit-repository/src/test/resources/application-test.properties
@@ -10,7 +10,7 @@
spring.data.mongodb.uri=mongodb://localhost/spArtifactRepository${random.value}
spring.data.mongodb.port=28017
-hawkbit.server.controller.security.authentication.header.enabled=true
+hawkbit.server.ddi.security.authentication.header.enabled=true
hawkbit.server.artifact.repo.upload.maxFileSize=5MB
@@ -29,11 +29,6 @@ flyway.initOnMigrate=true
flyway.sqlMigrationSuffix=${spring.jpa.database}.sql
#spring.jpa.show-sql=true
-# SP Controller configuration
+# DDI configuration
hawkbit.controller.pollingTime=00:01:00
-hawkbit.controller.pollingOverdueTime=00:01:00
-
-## Configuration for RabbitMQ integration
-hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter
-hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.connector.deadletter
-hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver
+hawkbit.controller.pollingOverdueTime=00:01:00
\ No newline at end of file
diff --git a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/controller/ArtifactStoreController.java b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/controller/ArtifactStoreController.java
index 05fd6c492..c2dbd3ba5 100644
--- a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/controller/ArtifactStoreController.java
+++ b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/controller/ArtifactStoreController.java
@@ -25,13 +25,11 @@ import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.rest.resource.helper.RestResourceConversionHelper;
+import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.util.IpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.bind.RelaxedPropertyResolver;
-import org.springframework.context.EnvironmentAware;
-import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.web.bind.annotation.AuthenticationPrincipal;
@@ -55,7 +53,7 @@ import org.springframework.web.bind.annotation.RestController;
*/
@RestController
@RequestMapping(ControllerConstants.ARTIFACTS_V1_REQUEST_MAPPING)
-public class ArtifactStoreController implements EnvironmentAware {
+public class ArtifactStoreController {
private static final Logger LOG = LoggerFactory.getLogger(ArtifactStoreController.class);
@Autowired
@@ -67,14 +65,8 @@ public class ArtifactStoreController implements EnvironmentAware {
@Autowired
private CacheWriteNotify cacheWriteNotify;
- private static final String SP_SERVER_CONFIG_PREFIX = "hawkbit.server.";
- private RelaxedPropertyResolver environment;
-
- @Override
- public void setEnvironment(final Environment environment) {
- this.environment = new RelaxedPropertyResolver(environment, SP_SERVER_CONFIG_PREFIX);
-
- }
+ @Autowired
+ private HawkbitSecurityProperties securityProperties;
/**
* Handles GET {@link Artifact} download request. This could be full or
@@ -138,8 +130,8 @@ public class ArtifactStoreController implements EnvironmentAware {
private Action checkAndReportDownloadByTarget(final HttpServletRequest request, final String targetid,
final LocalArtifact artifact) {
- final Target target = controllerManagement.updateLastTargetQuery(targetid, IpUtil.getClientIpFromRequest(
- request, environment.getProperty("security.rp.remote_ip_header", String.class, "X-Forwarded-For")));
+ final Target target = controllerManagement.updateLastTargetQuery(targetid,
+ IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
final Action action = controllerManagement
.getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), artifact.getSoftwareModule());
diff --git a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/controller/RootController.java b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/controller/RootController.java
index 2b0ac810e..6928ee7b5 100644
--- a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/controller/RootController.java
+++ b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/controller/RootController.java
@@ -41,15 +41,13 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.rest.resource.helper.RestResourceConversionHelper;
+import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.util.IpUtil;
import org.hibernate.validator.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.bind.RelaxedPropertyResolver;
-import org.springframework.context.EnvironmentAware;
-import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@@ -74,7 +72,7 @@ import org.springframework.web.bind.annotation.RestController;
*/
@RestController
@RequestMapping(ControllerConstants.BASE_V1_REQUEST_MAPPING)
-public class RootController implements EnvironmentAware {
+public class RootController {
private static final Logger LOG = LoggerFactory.getLogger(RootController.class);
private static final String GIVEN_ACTION_IS_NOT_ASSIGNED_TO_GIVEN_TARGET = "given action ({}) is not assigned to given target ({}).";
@@ -99,16 +97,8 @@ public class RootController implements EnvironmentAware {
@Autowired
private TenantAware tenantAware;
- private String requestHeader;
-
- @Override
- public void setEnvironment(final Environment environment) {
- final RelaxedPropertyResolver relaxedPropertyResolver = new RelaxedPropertyResolver(environment,
- SP_SERVER_CONFIG_PREFIX);
-
- requestHeader = relaxedPropertyResolver.getProperty("security.rp.remote_ip_header", String.class,
- "X-Forwarded-For");
- }
+ @Autowired
+ private HawkbitSecurityProperties securityProperties;
/**
* Returns all artifacts of a given software module and target.
@@ -155,12 +145,13 @@ public class RootController implements EnvironmentAware {
LOG.debug("getControllerBase({})", targetid);
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotexist(targetid,
- IpUtil.getClientIpFromRequest(request, requestHeader));
+ IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
if (target.getTargetInfo().getUpdateStatus() == TargetUpdateStatus.UNKNOWN) {
LOG.debug("target with {} extsisted but was in status UNKNOWN -> REGISTERED)", targetid);
controllerManagement.updateTargetStatus(target.getTargetInfo(), TargetUpdateStatus.REGISTERED,
- System.currentTimeMillis(), IpUtil.getClientIpFromRequest(request, requestHeader));
+ System.currentTimeMillis(),
+ IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
}
return new ResponseEntity<>(
@@ -195,7 +186,7 @@ public class RootController implements EnvironmentAware {
ResponseEntity result;
final Target target = controllerManagement.updateLastTargetQuery(targetid,
- IpUtil.getClientIpFromRequest(request, requestHeader));
+ IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
final SoftwareModule module = softwareManagement.findSoftwareModuleById(softwareModuleId);
if (checkModule(fileName, module)) {
@@ -265,7 +256,8 @@ public class RootController implements EnvironmentAware {
public ResponseEntity downloadArtifactMd5(@PathVariable final String targetid,
@PathVariable final Long softwareModuleId, @PathVariable final String fileName,
final HttpServletResponse response, final HttpServletRequest request) {
- controllerManagement.updateLastTargetQuery(targetid, IpUtil.getClientIpFromRequest(request, requestHeader));
+ controllerManagement.updateLastTargetQuery(targetid,
+ IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
final SoftwareModule module = softwareManagement.findSoftwareModuleById(softwareModuleId);
@@ -311,7 +303,7 @@ public class RootController implements EnvironmentAware {
LOG.debug("getControllerBasedeploymentAction({},{})", targetid, resource);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
- IpUtil.getClientIpFromRequest(request, requestHeader));
+ IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
final Action action = findActionWithExceptionIfNotFound(actionId);
if (!action.getTarget().getId().equals(target.getId())) {
@@ -362,7 +354,7 @@ public class RootController implements EnvironmentAware {
LOG.debug("provideBasedeploymentActionFeedback for target [{},{}]: {}", targetid, actionId, feedback);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
- IpUtil.getClientIpFromRequest(request, requestHeader));
+ IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
if (!actionId.equals(feedback.getId())) {
LOG.warn(
@@ -467,7 +459,8 @@ public class RootController implements EnvironmentAware {
+ ControllerConstants.CONFIG_DATA_ACTION, method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity putConfigData(@Valid @RequestBody final ConfigData configData,
@PathVariable final String targetid, final HttpServletRequest request) {
- controllerManagement.updateLastTargetQuery(targetid, IpUtil.getClientIpFromRequest(request, requestHeader));
+ controllerManagement.updateLastTargetQuery(targetid,
+ IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
controllerManagement.updateControllerAttributes(targetid, configData.getData());
@@ -493,7 +486,7 @@ public class RootController implements EnvironmentAware {
LOG.debug("getControllerCancelAction({})", targetid);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
- IpUtil.getClientIpFromRequest(request, requestHeader));
+ IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
final Action action = findActionWithExceptionIfNotFound(actionId);
if (!action.getTarget().getId().equals(target.getId())) {
@@ -540,7 +533,7 @@ public class RootController implements EnvironmentAware {
LOG.debug("provideCancelActionFeedback for target [{}]: {}", targetid, feedback);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
- IpUtil.getClientIpFromRequest(request, requestHeader));
+ IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
if (!actionId.equals(feedback.getId())) {
LOG.warn(
diff --git a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/PagingUtility.java b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/PagingUtility.java
index 1503b8bda..4fb854608 100644
--- a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/PagingUtility.java
+++ b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/PagingUtility.java
@@ -23,11 +23,6 @@ import org.springframework.data.domain.Sort.Direction;
/**
* Utility class for for paged body generation.
*
- *
- *
- *
- *
- *
*/
public final class PagingUtility {
/*
@@ -90,8 +85,9 @@ public final class PagingUtility {
if (sortParam != null) {
sorting = new Sort(SortUtility.parse(ActionFields.class, sortParam));
} else {
- // default sort
- sorting = new Sort(Direction.ASC, ActionFields.ID.getFieldName());
+ // default sort is DESC in case of action to match behavior
+ // of management UI (last entry on top)
+ sorting = new Sort(Direction.DESC, ActionFields.ID.getFieldName());
}
return sorting;
}
@@ -101,8 +97,9 @@ public final class PagingUtility {
if (sortParam != null) {
sorting = new Sort(SortUtility.parse(ActionStatusFields.class, sortParam));
} else {
- // default sort
- sorting = new Sort(Direction.ASC, ActionStatusFields.ID.getFieldName());
+ // default sort is DESC in case of action status to match behavior
+ // of management UI (last entry on top)
+ sorting = new Sort(Direction.DESC, ActionStatusFields.ID.getFieldName());
}
return sorting;
}
diff --git a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/TargetMapper.java b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/TargetMapper.java
index 4f6ddafb8..b6c6c1539 100644
--- a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/TargetMapper.java
+++ b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/TargetMapper.java
@@ -297,8 +297,8 @@ final public class TargetMapper {
final ActionStatusRest result = new ActionStatusRest();
result.setMessages(actionStatus.getMessages());
- result.setReportedAt(action.getCreatedAt());
- result.setStatusId(action.getId());
+ result.setReportedAt(actionStatus.getCreatedAt());
+ result.setStatusId(actionStatus.getId());
result.setType(getNameOfActionStatusType(actionStatus.getStatus()));
return result;
diff --git a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/TargetResource.java b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/TargetResource.java
index 01f018327..69a38f87d 100644
--- a/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/TargetResource.java
+++ b/hawkbit-rest-resource/src/main/java/org/eclipse/hawkbit/rest/resource/TargetResource.java
@@ -235,7 +235,7 @@ public class TargetResource implements TargetRestApi {
final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam);
final Sort sorting = PagingUtility.sanitizeActionStatusSortParam(sortParam);
- final Page statusList = this.deploymentManagement.findActionStatusMessagesByActionInDescOrder(
+ final Page statusList = this.deploymentManagement.findActionStatusByAction(
new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting), action, true);
return new ResponseEntity<>(
diff --git a/hawkbit-rest-resource/src/test/java/org/eclipse/hawkbit/rest/resource/TargetResourceTest.java b/hawkbit-rest-resource/src/test/java/org/eclipse/hawkbit/rest/resource/TargetResourceTest.java
index e9b0bd60a..a8ebfdd9d 100644
--- a/hawkbit-rest-resource/src/test/java/org/eclipse/hawkbit/rest/resource/TargetResourceTest.java
+++ b/hawkbit-rest-resource/src/test/java/org/eclipse/hawkbit/rest/resource/TargetResourceTest.java
@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.rest.resource;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.hasSize;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
@@ -34,6 +35,7 @@ import org.eclipse.hawkbit.TestDataUtil;
import org.eclipse.hawkbit.WithUser;
import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.im.authentication.SpPermission;
+import org.eclipse.hawkbit.repository.ActionFields;
import org.eclipse.hawkbit.repository.ActionStatusFields;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.model.Action;
@@ -109,27 +111,24 @@ public class TargetResourceTest extends AbstractIntegrationTest {
new ActionStatus(actions.get(0), Status.FINISHED, System.currentTimeMillis(), "testmessage"),
actions.get(0));
- final PageRequest pageRequest = new PageRequest(0, 1000, Direction.ASC, ActionStatusFields.ID.getFieldName());
+ final PageRequest pageRequest = new PageRequest(0, 1000, Direction.ASC, ActionFields.ID.getFieldName());
+ final ActionStatus status = deploymentManagement
+ .findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
+ .get(0).getActionStatus().stream().sorted((e1, e2) -> Long.compare(e2.getId(), e1.getId()))
+ .collect(Collectors.toList()).get(0);
- // limit to 1 - first page -> standard cancel message
- final Long reportAt = deploymentManagement
- .findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
- .get(0).getCreatedAt();
- final Long id = deploymentManagement
- .findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
- .get(0).getId();
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
+ RestConstants.TARGET_V1_ACTIONS + "/" + actions.get(0).getId() + "/status")
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(limitSize))
- .param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:ASC"))
+ .param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:DESC"))
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(3)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(limitSize)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(limitSize)))
- .andExpect(jsonPath("content.[0].id", equalTo(id.intValue())))
+ .andExpect(jsonPath("content.[0].id", equalTo(status.getId().intValue())))
.andExpect(jsonPath("content.[0].type", equalTo("finished")))
.andExpect(jsonPath("content.[0].messages", hasSize(1)))
- .andExpect(jsonPath("content.[0].reportedAt", equalTo(reportAt)))
+ .andExpect(jsonPath("content.[0].reportedAt", equalTo(status.getCreatedAt().longValue())))
.andExpect(jsonPath("content.[1].type", equalTo("canceling")));
}
@@ -839,7 +838,8 @@ public class TargetResourceTest extends AbstractIntegrationTest {
final List actions = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId);
mvc.perform(get(
- RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS))
+ RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS)
+ .param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:ASC"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("content.[1].id", equalTo(actions.get(1).getId().intValue())))
.andExpect(jsonPath("content.[1].type", equalTo("update")))
@@ -856,6 +856,108 @@ public class TargetResourceTest extends AbstractIntegrationTest {
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(2)));
}
+ @Test
+ @Description("Verfies that the API returns the status list with expected content.")
+ public void getMultipleActionStatus() throws Exception {
+ final String knownTargetId = "targetId";
+ final Action action = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId).get(0);
+ // retrieve list in default descending order for actionstaus entries
+ final List actionStatus = action.getActionStatus().stream()
+ .sorted((e1, e2) -> Long.compare(e2.getId(), e1.getId())).collect(Collectors.toList());
+
+ // sort is default descending order, latest status first
+ mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
+ + RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS))
+ .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
+ .andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(0).getId().intValue())))
+ .andExpect(jsonPath("content.[0].type", equalTo("canceling")))
+ .andExpect(jsonPath("content.[0].messages", hasItem("manual cancelation requested")))
+ .andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(0).getCreatedAt())))
+ .andExpect(jsonPath("content.[1].id", equalTo(actionStatus.get(1).getId().intValue())))
+ .andExpect(jsonPath("content.[1].type", equalTo("running")))
+ .andExpect(jsonPath("content.[1].reportedAt", equalTo(actionStatus.get(1).getCreatedAt())))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(2)))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(2)));
+ }
+
+ @Test
+ @Description("Verfies that the API returns the status list with expected content sorted by reportedAt field.")
+ public void getMultipleActionStatusSortedByReportedAt() throws Exception {
+ final String knownTargetId = "targetId";
+ final Action action = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId).get(0);
+ final List actionStatus = action.getActionStatus().stream()
+ .sorted((e1, e2) -> Long.compare(e1.getId(), e2.getId())).collect(Collectors.toList());
+
+ // descending order
+ mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
+ + RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS)
+ .param(RestConstants.REQUEST_PARAMETER_SORTING, "REPORTEDAT:DESC"))
+ .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
+ .andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(1).getId().intValue())))
+ .andExpect(jsonPath("content.[0].type", equalTo("canceling")))
+ .andExpect(jsonPath("content.[0].messages", hasItem("manual cancelation requested")))
+ .andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(1).getCreatedAt())))
+ .andExpect(jsonPath("content.[1].id", equalTo(actionStatus.get(0).getId().intValue())))
+ .andExpect(jsonPath("content.[1].type", equalTo("running")))
+ .andExpect(jsonPath("content.[1].reportedAt", equalTo(actionStatus.get(0).getCreatedAt())))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(2)))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(2)));
+
+ // ascending order
+ mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
+ + RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS)
+ .param(RestConstants.REQUEST_PARAMETER_SORTING, "REPORTEDAT:ASC"))
+ .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
+ .andExpect(jsonPath("content.[1].id", equalTo(actionStatus.get(1).getId().intValue())))
+ .andExpect(jsonPath("content.[1].type", equalTo("canceling")))
+ .andExpect(jsonPath("content.[1].messages", hasItem("manual cancelation requested")))
+ .andExpect(jsonPath("content.[1].reportedAt", equalTo(actionStatus.get(1).getCreatedAt())))
+ .andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(0).getId().intValue())))
+ .andExpect(jsonPath("content.[0].type", equalTo("running")))
+ .andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(0).getCreatedAt())))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(2)))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(2)));
+ }
+
+ @Test
+ @Description("Verfies that the API returns the status list with expected content split into two pages.")
+ public void getMultipleActionStatusWithPagingLimitRequestParameter() throws Exception {
+ final String knownTargetId = "targetId";
+
+ final Action action = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId).get(0);
+ final List actionStatus = action.getActionStatus().stream()
+ .sorted((e1, e2) -> Long.compare(e1.getId(), e2.getId())).collect(Collectors.toList());
+
+ // Page 1
+ mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
+ + RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS)
+ .param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1)))
+ .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
+ .andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(1).getId().intValue())))
+ .andExpect(jsonPath("content.[0].type", equalTo("canceling")))
+ .andExpect(jsonPath("content.[0].messages", hasItem("manual cancelation requested")))
+ .andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(1).getCreatedAt())))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(1)))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(1)));
+
+ // Page 2
+ mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
+ + RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS)
+ .param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1))
+ .param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1)))
+ .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
+ .andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(0).getId().intValue())))
+ .andExpect(jsonPath("content.[0].type", equalTo("running")))
+ .andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(0).getCreatedAt())))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(1)))
+ .andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(1)));
+ }
+
@Test
public void getMultipleActionsWithPagingLimitRequestParameter() throws Exception {
final String knownTargetId = "targetId";
@@ -864,7 +966,8 @@ public class TargetResourceTest extends AbstractIntegrationTest {
// page 1: one entry
mvc.perform(get(
RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS)
- .param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1)))
+ .param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1))
+ .param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:ASC"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("content.[0].id", equalTo(actions.get(0).getId().intValue())))
.andExpect(jsonPath("content.[0].type", equalTo("cancel")))
@@ -879,7 +982,9 @@ public class TargetResourceTest extends AbstractIntegrationTest {
mvc.perform(get(
RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS)
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1))
- .param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1)))
+ .param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1))
+ .param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1))
+ .param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:ASC"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("content.[0].id", equalTo(actions.get(1).getId().intValue())))
.andExpect(jsonPath("content.[0].type", equalTo("update")))
@@ -907,7 +1012,8 @@ public class TargetResourceTest extends AbstractIntegrationTest {
+ "?offset=0&limit=50&sort=id:DESC";
}
- private List generateTargetWithTwoUpdatesWithOneOverride(final String knownTargetId) {
+ private List generateTargetWithTwoUpdatesWithOneOverride(final String knownTargetId)
+ throws InterruptedException {
final PageRequest pageRequest = new PageRequest(0, 100, Direction.ASC, ActionStatusFields.ID.getFieldName());
@@ -925,6 +1031,8 @@ public class TargetResourceTest extends AbstractIntegrationTest {
final List updatedTargets = deploymentManagement.assignDistributionSet(one, targets)
.getAssignedTargets();
// 2nd update
+ // sleep 10ms to ensure that we can sort by reportedAt
+ Thread.sleep(10);
deploymentManagement.assignDistributionSet(two, updatedTargets);
// two updates, one cancelation
@@ -951,54 +1059,6 @@ public class TargetResourceTest extends AbstractIntegrationTest {
equalTo(generateStatusreferenceLink(knownTargetId, actions.get(1)))));
}
- @Test
- public void getActionStatusWithMultipleResultsWithPagingLimitRequestParameter() throws Exception {
- final int limitSize = 1;
- final String knownTargetId = "targetId";
- final List actions = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId);
- actions.get(0).setStatus(Status.RUNNING);
- controllerManagament.addUpdateActionStatus(
- new ActionStatus(actions.get(0), Status.RUNNING, System.currentTimeMillis(), "testmessage"),
- actions.get(0));
-
- final PageRequest pageRequest = new PageRequest(0, 1000, Direction.ASC, ActionStatusFields.ID.getFieldName());
-
- // limit to 1 - first page -> standard cancel message
- Long reportAt = deploymentManagement
- .findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
- .get(0).getCreatedAt();
- Long id = deploymentManagement
- .findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
- .get(0).getId();
- mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
- + RestConstants.TARGET_V1_ACTIONS + "/" + actions.get(0).getId() + "/status")
- .param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(limitSize)))
- .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
- .andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(3)))
- .andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(limitSize)))
- .andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(limitSize)))
- .andExpect(jsonPath("content.[0].id", equalTo(id.intValue())))
- .andExpect(jsonPath("content.[0].type", equalTo("running")))
- .andExpect(jsonPath("content.[0].messages", hasSize(1)))
- .andExpect(jsonPath("content.[0].reportedAt", equalTo(reportAt)));
-
- // limit to 1 - first page -> added custom message
- reportAt = deploymentManagement
- .findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
- .get(1).getCreatedAt();
- id = deploymentManagement
- .findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
- .get(1).getCreatedAt();
-
- mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
- + RestConstants.TARGET_V1_ACTIONS + "/" + actions.get(0).getId() + "/status")
- .param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(limitSize))
- .param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1)))
- .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
- .andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(3)))
- .andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(1)));
- }
-
@Test
public void assignDistributionSetToTarget() throws Exception {
diff --git a/hawkbit-rest-resource/src/test/resources/application-test.properties b/hawkbit-rest-resource/src/test/resources/application-test.properties
index bdd959ca2..92506caa4 100644
--- a/hawkbit-rest-resource/src/test/resources/application-test.properties
+++ b/hawkbit-rest-resource/src/test/resources/application-test.properties
@@ -24,7 +24,7 @@ hawkbit.server.database=H2
hawkbit.server.database.env=TEST
spring.main.show_banner=false
-hawkbit.server.controller.security.authentication.header=true
+hawkbit.server.ddi.security.authentication.header=true
hawkbit.server.artifact.repo.upload.maxFileSize=5MB
diff --git a/hawkbit-rest-resource/src/test/resources/log4j2.xml b/hawkbit-rest-resource/src/test/resources/log4j2.xml
index 26437af34..98ea99ac9 100644
--- a/hawkbit-rest-resource/src/test/resources/log4j2.xml
+++ b/hawkbit-rest-resource/src/test/resources/log4j2.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/hawkbit-security-core/pom.xml b/hawkbit-security-core/pom.xml
index 011acc95b..a3b262726 100644
--- a/hawkbit-security-core/pom.xml
+++ b/hawkbit-security-core/pom.xml
@@ -59,6 +59,11 @@
org.springframework.boot
spring-boot
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/DdiSecurityProperties.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/DdiSecurityProperties.java
new file mode 100644
index 000000000..ce1ff91d8
--- /dev/null
+++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/DdiSecurityProperties.java
@@ -0,0 +1,219 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.security;
+
+import java.util.List;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * The common properties for DDI security.
+ */
+@ConfigurationProperties("hawkbit.server.ddi.security")
+public class DdiSecurityProperties {
+
+ private final Rp rp = new Rp();
+ private final Authentication authentication = new Authentication();
+
+ public Authentication getAuthentication() {
+ return authentication;
+ }
+
+ public Rp getRp() {
+ return rp;
+ }
+
+ /**
+ * Reverse proxy configuration. Defines the security properties for
+ * authenticating controllers behind a reverse proxy which terminates the
+ * SSL session at the reverse proxy but adding request header which contains
+ * the CN of the certificate.
+ */
+ public static class Rp {
+
+ /**
+ * HTTP header field for common name of a DDI target client certificate.
+ */
+ private String cnHeader = "X-Ssl-Client-Cn";
+
+ /**
+ * HTTP header field for issuer hash of a DDI target client certificate.
+ */
+ private String sslIssuerHashHeader = "X-Ssl-Issuer-Hash-%d";
+
+ /**
+ * List of trusted (reverse proxy) IP addresses for performing DDI
+ * client certificate authentication.
+ */
+ private List trustedIPs;
+
+ /**
+ * @return the cnHeader
+ */
+ public String getCnHeader() {
+ return cnHeader;
+ }
+
+ /**
+ * @param cnHeader
+ * the cnHeader to set
+ */
+ public void setCnHeader(final String cnHeader) {
+ this.cnHeader = cnHeader;
+ }
+
+ /**
+ * @return the sslIssuerHashHeader
+ */
+ public String getSslIssuerHashHeader() {
+ return sslIssuerHashHeader;
+ }
+
+ /**
+ * @param sslIssuerHashHeader
+ * the sslIssuerHashHeader to set
+ */
+ public void setSslIssuerHashHeader(final String sslIssuerHashHeader) {
+ this.sslIssuerHashHeader = sslIssuerHashHeader;
+ }
+
+ /**
+ * @return the trustedIPs
+ */
+ public List getTrustedIPs() {
+ return trustedIPs;
+ }
+
+ /**
+ * @param trustedIPs
+ * the trustedIPs to set
+ */
+ public void setTrustedIPs(final List trustedIPs) {
+ this.trustedIPs = trustedIPs;
+ }
+
+ }
+
+ /**
+ * DDI Authentication options.
+ */
+ public static class Authentication {
+ private final Anonymous anonymous = new Anonymous();
+ private final Targettoken targettoken = new Targettoken();
+ private final Gatewaytoken gatewaytoken = new Gatewaytoken();
+
+ public Anonymous getAnonymous() {
+ return anonymous;
+ }
+
+ public Gatewaytoken getGatewaytoken() {
+ return gatewaytoken;
+ }
+
+ public Targettoken getTargettoken() {
+ return targettoken;
+ }
+
+ /**
+ * Target token authentication. Tokens are defined per target.
+ *
+ */
+ public static class Targettoken {
+ /**
+ * Set to true to enable target token authentication.
+ */
+ private boolean enabled = false;
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(final boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ }
+
+ /**
+ * Gateway token authentication. Tokens are defined per tenant. Use with
+ * care!
+ *
+ */
+ public static class Gatewaytoken {
+
+ /**
+ * Gateway token based authentication enabled.
+ */
+ private boolean enabled = false;
+
+ /**
+ * Default gateway token name.
+ */
+ private String name = "";
+
+ /**
+ * Default gateway token itself.
+ */
+ private String key = "";
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(final boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(final String key) {
+ this.key = key;
+ }
+
+ }
+
+ /**
+ * Anonymous authentication.
+ */
+ public static class Anonymous {
+
+ /**
+ * Set to true to enable anonymous DDI client authentication.
+ */
+ private boolean enabled = false;
+
+ /**
+ * @param enabled
+ * the enabled to set
+ */
+ public void setEnabled(final boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ /**
+ * @return the enabled
+ */
+ public boolean isEnabled() {
+ return enabled;
+ }
+ }
+
+ }
+
+}
diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/HawkbitSecurityProperties.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/HawkbitSecurityProperties.java
new file mode 100644
index 000000000..7b157da65
--- /dev/null
+++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/HawkbitSecurityProperties.java
@@ -0,0 +1,191 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.security;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * Security related hawkbit configuration.
+ *
+ */
+@Component
+@ConfigurationProperties("hawkbit.server.security")
+public class HawkbitSecurityProperties {
+
+ private final Clients clients = new Clients();
+ private final Dos dos = new Dos();
+ private final Xframe xframe = new Xframe();
+
+ public Dos getDos() {
+ return dos;
+ }
+
+ public Clients getClients() {
+ return clients;
+ }
+
+ public Xframe getXframe() {
+ return xframe;
+ }
+
+ /**
+ * Defines the XFrameOption policy.
+ *
+ */
+ public static class Xframe {
+
+ /**
+ * XFrame option. Allowed values: SAMEORIGIN, DENY, ALLOW-FROM
+ */
+ private String option = "DENY";
+
+ /**
+ * ALLOW-FROM defined URL, has to be filled in case ALLOW-FROM option is
+ * selected.
+ */
+ private String allowfrom = "";
+
+ public String getOption() {
+ return option;
+ }
+
+ public void setOption(final String option) {
+ this.option = option;
+ }
+
+ public String getAllowfrom() {
+ return allowfrom;
+ }
+
+ public void setAllowfrom(final String allowfrom) {
+ this.allowfrom = allowfrom;
+ }
+
+ }
+
+ /**
+ * Security configuration related to clients.
+ *
+ */
+ public static class Clients {
+
+ /**
+ * Blacklisted client (IP addresses) for for DDI and Management API.
+ */
+ private String blacklist = "";
+
+ /**
+ * Name of the http header from which the remote ip is extracted.
+ */
+ private String remoteIpHeader = "X-Forwarded-For";
+
+ public String getBlacklist() {
+ return blacklist;
+ }
+
+ public void setBlacklist(final String blacklist) {
+ this.blacklist = blacklist;
+ }
+
+ public String getRemoteIpHeader() {
+ return remoteIpHeader;
+ }
+
+ public void setRemoteIpHeader(final String remoteIpHeader) {
+ this.remoteIpHeader = remoteIpHeader;
+ }
+ }
+
+ /**
+ * Denial of service protection related properties.
+ *
+ */
+ public static class Dos {
+
+ /**
+ * Maximum number of status updates that the controller can report for
+ * an action (0 to disable).
+ */
+ private int maxStatusEntriesPerAction = 1000;
+
+ /**
+ * Maximum number of attributes that the controller can report;
+ */
+ private int maxAttributeEntriesPerTarget = 100;
+
+ private final Filter filter = new Filter();
+
+ public Filter getFilter() {
+ return filter;
+ }
+
+ public int getMaxStatusEntriesPerAction() {
+ return maxStatusEntriesPerAction;
+ }
+
+ public void setMaxStatusEntriesPerAction(final int maxStatusEntriesPerAction) {
+ this.maxStatusEntriesPerAction = maxStatusEntriesPerAction;
+ }
+
+ public int getMaxAttributeEntriesPerTarget() {
+ return maxAttributeEntriesPerTarget;
+ }
+
+ public void setMaxAttributeEntriesPerTarget(final int maxAttributeEntriesPerTarget) {
+ this.maxAttributeEntriesPerTarget = maxAttributeEntriesPerTarget;
+ }
+
+ public static class Filter {
+
+ /**
+ * White list of peer IP addresses for DOS filter (regular
+ * expression).
+ */
+ private String whitelist = "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|169\\.254\\.\\d{1,3}\\.\\d{1,3}|127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|172\\.1[6-9]{1}\\.\\d{1,3}\\.\\d{1,3}|172\\.2[0-9]{1}\\.\\d{1,3}\\.\\d{1,3}|172\\.3[0-1]{1}\\.\\d{1,3}\\.\\d{1,3}";
+
+ /**
+ * # Maximum number of allowed REST read/GET requests per second per
+ * client.
+ */
+ int maxRead = 200;
+
+ /**
+ * Maximum number of allowed REST write/(PUT/POST/etc.) requests per
+ * second per client.
+ */
+ int maxWrite = 50;
+
+ public String getWhitelist() {
+ return whitelist;
+ }
+
+ public void setWhitelist(final String whitelist) {
+ this.whitelist = whitelist;
+ }
+
+ public int getMaxRead() {
+ return maxRead;
+ }
+
+ public void setMaxRead(final int maxRead) {
+ this.maxRead = maxRead;
+ }
+
+ public int getMaxWrite() {
+ return maxWrite;
+ }
+
+ public void setMaxWrite(final int maxWrite) {
+ this.maxWrite = maxWrite;
+ }
+
+ }
+ }
+}
diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityProperties.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityProperties.java
deleted file mode 100644
index 8cc056f15..000000000
--- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SecurityProperties.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- */
-package org.eclipse.hawkbit.security;
-
-import java.util.List;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.stereotype.Component;
-
-/**
- * The common properties for security.
- *
- *
- *
- */
-@ConfigurationProperties
-public class SecurityProperties {
-
- /**
- * Inner class for reverse proxy configuration.
- */
- @Component
- @ConfigurationProperties("hawkbit.server.controller.security.rp")
- public static class RpProperties {
- private String cnHeader = "X-Ssl-Client-Cn";
- private String sslIssuerHashHeader = "X-Ssl-Issuer-Hash-%d";
- private List trustedIPs;
-
- /**
- * @return the cnHeader
- */
- public String getCnHeader() {
- return cnHeader;
- }
-
- /**
- * @param cnHeader
- * the cnHeader to set
- */
- public void setCnHeader(final String cnHeader) {
- this.cnHeader = cnHeader;
- }
-
- /**
- * @return the sslIssuerHashHeader
- */
- public String getSslIssuerHashHeader() {
- return sslIssuerHashHeader;
- }
-
- /**
- * @param sslIssuerHashHeader
- * the sslIssuerHashHeader to set
- */
- public void setSslIssuerHashHeader(final String sslIssuerHashHeader) {
- this.sslIssuerHashHeader = sslIssuerHashHeader;
- }
-
- /**
- * @return the trustedIPs
- */
- public List getTrustedIPs() {
- return trustedIPs;
- }
-
- /**
- * @param trustedIPs
- * the trustedIPs to set
- */
- public void setTrustedIPs(final List trustedIPs) {
- this.trustedIPs = trustedIPs;
- }
-
- }
-
- /**
- * Inner class for anonymous enable configuration.
- */
- @Component
- @ConfigurationProperties("hawkbit.server.controller.security.authentication.anonymous")
- public static class AnoymousAuthenticationProperties {
- private Boolean enabled = Boolean.FALSE;
-
- /**
- * @param enabled
- * the enabled to set
- */
- public void setEnabled(final Boolean enabled) {
- this.enabled = enabled;
- }
-
- /**
- * @return the enabled
- */
- public Boolean getEnabled() {
- return enabled;
- }
-
- }
-
- @Autowired
- private RpProperties rppProperties;
-
- @Autowired
- private AnoymousAuthenticationProperties authenticationsProperties;
-
- public String getRpCnHeader() {
- return rppProperties.getCnHeader();
- }
-
- public String getRpSslIssuerHashHeader() {
- return rppProperties.getSslIssuerHashHeader();
- }
-
- public List getRpTrustedIPs() {
- return rppProperties.getTrustedIPs();
- }
-
- public Boolean getAnonymousEnabled() {
- return authenticationsProperties.getEnabled();
- }
-
-}
diff --git a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/util/SPInfo.java b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/util/SPInfo.java
index 3a2a696df..feb94c0d7 100644
--- a/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/util/SPInfo.java
+++ b/hawkbit-security-core/src/main/java/org/eclipse/hawkbit/util/SPInfo.java
@@ -11,90 +11,24 @@ package org.eclipse.hawkbit.util;
import javax.servlet.MultipartConfigElement;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.EnvironmentAware;
-import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
/**
* Bean which contains all informations about the SP software, e.g. like
* version, built time etc. from the environment.
*
- *
- *
- *
*/
@Component
-public class SPInfo implements EnvironmentAware {
+public class SPInfo {
// package private for testing purposes
static final String UNKNOWN_VERSION = "unknown";
static final String UNKNOWN_CREDENTIAL = "unknown credential";
- private Environment environmentData;
-
@Autowired
private MultipartConfigElement configElement;
- /*
- * (non-Javadoc)
- *
- * @see org.springframework.context.EnvironmentAware#setEnvironment(org.
- * springframework.core.env. Environment)
- */
- @Override
- public void setEnvironment(final Environment environment) {
- this.environmentData = environment;
- }
-
- /**
- * @return the version in string format, e.g. 1.0.0 or {@code "UNKNOWN"} in
- * case the SP version info cannot be determined.
- */
- public String getVersion() {
- if (environmentData != null) {
- return environmentData.getProperty("info.build.version", UNKNOWN_VERSION);
- }
- return UNKNOWN_VERSION;
- }
-
- public String getSupportEmail() {
- if (environmentData != null) {
- return environmentData.getProperty("hawkbit.server.email.support");
- }
- return "";
- }
-
- public String getRequestAccountEmail() {
- if (environmentData != null) {
- return environmentData.getProperty("hawkbit.server.email.request.account");
- }
- return "";
- }
-
- public String getDemoTenant() {
- if (environmentData != null) {
- return environmentData.getProperty("hawkbit.server.demo.tenant");
- }
- return UNKNOWN_CREDENTIAL;
- }
-
- public String getDemoUser() {
- if (environmentData != null) {
- return environmentData.getProperty("hawkbit.server.demo.user");
- }
- return UNKNOWN_CREDENTIAL;
-
- }
-
- public String getDemoPassword() {
- if (environmentData != null) {
- return environmentData.getProperty("hawkbit.server.demo.password");
- }
- return UNKNOWN_CREDENTIAL;
-
- }
-
/**
* @return the max file size to upload artifact files in bytes which has
* been configured.
diff --git a/hawkbit-ui/pom.xml b/hawkbit-ui/pom.xml
index 0bd083e36..c9bd54b01 100644
--- a/hawkbit-ui/pom.xml
+++ b/hawkbit-ui/pom.xml
@@ -213,7 +213,6 @@
org.vaadin.addons
tokenfield
-
org.vaadin.alump.distributionbar
dbar-addon
@@ -222,7 +221,11 @@
org.vaadin.addons
contextmenu
-
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/UiProperties.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/UiProperties.java
new file mode 100644
index 000000000..b23935826
--- /dev/null
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/UiProperties.java
@@ -0,0 +1,162 @@
+/**
+ * Copyright (c) 2015 Bosch Software Innovations GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.eclipse.hawkbit.ui;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * Properties for Management UI customization.
+ *
+ */
+@Component
+@ConfigurationProperties("hawkbit.server.ui")
+public class UiProperties {
+
+ private final Links links = new Links();
+ private final Login login = new Login();
+ private final Demo demo = new Demo();
+
+ public Login getLogin() {
+ return login;
+ }
+
+ public Links getLinks() {
+ return links;
+ }
+
+ public Demo getDemo() {
+ return demo;
+ }
+
+ /**
+ * Demo account login information.
+ *
+ */
+ public static class Demo {
+
+ /**
+ * Demo tenant.
+ */
+ private String tenant = "DEFAULT";
+ /**
+ * Demo user name.
+ */
+ private String user = "admin";
+
+ /**
+ * Demo user password.
+ */
+ private String password = "admin";
+
+ public String getTenant() {
+ return tenant;
+ }
+
+ public void setTenant(final String tenant) {
+ this.tenant = tenant;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public void setUser(final String user) {
+ this.user = user;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(final String password) {
+ this.password = password;
+ }
+
+ }
+
+ /**
+ * Links to potentially other systems (e.g. support, user management etc.).
+ *
+ */
+ public static class Links {
+ /**
+ * Link to product support.
+ */
+ private String support = "";
+
+ /**
+ * Link to request a system account, access.
+ */
+ private String requestAccount = "";
+
+ /**
+ * Link to user management.
+ */
+ private String userManagement = "";
+
+ public String getSupport() {
+ return support;
+ }
+
+ public void setSupport(final String support) {
+ this.support = support;
+ }
+
+ public String getRequestAccount() {
+ return requestAccount;
+ }
+
+ public void setRequestAccount(final String requestAccount) {
+ this.requestAccount = requestAccount;
+ }
+
+ public String getUserManagement() {
+ return userManagement;
+ }
+
+ public void setUserManagement(final String userManagement) {
+ this.userManagement = userManagement;
+ }
+
+ }
+
+ /**
+ * Configuration of login view.
+ *
+ */
+ public static class Login {
+
+ private final Cookie cookie = new Cookie();
+
+ public Cookie getCookie() {
+ return cookie;
+ }
+
+ /**
+ * Cookie configuration for login credential cookie.
+ *
+ */
+ public static class Cookie {
+ /**
+ * Secure cookie enabled.
+ */
+ private boolean secure = true;
+
+ public boolean isSecure() {
+ return secure;
+ }
+
+ public void setSecure(final boolean secure) {
+ this.secure = secure;
+ }
+ }
+ }
+
+}
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/login/LoginView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/login/LoginView.java
index 9beeff56a..484333219 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/login/LoginView.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/login/LoginView.java
@@ -15,16 +15,14 @@ import javax.servlet.http.Cookie;
import org.eclipse.hawkbit.im.authentication.MultitenancyIndicator;
import org.eclipse.hawkbit.im.authentication.TenantUserPasswordAuthenticationToken;
+import org.eclipse.hawkbit.ui.UiProperties;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.documentation.DocumentationPageLink;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider;
-import org.eclipse.hawkbit.util.SPInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.EnvironmentAware;
-import org.springframework.core.env.Environment;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
@@ -61,7 +59,7 @@ import com.vaadin.ui.themes.ValoTheme;
*/
@SpringView(name = "")
@UIScope
-public class LoginView extends VerticalLayout implements View, EnvironmentAware {
+public class LoginView extends VerticalLayout implements View {
private static final String LOGIN_TEXTFIELD = "login-textfield";
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = LoggerFactory.getLogger(LoginView.class);
@@ -76,7 +74,7 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
private I18N i18n;
@Autowired
- private transient SPInfo spInfo;
+ private transient UiProperties uiProperties;
@Autowired
private transient MultitenancyIndicator multiTenancyIndicator;
@@ -86,9 +84,6 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
private PasswordField password;
private Button signin;
- private Boolean secureCookie = Boolean.TRUE;
- private String userManagementLoginUrl;
-
void loginAuthenticationFailedNotification() {
final Notification notification = new Notification(i18n.get("notification.login.failed.title"));
notification.setDescription(i18n.get("notification.login.failed.description"));
@@ -119,7 +114,8 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
final URI spURI = Page.getCurrent().getLocation();
final String lookForDemoFragment = spURI.toString();
if (lookForDemoFragment.contains("?demo")) {
- login(spInfo.getDemoTenant(), spInfo.getDemoUser(), spInfo.getDemoPassword(), false);
+ login(uiProperties.getDemo().getTenant(), uiProperties.getDemo().getUser(),
+ uiProperties.getDemo().getPassword(), false);
}
final Component loginForm = buildLoginForm();
@@ -243,18 +239,18 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
links.addComponent(demoLink);
demoLink.addStyleName(ValoTheme.LINK_SMALL);
- if (spInfo.getRequestAccountEmail() != null) {
+ if (!uiProperties.getLinks().getRequestAccount().isEmpty()) {
final Link requestAccountLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_REQUESTACCOUNT,
- i18n.get("link.requestaccount.name"), spInfo.getRequestAccountEmail(), FontAwesome.SHOPPING_CART,
- "", linkStyle, true);
+ i18n.get("link.requestaccount.name"), uiProperties.getLinks().getRequestAccount(),
+ FontAwesome.SHOPPING_CART, "", linkStyle, true);
links.addComponent(requestAccountLink);
requestAccountLink.addStyleName(ValoTheme.LINK_SMALL);
}
- if (userManagementLoginUrl != null) {
+ if (!uiProperties.getLinks().getUserManagement().isEmpty()) {
final Link userManagementLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_USERMANAGEMENT,
- i18n.get("link.usermanagement.name"), userManagementLoginUrl, FontAwesome.USERS, "_blank",
- linkStyle, true);
+ i18n.get("link.usermanagement.name"), uiProperties.getLinks().getUserManagement(),
+ FontAwesome.USERS, "_blank", linkStyle, true);
links.addComponent(userManagementLink);
userManagementLink.addStyleName(ValoTheme.LINK_SMALL);
}
@@ -315,7 +311,7 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
// 100 days
tenantCookie.setMaxAge(3600 * 24 * 100);
tenantCookie.setHttpOnly(true);
- tenantCookie.setSecure(secureCookie);
+ tenantCookie.setSecure(uiProperties.getLogin().getCookie().isSecure());
VaadinService.getCurrentResponse().addCookie(tenantCookie);
}
@@ -324,7 +320,7 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
// 100 days
usernameCookie.setMaxAge(3600 * 24 * 100);
usernameCookie.setHttpOnly(true);
- usernameCookie.setSecure(secureCookie);
+ usernameCookie.setSecure(uiProperties.getLogin().getCookie().isSecure());
VaadinService.getCurrentResponse().addCookie(usernameCookie);
}
@@ -368,16 +364,4 @@ public class LoginView extends VerticalLayout implements View, EnvironmentAware
loginAuthenticationFailedNotification();
}
}
-
- /*
- * (non-Javadoc)
- *
- * @see org.springframework.context.EnvironmentAware#setEnvironment(org.
- * springframework.core.env. Environment)
- */
- @Override
- public void setEnvironment(final Environment environment) {
- secureCookie = environment.getProperty("hawkbit.server.ui.login.cookie.secure", Boolean.class, Boolean.TRUE);
- userManagementLoginUrl = environment.getProperty("hawkbit.server.im.login.url", String.class);
- }
}
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/actionhistory/ActionHistoryTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/actionhistory/ActionHistoryTable.java
index df9d8a60d..f8d53b1bf 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/actionhistory/ActionHistoryTable.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/actionhistory/ActionHistoryTable.java
@@ -16,6 +16,7 @@ import java.util.StringJoiner;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
+import org.eclipse.hawkbit.repository.ActionStatusFields;
import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
import org.eclipse.hawkbit.repository.model.Action;
@@ -43,6 +44,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
@@ -417,10 +420,10 @@ public class ActionHistoryTable extends TreeTable implements Handler {
final org.eclipse.hawkbit.repository.model.Action action = deploymentManagement
.findActionWithDetails(actionId);
- final Pageable pageReq = new PageRequest(0, 1000);
- final Page actionStatusList = deploymentManagement
- .findActionStatusMessagesByActionInDescOrder(pageReq, action,
- managementUIState.isActionHistoryMaximized());
+ final Pageable pageReq = new PageRequest(0, 1000,
+ new Sort(Direction.DESC, ActionStatusFields.ID.getFieldName()));
+ final Page actionStatusList = deploymentManagement.findActionStatusByAction(pageReq, action,
+ managementUIState.isActionHistoryMaximized());
final List content = actionStatusList.getContent();
/*
* Since the recent action status and messages are already
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java
index 44ec9ea40..beff0e6b9 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/menu/DashboardMenu.java
@@ -18,17 +18,16 @@ import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
+import org.eclipse.hawkbit.HawkbitServerProperties;
import org.eclipse.hawkbit.im.authentication.PermissionService;
import org.eclipse.hawkbit.im.authentication.UserPrincipal;
+import org.eclipse.hawkbit.ui.UiProperties;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.documentation.DocumentationPageLink;
import org.eclipse.hawkbit.ui.menu.DashboardEvent.PostViewChangeEvent;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPUIComponetIdProvider;
-import org.eclipse.hawkbit.util.SPInfo;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.EnvironmentAware;
-import org.springframework.core.env.Environment;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
@@ -42,7 +41,6 @@ import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.spring.annotation.UIScope;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
-import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
@@ -50,7 +48,6 @@ import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Link;
import com.vaadin.ui.MenuBar;
-import com.vaadin.ui.MenuBar.Command;
import com.vaadin.ui.MenuBar.MenuItem;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
@@ -61,11 +58,17 @@ import com.vaadin.ui.themes.ValoTheme;
*/
@SpringComponent
@UIScope
-public final class DashboardMenu extends CustomComponent implements EnvironmentAware {
+public final class DashboardMenu extends CustomComponent {
@Autowired
private I18N i18n;
+ @Autowired
+ private transient UiProperties uiProperties;
+
+ @Autowired
+ private transient HawkbitServerProperties serverProperties;
+
private static final long serialVersionUID = 5394474618559481462L;
public static final String ID = "dashboard-menu";
@@ -74,16 +77,12 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
private static final String STYLE_VISIBLE = "valo-menu-visible";
// this should be resolved when we introduce event bus on UI to just inform
- // the buttons directly
- // via events
+ // the buttons directly via events
private final List menuButtons = new ArrayList<>();
@Autowired
private transient PermissionService permissionService;
- @Autowired
- private transient SPInfo spInfo;
-
@Autowired
private final List dashboardVaadinViews = new ArrayList<>();
@@ -91,12 +90,10 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
private boolean accessibleViewsEmpty;
- private String userManagementLoginUrl;
-
/**
* initializing the view and creating the layout, cannot be done in the
- * custructor because the constructor will be called by spring and the
- * dashabord must be initialized when the dashboard UI is creating.
+ * constructor because the constructor will be called by spring and the
+ * dashboard must be initialized when the dashboard UI is creating.
*/
public void init() {
initialViewName = "";
@@ -162,20 +159,20 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
links.addComponent(docuLink);
links.setComponentAlignment(docuLink, Alignment.BOTTOM_CENTER);
- if (userManagementLoginUrl != null) {
+ if (!uiProperties.getLinks().getUserManagement().isEmpty()) {
final Link userManagementLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_USERMANAGEMENT,
- i18n.get("link.usermanagement.name"), userManagementLoginUrl, FontAwesome.USERS, "_blank",
- linkStyle, true);
+ i18n.get("link.usermanagement.name"), uiProperties.getLinks().getUserManagement(),
+ FontAwesome.USERS, "_blank", linkStyle, true);
userManagementLink.setDescription(i18n.get("link.usermanagement.name"));
links.addComponent(userManagementLink);
userManagementLink.setSizeFull();
links.setComponentAlignment(userManagementLink, Alignment.BOTTOM_CENTER);
}
- if (spInfo.getSupportEmail() != null) {
+ if (!uiProperties.getLinks().getSupport().isEmpty()) {
final Link supportLink = SPUIComponentProvider.getLink(SPUIComponetIdProvider.LINK_SUPPORT,
- i18n.get("link.support.name"), spInfo.getSupportEmail(), FontAwesome.ENVELOPE_O, "", linkStyle,
- true);
+ i18n.get("link.support.name"), uiProperties.getLinks().getSupport(), FontAwesome.ENVELOPE_O, "",
+ linkStyle, true);
supportLink.setDescription(i18n.get("link.support.name"));
supportLink.setSizeFull();
links.addComponent(supportLink);
@@ -222,12 +219,7 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
settingsItem.setDescription(user.getUsername());
}
- settingsItem.addItem("Sign Out", new Command() {
- @Override
- public void menuSelected(final MenuItem selectedItem) {
- Page.getCurrent().setLocation("/UI/logout");
- }
- });
+ settingsItem.addItem("Sign Out", selectedItem -> Page.getCurrent().setLocation("/UI/logout"));
return settings;
}
@@ -254,14 +246,11 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
}
private Component buildToggleButton() {
- final Button valoMenuToggleButton = new Button("Menu", new ClickListener() {
- @Override
- public void buttonClick(final ClickEvent event) {
- if (getCompositionRoot().getStyleName().contains(STYLE_VISIBLE)) {
- getCompositionRoot().removeStyleName(STYLE_VISIBLE);
- } else {
- getCompositionRoot().addStyleName(STYLE_VISIBLE);
- }
+ final Button valoMenuToggleButton = new Button("Menu", (ClickListener) event -> {
+ if (getCompositionRoot().getStyleName().contains(STYLE_VISIBLE)) {
+ getCompositionRoot().removeStyleName(STYLE_VISIBLE);
+ } else {
+ getCompositionRoot().addStyleName(STYLE_VISIBLE);
}
});
valoMenuToggleButton.setIcon(FontAwesome.LIST);
@@ -307,7 +296,7 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
final Label label = new Label();
label.setSizeFull();
label.setStyleName("version-layout");
- label.setValue(spInfo.getVersion());
+ label.setValue(serverProperties.getBuild().getVersion());
return label;
}
@@ -341,11 +330,6 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
menuButtons.forEach(button -> button.postViewChange(event));
}
- @Override
- public void setEnvironment(final Environment environment) {
- userManagementLoginUrl = environment.getProperty("hawkbit.server.im.login.url", String.class);
- }
-
/**
* Returns the dashboard view type by a given view name.
*
@@ -411,12 +395,7 @@ public final class DashboardMenu extends CustomComponent implements EnvironmentA
setDescription(view.getDashboardCaptionLong());
/* Avoid double click */
setDisableOnClick(true);
- addClickListener(new ClickListener() {
- @Override
- public void buttonClick(final ClickEvent event) {
- event.getComponent().getUI().getNavigator().navigateTo(view.getViewName());
- }
- });
+ addClickListener(event -> event.getComponent().getUI().getNavigator().navigateTo(view.getViewName()));
}
diff --git a/pom.xml b/pom.xml
index 577e39515..3d70d980c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -559,7 +559,6 @@
org.json
json
${json.version}
- test
de.flapdoodle.embed