Merge remote-tracking branch 'origin/master' into fix_migration_to_new_spring_boot_version_merge

Signed-off-by: Ammar Bikic <ammar.bikic@bosch.io>
This commit is contained in:
Ammar Bikic
2020-10-23 13:30:59 +02:00
33 changed files with 206 additions and 107 deletions

View File

@@ -15,10 +15,16 @@ jobs:
docker: docker:
- image: circleci/openjdk:8u181-jdk-stretch - image: circleci/openjdk:8u181-jdk-stretch
auth:
username: $DOCKERHUB_USER
password: $DOCKERHUB_ACCESSTOKEN
environment: environment:
_JAVA_OPTIONS: "-Xms512m -Xmx1024m" _JAVA_OPTIONS: "-Xms512m -Xmx1024m"
- image: rabbitmq:3-management - image: rabbitmq:3-management
auth:
username: $DOCKERHUB_USER
password: $DOCKERHUB_ACCESSTOKEN
environment: environment:
RABBITMQ_DEFAULT_VHOST: "/" RABBITMQ_DEFAULT_VHOST: "/"

View File

@@ -20,6 +20,7 @@ import org.eclipse.hawkbit.ui.push.HawkbitEventPermissionChecker;
import org.eclipse.hawkbit.ui.push.HawkbitEventProvider; import org.eclipse.hawkbit.ui.push.HawkbitEventProvider;
import org.eclipse.hawkbit.ui.push.UIEventPermissionChecker; import org.eclipse.hawkbit.ui.push.UIEventPermissionChecker;
import org.eclipse.hawkbit.ui.push.UIEventProvider; import org.eclipse.hawkbit.ui.push.UIEventProvider;
import org.eclipse.hawkbit.ui.utils.SpringContextHolder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
@@ -81,6 +82,16 @@ public class MgmtUiAutoConfiguration {
return new HawkbitEventPermissionChecker(permChecker); return new HawkbitEventPermissionChecker(permChecker);
} }
/**
* Bean for creating a singleton instance of the {@link SpringContextHolder}
*
* @return the singleton instance of the {@link SpringContextHolder}
*/
@Bean
SpringContextHolder springContextHolder() {
return SpringContextHolder.getInstance();
}
/** /**
* The UI scoped event push strategy. Session scope is necessary, that every * The UI scoped event push strategy. Session scope is necessary, that every
* UI has an own strategy. * UI has an own strategy.

View File

@@ -35,7 +35,7 @@ public final class EventPublisherHolder {
} }
/** /**
* @return the cache manager holder singleton instance * @return the event publisher holder singleton instance
*/ */
public static EventPublisherHolder getInstance() { public static EventPublisherHolder getInstance() {
return SINGLETON; return SINGLETON;

View File

@@ -23,6 +23,7 @@ import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository; import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
/** /**
@@ -102,11 +103,12 @@ public class NoCountPagingRepository {
} }
@Override @Override
protected Page<T> readPage(final TypedQuery<T> query, final Pageable pageable, final Specification<T> spec) { protected <S extends T> Page<S> readPage(final TypedQuery<S> query, final Class<S> domainClass,
final Pageable pageable, @Nullable final Specification<S> spec) {
query.setFirstResult((int) pageable.getOffset()); query.setFirstResult((int) pageable.getOffset());
query.setMaxResults(pageable.getPageSize()); query.setMaxResults(pageable.getPageSize());
final List<T> content = query.getResultList(); final List<S> content = query.getResultList();
return new PageImpl<>(content, pageable, content.size()); return new PageImpl<>(content, pageable, content.size());
} }

View File

@@ -78,6 +78,7 @@ import org.slf4j.LoggerFactory;
@Index(name = "sp_idx_target_01", columnList = "tenant,name,assigned_distribution_set"), @Index(name = "sp_idx_target_01", columnList = "tenant,name,assigned_distribution_set"),
@Index(name = "sp_idx_target_03", columnList = "tenant,controller_id,assigned_distribution_set"), @Index(name = "sp_idx_target_03", columnList = "tenant,controller_id,assigned_distribution_set"),
@Index(name = "sp_idx_target_04", columnList = "tenant,created_at"), @Index(name = "sp_idx_target_04", columnList = "tenant,created_at"),
@Index(name = "sp_idx_target_05", columnList = "tenant,last_modified_at"),
@Index(name = "sp_idx_target_prim", columnList = "tenant,id") }, uniqueConstraints = @UniqueConstraint(columnNames = { @Index(name = "sp_idx_target_prim", columnList = "tenant,id") }, uniqueConstraints = @UniqueConstraint(columnNames = {
"controller_id", "tenant" }, name = "uk_tenant_controller_id")) "controller_id", "tenant" }, name = "uk_tenant_controller_id"))
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for

View File

@@ -0,0 +1 @@
CREATE INDEX sp_idx_target_05 ON sp_target (tenant, last_modified_at);

View File

@@ -0,0 +1 @@
CREATE INDEX sp_idx_target_05 ON sp_target (tenant, last_modified_at);

View File

@@ -0,0 +1 @@
CREATE INDEX sp_idx_target_05 ON sp_target (tenant, last_modified_at);

View File

@@ -0,0 +1,3 @@
CREATE INDEX sp_idx_target_05
ON sp_target
USING BTREE (tenant, last_modified_at);

View File

@@ -0,0 +1 @@
CREATE INDEX sp_idx_target_05 ON sp_target (tenant, last_modified_at);

View File

@@ -18,11 +18,12 @@ import org.eclipse.hawkbit.ui.push.UIEventProvider;
import org.eclipse.hawkbit.ui.themes.HawkbitTheme; import org.eclipse.hawkbit.ui.themes.HawkbitTheme;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil; import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.support.AbstractApplicationContext;
import org.vaadin.spring.events.EventBus.UIEventBus; import org.vaadin.spring.events.EventBus.UIEventBus;
import com.vaadin.annotations.Theme; import com.vaadin.annotations.Theme;
@@ -100,6 +101,19 @@ public abstract class AbstractHawkbitUI extends UI implements DetachListener {
if (pushStrategy != null) { if (pushStrategy != null) {
pushStrategy.clean(); pushStrategy.clean();
clearContextListener();
}
}
private void clearContextListener() {
if (pushStrategy instanceof ApplicationListener && context instanceof AbstractApplicationContext) {
final ApplicationListener<?> listener = (ApplicationListener<?>) pushStrategy;
((AbstractApplicationContext) context).getApplicationListeners().remove(listener);
// we do not need to explicitly remove the listener from
// ApplicationEventMulticaster because it is done by
// UIBeanStore#destroy delegating to
// ApplicationListenerDetector#postProcessBeforeDestruction
} }
} }
@@ -110,7 +124,6 @@ public abstract class AbstractHawkbitUI extends UI implements DetachListener {
pushStrategy.init(getUI()); pushStrategy.init(getUI());
} }
addDetachListener(this); addDetachListener(this);
SpringContextHelper.setContext(context);
Responsive.makeResponsive(this); Responsive.makeResponsive(this);
addStyleName(ValoTheme.UI_WITH_MENU); addStyleName(ValoTheme.UI_WITH_MENU);

View File

@@ -8,11 +8,13 @@
*/ */
package org.eclipse.hawkbit.ui.artifacts.smtable; package org.eclipse.hawkbit.ui.artifacts.smtable;
import java.util.function.BooleanSupplier;
import org.eclipse.hawkbit.ui.common.detailslayout.MetaDataAddUpdateWindowLayout; import org.eclipse.hawkbit.ui.common.detailslayout.MetaDataAddUpdateWindowLayout;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import com.vaadin.ui.CheckBox; import com.vaadin.ui.CheckBox;
import com.vaadin.ui.ComponentContainer; import com.vaadin.ui.VerticalLayout;
/** /**
* Class for sm metadata add/update window layout. * Class for sm metadata add/update window layout.
@@ -24,23 +26,28 @@ public class SmMetaDataAddUpdateWindowLayout extends MetaDataAddUpdateWindowLayo
* Constructor for AbstractTagWindowLayout * Constructor for AbstractTagWindowLayout
* *
* @param i18n * @param i18n
* I18N * VaadinMessageSource
* @param hasMetadataChangePermission
* checks the permission allowing to change metadata entities
*/ */
public SmMetaDataAddUpdateWindowLayout(final VaadinMessageSource i18n) { public SmMetaDataAddUpdateWindowLayout(final VaadinMessageSource i18n,
super(i18n); final BooleanSupplier hasMetadataChangePermission) {
super(i18n, hasMetadataChangePermission);
this.isVisibleForTarget = metaDataComponentBuilder.createVisibleForTargetsField(binder); this.isVisibleForTarget = metaDataComponentBuilder.createVisibleForTargetsField(binder);
} }
/**
* @return form layout checkbox container for software module
*/
@Override @Override
public ComponentContainer getRootComponent() { protected VerticalLayout getMetadataAddUpdateLayout() {
final ComponentContainer formLayout = super.getRootComponent(); final VerticalLayout addUpdateLayout = super.getMetadataAddUpdateLayout();
addUpdateLayout.addComponent(isVisibleForTarget);
formLayout.addComponent(isVisibleForTarget); return addUpdateLayout;
}
return formLayout; @Override
protected void disableMetadataInputComponents() {
super.disableMetadataInputComponents();
isVisibleForTarget.setEnabled(false);
} }
} }

