diff --git a/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/MyLoginUI.java b/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/MyLoginUI.java index bc6aaa147..225a0573d 100644 --- a/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/MyLoginUI.java +++ b/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/MyLoginUI.java @@ -8,7 +8,7 @@ */ package org.eclipse.hawkbit.app; -import org.eclipse.hawkbit.ui.login.HawkbitLoginUI; +import org.eclipse.hawkbit.ui.login.AbstractHawkbitLoginUI; import org.eclipse.hawkbit.ui.themes.HawkbitTheme; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; @@ -23,14 +23,14 @@ import com.vaadin.spring.navigator.SpringViewProvider; * * A {@link SpringUI} annotated class must be present in the classpath for the * login path. The easiest way to get an hawkBit login UI running is to extend - * the {@link HawkbitLoginUI} and to annotated it with {@link SpringUI} as in + * the {@link AbstractHawkbitLoginUI} and to annotated it with {@link SpringUI} as in * this example to the defined {@link HawkbitTheme#LOGIN_UI_PATH}. * */ @SpringUI(path = HawkbitTheme.LOGIN_UI_PATH) @Title("hawkBit Theme example") @Theme(value = "exampletheme") -public class MyLoginUI extends HawkbitLoginUI { +public class MyLoginUI extends AbstractHawkbitLoginUI { private static final long serialVersionUID = 1L; diff --git a/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/MyUI.java b/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/MyUI.java index c5fa5f979..94e275d51 100644 --- a/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/MyUI.java +++ b/examples/hawkbit-custom-theme-example/src/main/java/org/eclipse/hawkbit/app/MyUI.java @@ -8,7 +8,7 @@ package org.eclipse.hawkbit.app; * http://www.eclipse.org/legal/epl-v10.html */ -import org.eclipse.hawkbit.ui.HawkbitUI; +import org.eclipse.hawkbit.ui.AbstractHawkbitUI; import org.eclipse.hawkbit.ui.push.EventPushStrategy; import com.vaadin.annotations.Push; @@ -22,7 +22,7 @@ import com.vaadin.spring.annotation.SpringUI; * Example hawkBit UI implementation. * * A {@link SpringUI} annotated class must be present in the classpath. The - * easiest way to get an hawkBit UI running is to extend the {@link HawkbitUI} + * easiest way to get an hawkBit UI running is to extend the {@link AbstractHawkbitUI} * and to annotated it with {@link SpringUI} as in this example. * */ @@ -30,7 +30,7 @@ import com.vaadin.spring.annotation.SpringUI; @Push(value = PushMode.AUTOMATIC, transport = Transport.WEBSOCKET) @Title("hawkBit Theme example") @Theme(value = "exampletheme") -public class MyUI extends HawkbitUI { +public class MyUI extends AbstractHawkbitUI { private static final long serialVersionUID = 1L; diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java index 65b727bf8..9481430bd 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherServiceTest.java @@ -306,7 +306,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest { assertEquals(downloadAndUpdateRequest.getActionId(), action); assertEquals("The topic of the event shuold contain DOWNLOAD_AND_INSTALL", EventTopic.DOWNLOAD_AND_INSTALL, sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC)); - assertEquals("Security token of target", downloadAndUpdateRequest.getTargetSecurityToken(), TEST_TOKEN); + assertEquals("Security token of target", TEST_TOKEN, downloadAndUpdateRequest.getTargetSecurityToken()); return downloadAndUpdateRequest; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/PropertyMapper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/PropertyMapper.java index db4417960..e3560e81c 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/PropertyMapper.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/rsql/PropertyMapper.java @@ -36,9 +36,7 @@ public final class PropertyMapper { * property name */ public static void addNewMapping(final Class type, final String property, final String mapping) { - if (allowedColmns.get(type) == null) { - allowedColmns.put(type, new HashMap()); - } + allowedColmns.computeIfAbsent(type, k -> new HashMap<>()); allowedColmns.get(type).put(property, mapping); } diff --git a/hawkbit-runtime/hawkbit-update-server/src/main/java/org/eclipse/hawkbit/app/MyLoginUI.java b/hawkbit-runtime/hawkbit-update-server/src/main/java/org/eclipse/hawkbit/app/MyLoginUI.java index 28d262491..a99c6c1b1 100644 --- a/hawkbit-runtime/hawkbit-update-server/src/main/java/org/eclipse/hawkbit/app/MyLoginUI.java +++ b/hawkbit-runtime/hawkbit-update-server/src/main/java/org/eclipse/hawkbit/app/MyLoginUI.java @@ -8,33 +8,36 @@ */ package org.eclipse.hawkbit.app; -import org.eclipse.hawkbit.ui.login.HawkbitLoginUI; +import org.eclipse.hawkbit.im.authentication.MultitenancyIndicator; +import org.eclipse.hawkbit.ui.UiProperties; +import org.eclipse.hawkbit.ui.login.AbstractHawkbitLoginUI; import org.eclipse.hawkbit.ui.themes.HawkbitTheme; +import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; +import org.vaadin.spring.security.VaadinSecurity; import com.vaadin.spring.annotation.SpringUI; -import com.vaadin.spring.navigator.SpringViewProvider; /** * Example hawkBit login UI implementation. * * A {@link SpringUI} annotated class must be present in the classpath for the * login path. The easiest way to get an hawkBit login UI running is to extend - * the {@link HawkbitLoginUI} and to annotated it with {@link SpringUI} as in - * this example to the defined {@link HawkbitTheme#LOGIN_UI_PATH}. + * the {@link AbstractHawkbitLoginUI} and to annotated it with {@link SpringUI} + * as in this example to the defined {@link HawkbitTheme#LOGIN_UI_PATH}. */ @SpringUI(path = HawkbitTheme.LOGIN_UI_PATH) // Exception squid:MaximumInheritanceDepth - Most of the inheritance comes from // Vaadin. @SuppressWarnings({ "squid:MaximumInheritanceDepth" }) -public class MyLoginUI extends HawkbitLoginUI { - - @Autowired - protected MyLoginUI(final SpringViewProvider viewProvider, final ApplicationContext context) { - super(viewProvider, context); - } - +public class MyLoginUI extends AbstractHawkbitLoginUI { private static final long serialVersionUID = 1L; + @Autowired + MyLoginUI(final ApplicationContext context, final VaadinSecurity vaadinSecurity, final VaadinMessageSource i18n, + final UiProperties uiProperties, final MultitenancyIndicator multiTenancyIndicator) { + super(context, vaadinSecurity, i18n, uiProperties, multiTenancyIndicator); + } + } diff --git a/hawkbit-runtime/hawkbit-update-server/src/main/java/org/eclipse/hawkbit/app/MyUI.java b/hawkbit-runtime/hawkbit-update-server/src/main/java/org/eclipse/hawkbit/app/MyUI.java index 5a6ce146c..1fe825c4d 100644 --- a/hawkbit-runtime/hawkbit-update-server/src/main/java/org/eclipse/hawkbit/app/MyUI.java +++ b/hawkbit-runtime/hawkbit-update-server/src/main/java/org/eclipse/hawkbit/app/MyUI.java @@ -8,20 +8,28 @@ */ package org.eclipse.hawkbit.app; -import org.eclipse.hawkbit.ui.HawkbitUI; +import org.eclipse.hawkbit.ui.AbstractHawkbitUI; +import org.eclipse.hawkbit.ui.ErrorView; +import org.eclipse.hawkbit.ui.components.NotificationUnreadButton; +import org.eclipse.hawkbit.ui.menu.DashboardMenu; import org.eclipse.hawkbit.ui.push.EventPushStrategy; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.vaadin.spring.events.EventBus.UIEventBus; import com.vaadin.annotations.Push; import com.vaadin.shared.communication.PushMode; import com.vaadin.shared.ui.ui.Transport; import com.vaadin.spring.annotation.SpringUI; +import com.vaadin.spring.navigator.SpringViewProvider; /** * Example hawkBit UI implementation. * * A {@link SpringUI} annotated class must be present in the classpath. The - * easiest way to get an hawkBit UI running is to extend the {@link HawkbitUI} - * and to annotated it with {@link SpringUI} as in this example. + * easiest way to get an hawkBit UI running is to extend the + * {@link AbstractHawkbitUI} and to annotated it with {@link SpringUI} as in + * this example. * */ @SpringUI @@ -29,19 +37,14 @@ import com.vaadin.spring.annotation.SpringUI; // Exception squid:MaximumInheritanceDepth - Most of the inheritance comes from // Vaadin. @SuppressWarnings({ "squid:MaximumInheritanceDepth" }) -public class MyUI extends HawkbitUI { +public class MyUI extends AbstractHawkbitUI { private static final long serialVersionUID = 1L; - /** - * Constructor - * - * @param pushStrategy - * the push strategy - * @param eventBus - * the event bus - */ - public MyUI(final EventPushStrategy pushStrategy) { - super(pushStrategy); + @Autowired + MyUI(final EventPushStrategy pushStrategy, final UIEventBus eventBus, final SpringViewProvider viewProvider, + final ApplicationContext context, final DashboardMenu dashboardMenu, final ErrorView errorview, + final NotificationUnreadButton notificationUnreadButton) { + super(pushStrategy, eventBus, viewProvider, context, dashboardMenu, errorview, notificationUnreadButton); } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitUI.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/AbstractHawkbitUI.java similarity index 86% rename from hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitUI.java rename to hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/AbstractHawkbitUI.java index 931873038..ef02f3d28 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/HawkbitUI.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/AbstractHawkbitUI.java @@ -19,16 +19,19 @@ import org.eclipse.hawkbit.ui.menu.DashboardEvent.PostViewChangeEvent; import org.eclipse.hawkbit.ui.menu.DashboardMenu; import org.eclipse.hawkbit.ui.menu.DashboardMenuItem; import org.eclipse.hawkbit.ui.push.EventPushStrategy; +import org.eclipse.hawkbit.ui.themes.HawkbitTheme; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.SPUIDefinitions; import org.eclipse.hawkbit.ui.utils.SpringContextHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.vaadin.spring.events.EventBus; +import org.vaadin.spring.events.EventBus.UIEventBus; +import com.vaadin.annotations.Theme; import com.vaadin.annotations.Title; +import com.vaadin.annotations.Widgetset; import com.vaadin.navigator.Navigator; import com.vaadin.navigator.View; import com.vaadin.navigator.ViewChangeListener; @@ -53,43 +56,41 @@ import com.vaadin.ui.themes.ValoTheme; * */ @Title("hawkBit Update Server") -public class HawkbitUI extends DefaultHawkbitUI implements DetachListener { +@Widgetset(value = HawkbitTheme.WIDGET_SET_NAME) +@Theme(HawkbitTheme.THEME_NAME) +public abstract class AbstractHawkbitUI extends UI implements DetachListener { private static final long serialVersionUID = 1L; - private static final Logger LOG = LoggerFactory.getLogger(HawkbitUI.class); + private static final Logger LOG = LoggerFactory.getLogger(AbstractHawkbitUI.class); private static final String EMPTY_VIEW = ""; private transient EventPushStrategy pushStrategy; - @Autowired - protected transient EventBus.UIEventBus eventBus; + protected final transient EventBus.UIEventBus eventBus; - @Autowired - private SpringViewProvider viewProvider; + private final SpringViewProvider viewProvider; - @Autowired - private transient ApplicationContext context; + private final transient ApplicationContext context; - @Autowired - private DashboardMenu dashboardMenu; + private final DashboardMenu dashboardMenu; - @Autowired - private ErrorView errorview; + private final ErrorView errorview; - @Autowired - private NotificationUnreadButton notificationUnreadButton; + private final NotificationUnreadButton notificationUnreadButton; private Label viewTitle; - /** - * Constructor taking the push strategy. - * - * @param pushStrategy - * the strategy to push events from the backend to the UI - */ - public HawkbitUI(final EventPushStrategy pushStrategy) { + protected AbstractHawkbitUI(final EventPushStrategy pushStrategy, final UIEventBus eventBus, + final SpringViewProvider viewProvider, final ApplicationContext context, final DashboardMenu dashboardMenu, + final ErrorView errorview, final NotificationUnreadButton notificationUnreadButton) { this.pushStrategy = pushStrategy; + this.eventBus = eventBus; + this.viewProvider = viewProvider; + this.context = context; + this.dashboardMenu = dashboardMenu; + this.errorview = errorview; + this.notificationUnreadButton = notificationUnreadButton; } @Override diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/DefaultHawkbitUI.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/DefaultHawkbitUI.java deleted file mode 100644 index 623734218..000000000 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/DefaultHawkbitUI.java +++ /dev/null @@ -1,25 +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.ui; - -import org.eclipse.hawkbit.ui.themes.HawkbitTheme; - -import com.vaadin.annotations.Theme; -import com.vaadin.annotations.Widgetset; -import com.vaadin.ui.UI; - -/** - * Abstract class for the ui to set widgetset and theme. - */ -@SuppressWarnings("serial") -@Widgetset(value = HawkbitTheme.WIDGET_SET_NAME) -@Theme(HawkbitTheme.THEME_NAME) -public abstract class DefaultHawkbitUI extends UI { - -} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/ErrorView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/ErrorView.java index 7e1eb886f..65b0b6da1 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/ErrorView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/ErrorView.java @@ -34,7 +34,7 @@ import com.vaadin.ui.VerticalLayout; */ @SpringComponent @UIScope -class ErrorView extends VerticalLayout implements View { +public class ErrorView extends VerticalLayout implements View { private static final long serialVersionUID = 1L; @@ -62,8 +62,8 @@ class ErrorView extends VerticalLayout implements View { } if (dashboardMenu.isAccessDenied(event.getViewName())) { final Notification nt = new Notification("Access denied", - i18n.getMessage("message.accessdenied.view", new Object[] { event.getViewName() }), Type.ERROR_MESSAGE, - false); + i18n.getMessage("message.accessdenied.view", new Object[] { event.getViewName() }), + Type.ERROR_MESSAGE, false); nt.setStyleName(SPUILabelDefinitions.SP_NOTIFICATION_ERROR_MESSAGE_STYLE); nt.setPosition(Position.BOTTOM_RIGHT); nt.show(UI.getCurrent().getPage()); diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java index b0f97a456..316127733 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/UploadArtifactView.java @@ -16,7 +16,7 @@ import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; -import org.eclipse.hawkbit.ui.HawkbitUI; +import org.eclipse.hawkbit.ui.AbstractHawkbitUI; import org.eclipse.hawkbit.ui.SpPermissionChecker; import org.eclipse.hawkbit.ui.artifacts.details.ArtifactDetailsLayout; import org.eclipse.hawkbit.ui.artifacts.event.ArtifactDetailsEvent; @@ -54,7 +54,7 @@ import com.vaadin.ui.VerticalLayout; * Display artifacts upload view. */ @UIScope -@SpringView(name = UploadArtifactView.VIEW_NAME, ui = HawkbitUI.class) +@SpringView(name = UploadArtifactView.VIEW_NAME, ui = AbstractHawkbitUI.class) public class UploadArtifactView extends VerticalLayout implements View, BrowserWindowResizeListener { private static final long serialVersionUID = 1L; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/DistributionsView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/DistributionsView.java index 5c8d63354..417a2d154 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/DistributionsView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/distributions/DistributionsView.java @@ -21,7 +21,7 @@ import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TargetManagement; -import org.eclipse.hawkbit.ui.HawkbitUI; +import org.eclipse.hawkbit.ui.AbstractHawkbitUI; import org.eclipse.hawkbit.ui.SpPermissionChecker; import org.eclipse.hawkbit.ui.artifacts.event.SoftwareModuleEvent; import org.eclipse.hawkbit.ui.artifacts.state.ArtifactUploadState; @@ -64,7 +64,7 @@ import com.vaadin.ui.GridLayout; * Manage distributions and distributions type view. */ @UIScope -@SpringView(name = DistributionsView.VIEW_NAME, ui = HawkbitUI.class) +@SpringView(name = DistributionsView.VIEW_NAME, ui = AbstractHawkbitUI.class) public class DistributionsView extends AbstractNotificationView implements BrowserWindowResizeListener { private static final long serialVersionUID = 1L; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/FilterManagementView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/FilterManagementView.java index 8f77c3882..73c6ab9ae 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/FilterManagementView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/filtermanagement/FilterManagementView.java @@ -14,7 +14,7 @@ import javax.annotation.PreDestroy; import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetManagement; -import org.eclipse.hawkbit.ui.HawkbitUI; +import org.eclipse.hawkbit.ui.AbstractHawkbitUI; import org.eclipse.hawkbit.ui.SpPermissionChecker; import org.eclipse.hawkbit.ui.UiProperties; import org.eclipse.hawkbit.ui.distributions.state.ManageDistUIState; @@ -43,7 +43,7 @@ import com.vaadin.ui.VerticalLayout; * View for custom target filter management. */ @UIScope -@SpringView(name = FilterManagementView.VIEW_NAME, ui = HawkbitUI.class) +@SpringView(name = FilterManagementView.VIEW_NAME, ui = AbstractHawkbitUI.class) public class FilterManagementView extends VerticalLayout implements View { private static final long serialVersionUID = 8751545414237389386L; 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/AbstractHawkbitLoginUI.java similarity index 68% rename from hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/login/LoginView.java rename to hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/login/AbstractHawkbitLoginUI.java index 28ce89671..082ee25c2 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/AbstractHawkbitLoginUI.java @@ -8,67 +8,87 @@ */ package org.eclipse.hawkbit.ui.login; -import java.net.URI; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.AbstractMap.SimpleImmutableEntry; +import java.util.Arrays; +import java.util.Collections; import java.util.Map; +import java.util.stream.Collectors; -import javax.annotation.PostConstruct; import javax.servlet.http.Cookie; import org.eclipse.hawkbit.im.authentication.MultitenancyIndicator; import org.eclipse.hawkbit.im.authentication.TenantUserPasswordAuthenticationToken; +import org.eclipse.hawkbit.ui.AbstractHawkbitUI; import org.eclipse.hawkbit.ui.UiProperties; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; +import org.eclipse.hawkbit.ui.themes.HawkbitTheme; +import org.eclipse.hawkbit.ui.utils.SpringContextHelper; import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.core.io.Resource; import org.springframework.security.authentication.CredentialsExpiredException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.AuthenticationException; -import org.springframework.util.AntPathMatcher; +import org.springframework.util.StringUtils; import org.vaadin.spring.security.VaadinSecurity; +import com.vaadin.annotations.Theme; +import com.vaadin.annotations.Title; +import com.vaadin.annotations.Widgetset; import com.vaadin.event.ShortcutAction.KeyCode; -import com.vaadin.navigator.View; -import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; import com.vaadin.server.FontAwesome; import com.vaadin.server.Page; import com.vaadin.server.Responsive; +import com.vaadin.server.VaadinRequest; import com.vaadin.server.VaadinService; import com.vaadin.server.WebBrowser; import com.vaadin.shared.Position; -import com.vaadin.spring.annotation.SpringView; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; import com.vaadin.ui.Component; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.CustomLayout; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Link; import com.vaadin.ui.Notification; import com.vaadin.ui.PasswordField; import com.vaadin.ui.TextField; +import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.themes.ValoTheme; /** - * Login view for login credentials. + * Login UI window that is independent of the {@link AbstractHawkbitUI} itself. + * */ -@SpringView(name = "") -public class LoginView extends VerticalLayout implements View { - private static final String TENANT_PATTERN_PLACEHOLDER = "tenant"; - private static final String USER_PATTERN_PLACEHOLDER = "user"; - private static final String LOGIN_TENANT_USER_URL_PATTERN = "**/#/{" + TENANT_PATTERN_PLACEHOLDER + "}/{" - + USER_PATTERN_PLACEHOLDER + "}"; - private static final String LOGIN_USER_URL_PATTERN = "**/#/{" + USER_PATTERN_PLACEHOLDER + "}"; +@Title("hawkBit UI - Login") +@Widgetset(value = HawkbitTheme.WIDGET_SET_NAME) +@Theme(HawkbitTheme.THEME_NAME) +public abstract class AbstractHawkbitLoginUI extends UI { + private static final Logger LOG = LoggerFactory.getLogger(AbstractHawkbitLoginUI.class); - private static final String LOGIN_TEXTFIELD = "login-textfield"; private static final long serialVersionUID = 1L; - private static final Logger LOGGER = LoggerFactory.getLogger(LoginView.class); + + private static final String USER_PARAMETER = "user"; + private static final String TENANT_PARAMETER = "tenant"; + private static final String DEMO_PARAMETER = "demo"; + private static final int HUNDRED_DAYS_IN_SECONDS = 3600 * 24 * 100; + private static final String LOGIN_TEXTFIELD = "login-textfield"; private static final String SP_LOGIN_USER = "sp-login-user"; private static final String SP_LOGIN_TENANT = "sp-login-tenant"; + private final transient ApplicationContext context; + private final transient VaadinSecurity vaadinSecurity; private final VaadinMessageSource i18n; @@ -77,7 +97,6 @@ public class LoginView extends VerticalLayout implements View { private final transient MultitenancyIndicator multiTenancyIndicator; - private final transient AntPathMatcher matcher = new AntPathMatcher(); private boolean useCookie = true; private TextField username; @@ -85,104 +104,139 @@ public class LoginView extends VerticalLayout implements View { private PasswordField password; private Button signin; + private Map params; + @Autowired - LoginView(final VaadinSecurity vaadinSecurity, final VaadinMessageSource i18n, final UiProperties uiProperties, + protected AbstractHawkbitLoginUI(final ApplicationContext context, final VaadinSecurity vaadinSecurity, + final VaadinMessageSource i18n, final UiProperties uiProperties, final MultitenancyIndicator multiTenancyIndicator) { + this.context = context; this.vaadinSecurity = vaadinSecurity; this.i18n = i18n; this.uiProperties = uiProperties; this.multiTenancyIndicator = multiTenancyIndicator; } - void loginAuthenticationFailedNotification() { + @Override + protected void init(final VaadinRequest request) { + SpringContextHelper.setContext(context); + + try { + params = getQueryParams(Page.getCurrent().getLocation().toURL()); + } catch (final MalformedURLException e) { + // Ignore params silently + } + + if (params.containsKey(DEMO_PARAMETER)) { + login(uiProperties.getDemo().getTenant(), uiProperties.getDemo().getUser(), + uiProperties.getDemo().getPassword(), false); + } + + setContent(buildContent()); + + filloutUsernameTenantFields(); + readCookie(); + } + + private VerticalLayout buildContent() { + final VerticalLayout rootLayout = new VerticalLayout(); + rootLayout.setSizeFull(); + rootLayout.setStyleName("main-content"); + + rootLayout.addComponent(buildHeader()); + + addLoginForm(rootLayout); + + addFooter(rootLayout); + + return rootLayout; + } + + private void addLoginForm(final VerticalLayout rootLayout) { + final Component loginForm = buildLoginForm(); + rootLayout.addComponent(loginForm); + rootLayout.setComponentAlignment(loginForm, Alignment.MIDDLE_CENTER); + } + + private void addFooter(final VerticalLayout rootLayout) { + final Resource resource = context + .getResource("classpath:/VAADIN/themes/" + UI.getCurrent().getTheme() + "/layouts/footer.html"); + + try (InputStream resourceStream = resource.getInputStream()) { + final CustomLayout customLayout = new CustomLayout(resourceStream); + customLayout.setSizeUndefined(); + rootLayout.addComponent(customLayout); + rootLayout.setComponentAlignment(customLayout, Alignment.BOTTOM_LEFT); + } catch (final IOException ex) { + LOG.error("Footer file cannot be loaded", ex); + } + } + + private static Component buildHeader() { + final CssLayout cssLayout = new CssLayout(); + cssLayout.setStyleName("view-header"); + return cssLayout; + } + + private void loginAuthenticationFailedNotification() { final Notification notification = new Notification(i18n.getMessage("notification.login.failed.title")); notification.setDescription(i18n.getMessage("notification.login.failed.description")); notification.setHtmlContentAllowed(true); notification.setStyleName("error closable"); notification.setPosition(Position.BOTTOM_CENTER); - notification.setDelayMsec(1000); + notification.setDelayMsec(1_000); notification.show(Page.getCurrent()); } - void loginCredentialsExpiredNotification() { + private void loginCredentialsExpiredNotification() { final Notification notification = new Notification( i18n.getMessage("notification.login.failed.credentialsexpired.title")); notification.setDescription(i18n.getMessage("notification.login.failed.credentialsexpired.description")); - notification.setDelayMsec(10000); + notification.setDelayMsec(10_000); notification.setHtmlContentAllowed(true); notification.setStyleName("error closeable"); notification.setPosition(Position.BOTTOM_CENTER); notification.show(Page.getCurrent()); } - /** - * Renders the {@link View}. - */ - @PostConstruct - public void render() { - final URI spURI = Page.getCurrent().getLocation(); - final String uriPath = spURI.toString(); - if (uriPath.contains("?demo")) { - login(uiProperties.getDemo().getTenant(), uiProperties.getDemo().getUser(), - uiProperties.getDemo().getPassword(), false); - } - final Component loginForm = buildLoginForm(); - addComponent(loginForm); - setComponentAlignment(loginForm, Alignment.MIDDLE_CENTER); - - readCredentialsFromUriPath(uriPath); - } - - private void readCredentialsFromUriPath(final String uriPath) { - String urlTenant = null; - String urlUser = null; - if (matcher.match(LOGIN_USER_URL_PATTERN, uriPath)) { - urlUser = matcher.extractUriTemplateVariables(LOGIN_USER_URL_PATTERN, uriPath) - .get(USER_PATTERN_PLACEHOLDER); - } else if (matcher.match(LOGIN_TENANT_USER_URL_PATTERN, uriPath)) { - final Map extractUriTemplateVariables = matcher - .extractUriTemplateVariables(LOGIN_TENANT_USER_URL_PATTERN, uriPath); - urlTenant = extractUriTemplateVariables.get(TENANT_PATTERN_PLACEHOLDER); - urlUser = extractUriTemplateVariables.get(USER_PATTERN_PLACEHOLDER); - } - - if (urlUser != null) { + private void filloutUsernameTenantFields() { + if (tenant != null && params.containsKey(TENANT_PARAMETER)) { + tenant.setValue(params.get(TENANT_PARAMETER)); + tenant.setVisible(false); + useCookie = false; + } + + if (params.containsKey(USER_PARAMETER)) { + username.setValue(params.get(USER_PARAMETER)); useCookie = false; - filloutUsernameTenantFields(urlTenant, urlUser); } } - private void filloutUsernameTenantFields(final String tenantValue, final String userValue) { - if (tenant != null && tenantValue != null) { - tenant.setValue(tenantValue); - } - if (userValue != null) { - username.setValue(userValue); - } - } - - private Component buildLoginForm() { + protected Component buildLoginForm() { final VerticalLayout loginPanel = new VerticalLayout(); loginPanel.setSizeUndefined(); loginPanel.setSpacing(true); - loginPanel.addStyleName("dashboard-view"); loginPanel.addStyleName("login-panel"); Responsive.makeResponsive(loginPanel); loginPanel.addComponent(buildFields()); loginPanel.addComponent(buildLinks()); + checkBrowserSupport(loginPanel); + + return loginPanel; + } + + protected void checkBrowserSupport(final VerticalLayout loginPanel) { // Check if IE browser is not supported ( < IE11 ) if (isUnsupportedBrowser()) { // Disable sign-in button and display a message signin.setEnabled(Boolean.FALSE); loginPanel.addComponent(buildUnsupportedMessage()); } - - return loginPanel; } - private Component buildFields() { + protected Component buildFields() { final HorizontalLayout fields = new HorizontalLayout(); fields.setSpacing(true); fields.addStyleName("fields"); @@ -259,7 +313,7 @@ public class LoginView extends VerticalLayout implements View { } } - private Component buildLinks() { + protected Component buildLinks() { final HorizontalLayout links = new HorizontalLayout(); links.setSpacing(true); @@ -306,23 +360,12 @@ public class LoginView extends VerticalLayout implements View { return label; } - private boolean isUnsupportedBrowser() { + private static boolean isUnsupportedBrowser() { final WebBrowser webBrowser = Page.getCurrent().getWebBrowser(); - if (webBrowser.isIE() && webBrowser.getBrowserMajorVersion() < 11) { - return true; - } - return false; + return webBrowser.isIE() && webBrowser.getBrowserMajorVersion() < 11; } - /* - * (non-Javadoc) - * - * @see - * com.vaadin.navigator.View#enter(com.vaadin.navigator.ViewChangeListener. - * ViewChangeEvent) - */ - @Override - public void enter(final ViewChangeEvent event) { + private void readCookie() { if (!useCookie) { return; } @@ -354,7 +397,7 @@ public class LoginView extends VerticalLayout implements View { final Cookie tenantCookie = new Cookie(SP_LOGIN_TENANT, tenant.getValue().toUpperCase()); tenantCookie.setPath("/"); // 100 days - tenantCookie.setMaxAge(3600 * 24 * 100); + tenantCookie.setMaxAge(HUNDRED_DAYS_IN_SECONDS); tenantCookie.setHttpOnly(true); tenantCookie.setSecure(uiProperties.getLogin().getCookie().isSecure()); VaadinService.getCurrentResponse().addCookie(tenantCookie); @@ -363,13 +406,13 @@ public class LoginView extends VerticalLayout implements View { final Cookie usernameCookie = new Cookie(SP_LOGIN_USER, username.getValue()); usernameCookie.setPath("/"); // 100 days - usernameCookie.setMaxAge(3600 * 24 * 100); + usernameCookie.setMaxAge(HUNDRED_DAYS_IN_SECONDS); usernameCookie.setHttpOnly(true); usernameCookie.setSecure(uiProperties.getLogin().getCookie().isSecure()); VaadinService.getCurrentResponse().addCookie(usernameCookie); } - private Cookie getCookieByName(final String name) { + private static Cookie getCookieByName(final String name) { // Fetch all cookies from the request final Cookie[] cookies = VaadinService.getCurrentRequest().getCookies(); @@ -398,15 +441,50 @@ public class LoginView extends VerticalLayout implements View { } } catch (final CredentialsExpiredException e) { - LOGGER.debug("Credential expired", e); + LOG.debug("Credential expired", e); loginCredentialsExpiredNotification(); } catch (final AuthenticationException e) { - LOGGER.debug("Authentication failed", e); + LOG.debug("Authentication failed", e); /* if not successful */ loginAuthenticationFailedNotification(); } catch (final Exception e) { - LOGGER.debug("Login failed", e); + LOG.debug("Login failed", e); loginAuthenticationFailedNotification(); } } + + protected Map getParams() { + return params; + } + + protected TextField getUsername() { + return username; + } + + protected TextField getTenant() { + return tenant; + } + + protected PasswordField getPassword() { + return password; + } + + protected VaadinMessageSource getI18n() { + return i18n; + } + + private static Map getQueryParams(final URL url) { + if (!StringUtils.hasLength(url.getQuery())) { + return Collections.emptyMap(); + } + return Arrays.stream(url.getQuery().split("&")).map(AbstractHawkbitLoginUI::splitQueryParameter) + .collect(Collectors.toMap(SimpleImmutableEntry::getKey, SimpleImmutableEntry::getValue)); + } + + private static SimpleImmutableEntry splitQueryParameter(final String it) { + final int idx = it.indexOf("="); + final String key = idx > 0 ? it.substring(0, idx) : it; + final String value = idx > 0 && it.length() > idx + 1 ? it.substring(idx + 1) : null; + return new SimpleImmutableEntry<>(key.toLowerCase(), value); + } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/login/HawkbitLoginUI.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/login/HawkbitLoginUI.java deleted file mode 100644 index 346c6f4e0..000000000 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/login/HawkbitLoginUI.java +++ /dev/null @@ -1,94 +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.ui.login; - -import java.io.IOException; -import java.io.InputStream; - -import org.eclipse.hawkbit.ui.DefaultHawkbitUI; -import org.eclipse.hawkbit.ui.HawkbitUI; -import org.eclipse.hawkbit.ui.utils.SpringContextHelper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.core.io.Resource; - -import com.vaadin.annotations.Title; -import com.vaadin.navigator.Navigator; -import com.vaadin.server.VaadinRequest; -import com.vaadin.spring.navigator.SpringViewProvider; -import com.vaadin.ui.Component; -import com.vaadin.ui.CssLayout; -import com.vaadin.ui.CustomLayout; -import com.vaadin.ui.HorizontalLayout; -import com.vaadin.ui.UI; -import com.vaadin.ui.VerticalLayout; - -/** - * Login UI window that is independent of the {@link HawkbitUI} itself. - * - */ -@Title("hawkBit UI - Login") -public class HawkbitLoginUI extends DefaultHawkbitUI { - private static final Logger LOG = LoggerFactory.getLogger(HawkbitLoginUI.class); - - private static final long serialVersionUID = 1L; - - private final SpringViewProvider viewProvider; - - private final transient ApplicationContext context; - - @Autowired - protected HawkbitLoginUI(final SpringViewProvider viewProvider, final ApplicationContext context) { - this.viewProvider = viewProvider; - this.context = context; - } - - @Override - protected void init(final VaadinRequest request) { - SpringContextHelper.setContext(context); - - final VerticalLayout rootLayout = new VerticalLayout(); - final Component header = buildHeader(); - - rootLayout.addComponent(header); - rootLayout.setSizeFull(); - - final HorizontalLayout content = new HorizontalLayout(); - rootLayout.addComponent(content); - content.setStyleName("view-content"); - content.setSizeFull(); - rootLayout.setStyleName("main-content"); - - rootLayout.setExpandRatio(header, 1.0F); - rootLayout.setExpandRatio(content, 2.0F); - final Resource resource = context - .getResource("classpath:/VAADIN/themes/" + UI.getCurrent().getTheme() + "/layouts/footer.html"); - - try (InputStream resourceStream = resource.getInputStream()) { - final CustomLayout customLayout = new CustomLayout(resourceStream); - customLayout.setSizeUndefined(); - rootLayout.addComponent(customLayout); - } catch (final IOException ex) { - LOG.error("Footer file cannot be loaded", ex); - } - setContent(rootLayout); - - final Navigator navigator = new Navigator(this, content); - navigator.addProvider(viewProvider); - setNavigator(navigator); - } - - private Component buildHeader() { - final CssLayout cssLayout = new CssLayout(); - cssLayout.setStyleName("view-header"); - return cssLayout; - } -} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/DeploymentView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/DeploymentView.java index 82de22d3b..e9c23502c 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/DeploymentView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/DeploymentView.java @@ -22,7 +22,7 @@ import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetTagManagement; -import org.eclipse.hawkbit.ui.HawkbitUI; +import org.eclipse.hawkbit.ui.AbstractHawkbitUI; import org.eclipse.hawkbit.ui.SpPermissionChecker; import org.eclipse.hawkbit.ui.UiProperties; import org.eclipse.hawkbit.ui.common.table.BaseEntityEventType; @@ -82,7 +82,7 @@ import com.vaadin.ui.UI; * Target status and deployment management view */ @UIScope -@SpringView(name = DeploymentView.VIEW_NAME, ui = HawkbitUI.class) +@SpringView(name = DeploymentView.VIEW_NAME, ui = AbstractHawkbitUI.class) public class DeploymentView extends AbstractNotificationView implements BrowserWindowResizeListener { private static final long serialVersionUID = 1L; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/RolloutView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/RolloutView.java index 1c79e7eb5..9b9b4e57a 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/RolloutView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/RolloutView.java @@ -20,7 +20,7 @@ import org.eclipse.hawkbit.repository.RolloutManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.model.Rollout; -import org.eclipse.hawkbit.ui.HawkbitUI; +import org.eclipse.hawkbit.ui.AbstractHawkbitUI; import org.eclipse.hawkbit.ui.SpPermissionChecker; import org.eclipse.hawkbit.ui.UiProperties; import org.eclipse.hawkbit.ui.rollout.event.RolloutEvent; @@ -46,7 +46,7 @@ import com.vaadin.ui.VerticalLayout; * Rollout management view. */ @UIScope -@SpringView(name = RolloutView.VIEW_NAME, ui = HawkbitUI.class) +@SpringView(name = RolloutView.VIEW_NAME, ui = AbstractHawkbitUI.class) public class RolloutView extends VerticalLayout implements View { private static final long serialVersionUID = -6199789714170913988L; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/TenantConfigurationDashboardView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/TenantConfigurationDashboardView.java index d5f1300bc..6d60a245b 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/TenantConfigurationDashboardView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/TenantConfigurationDashboardView.java @@ -19,7 +19,7 @@ import org.eclipse.hawkbit.repository.DistributionSetTypeManagement; import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.security.SecurityTokenGenerator; -import org.eclipse.hawkbit.ui.HawkbitUI; +import org.eclipse.hawkbit.ui.AbstractHawkbitUI; import org.eclipse.hawkbit.ui.SpPermissionChecker; import org.eclipse.hawkbit.ui.UiProperties; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; @@ -48,7 +48,7 @@ import com.vaadin.ui.VerticalLayout; * Main UI for the system configuration view. */ @UIScope -@SpringView(name = TenantConfigurationDashboardView.VIEW_NAME, ui = HawkbitUI.class) +@SpringView(name = TenantConfigurationDashboardView.VIEW_NAME, ui = AbstractHawkbitUI.class) public class TenantConfigurationDashboardView extends CustomComponent implements View, ConfigurationItemChangeListener { public static final String VIEW_NAME = "spSystemConfig"; diff --git a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/login.scss b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/login.scss index b21f871eb..dbaf3bbab 100644 --- a/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/login.scss +++ b/hawkbit-ui/src/main/resources/VAADIN/themes/hawkbit/customstyles/login.scss @@ -62,20 +62,6 @@ } } - .labels { - display: block; - - .h4 { - margin: 0; - vertical-align: baseline; - } - - .h3 { - margin: 0; - float: right; - } - } - .fields .v-icon { opacity: .3; }