View File

@@ -67,9 +67,10 @@ public class SmMetaDataWindowLayout extends AbstractMetaDataWindowLayout<Long> {
this.entityFactory = entityFactory; this.entityFactory = entityFactory;
this.smMetaDataWindowGrid = new MetaDataWindowGrid<>(i18n, eventBus, permChecker, uiNotification, this.smMetaDataWindowGrid = new MetaDataWindowGrid<>(i18n, eventBus, permChecker, uiNotification,
new SmMetaDataDataProvider(smManagement), this::deleteMetaData); new SmMetaDataDataProvider(smManagement), this::hasMetadataChangePermission, this::deleteMetaData);
this.smMetaDataAddUpdateWindowLayout = new SmMetaDataAddUpdateWindowLayout(i18n); this.smMetaDataAddUpdateWindowLayout = new SmMetaDataAddUpdateWindowLayout(i18n,
this::hasMetadataChangePermission);
this.addSmMetaDataWindowController = new AddMetaDataWindowController(i18n, uiNotification, this.addSmMetaDataWindowController = new AddMetaDataWindowController(i18n, uiNotification,
smMetaDataAddUpdateWindowLayout, this::createMetaData, this::isDuplicate); smMetaDataAddUpdateWindowLayout, this::createMetaData, this::isDuplicate);
this.updateSmMetaDataWindowController = new UpdateMetaDataWindowController(i18n, uiNotification, this.updateSmMetaDataWindowController = new UpdateMetaDataWindowController(i18n, uiNotification,

View File

@@ -33,7 +33,7 @@ import org.eclipse.hawkbit.ui.common.data.proxies.ProxySoftwareModule;
import org.eclipse.hawkbit.ui.common.event.EntityModifiedEventPayload; import org.eclipse.hawkbit.ui.common.event.EntityModifiedEventPayload;
import org.eclipse.hawkbit.ui.common.event.EntityModifiedEventPayload.EntityModifiedEventType; import org.eclipse.hawkbit.ui.common.event.EntityModifiedEventPayload.EntityModifiedEventType;
import org.eclipse.hawkbit.ui.common.event.EventTopics; import org.eclipse.hawkbit.ui.common.event.EventTopics;
import org.eclipse.hawkbit.ui.utils.SpringContextHelper; import org.eclipse.hawkbit.ui.utils.SpringContextHolder;
import org.eclipse.hawkbit.ui.utils.UINotification; import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -78,9 +78,9 @@ public abstract class AbstractFileTransferHandler implements Serializable {
final Lock uploadLock) { final Lock uploadLock) {
this.artifactManagement = artifactManagement; this.artifactManagement = artifactManagement;
this.i18n = i18n; this.i18n = i18n;
this.eventBus = SpringContextHelper.getBean(EventBus.UIEventBus.class); this.eventBus = SpringContextHolder.getInstance().getBean(EventBus.UIEventBus.class);
this.artifactUploadState = SpringContextHelper.getBean(ArtifactUploadState.class); this.artifactUploadState = SpringContextHolder.getInstance().getBean(ArtifactUploadState.class);
this.uiNotification = SpringContextHelper.getBean(UINotification.class); this.uiNotification = SpringContextHolder.getInstance().getBean(UINotification.class);
this.uploadLock = uploadLock; this.uploadLock = uploadLock;
} }
@@ -103,8 +103,9 @@ public abstract class AbstractFileTransferHandler implements Serializable {
protected void startTransferToRepositoryThread(final InputStream inputStream, final FileUploadId fileUploadId, protected void startTransferToRepositoryThread(final InputStream inputStream, final FileUploadId fileUploadId,
final String mimeType) { final String mimeType) {
SpringContextHelper.getBean("uiExecutor", Executor.class).execute(new TransferArtifactToRepositoryRunnable( SpringContextHolder.getInstance().getBean("uiExecutor", Executor.class)
inputStream, fileUploadId, mimeType, UI.getCurrent(), uploadLock)); .execute(new TransferArtifactToRepositoryRunnable(inputStream, fileUploadId, mimeType, UI.getCurrent(),
uploadLock));
} }
private void interruptUploadAndSetReason(final String failureReason) { private void interruptUploadAndSetReason(final String failureReason) {

View File

@@ -15,7 +15,7 @@ import org.apache.commons.lang3.StringUtils;
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails; import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
import org.eclipse.hawkbit.im.authentication.UserPrincipal; import org.eclipse.hawkbit.im.authentication.UserPrincipal;
import org.eclipse.hawkbit.repository.model.BaseEntity; import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.ui.utils.SpringContextHelper; import org.eclipse.hawkbit.ui.utils.SpringContextHolder;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.User;
@@ -179,10 +179,10 @@ public final class UserDetailsFormatter {
public static UserDetails getCurrentUser() { public static UserDetails getCurrentUser() {
final SecurityContext context = (SecurityContext) VaadinService.getCurrentRequest().getWrappedSession() final SecurityContext context = (SecurityContext) VaadinService.getCurrentRequest().getWrappedSession()
.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY); .getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
Authentication authentication = context.getAuthentication(); final Authentication authentication = context.getAuthentication();
if (authentication instanceof OAuth2AuthenticationToken) { if (authentication instanceof OAuth2AuthenticationToken) {
OidcUser oidcUser = (OidcUser) authentication.getPrincipal(); final OidcUser oidcUser = (OidcUser) authentication.getPrincipal();
Object details = authentication.getDetails(); final Object details = authentication.getDetails();
String tenant = "DEFAULT"; String tenant = "DEFAULT";
if (details instanceof TenantAwareAuthenticationDetails) { if (details instanceof TenantAwareAuthenticationDetails) {
tenant = ((TenantAwareAuthenticationDetails) details).getTenant(); tenant = ((TenantAwareAuthenticationDetails) details).getTenant();
@@ -207,7 +207,8 @@ public final class UserDetailsFormatter {
// Exception squid:S1166 - exception has to be hidden // Exception squid:S1166 - exception has to be hidden
@SuppressWarnings({ "squid:S1166" }) @SuppressWarnings({ "squid:S1166" })
private static UserDetails loadUserByUsername(final String username) { private static UserDetails loadUserByUsername(final String username) {
final UserDetailsService userDetailsService = SpringContextHelper.getBean(UserDetailsService.class); final UserDetailsService userDetailsService = SpringContextHolder.getInstance()
.getBean(UserDetailsService.class);
try { try {
return userDetailsService.loadUserByUsername(username); return userDetailsService.loadUserByUsername(username);
} catch (final UsernameNotFoundException e) { } catch (final UsernameNotFoundException e) {

View File

@@ -38,6 +38,7 @@ public abstract class AbstractMetaDataWindowLayout<F> extends HorizontalLayout {
protected final VaadinMessageSource i18n; protected final VaadinMessageSource i18n;
protected final transient UIEventBus eventBus; protected final transient UIEventBus eventBus;
protected final UINotification uiNotification; protected final UINotification uiNotification;
protected final SpPermissionChecker permChecker;
private final MetadataWindowGridHeader metadataWindowGridHeader; private final MetadataWindowGridHeader metadataWindowGridHeader;
@@ -62,9 +63,23 @@ public abstract class AbstractMetaDataWindowLayout<F> extends HorizontalLayout {
this.i18n = i18n; this.i18n = i18n;
this.eventBus = eventBus; this.eventBus = eventBus;
this.uiNotification = uiNotification; this.uiNotification = uiNotification;
this.permChecker = permChecker;
this.metadataWindowGridHeader = new MetadataWindowGridHeader(i18n, permChecker, eventBus, this.metadataWindowGridHeader = new MetadataWindowGridHeader(i18n, permChecker, eventBus,
this::showAddMetaDataLayout); this::hasMetadataChangePermission, this::showAddMetaDataLayout);
}
// can be overriden in child classes for entity-specific permission
protected boolean hasMetadataChangePermission() {
return permChecker.hasUpdateRepositoryPermission();
}
private void showAddMetaDataLayout() {
getMetaDataWindowGrid().deselectAll();
getAddMetaDataWindowController().populateWithData(null);
saveCallback.accept(getAddMetaDataWindowController().getSaveDialogCloseListener());
resetSaveButton();
} }
protected MetaData createMetaData(final ProxyMetaData entity) { protected MetaData createMetaData(final ProxyMetaData entity) {
@@ -129,14 +144,6 @@ public abstract class AbstractMetaDataWindowLayout<F> extends HorizontalLayout {
protected abstract void doDeleteMetaDataByKey(final String metaDataKey); protected abstract void doDeleteMetaDataByKey(final String metaDataKey);
private void showAddMetaDataLayout() {
getMetaDataWindowGrid().deselectAll();
getAddMetaDataWindowController().populateWithData(null);
saveCallback.accept(getAddMetaDataWindowController().getSaveDialogCloseListener());
resetSaveButton();
}
/** /**
* @return add meta data window controller * @return add meta data window controller
*/ */

View File

@@ -72,11 +72,6 @@ public class DistributionSetDetailsHeader extends AbstractDetailsHeader<ProxyDis
return masterEntity.getNameVersion(); return masterEntity.getNameVersion();
} }
@Override
protected boolean hasEditPermission() {
return permChecker.hasUpdateRepositoryPermission();
}
@Override @Override
protected String getEditIconId() { protected String getEditIconId() {
return UIComponentIdProvider.DS_EDIT_BUTTON; return UIComponentIdProvider.DS_EDIT_BUTTON;

View File

@@ -8,6 +8,8 @@
*/ */
package org.eclipse.hawkbit.ui.common.detailslayout; package org.eclipse.hawkbit.ui.common.detailslayout;
import java.util.function.BooleanSupplier;
import org.eclipse.hawkbit.ui.common.AbstractEntityWindowLayout; import org.eclipse.hawkbit.ui.common.AbstractEntityWindowLayout;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyMetaData; import org.eclipse.hawkbit.ui.common.data.proxies.ProxyMetaData;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
@@ -21,6 +23,7 @@ import com.vaadin.ui.VerticalLayout;
* Class for metadata add/update window layout. * Class for metadata add/update window layout.
*/ */
public class MetaDataAddUpdateWindowLayout extends AbstractEntityWindowLayout<ProxyMetaData> { public class MetaDataAddUpdateWindowLayout extends AbstractEntityWindowLayout<ProxyMetaData> {
private final BooleanSupplier hasMetadataChangePermission;
protected final MetaDataAddUpdateWindowLayoutComponentBuilder metaDataComponentBuilder; protected final MetaDataAddUpdateWindowLayoutComponentBuilder metaDataComponentBuilder;
private final TextField metadataKey; private final TextField metadataKey;
@@ -30,11 +33,15 @@ public class MetaDataAddUpdateWindowLayout extends AbstractEntityWindowLayout<Pr
* Constructor for AbstractTagWindowLayout * Constructor for AbstractTagWindowLayout
* *
* @param i18n * @param i18n
* I18N * VaadinMessageSource
* @param hasMetadataChangePermission
* checks the permission allowing to change metadata entities
*/ */
public MetaDataAddUpdateWindowLayout(final VaadinMessageSource i18n) { public MetaDataAddUpdateWindowLayout(final VaadinMessageSource i18n,
final BooleanSupplier hasMetadataChangePermission) {
super(); super();
this.hasMetadataChangePermission = hasMetadataChangePermission;
this.metaDataComponentBuilder = new MetaDataAddUpdateWindowLayoutComponentBuilder(i18n); this.metaDataComponentBuilder = new MetaDataAddUpdateWindowLayoutComponentBuilder(i18n);
this.metadataKey = metaDataComponentBuilder.createKeyField(binder); this.metadataKey = metaDataComponentBuilder.createKeyField(binder);
@@ -43,6 +50,16 @@ public class MetaDataAddUpdateWindowLayout extends AbstractEntityWindowLayout<Pr
@Override @Override
public ComponentContainer getRootComponent() { public ComponentContainer getRootComponent() {
final VerticalLayout addUpdateLayout = getMetadataAddUpdateLayout();
if (!hasMetadataChangePermission.getAsBoolean()) {
disableMetadataInputComponents();
}
return addUpdateLayout;
}
protected VerticalLayout getMetadataAddUpdateLayout() {
final VerticalLayout addUpdateLayout = new VerticalLayout(); final VerticalLayout addUpdateLayout = new VerticalLayout();
addUpdateLayout.setSpacing(true); addUpdateLayout.setSpacing(true);
addUpdateLayout.setMargin(false); addUpdateLayout.setMargin(false);
@@ -57,12 +74,19 @@ public class MetaDataAddUpdateWindowLayout extends AbstractEntityWindowLayout<Pr
return addUpdateLayout; return addUpdateLayout;
} }
protected void disableMetadataInputComponents() {
metadataKey.setEnabled(false);
metadataValue.setEnabled(false);
}
/** /**
* Enable meta data key * Enable meta data key
*/ */
public void enableMetadataKey() { public void enableMetadataKey() {
if (hasMetadataChangePermission.getAsBoolean()) {
metadataKey.setEnabled(true); metadataKey.setEnabled(true);
} }
}
/** /**
* Disable meta data key * Disable meta data key

View File

@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.ui.common.detailslayout; package org.eclipse.hawkbit.ui.common.detailslayout;
import java.util.Collection; import java.util.Collection;
import java.util.function.BooleanSupplier;
import java.util.function.Predicate; import java.util.function.Predicate;
import org.eclipse.hawkbit.ui.SpPermissionChecker; import org.eclipse.hawkbit.ui.SpPermissionChecker;
@@ -38,6 +39,7 @@ public class MetaDataWindowGrid<F> extends AbstractGrid<ProxyMetaData, F> implem
public static final String META_DATA_VALUE_ID = "metaDataValue"; public static final String META_DATA_VALUE_ID = "metaDataValue";
public static final String META_DATA_DELETE_BUTTON_ID = "metaDataDeleteButton"; public static final String META_DATA_DELETE_BUTTON_ID = "metaDataDeleteButton";
private final transient BooleanSupplier hasMetadataChangePermission;
private final transient DeleteSupport<ProxyMetaData> metaDataDeleteSupport; private final transient DeleteSupport<ProxyMetaData> metaDataDeleteSupport;
/** /**
@@ -52,17 +54,20 @@ public class MetaDataWindowGrid<F> extends AbstractGrid<ProxyMetaData, F> implem
* @param notification * @param notification
* UINotification * UINotification
* @param dataProvider * @param dataProvider
* AbstractMetaDataDataProvider for filter support * provides entity-specific metadata entities
* @param hasMetadataChangePermission
* checks the permission allowing to change metadata entities
* @param itemsDeletionCallback * @param itemsDeletionCallback
* Grid item deletion Call back for event listener * callback method to delete metadata entities
* *
*/ */
public MetaDataWindowGrid(final VaadinMessageSource i18n, final UIEventBus eventBus, public MetaDataWindowGrid(final VaadinMessageSource i18n, final UIEventBus eventBus,
final SpPermissionChecker permissionChecker, final UINotification notification, final SpPermissionChecker permissionChecker, final UINotification notification,
final AbstractMetaDataDataProvider<?, F> dataProvider, final AbstractMetaDataDataProvider<?, F> dataProvider, final BooleanSupplier hasMetadataChangePermission,
final Predicate<Collection<ProxyMetaData>> itemsDeletionCallback) { final Predicate<Collection<ProxyMetaData>> itemsDeletionCallback) {
super(i18n, eventBus, permissionChecker); super(i18n, eventBus, permissionChecker);
this.hasMetadataChangePermission = hasMetadataChangePermission;
this.metaDataDeleteSupport = new DeleteSupport<>(this, i18n, notification, "caption.metadata", this.metaDataDeleteSupport = new DeleteSupport<>(this, i18n, notification, "caption.metadata",
"caption.metadata.plur", ProxyMetaData::getKey, itemsDeletionCallback, "caption.metadata.plur", ProxyMetaData::getKey, itemsDeletionCallback,
UIComponentIdProvider.METADATA_DELETE_CONFIRMATION_DIALOG); UIComponentIdProvider.METADATA_DELETE_CONFIRMATION_DIALOG);
@@ -79,7 +84,7 @@ public class MetaDataWindowGrid<F> extends AbstractGrid<ProxyMetaData, F> implem
@Override @Override
public String getGridId() { public String getGridId() {
return UIComponentIdProvider.METDATA_WINDOW_TABLE_ID; return UIComponentIdProvider.METADATA_WINDOW_TABLE_ID;
} }
@Override @Override
@@ -91,7 +96,7 @@ public class MetaDataWindowGrid<F> extends AbstractGrid<ProxyMetaData, F> implem
.setCaption(i18n.getMessage("header.value")).setHidden(true).setHidable(true); .setCaption(i18n.getMessage("header.value")).setHidden(true).setHidable(true);
GridComponentBuilder.addDeleteColumn(this, i18n, META_DATA_DELETE_BUTTON_ID, metaDataDeleteSupport, GridComponentBuilder.addDeleteColumn(this, i18n, META_DATA_DELETE_BUTTON_ID, metaDataDeleteSupport,
UIComponentIdProvider.META_DATA_DELET_ICON, e -> permissionChecker.hasDeleteRepositoryPermission()); UIComponentIdProvider.META_DATA_DELET_ICON, e -> hasMetadataChangePermission.getAsBoolean());
} }
@Override @Override

View File

@@ -83,7 +83,7 @@ public class MetadataDetailsGrid<F> extends AbstractGrid<ProxyMetaData, F> imple
@Override @Override
public String getGridId() { public String getGridId() {
return typePrefix + "." + UIComponentIdProvider.METDATA_DETAILS_TABLE_ID; return typePrefix + "." + UIComponentIdProvider.METADATA_DETAILS_TABLE_ID;
} }
@Override @Override

View File

@@ -8,6 +8,8 @@
*/ */
package org.eclipse.hawkbit.ui.common.detailslayout; package org.eclipse.hawkbit.ui.common.detailslayout;
import java.util.function.BooleanSupplier;
import org.eclipse.hawkbit.ui.SpPermissionChecker; import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.common.grid.header.AbstractGridHeader; import org.eclipse.hawkbit.ui.common.grid.header.AbstractGridHeader;
import org.eclipse.hawkbit.ui.common.grid.header.support.AddHeaderSupport; import org.eclipse.hawkbit.ui.common.grid.header.support.AddHeaderSupport;
@@ -35,15 +37,18 @@ public class MetadataWindowGridHeader extends AbstractGridHeader {
* SpPermissionChecker * SpPermissionChecker
* @param eventBus * @param eventBus
* UIEventBus * UIEventBus
* @param hasMetadataChangePermission
* checks the permission allowing to change metadata entities
* @param addNewItemCallback * @param addNewItemCallback
* Runnable * callback method to add new metadata entities
*/ */
public MetadataWindowGridHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker, public MetadataWindowGridHeader(final VaadinMessageSource i18n, final SpPermissionChecker permChecker,
final UIEventBus eventBus, final Runnable addNewItemCallback) { final UIEventBus eventBus, final BooleanSupplier hasMetadataChangePermission,
final Runnable addNewItemCallback) {
super(i18n, permChecker, eventBus); super(i18n, permChecker, eventBus);
if (permChecker.hasCreateRepositoryPermission()) { if (hasMetadataChangePermission.getAsBoolean()) {
this.addHeaderSupport = new AddHeaderSupport(i18n, UIComponentIdProvider.METADTA_ADD_ICON_ID, this.addHeaderSupport = new AddHeaderSupport(i18n, UIComponentIdProvider.METADATA_ADD_ICON_ID,
addNewItemCallback, () -> false); addNewItemCallback, () -> false);
} else { } else {
this.addHeaderSupport = null; this.addHeaderSupport = null;

View File

@@ -95,11 +95,6 @@ public class SoftwareModuleDetailsHeader extends AbstractDetailsHeader<ProxySoft
} }
} }
@Override
protected boolean hasEditPermission() {
return permChecker.hasUpdateRepositoryPermission();
}
@Override @Override
protected String getEditIconId() { protected String getEditIconId() {
return UIComponentIdProvider.UPLOAD_SW_MODULE_EDIT_BUTTON; return UIComponentIdProvider.UPLOAD_SW_MODULE_EDIT_BUTTON;

View File

@@ -53,17 +53,29 @@ public abstract class AbstractDetailsHeader<T> extends AbstractMasterAwareGridHe
if (hasEditPermission()) { if (hasEditPermission()) {
this.editDetailsHeaderSupport = new EditDetailsHeaderSupport(i18n, getEditIconId(), this::onEdit); this.editDetailsHeaderSupport = new EditDetailsHeaderSupport(i18n, getEditIconId(), this::onEdit);
} else {
this.editDetailsHeaderSupport = null;
}
if (hasMetadataReadPermission()) {
this.metaDataDetailsHeaderSupport = new MetaDataDetailsHeaderSupport(i18n, getMetaDataIconId(), this.metaDataDetailsHeaderSupport = new MetaDataDetailsHeaderSupport(i18n, getMetaDataIconId(),
this::showMetaData); this::showMetaData);
} else { } else {
this.editDetailsHeaderSupport = null;
this.metaDataDetailsHeaderSupport = null; this.metaDataDetailsHeaderSupport = null;
} }
addHeaderSupports(Arrays.asList(editDetailsHeaderSupport, metaDataDetailsHeaderSupport)); addHeaderSupports(Arrays.asList(editDetailsHeaderSupport, metaDataDetailsHeaderSupport));
} }
protected abstract boolean hasEditPermission(); // can be overriden in child classes for entity-specific permission
protected boolean hasEditPermission() {
return permChecker.hasUpdateRepositoryPermission();
}
// can be overriden in child classes for entity-specific permission
protected boolean hasMetadataReadPermission() {
return permChecker.hasReadRepositoryPermission();
}
protected abstract String getEditIconId(); protected abstract String getEditIconId();

View File

@@ -35,13 +35,13 @@ public class AddHeaderSupport implements HeaderSupport {
* Constructor for AddHeaderSupport * Constructor for AddHeaderSupport
* *
* @param i18n * @param i18n
* AddHeaderSupport * VaadinMessageSource
* @param addIconId * @param addIconId
* Add icon id * Add icon id
* @param addItemCallback * @param addItemCallback
* Runnable * callback method to add new entities
* @param maximizedStateSupplier * @param maximizedStateSupplier
* BooleanSupplier * provides the max/min state of the grid
*/ */
public AddHeaderSupport(final VaadinMessageSource i18n, final String addIconId, final Runnable addItemCallback, public AddHeaderSupport(final VaadinMessageSource i18n, final String addIconId, final Runnable addItemCallback,
final BooleanSupplier maximizedStateSupplier) { final BooleanSupplier maximizedStateSupplier) {

View File

@@ -17,7 +17,7 @@ import javax.validation.ConstraintViolationException;
import org.eclipse.hawkbit.ui.common.notification.ParallelNotification; import org.eclipse.hawkbit.ui.common.notification.ParallelNotification;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.SpringContextHelper; import org.eclipse.hawkbit.ui.utils.SpringContextHolder;
import org.eclipse.hawkbit.ui.utils.UINotification; import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -106,7 +106,7 @@ public class HawkbitUIErrorHandler extends DefaultErrorHandler {
LOG.error("Error in UI: ", ex); LOG.error("Error in UI: ", ex);
final String errorMessage = extractMessageFrom(ex); final String errorMessage = extractMessageFrom(ex);
final VaadinMessageSource i18n = SpringContextHelper.getBean(VaadinMessageSource.class); final VaadinMessageSource i18n = SpringContextHolder.getInstance().getBean(VaadinMessageSource.class);
return buildErrorNotification(i18n.getMessage("caption.error"), errorMessage); return buildErrorNotification(i18n.getMessage("caption.error"), errorMessage);
} }

View File

@@ -69,9 +69,9 @@ public class DsMetaDataWindowLayout extends AbstractMetaDataWindowLayout<Long> {
this.entityFactory = entityFactory; this.entityFactory = entityFactory;
this.dsMetaDataWindowGrid = new MetaDataWindowGrid<>(i18n, eventBus, permChecker, uiNotification, this.dsMetaDataWindowGrid = new MetaDataWindowGrid<>(i18n, eventBus, permChecker, uiNotification,
new DsMetaDataDataProvider(dsManagement), this::deleteMetaData); new DsMetaDataDataProvider(dsManagement), this::hasMetadataChangePermission, this::deleteMetaData);
this.metaDataAddUpdateWindowLayout = new MetaDataAddUpdateWindowLayout(i18n); this.metaDataAddUpdateWindowLayout = new MetaDataAddUpdateWindowLayout(i18n, this::hasMetadataChangePermission);
this.addDsMetaDataWindowController = new AddMetaDataWindowController(i18n, uiNotification, this.addDsMetaDataWindowController = new AddMetaDataWindowController(i18n, uiNotification,
metaDataAddUpdateWindowLayout, this::createMetaData, this::isDuplicate); metaDataAddUpdateWindowLayout, this::createMetaData, this::isDuplicate);
this.updateDsMetaDataWindowController = new UpdateMetaDataWindowController(i18n, uiNotification, this.updateDsMetaDataWindowController = new UpdateMetaDataWindowController(i18n, uiNotification,

View File

@@ -21,7 +21,6 @@ import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.themes.HawkbitTheme; import org.eclipse.hawkbit.ui.themes.HawkbitTheme;
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil; import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions; import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.SpringContextHelper;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification; import org.eclipse.hawkbit.ui.utils.UINotification;
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
@@ -117,7 +116,6 @@ public abstract class AbstractHawkbitLoginUI extends UI {
@Override @Override
protected void init(final VaadinRequest request) { protected void init(final VaadinRequest request) {
HawkbitCommonUtil.initLocalization(this, uiProperties.getLocalization(), i18n); HawkbitCommonUtil.initLocalization(this, uiProperties.getLocalization(), i18n);
SpringContextHelper.setContext(context);
params = UriComponentsBuilder.fromUri(Page.getCurrent().getLocation()).build().getQueryParams(); params = UriComponentsBuilder.fromUri(Page.getCurrent().getLocation()).build().getQueryParams();

View File

@@ -87,7 +87,7 @@ public class TargetDetails extends AbstractGridDetailsLayout<ProxyTarget> {
new SimpleEntry<>(i18n.getMessage("caption.tags.tab"), getTargetTagToken().getTagPanel()), new SimpleEntry<>(i18n.getMessage("caption.tags.tab"), getTargetTagToken().getTagPanel()),
new SimpleEntry<>(i18n.getMessage("caption.logs.tab"), logDetails))); new SimpleEntry<>(i18n.getMessage("caption.logs.tab"), logDetails)));
if (permissionChecker.hasCreateRepositoryPermission()) { if (permissionChecker.hasReadRepositoryPermission()) {
this.targetMetadataGrid = new MetadataDetailsGrid<>(i18n, eventBus, this.targetMetadataGrid = new MetadataDetailsGrid<>(i18n, eventBus,
UIComponentIdProvider.TARGET_TYPE_PREFIX, this::showMetadataDetails, UIComponentIdProvider.TARGET_TYPE_PREFIX, this::showMetadataDetails,
new TargetMetaDataDataProvider(targetManagement)); new TargetMetaDataDataProvider(targetManagement));

View File

@@ -70,9 +70,10 @@ public class TargetMetaDataWindowLayout extends AbstractMetaDataWindowLayout<Str
this.entityFactory = entityFactory; this.entityFactory = entityFactory;
this.targetMetaDataWindowGrid = new MetaDataWindowGrid<>(i18n, eventBus, permChecker, uiNotification, this.targetMetaDataWindowGrid = new MetaDataWindowGrid<>(i18n, eventBus, permChecker, uiNotification,
new TargetMetaDataDataProvider(targetManagement), this::deleteMetaData); new TargetMetaDataDataProvider(targetManagement), this::hasMetadataChangePermission,
this::deleteMetaData);
this.metaDataAddUpdateWindowLayout = new MetaDataAddUpdateWindowLayout(i18n); this.metaDataAddUpdateWindowLayout = new MetaDataAddUpdateWindowLayout(i18n, this::hasMetadataChangePermission);
this.addTargetMetaDataWindowController = new AddMetaDataWindowController(i18n, uiNotification, this.addTargetMetaDataWindowController = new AddMetaDataWindowController(i18n, uiNotification,
metaDataAddUpdateWindowLayout, this::createMetaData, this::isDuplicate); metaDataAddUpdateWindowLayout, this::createMetaData, this::isDuplicate);
this.updateTargetMetaDataWindowController = new UpdateMetaDataWindowController(i18n, uiNotification, this.updateTargetMetaDataWindowController = new UpdateMetaDataWindowController(i18n, uiNotification,

View File

@@ -131,6 +131,9 @@ public class DelayedEventBusPushStrategy
LOG.debug("Cleanup delayed event push strategy for UI {}", vaadinUI.getUIId()); LOG.debug("Cleanup delayed event push strategy for UI {}", vaadinUI.getUIId());
jobHandle.cancel(true); jobHandle.cancel(true);
queue.clear(); queue.clear();
jobHandle = null;
vaadinUI = null;
} }
private final class DispatchRunnable implements Runnable { private final class DispatchRunnable implements Runnable {

View File

@@ -8,27 +8,31 @@
*/ */
package org.eclipse.hawkbit.ui.utils; package org.eclipse.hawkbit.ui.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
/** /**
* Singleton for the spring application context. * Singleton for the spring application context.
*
*
*
*/ */
public final class SpringContextHelper { public final class SpringContextHolder {
private static ApplicationContext context; private static final SpringContextHolder SINGLETON = new SpringContextHolder();
@Autowired
private ApplicationContext context;
/** /**
* Private Constructor. * Private Constructor.
*/ */
private SpringContextHelper() { private SpringContextHolder() {
// Utility class // Utility class
} }
public static void setContext(final ApplicationContext context) { /**
SpringContextHelper.context = context; * @return the spring context holder singleton instance
*/
public static SpringContextHolder getInstance() {
return SINGLETON;
} }
/** /**
@@ -39,7 +43,7 @@ public final class SpringContextHelper {
* application context * application context
* @return the requested bean * @return the requested bean
*/ */
public static Object getBean(final String beanName) { public Object getBean(final String beanName) {
return context.getBean(beanName); return context.getBean(beanName);
} }
@@ -51,7 +55,7 @@ public final class SpringContextHelper {
* application context * application context
* @return the requested bean * @return the requested bean
*/ */
public static <T> T getBean(final Class<T> beanClazz) { public <T> T getBean(final Class<T> beanClazz) {
return context.getBean(beanClazz); return context.getBean(beanClazz);
} }
@@ -66,8 +70,7 @@ public final class SpringContextHelper {
* application context * application context
* @return the requested bean * @return the requested bean
*/ */
public static <T> T getBean(final String beanName, final Class<T> beanClazz) { public <T> T getBean(final String beanName, final Class<T> beanClazz) {
return context.getBean(beanName, beanClazz); return context.getBean(beanName, beanClazz);
} }
} }

View File

@@ -1244,15 +1244,15 @@ public final class UIComponentIdProvider {
/** /**
* Metadata add icon id. * Metadata add icon id.
*/ */
public static final String METADTA_ADD_ICON_ID = "metadata.add.icon.id"; public static final String METADATA_ADD_ICON_ID = "metadata.add.icon.id";
/** /**
* Metadata details table id. * Metadata details table id.
*/ */
public static final String METDATA_DETAILS_TABLE_ID = "metadata.details.table.id"; public static final String METADATA_DETAILS_TABLE_ID = "metadata.details.table.id";
/** /**
* Metadata window table id. * Metadata window table id.
*/ */
public static final String METDATA_WINDOW_TABLE_ID = "metadata.window.table.id"; public static final String METADATA_WINDOW_TABLE_ID = "metadata.window.table.id";
/** /**
* Distribution set table - Manage metadata id. * Distribution set table - Manage metadata id.

View File

@@ -12,6 +12,7 @@ vaadin.servlet.productionMode=true
vaadin.servlet.urlMapping=/UI/* vaadin.servlet.urlMapping=/UI/*
vaadin.servlet.heartbeatInterval=60 vaadin.servlet.heartbeatInterval=60
vaadin.servlet.closeIdleSessions=false vaadin.servlet.closeIdleSessions=false
server.servlet.session.timeout=300
hawkbit.server.ui.links.documentation.root=https://www.eclipse.org/hawkbit/ hawkbit.server.ui.links.documentation.root=https://www.eclipse.org/hawkbit/
hawkbit.server.ui.links.documentation.security=https://www.eclipse.org/hawkbit/concepts/authorization/ hawkbit.server.ui.links.documentation.security=https://www.eclipse.org/hawkbit/concepts/authorization/