Refactor hawkbit core and security (#2833)

* Refactor hawkbit core and security

* improve access to the base core features - static
* thus easiear access
* and less boilerplate passing of instances

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>

* Refactor context classes

* make JSON context serialization default

* AccessContext

* Split hawkbit-security-core to other modules and remove it

---------

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-11-27 13:07:49 +02:00
committed by GitHub
parent 58dbc32a80
commit f6f62db0ad
274 changed files with 2534 additions and 4458 deletions

View File

@@ -29,14 +29,12 @@
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.hawkbit</groupId> <groupId>org.springframework.security</groupId>
<artifactId>hawkbit-repository-jpa</artifactId> <artifactId>spring-security-web</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.hawkbit</groupId> <groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-security-core</artifactId> <artifactId>hawkbit-repository-jpa</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>

View File

@@ -9,30 +9,13 @@
*/ */
package org.eclipse.hawkbit.autoconfigure.security; package org.eclipse.hawkbit.autoconfigure.security;
import java.util.Collections; import java.util.Optional;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.ContextAware;
import org.eclipse.hawkbit.audit.AuditContextProvider;
import org.eclipse.hawkbit.audit.AuditLoggingAspect; import org.eclipse.hawkbit.audit.AuditLoggingAspect;
import org.eclipse.hawkbit.context.AccessContext;
import org.eclipse.hawkbit.repository.RepositoryConfiguration; import org.eclipse.hawkbit.repository.RepositoryConfiguration;
import org.eclipse.hawkbit.tenancy.TenantAware.DefaultTenantResolver;
import org.eclipse.hawkbit.tenancy.TenantAware.TenantResolver;
import org.eclipse.hawkbit.tenancy.TenantAwareUserProperties;
import org.eclipse.hawkbit.tenancy.TenantAwareUserProperties.User;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties; import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.security.InMemoryUserAuthoritiesResolver; import org.eclipse.hawkbit.tenancy.TenantAwareUserProperties;
import org.eclipse.hawkbit.security.MdcHandler;
import org.eclipse.hawkbit.security.SecurityContextSerializer;
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
import org.eclipse.hawkbit.security.SecurityTokenGenerator;
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.boot.autoconfigure.security.SecurityProperties;
@@ -41,14 +24,12 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.data.domain.AuditorAware; import org.springframework.data.domain.AuditorAware;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutHandler; import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler; import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import org.springframework.util.CollectionUtils;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for security. * {@link EnableAutoConfiguration Auto-configuration} for security.
@@ -58,48 +39,6 @@ import org.springframework.util.CollectionUtils;
@Import(RepositoryConfiguration.class) @Import(RepositoryConfiguration.class)
public class SecurityAutoConfiguration { public class SecurityAutoConfiguration {
/**
* Creates a {@link ContextAware} (hence {@link TenantAware}) bean based on the given {@link UserAuthoritiesResolver},
* {@link SecurityContextSerializer} and {@link TenantResolver}.
*
* @param authoritiesResolver The user authorities/roles resolver
* @param securityContextSerializer The security context serializer (optional, if not found the default {@link SecurityContextSerializer#NOP} is used).
* @param tenantResolver The tenant resolver (optional, if not found the default {@link DefaultTenantResolver} is used).
* @return the {@link ContextAware} singleton bean.
*/
@Bean
@ConditionalOnMissingBean
public ContextAware contextAware(
final UserAuthoritiesResolver authoritiesResolver,
@Autowired(required = false) final SecurityContextSerializer securityContextSerializer,
@Autowired(required = false) final TenantResolver tenantResolver) {
return new SecurityContextTenantAware(authoritiesResolver, securityContextSerializer, tenantResolver);
}
/**
* Creates a {@link UserAuthoritiesResolver} bean that is responsible for resolving user authorities/roles.
*
* @param securityProperties The Spring {@link SecurityProperties} for the security user
* @param tenantAwareUserProperties The {@link TenantAwareUserProperties} for the managed users
* @return an {@link InMemoryUserAuthoritiesResolver} bean
*/
@Bean
@ConditionalOnMissingBean
public UserAuthoritiesResolver inMemoryAuthoritiesResolver(
final SecurityProperties securityProperties,
final TenantAwareUserProperties tenantAwareUserProperties) {
final Map<String, User> tenantAwareUsers = tenantAwareUserProperties.getUser();
final Map<String, List<String>> usersToPermissions;
if (!CollectionUtils.isEmpty(tenantAwareUsers)) {
usersToPermissions = tenantAwareUsers.entrySet().stream().collect(
Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getRoles()));
} else {
usersToPermissions = Collections.singletonMap(securityProperties.getUser().getName(),
securityProperties.getUser().getRoles());
}
return new InMemoryUserAuthoritiesResolver(usersToPermissions);
}
/** /**
* Creates the auditor aware. * Creates the auditor aware.
* *
@@ -108,13 +47,7 @@ public class SecurityAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public AuditorAware<String> auditorAware() { public AuditorAware<String> auditorAware() {
return new SpringSecurityAuditorAware(); return () -> Optional.ofNullable(AccessContext.actor());
}
@Bean
@ConditionalOnMissingBean
public AuditContextProvider auditContextProvider() {
return AuditContextProvider.getInstance();
} }
@Bean @Bean
@@ -123,28 +56,6 @@ public class SecurityAutoConfiguration {
return new AuditLoggingAspect(); return new AuditLoggingAspect();
} }
/**
* @param tenantAware singleton bean
* @return tenantAware {@link SystemSecurityContext}
*/
@Bean
@ConditionalOnMissingBean
public SystemSecurityContext systemSecurityContext(final TenantAware tenantAware, final RoleHierarchy roleHierarchy) {
return new SystemSecurityContext(tenantAware, roleHierarchy);
}
@Bean
@ConditionalOnMissingBean
public MdcHandler mdcHandler() {
return MdcHandler.getInstance();
}
@Bean
@ConditionalOnMissingBean
public SecurityTokenGenerator securityTokenGenerator() {
return new SecurityTokenGenerator();
}
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public AuthenticationSuccessHandler authenticationSuccessHandler() { public AuthenticationSuccessHandler authenticationSuccessHandler() {

View File

@@ -9,7 +9,7 @@
*/ */
package org.eclipse.hawkbit.autoconfigure.security; package org.eclipse.hawkbit.autoconfigure.security;
import org.eclipse.hawkbit.im.authentication.StaticAuthenticationProvider; import org.eclipse.hawkbit.auth.StaticAuthenticationProvider;
import org.eclipse.hawkbit.tenancy.TenantAwareUserProperties; import org.eclipse.hawkbit.tenancy.TenantAwareUserProperties;
import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;

View File

@@ -14,7 +14,7 @@ hawkbit.artifact.url.protocols.download-http.hostname=localhost
hawkbit.artifact.url.protocols.download-http.ip=127.0.0.1 hawkbit.artifact.url.protocols.download-http.ip=127.0.0.1
hawkbit.artifact.url.protocols.download-http.protocol=http hawkbit.artifact.url.protocols.download-http.protocol=http
hawkbit.artifact.url.protocols.download-http.port=8080 hawkbit.artifact.url.protocols.download-http.port=8080
hawkbit.artifact.url.protocols.download-http.supports=DMF,DDI hawkbit.artifact.url.protocols.download-http.supports=DDI,DMF
hawkbit.artifact.url.protocols.download-http.ref={protocolRequest}://{hostnameRequest}:{portRequest}/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName} hawkbit.artifact.url.protocols.download-http.ref={protocolRequest}://{hostnameRequest}:{portRequest}/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{artifactFileName}
hawkbit.artifact.url.protocols.md5sum-http.rel=md5sum-http hawkbit.artifact.url.protocols.md5sum-http.rel=md5sum-http
hawkbit.artifact.url.protocols.md5sum-http.protocol=${hawkbit.artifact.url.protocols.download-http.protocol} hawkbit.artifact.url.protocols.md5sum-http.protocol=${hawkbit.artifact.url.protocols.download-http.protocol}

View File

@@ -33,7 +33,6 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator-autoconfigure</artifactId> <artifactId>spring-boot-actuator-autoconfigure</artifactId>
<scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
@@ -47,6 +46,20 @@
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId> <artifactId>spring-context-support</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<!-- needed for web MDC filter -->
<optional>true</optional>
</dependency>
<dependency> <dependency>
<groupId>jakarta.validation</groupId> <groupId>jakarta.validation</groupId>
@@ -65,6 +78,13 @@
<artifactId>caffeine</artifactId> <artifactId>caffeine</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<!-- needed for JSON context serialization -->
<optional>true</optional>
</dependency>
<!-- TEST --> <!-- TEST -->
<dependency> <dependency>
<groupId>io.github.classgraph</groupId> <groupId>io.github.classgraph</groupId>

View File

@@ -1,61 +0,0 @@
/**
* Copyright (c) 2023 Bosch.IO GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import org.eclipse.hawkbit.tenancy.TenantAware;
/**
* {@link ContextAware} provides means for getting the current context (via {@link #getCurrentContext()}) and then
* to execute a {@link Runnable} or a {@link Function} in the same context using {@link #runInContext(String, Runnable)}
* or {@link #runInContext(String, Function, Object)}.
* <p/>
* This is useful for scheduled background operations like rollouts and auto assignments where they shall
* be processed in the scope of the creator.
*/
public interface ContextAware extends TenantAware {
/**
* Return the current context encoded as a {@link String}. Depending on the implementation it could,
* for instance, be a serialized context or a reference to such.
*
* @return could be empty if there is nothing to serialize or context aware is not supported.
*/
Optional<String> getCurrentContext();
/**
* Wrap a specific execution in a known and pre-serialized context.
*
* @param <T> the type of the input to the function
* @param <R> the type of the result of the function
* @param serializedContext created by {@link #getCurrentContext()}. Must be non-<code>null</code>.
* @param function function to call in the reconstructed context. Must be non-<code>null</code>.
* @param t the argument that will be passed to the function
* @return the function result
*/
<T, R> R runInContext(String serializedContext, Function<T, R> function, T t);
/**
* Wrap a specific execution in a known and pre-serialized context.
*
* @param serializedContext created by {@link #getCurrentContext()}. Must be non-<code>null</code>.
* @param runnable runnable to call in the reconstructed context. Must be non-<code>null</code>.
*/
default void runInContext(String serializedContext, Runnable runnable) {
Objects.requireNonNull(runnable);
runInContext(serializedContext, v -> {
runnable.run();
return null;
}, null);
}
}

View File

@@ -0,0 +1,28 @@
/**
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.audit;
import java.util.Optional;
import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.context.AccessContext;
@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE)
@SuppressWarnings("java:S6548") // java:S6548 - singleton holder ensures static access to spring resources in some places
public class AuditContextProvider {
public static AuditContext getAuditContext() {
return new AuditContext(
Optional.ofNullable(AccessContext.tenant()).orElse("n/a"),
Optional.ofNullable(AccessContext.actor()).orElse(AccessContext.SYSTEM_ACTOR));
}
public record AuditContext(String tenant, String username) {}
}

View File

@@ -17,8 +17,6 @@ import org.slf4j.LoggerFactory;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @NoArgsConstructor(access = AccessLevel.PRIVATE)
public class AuditLogger { public class AuditLogger {
private static final AuditContextProvider AUDIT_CONTEXT_PROVIDER = AuditContextProvider.getInstance();
public static void info(final String entity, final String message) { public static void info(final String entity, final String message) {
logMessage(entity, message, AuditLog.Level.INFO); logMessage(entity, message, AuditLog.Level.INFO);
} }
@@ -44,13 +42,13 @@ public class AuditLogger {
} }
private static void logMessage(final String entity, final String message, final AuditLog.Level level) { private static void logMessage(final String entity, final String message, final AuditLog.Level level) {
logMessage(AUDIT_CONTEXT_PROVIDER.getAuditContext().tenant(), AUDIT_CONTEXT_PROVIDER.getAuditContext().username(), entity, message, final AuditContextProvider.AuditContext auditContext = AuditContextProvider.getAuditContext();
level); logMessage(auditContext.tenant(), auditContext.username(), entity, message, level);
} }
private static void logMessage( private static void logMessage(
final String tenant, final String username, final String entity, final String message, final AuditLog.Level level) { final String tenant, final String username, final String entity, final String message, final AuditLog.Level level) {
final String logMessage = String.format("[%s] User: %s, Tenant: %s - %s", entity, username, tenant, message); final String logMessage = String.format("[%s] User: %s, AccessContext: %s - %s", entity, username, tenant, message);
final Logger auditLogger = LoggerFactory.getLogger("AUDIT" + (entity != null ? ("." + entity.toUpperCase()) : "")); final Logger auditLogger = LoggerFactory.getLogger("AUDIT" + (entity != null ? ("." + entity.toUpperCase()) : ""));
switch (level) { switch (level) {
case INFO: case INFO:

View File

@@ -70,8 +70,8 @@ public class AuditLoggingAspect {
* Logs both the request details and the response. * Logs both the request details and the response.
*/ */
private void logAudit( private void logAudit(
final JoinPoint joinPoint, final AuditLog auditLog, final String resultMessage, final String paramsToLog, final JoinPoint joinPoint,
final AuditLog.Level logLevel) { final AuditLog auditLog, final String resultMessage, final String paramsToLog, final AuditLog.Level logLevel) {
final String methodName = joinPoint.getSignature().getName(); final String methodName = joinPoint.getSignature().getName();
final String logMessage = String.format( final String logMessage = String.format(

View File

@@ -1,5 +1,5 @@
/** /**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others * Copyright (c) 2025 Contributors to the Eclipse Foundation
* *
* This program and the accompanying materials are made * This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0 * available under the terms of the Eclipse Public License 2.0
@@ -7,19 +7,18 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.security; package org.eclipse.hawkbit.audit;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Constants related to security. * Constants related to security.
*/ */
@NoArgsConstructor(access = AccessLevel.PRIVATE) @NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class SecurityConstants { public final class SecurityLogger {
/** public static final Logger LOGGER = LoggerFactory.getLogger("SERVER.SECURITY");
* Logger prefix used for security logging.
*/
public static final String SECURITY_LOG_PREFIX = "server-security";
} }

View File

@@ -7,10 +7,11 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.im.authentication; package org.eclipse.hawkbit.auth;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Hierarchy { public class Hierarchy {
@@ -23,4 +24,14 @@ public class Hierarchy {
SpPermission.TENANT_CONFIGURATION_HIERARCHY + SpPermission.TENANT_CONFIGURATION_HIERARCHY +
SpRole.DEFAULT_ROLE_HIERARCHY; SpRole.DEFAULT_ROLE_HIERARCHY;
// @formatter:on // @formatter:on
private static RoleHierarchy roleHierarchy;
public static RoleHierarchy getRoleHierarchy() {
return roleHierarchy;
}
public static void setRoleHierarchy(final RoleHierarchy roleHierarchy) {
Hierarchy.roleHierarchy = roleHierarchy;
}
} }

View File

@@ -7,8 +7,9 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.im.authentication; package org.eclipse.hawkbit.auth;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@@ -16,7 +17,12 @@ import java.util.Set;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.ObjectUtils;
import org.springframework.util.function.SingletonSupplier; import org.springframework.util.function.SingletonSupplier;
/** /**
@@ -164,4 +170,27 @@ public final class SpPermission {
public static Set<String> getAllTenantAuthorities() { public static Set<String> getAllTenantAuthorities() {
return ALL_TENANT_AUTHORITIES.get(); return ALL_TENANT_AUTHORITIES.get();
} }
@SuppressWarnings("java:S3776") // java:S3776 - better in one place for better readability
public static boolean hasPermission(final String permission) {
final SecurityContext context = SecurityContextHolder.getContext();
if (context != null) {
final Authentication authentication = context.getAuthentication();
if (authentication != null) {
Collection<? extends GrantedAuthority> grantedAuthorities = authentication.getAuthorities();
final RoleHierarchy roleHierarchy = Hierarchy.getRoleHierarchy();
if (!ObjectUtils.isEmpty(grantedAuthorities)) {
if (roleHierarchy != null) {
grantedAuthorities = roleHierarchy.getReachableGrantedAuthorities(grantedAuthorities);
}
for (final GrantedAuthority authority : grantedAuthorities) {
if (authority.getAuthority().equals(permission)) {
return true;
}
}
}
}
}
return false;
}
} }

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.im.authentication; package org.eclipse.hawkbit.auth;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.im.authentication; package org.eclipse.hawkbit.auth;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@@ -23,7 +23,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
* hasRole([role]) Returns true if the current principal has the specified role. * hasRole([role]) Returns true if the current principal has the specified role.
* hasAnyRole([role1,role2]) Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings) * hasAnyRole([role1,role2]) Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings)
* principal Allows direct access to the principal object representing the current user * principal Allows direct access to the principal object representing the current user
* authentication Allows direct access to the current Authentication object obtained from the SecurityContext * auth Allows direct access to the current Authentication object obtained from the SecurityContext
* permitAll Always evaluates to true * permitAll Always evaluates to true
* denyAll Always evaluates to false * denyAll Always evaluates to false
* isAnonymous() Returns true if the current principal is an anonymous user * isAnonymous() Returns true if the current principal is an anonymous user

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.im.authentication; package org.eclipse.hawkbit.auth;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@@ -82,8 +82,10 @@ public class StaticAuthenticationProvider extends DaoAuthenticationProvider {
return new FixedInMemoryTenantAwareUserDetailsService(userPrincipals); return new FixedInMemoryTenantAwareUserDetailsService(userPrincipals);
} }
public static final Pattern HAS_SCHEMA = Pattern.compile("^\\{[^{]+}.+$");
private static String password(final String password) { private static String password(final String password) {
return !Pattern.compile("^\\{.+}.*$").matcher(password).matches() ? "{noop}" + password : password; return !HAS_SCHEMA.matcher(password).matches() ? "{noop}" + password : password;
} }
private static List<GrantedAuthority> createAuthorities( private static List<GrantedAuthority> createAuthorities(

View File

@@ -0,0 +1,449 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.context;
import java.io.Serial;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Stream;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.auth.SpRole;
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
import org.eclipse.hawkbit.tenancy.TenantAwareUser;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
/**
* A 'static' class providing methods related to access context:
* <ul>
* <li>read / lookup - find out the current tenant, principal (actor), security context</li>
* <li>switch context - run code as system, as system but scoped for a tenant, with a specific context</li>
* </ul>
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public class AccessContext {
// Note! There shall be no regular 'system'!
public static final String SYSTEM_ACTOR = "system";
/**
* Return the current context encoded as a {@link String}. Depending on the implementation it could,
* for instance, be a serialized context or a reference to such.
*
* @return could be empty if there is nothing to serialize or context aware is not supported.
*/
public static Optional<String> securityContext() {
return Optional.ofNullable(SecurityContextHolder.getContext()).map(AccessContext::serialize);
}
/**
* Implementation might retrieve the current tenant from a session or thread-local.
*
* @return the current tenant
*/
public static String tenant() {
final SecurityContext context = SecurityContextHolder.getContext();
if (context.getAuthentication() != null) {
final Object principal = context.getAuthentication().getPrincipal();
if (context.getAuthentication().getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareAuthenticationDetails) {
return tenantAwareAuthenticationDetails.tenant();
} else if (principal instanceof TenantAwareUser tenantAwareUser) {
return tenantAwareUser.getTenant();
}
}
return null;
}
// Sometimes 'system' need to override the auditor when do create/modify actions in context of a tenant and user.
// Though this could be made using runAsTenantAsUser sometimes (as in transaction) this override is needed
// after runAsTenantAsUser (because it seems that auditor is got in commit time).
// So this thread local variable provides option to override explicitly the auditor.
private static final ThreadLocal<String> ACTOR_OVERRIDE = new ThreadLocal<>();
// Return the current actor / auditor / principal name. It could be a user (person), technical user, device, etc.
public static String actor() {
if (ACTOR_OVERRIDE.get() != null) {
return ACTOR_OVERRIDE.get();
} else {
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (isAuthenticationInvalid(authentication)) {
return null;
} else {
return resolve(authentication);
}
}
}
/**
* Wrap a specific execution in a known and pre-serialized context.
*
* @param serializedContext created by {@link #securityContext()}. Must be non-<code>null</code>.
* @param runnable runnable to run in the reconstructed context. Must be non-<code>null</code>.
*/
public static void withSecurityContext(final String serializedContext, final Runnable runnable) {
Objects.requireNonNull(runnable);
withSecurityContext(serializedContext, () -> {
runnable.run();
return null;
});
}
/**
* Wrap a specific execution / call in a known and pre-serialized context.
*
* @param <T> the type of the output of the supplier
* @param serializedContext created by {@link #securityContext()}. Must be non-<code>null</code>.
* @param supplier function to call in the reconstructed context. Must be non-<code>null</code>.
* @return the function result
*/
public static <T> T withSecurityContext(final String serializedContext, final Supplier<T> supplier) {
Objects.requireNonNull(serializedContext);
Objects.requireNonNull(supplier);
final SecurityContext securityContext = deserialize(serializedContext);
Objects.requireNonNull(securityContext);
return withSecurityContext(securityContext, supplier);
}
public static <T> T withSecurityContext(final SecurityContext securityContext, final Supplier<T> supplier) {
final SecurityContext originalContext = SecurityContextHolder.getContext();
if (Objects.equals(securityContext, originalContext)) {
return supplier.get();
} else {
SecurityContextHolder.setContext(securityContext);
try {
return Mdc.withAuthRe(supplier::get);
} finally {
SecurityContextHolder.setContext(originalContext);
}
}
}
public static void asActor(final String actor, final Runnable runnable) {
asActor(actor, () -> {
runnable.run();
return null;
});
}
public static <T> T asActor(final String actor, final Supplier<T> supplier) {
final String currentAuditor = ACTOR_OVERRIDE.get();
try {
setActor(actor);
return supplier.get();
} finally {
setActor(currentAuditor);
}
}
/**
* Runs a given {@link Runnable} within a system security context, which is permitted to call secured system code. Often the system needs
* to call secured methods by its own without relying on the current security context e.g. if the current security context does not contain
* the necessary permission it's necessary to execute code as system code to execute necessary methods and functionality. <br/>
* The security context will be switched to the system code and back after the supplier is called. <br/>
* The system code is executed for a current tenant by using the {@link AccessContext#tenant()}.
*
* @param runnable the runnable to run within the system security context
*/
public static void asSystem(final Runnable runnable) {
asSystemAsTenant(tenant(), () -> {
runnable.run();
return null;
});
}
/**
* Runs a given {@link Supplier} within a system security context, which is permitted to call secured system code. Often the system needs
* to call secured methods by its own without relying on the current security context e.g. if the current security context does not contain
* the necessary permission it's necessary to execute code as system code to execute necessary methods and functionality. <br/>
* The security context will be switched to the system code and back after the supplier is called. <br/>
* The system code is executed for a current tenant by using the {@link AccessContext#tenant()}.
*
* @param supplier the supplier to call within the system security context
* @return the return value of the {@link Supplier#get()} method.
*/
public static <T> T asSystem(final Supplier<T> supplier) {
return asSystemAsTenant(tenant(), supplier);
}
/**
* Runs a given {@link Runnable} within a system security context, which is permitted to call secured system code. Often the system needs
* to call secured methods by its own without relying on the current security context e.g. if the current security context does not contain
* the necessary permission it's necessary to execute code as system code to execute necessary methods and functionality.<br/>
* The security context will be switched to the system code and back after the runnable is run.<br/>
* The system code is executed for a specific given tenant by using the {@link AccessContext}.
*
* @param tenant the tenant to act as system code
* @param runnable the runnable to run within the system security context
*/
public static void asSystemAsTenant(final String tenant, final Runnable runnable) {
asSystemAsTenant(tenant, () -> {
runnable.run();
return null;
});
}
/**
* Runs a given {@link Supplier} within a system security context, which is permitted to call secured system code. Often the system needs
* to call secured methods by its own without relying on the current security context e.g. if the current security context does not contain
* the necessary permission it's necessary to execute code as system code to execute necessary methods and functionality.<br/>
* The security context will be switched to the system code and back after the supplier is run.<br/>
* The system code is executed for a specific given tenant by using the {@link AccessContext}.
*
* @param tenant the tenant to act as system code
* @param supplier the supplier to call within the system security context
* @return the return value of the {@link Supplier#get()} method.
*/
public static <T> T asSystemAsTenant(final String tenant, final Supplier<T> supplier) {
final SecurityContext currentContext = SecurityContextHolder.getContext();
try {
log.debug("Entering system code execution");
final SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
securityContext.setAuthentication(new SystemCodeAuthentication(tenant));
return withSecurityContext(securityContext, supplier);
} finally {
SecurityContextHolder.setContext(currentContext);
log.debug("Leaving system code execution");
}
}
private static void setActor(final String currentAuditor) {
if (currentAuditor == null) {
ACTOR_OVERRIDE.remove();
} else {
ACTOR_OVERRIDE.set(currentAuditor);
}
}
/**
* @return {@code true} if the current running code is running as system code block.
*/
public static boolean isCurrentThreadSystemCode() {
return SecurityContextHolder.getContext().getAuthentication() instanceof SystemCodeAuthentication;
}
private static String resolve(final Authentication authentication) {
if (authentication.getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails && tenantAwareDetails.controller()) {
return "CONTROLLER_PLUG_AND_PLAY";
}
final Object principal = authentication.getPrincipal();
if (principal instanceof ActorAware actorAware) {
return actorAware.getActor();
}
if (principal instanceof UserDetails userDetails) {
return userDetails.getUsername();
}
if (principal instanceof OidcUser oidcUser) {
return oidcUser.getPreferredUsername();
}
return principal.toString();
}
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
/**
* Return security context as string (could be just a reference)
*
* @param securityContext the security context
* @return the securityContext as string
*/
@SuppressWarnings("java:S112") // java:S112 - generic method
private static String serialize(final SecurityContext securityContext) {
Objects.requireNonNull(securityContext);
try {
return OBJECT_MAPPER.writeValueAsString(new SecCtxInfo(securityContext));
} catch (final JsonProcessingException e) {
throw new RuntimeException(e);
}
}
/**
* Deserialize security context
*
* @param securityContextString string representing the security context
* @return deserialized security context
*/
@SuppressWarnings("java:S112") // java:S112 - generic method
private static SecurityContext deserialize(final String securityContextString) {
Objects.requireNonNull(securityContextString);
final String securityContextTrimmed = securityContextString.trim();
try {
return OBJECT_MAPPER.readerFor(SecCtxInfo.class).<SecCtxInfo> readValue(securityContextTrimmed).toSecurityContext();
} catch (final JsonProcessingException e) {
throw new RuntimeException(e);
}
}
private static boolean isAuthenticationInvalid(final Authentication authentication) {
return authentication == null || !authentication.isAuthenticated() || authentication.getPrincipal() == null;
}
public interface ActorAware {
String getActor();
}
// simplified info for the security context keeping just the basic info needed for background execution of
// controller auth is not supported - always is false
// only authenticated user is supported
@NoArgsConstructor
@Data
private static class SecCtxInfo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String tenant;
// auditor / username (auth principal name)
private String auditor = "n/a"; // default value "n/a" is used only on deserialization if field is missing
@JsonProperty(required = true)
private String[] authorities;
private SecCtxInfo(final SecurityContext securityContext) {
final Authentication authentication = securityContext.getAuthentication();
if (!authentication.isAuthenticated()) {
throw new IllegalStateException("Only authenticated context could be serialized");
}
if (authentication.getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails) {
if (tenantAwareDetails.controller()) {
throw new IllegalStateException("Controller auth context is not supported");
}
tenant = tenantAwareDetails.tenant();
} else if (authentication.getPrincipal() instanceof TenantAwareUser tenantAwareUser) {
tenant = tenantAwareUser.getTenant();
}
// keep the auditor, ofr audit purposes,
// sets principal to the resolved auditor and then deserialized auth will return it as principal
// since the class is not known to auditor aware - it shall used default - principal as auditor
auditor = resolve(authentication);
authorities = authentication.getAuthorities().stream().map(Object::toString).toArray(String[]::new);
}
private SecurityContext toSecurityContext() {
final SecurityContext ctx = SecurityContextHolder.createEmptyContext();
final Object details = tenant == null ? null : new TenantAwareAuthenticationDetails(tenant, false);
final ActorAware principal = () -> auditor;
final Collection<? extends GrantedAuthority> grantedAuthorities =
Stream.of(authorities).map(SimpleGrantedAuthority::new).toList();
ctx.setAuthentication(new Authentication() {
@Override
public Object getPrincipal() {
return principal;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return grantedAuthorities;
}
@Override
public boolean isAuthenticated() {
return true;
}
@Override
public Object getDetails() {
return details;
}
@Override
public Object getCredentials() {
return null;
}
@Override
public void setAuthenticated(final boolean isAuthenticated) throws IllegalArgumentException {
throw new UnsupportedOperationException();
}
@Override
public String getName() {
return auditor;
}
});
return ctx;
}
}
/**
* An implementation of the Spring's {@link Authentication} object which is used within a system security code block and
* wraps the original auth object. The wrapped object contains the necessary {@link SpRole#SYSTEM_ROLE}
* which is allowed to execute all secured methods.
*/
static final class SystemCodeAuthentication implements Authentication {
@Serial
private static final long serialVersionUID = 1L;
private static final List<SimpleGrantedAuthority> AUTHORITIES = List.of(new SimpleGrantedAuthority(SpRole.SYSTEM_ROLE));
private final TenantAwareAuthenticationDetails details;
private final TenantAwareUser principal;
private SystemCodeAuthentication(final String tenant) {
details = new TenantAwareAuthenticationDetails(tenant, false);
principal = new TenantAwareUser(SYSTEM_ACTOR, SYSTEM_ACTOR, AUTHORITIES, tenant);
}
@Override
public String getName() {
return null;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return AUTHORITIES;
}
@Override
public Object getCredentials() {
return null;
}
@Override
public Object getDetails() {
return details;
}
@Override
public Object getPrincipal() {
return principal;
}
@Override
public boolean isAuthenticated() {
return true;
}
@Override
public void setAuthenticated(final boolean isAuthenticated) {
throw new UnsupportedOperationException();
}
}
}

View File

@@ -7,10 +7,11 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.security; package org.eclipse.hawkbit.context;
import java.io.IOException; import java.io.IOException;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;
@@ -22,8 +23,6 @@ import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails; import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
import org.slf4j.MDC; import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
@@ -31,42 +30,34 @@ import org.springframework.security.web.access.intercept.AuthorizationFilter;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
@NoArgsConstructor(access = AccessLevel.PRIVATE) @NoArgsConstructor(access = AccessLevel.PRIVATE)
// java:S6548 - singleton holder ensures static access to spring resources in some places
// java:S112 - it is generic class so a generic exception is fine // java:S112 - it is generic class so a generic exception is fine
@SuppressWarnings({ "java:S6548", "java:S112" }) @SuppressWarnings("java:S112")
public class MdcHandler { public class Mdc {
public static final String MDC_KEY_TENANT = "tenant"; public static final String MDC_KEY_TENANT = "tenant";
public static final String MDC_KEY_USER = "user"; // in the MDC the default actor key is "user"
public static final String MDC_KEY_ACTOR = System.getProperty(
"hawkbit.mdc.actor.key", // first by priority: system property
Optional.ofNullable(System.getenv("HAWKBIT_MDC_ACTOR_KEY")) // second by priority: environment variable
.orElse("user")); // default if not set
private static final MdcHandler SINGLETON = new MdcHandler(); private static boolean enabled = true;
@Value("${hawkbit.logging.mdchandler.enabled:true}") // hook to disable (otherwise enabled by default) MDC context management
private boolean mdcEnabled; public static void setEnabled(final boolean enabled) {
private SpringSecurityAuditorAware springSecurityAuditorAware = new SpringSecurityAuditorAware(); Mdc.enabled = enabled;
/**
* @return The holder singleton instance.
*/
public static MdcHandler getInstance() {
return SINGLETON;
}
@Autowired(required = false) // spring setter injection
public void setSpringSecurityAuditorAware(final SpringSecurityAuditorAware springSecurityAuditorAware) {
this.springSecurityAuditorAware = springSecurityAuditorAware;
} }
/** /**
* Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or user from the authentication in the MDC context. * Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or actor from the auth in the MDC context.
* *
* @param <T> the return type * @param <T> the return type
* @param callable the callable to execute * @param callable the callable to execute
* @return the result * @return the result
* @throws Exception if thrown by the callable * @throws Exception if thrown by the callable
*/ */
public <T> T callWithAuth(final Callable<T> callable) throws Exception { public static <T> T withAuth(final Callable<T> callable) throws Exception {
if (!mdcEnabled) { if (!enabled) {
return callable.call(); return callable.call();
} }
@@ -82,25 +73,24 @@ public class MdcHandler {
tenant = null; tenant = null;
} }
final String user = springSecurityAuditorAware final String actor = Optional.ofNullable(AccessContext.actor())
.getCurrentAuditor() .filter(ctxActor -> !ctxActor.equals(AccessContext.SYSTEM_ACTOR)) // null and system are the same - system actor
.filter(username -> !username.equals(SecurityContextTenantAware.SYSTEM_USER)) // null and system are the same - system user
.orElse(null); .orElse(null);
return callWithTenantAndUser0(callable, tenant, user); return asTenantAsActor0(tenant, actor, callable);
} }
/** /**
* Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or user from the authentication in the MDC context. * Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or actor from the auth in the MDC context.
* Calls the {@link #callWithAuth(Callable)} method and wraps any catchable exception into a {@link RuntimeException}. * Calls the {@link #withAuth(Callable)} method and wraps any catchable exception into a {@link RuntimeException}.
* *
* @param <T> the return type * @param <T> the return type
* @param callable the callable to execute * @param callable the callable to execute
* @return the result * @return the result
*/ */
public <T> T callWithAuthRE(final Callable<T> callable) { public static <T> T withAuthRe(final Callable<T> callable) {
try { try {
return callWithAuth(callable); return withAuth(callable);
} catch (final RuntimeException re) { } catch (final RuntimeException re) {
throw re; throw re;
} catch (final Exception e) { } catch (final Exception e) {
@@ -109,35 +99,35 @@ public class MdcHandler {
} }
/** /**
* Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or user in the MDC context. * Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or actor in the MDC context.
* *
* @param <T> the return type * @param <T> the return type
* @param callable the callable to execute
* @param tenant the tenant to set in the MDC context * @param tenant the tenant to set in the MDC context
* @param user the user to set in the MDC context * @param actor the actor to set in the MDC context
* @param callable the callable to execute
* @return the result * @return the result
*/ */
public <T> T callWithTenantAndUser(final Callable<T> callable, final String tenant, final String user) throws Exception { public static <T> T asTenantAsActor(final String tenant, final String actor, final Callable<T> callable) throws Exception {
if (!mdcEnabled) { if (!enabled) {
return callable.call(); return callable.call();
} }
return callWithTenantAndUser0(callable, tenant, user); return asTenantAsActor0(tenant, actor, callable);
} }
/** /**
* Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or user from the authentication in the MDC context. * Executes callable and returns the result. If MDC is enabled, it sets the tenant and / or actor from the auth in the MDC context.
* Calls the {@link #callWithTenantAndUser(Callable, String, String)} method and wraps any catchable exception into a {@link RuntimeException}. * Calls the {@link #asTenantAsActor(String, String, Callable)} method and wraps any catchable exception into a {@link RuntimeException}.
* *
* @param <T> the return type * @param <T> the return type
* @param callable the callable to execute
* @param tenant the tenant to set in the MDC context * @param tenant the tenant to set in the MDC context
* @param user the user to set in the MDC context * @param actor the actor to set in the MDC context
* @param callable the callable to execute
* @return the result * @return the result
*/ */
public <T> T callWithTenantAndUserRE(final Callable<T> callable, final String tenant, final String user) { public static <T> T asTenantAsActorRe(final String tenant, final String actor, final Callable<T> callable) {
try { try {
return callWithTenantAndUser(callable, tenant, user); return asTenantAsActor(tenant, actor, callable);
} catch (final RuntimeException re) { } catch (final RuntimeException re) {
throw re; throw re;
} catch (final Exception e) { } catch (final Exception e) {
@@ -145,30 +135,30 @@ public class MdcHandler {
} }
} }
private static <T> T callWithTenantAndUser0(final Callable<T> callable, final String tenant, final String user) throws Exception { private static <T> T asTenantAsActor0(final String tenant, final String actor, final Callable<T> callable) throws Exception {
final String currentTenant = MDC.get(MDC_KEY_TENANT); final String currentTenant = MDC.get(MDC_KEY_TENANT);
if (Objects.equals(currentTenant, tenant)) { if (Objects.equals(currentTenant, tenant)) {
return callWithUser(callable, user); return asActor(callable, actor);
} else { } else {
put(MDC_KEY_TENANT, tenant); put(MDC_KEY_TENANT, tenant);
try { try {
return callWithUser(callable, user); return asActor(callable, actor);
} finally { } finally {
put(MDC_KEY_TENANT, currentTenant); put(MDC_KEY_TENANT, currentTenant);
} }
} }
} }
private static <T> T callWithUser(final Callable<T> callable, final String user) throws Exception { private static <T> T asActor(final Callable<T> callable, final String actor) throws Exception {
final String currentUser = MDC.get(MDC_KEY_USER); final String currentActor = MDC.get(MDC_KEY_ACTOR);
if (Objects.equals(currentUser, user)) { if (Objects.equals(currentActor, actor)) {
return callable.call(); return callable.call();
} else { } else {
put(MDC_KEY_USER, user); put(MDC_KEY_ACTOR, actor);
try { try {
return callable.call(); return callable.call();
} finally { } finally {
put(MDC_KEY_USER, currentUser); put(MDC_KEY_ACTOR, currentActor);
} }
} }
} }
@@ -187,14 +177,12 @@ public class MdcHandler {
public static void addMdcFilter(final HttpSecurity httpSecurity) { public static void addMdcFilter(final HttpSecurity httpSecurity) {
httpSecurity.addFilterBefore(new OncePerRequestFilter() { httpSecurity.addFilterBefore(new OncePerRequestFilter() {
private final MdcHandler mdcFilter = MdcHandler.getInstance();
@Override @Override
protected void doFilterInternal( protected void doFilterInternal(
final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain) final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain)
throws ServletException, IOException { throws ServletException, IOException {
try { try {
mdcFilter.callWithAuth(() -> { Mdc.withAuth(() -> {
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
return null; return null;
}); });

View File

@@ -12,7 +12,7 @@ package org.eclipse.hawkbit.exception;
import lombok.Getter; import lombok.Getter;
/** /**
* Define the Error codes for Error handling * Define the error codes for error handling
*/ */
@Getter @Getter
public enum SpServerError { public enum SpServerError {
@@ -182,9 +182,6 @@ public enum SpServerError {
private final String key; private final String key;
private final String message; private final String message;
/**
* Repository side Error codes
*/
SpServerError(final String key, final String message) { SpServerError(final String key, final String message) {
this.key = key; this.key = key;
this.message = message; this.message = message;

View File

@@ -43,11 +43,11 @@ public class HawkbitSecurityProperties {
*/ */
private List<String> httpFirewallIgnoredPaths; private List<String> httpFirewallIgnoredPaths;
/** /**
* Basic authentication realm, see https://tools.ietf.org/html/rfc2617#page-3 . * Basic auth realm, see https://tools.ietf.org/html/rfc2617#page-3 .
*/ */
private String basicRealm = "hawkBit"; private String basicRealm = "hawkBit";
/** /**
* If to allow http authentication when there is OAuth2 authentication enabled. * If to allow http auth when there is OAuth2 auth enabled.
*/ */
private boolean allowHttpBasicOnOAuthEnabled = false; private boolean allowHttpBasicOnOAuthEnabled = false;
@@ -103,7 +103,7 @@ public class HawkbitSecurityProperties {
public static final String X_FORWARDED_FOR = "X-Forwarded-For"; public static final String X_FORWARDED_FOR = "X-Forwarded-For";
/** /**
* Blacklisted client (IP addresses) for for DDI and Management API. * Blacklisted client (IP addresses) for DDI and Management API.
*/ */
private String blacklist = ""; private String blacklist = "";
/** /**
@@ -117,7 +117,7 @@ public class HawkbitSecurityProperties {
} }
/** /**
* Denial of service protection related properties. * Denial-of-service (DoS) protection related properties.
*/ */
@Data @Data
public static class Dos { public static class Dos {

View File

@@ -18,6 +18,7 @@ import io.micrometer.common.KeyValues;
import io.micrometer.core.instrument.Tag; import io.micrometer.core.instrument.Tag;
import io.micrometer.observation.ObservationRegistry; import io.micrometer.observation.ObservationRegistry;
import lombok.NonNull; import lombok.NonNull;
import org.eclipse.hawkbit.context.AccessContext;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties; import org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties;
import org.springframework.boot.actuate.autoconfigure.observation.web.servlet.WebMvcObservationAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.observation.web.servlet.WebMvcObservationAutoConfiguration;
@@ -44,12 +45,6 @@ public class DefaultTenantConfiguration {
public static final String TENANT_TAG = "tenant"; public static final String TENANT_TAG = "tenant";
@Bean
@ConditionalOnMissingBean
TenantAware.TenantResolver tenantResolver() {
return new TenantAware.DefaultTenantResolver();
}
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
TenantAwareCacheManager cacheManager() { TenantAwareCacheManager cacheManager() {
@@ -62,12 +57,12 @@ public class DefaultTenantConfiguration {
@ConditionalOnProperty(name = "hawkbit.metrics.tenancy.web.enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnProperty(name = "hawkbit.metrics.tenancy.web.enabled", havingValue = "true", matchIfMissing = true)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass(name = { "org.springframework.web.servlet.DispatcherServlet", "io.micrometer.observation.Observation" }) @ConditionalOnClass(name = { "org.springframework.web.servlet.DispatcherServlet", "io.micrometer.observation.Observation" })
@ConditionalOnBean({ ObservationRegistry.class, TenantAware.TenantResolver.class }) @ConditionalOnBean(ObservationRegistry.class)
public static class WebConfig { public static class WebConfig {
@Bean @Bean
@Primary @Primary
public DefaultServerRequestObservationConvention serverRequestObservationConvention(final TenantAware.TenantResolver tenantResolver) { public DefaultServerRequestObservationConvention serverRequestObservationConvention() {
return new DefaultServerRequestObservationConvention() { return new DefaultServerRequestObservationConvention() {
@NonNull @NonNull
@@ -78,7 +73,7 @@ public class DefaultTenantConfiguration {
} }
private KeyValue tenant() { private KeyValue tenant() {
return KeyValue.of(TENANT_TAG, Optional.ofNullable(tenantResolver.resolveTenant()).orElse("n/a")); return KeyValue.of(TENANT_TAG, Optional.ofNullable(AccessContext.tenant()).orElse("n/a"));
} }
}; };
} }
@@ -104,17 +99,16 @@ public class DefaultTenantConfiguration {
@ConditionalOnClass(name = { @ConditionalOnClass(name = {
"io.micrometer.core.instrument.Tag", "io.micrometer.core.instrument.Tag",
"org.springframework.data.repository.core.support.RepositoryMethodInvocationListener" }) "org.springframework.data.repository.core.support.RepositoryMethodInvocationListener" })
@ConditionalOnBean(TenantAware.TenantResolver.class)
public static class RepositoryConfig { public static class RepositoryConfig {
@Bean @Bean
public RepositoryTagsProvider repositoryTagsProvider(final TenantAware.TenantResolver tenantResolver) { public RepositoryTagsProvider repositoryTagsProvider() {
return new DefaultRepositoryTagsProvider() { return new DefaultRepositoryTagsProvider() {
@Override @Override
public Iterable<Tag> repositoryTags(final RepositoryMethodInvocationListener.RepositoryMethodInvocation invocation) { public Iterable<Tag> repositoryTags(final RepositoryMethodInvocationListener.RepositoryMethodInvocation invocation) {
final Iterable<Tag> defaultTags = super.repositoryTags(invocation); final Iterable<Tag> defaultTags = super.repositoryTags(invocation);
final String tenant = Optional.ofNullable(tenantResolver.resolveTenant()).orElse("n/a"); final String tenant = Optional.ofNullable(AccessContext.tenant()).orElse("n/a");
return () -> { return () -> {
final Iterator<Tag> defaultTagsIterator = defaultTags.iterator(); final Iterator<Tag> defaultTagsIterator = defaultTags.iterator();
return new Iterator<>() { return new Iterator<>() {

View File

@@ -1,79 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.tenancy;
import java.util.concurrent.Callable;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* Interface for components that are aware of the application's current tenant.
*/
public interface TenantAware {
/**
* Implementation might retrieve the current tenant from a session or thread-local.
*
* @return the current tenant
*/
String getCurrentTenant();
/**
* @return the username of the currently logged-in user
*/
String getCurrentUsername();
/**
* Gives the possibility to run a certain code under a specific given {@code tenant}. Only the given {@link Callable} is executed
* under the specific tenant e.g. under control of an {@link ThreadLocal}. After the {@link Callable} it must be ensured that the
* original tenant before this invocation is reset.
*
* @param tenant the tenant which the specific code should run
* @param callable the runner which is implemented to run this specific code under the given tenant
* @return the return type of the {@link Callable}
*/
<T> T runAsTenant(String tenant, Callable<T> callable);
/**
* Gives the possibility to run a certain code under a specific given {@code tenant} and {@code username}.
* Only the given {@link Runnable} is executed under the specific tenant and user e.g. under control of an {@link ThreadLocal}.
* After the {@link Runnable} it must be ensured that the original tenant before this invocation is reset.
*
* @param tenant the tenant which the specific code should run with
* @param username the username which the specific code should run with
*/
void runAsTenantAsUser(String tenant, String username, Runnable runnable);
/**
* Resolves the tenant from the current context.
*/
interface TenantResolver {
String resolveTenant();
}
class DefaultTenantResolver implements TenantResolver {
@Override
public String resolveTenant() {
final SecurityContext context = SecurityContextHolder.getContext();
if (context.getAuthentication() != null) {
final Object principal = context.getAuthentication().getPrincipal();
if (context.getAuthentication().getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareAuthenticationDetails) {
return tenantAwareAuthenticationDetails.tenant();
} else if (principal instanceof TenantAwareUser tenantAwareUser) {
return tenantAwareUser.getTenant();
}
}
return null;
}
}
}

View File

@@ -15,8 +15,8 @@ import java.io.Serializable;
import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.authentication.AbstractAuthenticationToken;
/** /**
* An authentication details object {@link AbstractAuthenticationToken#getDetails()} which is stored in the * An auth details object {@link AbstractAuthenticationToken#getDetails()} which is stored in the
* spring security authentication token details to transport the principal and tenant in the security context session. * spring security auth token details to transport the principal and tenant in the security context session.
*/ */
public record TenantAwareAuthenticationDetails(String tenant, boolean controller) implements Serializable { public record TenantAwareAuthenticationDetails(String tenant, boolean controller) implements Serializable {

View File

@@ -22,7 +22,7 @@ import lombok.NoArgsConstructor;
import lombok.NonNull; import lombok.NonNull;
import lombok.Value; import lombok.Value;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.tenancy.TenantAware.TenantResolver; import org.eclipse.hawkbit.context.AccessContext;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache; import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
@@ -34,7 +34,7 @@ import org.springframework.lang.Nullable;
/** /**
* A spring Cache Manager that handles the multi tenancy. * A spring Cache Manager that handles the multi tenancy.
* <ul> * <ul>
* <li>If a tenant is resolved by the {@link TenantResolver}, a dedicated cache manager for that tenant is used/created.</li> * <li>If a tenant is resolved by the {@link AccessContext}, a dedicated cache manager for that tenant is used/created.</li>
* <li>If no tenant is resolved, a global cache manager is used.</li> * <li>If no tenant is resolved, a global cache manager is used.</li>
* </ul> * </ul>
*/ */
@@ -50,7 +50,6 @@ public class TenantAwareCacheManager implements CacheManager {
private CacheManager globalCacheManager; private CacheManager globalCacheManager;
private final Map<String, CacheManager> tenant2CacheManager = new ConcurrentHashMap<>(); private final Map<String, CacheManager> tenant2CacheManager = new ConcurrentHashMap<>();
private TenantResolver resolver;
private Environment env; private Environment env;
// default caffeine cache spec - see com.github.benmanes.caffeine.cache.CaffeineSpec javadoc for format details // default caffeine cache spec - see com.github.benmanes.caffeine.cache.CaffeineSpec javadoc for format details
@@ -61,8 +60,7 @@ public class TenantAwareCacheManager implements CacheManager {
} }
@Autowired @Autowired
public void init(final TenantResolver resolver, final Environment env) { public void init(final Environment env) {
this.resolver = resolver;
this.env = env; this.env = env;
defaultSpec = env.resolvePlaceholders("${" + CONFIG_PREFIX + CONFIG_SPEC + ":expireAfterWrite=${hawkbit.cache.ttl:10s}}"); defaultSpec = env.resolvePlaceholders("${" + CONFIG_PREFIX + CONFIG_SPEC + ":expireAfterWrite=${hawkbit.cache.ttl:10s}}");
globalCacheManager = new TenantCacheManager(null); globalCacheManager = new TenantCacheManager(null);
@@ -71,7 +69,7 @@ public class TenantAwareCacheManager implements CacheManager {
@NonNull @NonNull
@Override @Override
public Cache getCache(@NonNull final String name) { public Cache getCache(@NonNull final String name) {
final Cache cache = Optional.ofNullable(resolver.resolveTenant()) final Cache cache = Optional.ofNullable(AccessContext.tenant())
.map(currentTenant -> tenant2CacheManager.computeIfAbsent(currentTenant, TenantCacheManager::new)) .map(currentTenant -> tenant2CacheManager.computeIfAbsent(currentTenant, TenantCacheManager::new))
.orElse(globalCacheManager) .orElse(globalCacheManager)
.getCache(name); .getCache(name);
@@ -81,7 +79,7 @@ public class TenantAwareCacheManager implements CacheManager {
@NonNull @NonNull
@Override @Override
public Collection<String> getCacheNames() { public Collection<String> getCacheNames() {
final String currentTenant = resolver.resolveTenant(); final String currentTenant = AccessContext.tenant();
if (currentTenant == null) { if (currentTenant == null) {
return globalCacheManager.getCacheNames(); return globalCacheManager.getCacheNames();
} else { } else {

View File

@@ -1,27 +0,0 @@
/**
* Copyright (c) 2020 Bosch.IO GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.tenancy;
import java.util.Collection;
/**
* The service responsible for making the lookup for user authorities/roles based on his tenant and username
*/
@FunctionalInterface
public interface UserAuthoritiesResolver {
/**
* User authorities/roles lookup based on the username and the tenant context
*
* @param username The username of the user
* @return a {@link Collection} of authorities/roles for this user
*/
Collection<String> getUserAuthorities(String username);
}

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.util; package org.eclipse.hawkbit.utils;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.net.URI; import java.net.URI;

View File

@@ -7,16 +7,16 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.security; package org.eclipse.hawkbit.context;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.hawkbit.security.SecurityContextSerializer.JSON_SERIALIZATION; import static org.eclipse.hawkbit.context.AccessContext.withSecurityContext;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.auth.SpPermission;
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails; import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -39,11 +39,12 @@ class SecurityContextSerializerTest {
userPassAuthentication.setDetails(details); userPassAuthentication.setDetails(details);
securityContext.setAuthentication(userPassAuthentication); securityContext.setAuthentication(userPassAuthentication);
final String serialized = JSON_SERIALIZATION.serialize(securityContext); final String serialized = serialize(securityContext);
final SecurityContext deserialized = JSON_SERIALIZATION.deserialize(serialized); final SecurityContext deserialized = deserialize(serialized);
final Authentication authentication = deserialized.getAuthentication(); final Authentication authentication = deserialized.getAuthentication();
assertThat(SpringSecurityAuditorAware.resolveAuditor(authentication)).hasToString("user"); assertThat(resolve(authentication)).hasToString("user");
assertThat(authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet())).isEqualTo(AUTHORITIES); assertThat(authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet()))
.isEqualTo(AUTHORITIES);
assertThat(authentication.isAuthenticated()).isTrue(); assertThat(authentication.isAuthenticated()).isTrue();
assertThat(authentication.getDetails()).isEqualTo(details); assertThat(authentication.getDetails()).isEqualTo(details);
} }
@@ -53,34 +54,16 @@ class SecurityContextSerializerTest {
final SecurityContext securityContext = SecurityContextHolder.getContext(); final SecurityContext securityContext = SecurityContextHolder.getContext();
final UsernamePasswordAuthenticationToken userPassAuthentication = new UsernamePasswordAuthenticationToken( final UsernamePasswordAuthenticationToken userPassAuthentication = new UsernamePasswordAuthenticationToken(
"FirstName.FamilyName@domain1.domain0.com", "FirstName.FamilyName@domain1.domain0.com",
Map.of("should not be in" + bigString(10_000),"the output" + bigString(15_000)), Map.of("should not be in" + bigString(10_000), "the output" + bigString(15_000)),
AUTHORITIES.stream().map(SimpleGrantedAuthority::new).toList()); AUTHORITIES.stream().map(SimpleGrantedAuthority::new).toList());
final TenantAwareAuthenticationDetails details = new TenantAwareAuthenticationDetails("my_test_enant", false); final TenantAwareAuthenticationDetails details = new TenantAwareAuthenticationDetails("my_test_enant", false);
userPassAuthentication.setDetails(details); userPassAuthentication.setDetails(details);
securityContext.setAuthentication(userPassAuthentication); securityContext.setAuthentication(userPassAuthentication);
final String serialized = JSON_SERIALIZATION.serialize(securityContext); final String serialized = serialize(securityContext);
assertThat(serialized).hasSizeLessThan(4096); // ensure that it is not too big assertThat(serialized).hasSizeLessThan(4096); // ensure that it is not too big
} }
@Test
void testUsername() {
final SecurityContext securityContext = SecurityContextHolder.getContext();
final UsernamePasswordAuthenticationToken userPassAuthentication = new UsernamePasswordAuthenticationToken(
"user", null, AUTHORITIES.stream().map(SimpleGrantedAuthority::new).toList());
final TenantAwareAuthenticationDetails details = new TenantAwareAuthenticationDetails("my_tenant", false);
userPassAuthentication.setDetails(details);
securityContext.setAuthentication(userPassAuthentication);
final String serialized = JSON_SERIALIZATION.serialize(securityContext).replace("auditor", "username");
final SecurityContext deserialized = JSON_SERIALIZATION.deserialize(serialized);
final Authentication authentication = deserialized.getAuthentication();
assertThat(SpringSecurityAuditorAware.resolveAuditor(authentication)).hasToString("user");
assertThat(authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet())).isEqualTo(AUTHORITIES);
assertThat(authentication.isAuthenticated()).isTrue();
assertThat(authentication.getDetails()).isEqualTo(details);
}
private static String bigString(final int length) { private static String bigString(final int length) {
final StringBuilder sb = new StringBuilder(length); final StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
@@ -88,4 +71,18 @@ class SecurityContextSerializerTest {
} }
return sb.toString(); return sb.toString();
} }
private static String serialize(final SecurityContext securityContext) {
return withSecurityContext(securityContext, () -> AccessContext.securityContext().orElseThrow());
}
private static SecurityContext deserialize(final String serialized) {
return withSecurityContext(serialized, SecurityContextHolder::getContext);
}
private static String resolve(final Authentication authentication) {
final SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
securityContext.setAuthentication(authentication);
return withSecurityContext(securityContext, AccessContext::actor);
}
} }

View File

@@ -0,0 +1,69 @@
/**
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.context;
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
import java.util.List;
import org.assertj.core.api.Assertions;
import org.eclipse.hawkbit.auth.SpRole;
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
import org.junit.jupiter.api.Test;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
class SystemSecurityContextTest {
@Test
void test() {
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("test", "pass", List.of(new SimpleGrantedAuthority("anonymous")));
auth.setDetails("string details");
test(auth);
}
@Test
void testWithNullPrincipal() {
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(null, "pass", List.of(new SimpleGrantedAuthority("anonymous")));
auth.setDetails("string details");
test(auth);
}
@Test
void testWithNullCredentials() {
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("test", null, List.of(new SimpleGrantedAuthority("anonymous")));
auth.setDetails("string details");
test(auth);
}
@Test
void testWitAllNull() {
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(null, null, List.of(new SimpleGrantedAuthority("anonymous")));
auth.setDetails(null);
test(auth);
}
private static void test(final UsernamePasswordAuthenticationToken auth) {
final SecurityContext sc = SecurityContextHolder.createEmptyContext();
sc.setAuthentication(auth);
SecurityContextHolder.setContext(sc);
asSystemAsTenant("tenant", () -> {
final Authentication currentAuth = SecurityContextHolder.getContext().getAuthentication();
Assertions.assertThat(currentAuth.getClass().getSimpleName()).isEqualTo("SystemCodeAuthentication");
Assertions.assertThat(currentAuth.getCredentials()).isNull();
Assertions.assertThat(currentAuth.getAuthorities()).isEqualTo(List.of(new SimpleGrantedAuthority(SpRole.SYSTEM_ROLE)));
Assertions.assertThat(currentAuth.getDetails()).isEqualTo(new TenantAwareAuthenticationDetails("tenant", false));
});
SecurityContextHolder.clearContext();
}
}

View File

@@ -13,6 +13,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import java.util.Collection; import java.util.Collection;
import org.eclipse.hawkbit.auth.SpPermission;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** /**

View File

@@ -21,17 +21,18 @@ import jakarta.servlet.http.HttpServletRequest;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties; import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties.Clients; import org.eclipse.hawkbit.security.HawkbitSecurityProperties.Clients;
import org.eclipse.hawkbit.utils.IpUtil;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
/** /**
* Feature: Unit Tests - Security<br/> * Feature: Unit Tests - Security<br/>
* Story: IP Util Test * Story: IP Util Test
*/ */
@ExtendWith(MockitoExtension.class)
class IpUtilTest { class IpUtilTest {
private static final String X_FORWARDED_FOR = HawkbitSecurityProperties.Clients.X_FORWARDED_FOR; private static final String X_FORWARDED_FOR = HawkbitSecurityProperties.Clients.X_FORWARDED_FOR;

View File

@@ -68,7 +68,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -107,7 +107,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to " +
"be changed (i.e. read-only) or data volume restriction applies.", "be changed (i.e. read-only) or data volume restriction applies.",
@@ -143,7 +143,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be" + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be" +
" changed (i.e. read-only) or data volume restriction applies.", " changed (i.e. read-only) or data volume restriction applies.",
@@ -181,7 +181,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -244,7 +244,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", content = @Content(mediaType = "application/json",
schema = @Schema(implementation = ExceptionInfo.class))), schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -289,7 +289,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -336,7 +336,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -377,7 +377,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -414,7 +414,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -474,7 +474,7 @@ public interface DdiRootControllerRestApi {
"""), """),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -516,7 +516,7 @@ public interface DdiRootControllerRestApi {
"""), """),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -565,7 +565,7 @@ public interface DdiRootControllerRestApi {
"the action awaiting confirmation in the same format as for the deploymentBase operation."), "the action awaiting confirmation in the same format as for the deploymentBase operation."),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -607,7 +607,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -658,7 +658,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -701,7 +701,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -744,7 +744,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) " +
"or data volume restriction applies.", "or data volume restriction applies.",

View File

@@ -16,6 +16,7 @@ import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver; import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver;
import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver.DownloadDescriptor; import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver.DownloadDescriptor;
import org.eclipse.hawkbit.context.AccessContext;
import org.eclipse.hawkbit.ddi.json.model.DdiArtifact; import org.eclipse.hawkbit.ddi.json.model.DdiArtifact;
import org.eclipse.hawkbit.ddi.json.model.DdiArtifactHash; import org.eclipse.hawkbit.ddi.json.model.DdiArtifactHash;
import org.eclipse.hawkbit.ddi.json.model.DdiAutoConfirmationState; import org.eclipse.hawkbit.ddi.json.model.DdiAutoConfirmationState;
@@ -34,7 +35,6 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TenantMetaData; import org.eclipse.hawkbit.repository.model.TenantMetaData;
import org.eclipse.hawkbit.rest.json.model.ResponseList; import org.eclipse.hawkbit.rest.json.model.ResponseList;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.hateoas.Link; import org.springframework.hateoas.Link;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.http.HttpRequest; import org.springframework.http.HttpRequest;
@@ -47,25 +47,24 @@ import org.springframework.util.CollectionUtils;
public final class DataConversionHelper { public final class DataConversionHelper {
public static DdiConfirmationBase createConfirmationBase( public static DdiConfirmationBase createConfirmationBase(
final Target target, final Action activeAction, final Target target, final Action activeAction, final DdiAutoConfirmationState autoConfirmationState) {
final DdiAutoConfirmationState autoConfirmationState, final TenantAware tenantAware) {
final String controllerId = target.getControllerId(); final String controllerId = target.getControllerId();
final DdiConfirmationBase confirmationBase = new DdiConfirmationBase(autoConfirmationState); final DdiConfirmationBase confirmationBase = new DdiConfirmationBase(autoConfirmationState);
if (autoConfirmationState.isActive()) { if (autoConfirmationState.isActive()) {
confirmationBase.add(WebMvcLinkBuilder confirmationBase.add(WebMvcLinkBuilder
.linkTo(WebMvcLinkBuilder.methodOn(DdiRootController.class, tenantAware.getCurrentTenant()) .linkTo(WebMvcLinkBuilder.methodOn(DdiRootController.class, AccessContext.tenant())
.deactivateAutoConfirmation(tenantAware.getCurrentTenant(), controllerId)) .deactivateAutoConfirmation(AccessContext.tenant(), controllerId))
.withRel(DdiRestConstants.AUTO_CONFIRM_DEACTIVATE).expand()); .withRel(DdiRestConstants.AUTO_CONFIRM_DEACTIVATE).expand());
} else { } else {
confirmationBase.add(WebMvcLinkBuilder confirmationBase.add(WebMvcLinkBuilder
.linkTo(WebMvcLinkBuilder.methodOn(DdiRootController.class, tenantAware.getCurrentTenant()) .linkTo(WebMvcLinkBuilder.methodOn(DdiRootController.class, AccessContext.tenant())
.activateAutoConfirmation(tenantAware.getCurrentTenant(), controllerId, null)) .activateAutoConfirmation(AccessContext.tenant(), controllerId, null))
.withRel(DdiRestConstants.AUTO_CONFIRM_ACTIVATE).expand()); .withRel(DdiRestConstants.AUTO_CONFIRM_ACTIVATE).expand());
} }
if (activeAction != null && activeAction.isWaitingConfirmation()) { if (activeAction != null && activeAction.isWaitingConfirmation()) {
confirmationBase.add(WebMvcLinkBuilder confirmationBase.add(WebMvcLinkBuilder
.linkTo(WebMvcLinkBuilder.methodOn(DdiRootController.class, tenantAware.getCurrentTenant()) .linkTo(WebMvcLinkBuilder.methodOn(DdiRootController.class, AccessContext.tenant())
.getConfirmationBaseAction(tenantAware.getCurrentTenant(), controllerId, .getConfirmationBaseAction(AccessContext.tenant(), controllerId,
activeAction.getId(), calculateEtag(activeAction), null)) activeAction.getId(), calculateEtag(activeAction), null))
.withRel(DdiRestConstants.CONFIRMATION_BASE).expand()); .withRel(DdiRestConstants.CONFIRMATION_BASE).expand());
} }
@@ -75,22 +74,22 @@ public final class DataConversionHelper {
public static DdiControllerBase fromTarget( public static DdiControllerBase fromTarget(
final Target target, final Action installedAction, final Target target, final Action installedAction,
final Action activeAction, final String defaultControllerPollTime, final TenantAware tenantAware) { final Action activeAction, final String defaultControllerPollTime) {
final DdiControllerBase result = new DdiControllerBase( final DdiControllerBase result = new DdiControllerBase(
new DdiConfig(new DdiPolling(defaultControllerPollTime))); new DdiConfig(new DdiPolling(defaultControllerPollTime)));
if (activeAction != null) { if (activeAction != null) {
if (activeAction.isWaitingConfirmation()) { if (activeAction.isWaitingConfirmation()) {
result.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder result.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder
.methodOn(DdiRootController.class, tenantAware.getCurrentTenant()) .methodOn(DdiRootController.class, AccessContext.tenant())
.getConfirmationBaseAction(tenantAware.getCurrentTenant(), target.getControllerId(), .getConfirmationBaseAction(AccessContext.tenant(), target.getControllerId(),
activeAction.getId(), calculateEtag(activeAction), null)) activeAction.getId(), calculateEtag(activeAction), null))
.withRel(DdiRestConstants.CONFIRMATION_BASE).expand()); .withRel(DdiRestConstants.CONFIRMATION_BASE).expand());
} else if (activeAction.isCancelingOrCanceled()) { } else if (activeAction.isCancelingOrCanceled()) {
result.add(WebMvcLinkBuilder result.add(WebMvcLinkBuilder
.linkTo(WebMvcLinkBuilder.methodOn(DdiRootController.class, tenantAware.getCurrentTenant()) .linkTo(WebMvcLinkBuilder.methodOn(DdiRootController.class, AccessContext.tenant())
.getControllerCancelAction(tenantAware.getCurrentTenant(), target.getControllerId(), .getControllerCancelAction(AccessContext.tenant(), target.getControllerId(),
activeAction.getId())) activeAction.getId()))
.withRel(DdiRestConstants.CANCEL_ACTION).expand()); .withRel(DdiRestConstants.CANCEL_ACTION).expand());
} else { } else {
@@ -98,9 +97,9 @@ public final class DataConversionHelper {
// have changed from 'soft' to 'forced' type, and we need to change the payload of the // have changed from 'soft' to 'forced' type, and we need to change the payload of the
// response because of eTags. // response because of eTags.
result.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder result.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder
.methodOn(DdiRootController.class, tenantAware.getCurrentTenant()) .methodOn(DdiRootController.class, AccessContext.tenant())
.getControllerDeploymentBaseAction( .getControllerDeploymentBaseAction(
tenantAware.getCurrentTenant(), target.getControllerId(), AccessContext.tenant(), target.getControllerId(),
activeAction.getId(), calculateEtag(activeAction), null)) activeAction.getId(), calculateEtag(activeAction), null))
.withRel(DdiRestConstants.DEPLOYMENT_BASE_ACTION).expand()); .withRel(DdiRestConstants.DEPLOYMENT_BASE_ACTION).expand());
} }
@@ -109,8 +108,8 @@ public final class DataConversionHelper {
if (installedAction != null && !installedAction.isActive()) { if (installedAction != null && !installedAction.isActive()) {
result.add( result.add(
WebMvcLinkBuilder WebMvcLinkBuilder
.linkTo(WebMvcLinkBuilder.methodOn(DdiRootController.class, tenantAware.getCurrentTenant()) .linkTo(WebMvcLinkBuilder.methodOn(DdiRootController.class, AccessContext.tenant())
.getControllerInstalledAction(tenantAware.getCurrentTenant(), .getControllerInstalledAction(AccessContext.tenant(),
target.getControllerId(), installedAction.getId(), null)) target.getControllerId(), installedAction.getId(), null))
.withRel(DdiRestConstants.INSTALLED_BASE_ACTION).expand()); .withRel(DdiRestConstants.INSTALLED_BASE_ACTION).expand());
} }
@@ -118,9 +117,9 @@ public final class DataConversionHelper {
if (target.isRequestControllerAttributes()) { if (target.isRequestControllerAttributes()) {
result.add(WebMvcLinkBuilder result.add(WebMvcLinkBuilder
.linkTo(WebMvcLinkBuilder .linkTo(WebMvcLinkBuilder
.methodOn(DdiRootController.class, tenantAware.getCurrentTenant()) .methodOn(DdiRootController.class, AccessContext.tenant())
// doesn't really call the putConfigData with null, just create the link // doesn't really call the putConfigData with null, just create the link
.putConfigData(null, tenantAware.getCurrentTenant(), target.getControllerId())) .putConfigData(null, AccessContext.tenant(), target.getControllerId()))
.withRel(DdiRestConstants.CONFIG_DATA_ACTION).expand()); .withRel(DdiRestConstants.CONFIG_DATA_ACTION).expand());
} }

View File

@@ -24,6 +24,7 @@ import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.artifact.model.ArtifactStream; import org.eclipse.hawkbit.artifact.model.ArtifactStream;
import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver; import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver;
import org.eclipse.hawkbit.audit.AuditLog; import org.eclipse.hawkbit.audit.AuditLog;
import org.eclipse.hawkbit.context.AccessContext;
import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback; import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback;
import org.eclipse.hawkbit.ddi.json.model.DdiActionHistory; import org.eclipse.hawkbit.ddi.json.model.DdiActionHistory;
import org.eclipse.hawkbit.ddi.json.model.DdiActivateAutoConfirmation; import org.eclipse.hawkbit.ddi.json.model.DdiActivateAutoConfirmation;
@@ -68,8 +69,7 @@ import org.eclipse.hawkbit.rest.util.FileStreamingUtil;
import org.eclipse.hawkbit.rest.util.HttpUtil; import org.eclipse.hawkbit.rest.util.HttpUtil;
import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder; import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties; import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.utils.IpUtil;
import org.eclipse.hawkbit.util.IpUtil;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
@@ -102,7 +102,6 @@ public class DdiRootController implements DdiRootControllerRestApi {
private final SystemManagement systemManagement; private final SystemManagement systemManagement;
private final ApplicationEventPublisher eventPublisher; private final ApplicationEventPublisher eventPublisher;
private final HawkbitSecurityProperties securityProperties; private final HawkbitSecurityProperties securityProperties;
private final TenantAware tenantAware;
@SuppressWarnings("java:S107") @SuppressWarnings("java:S107")
public DdiRootController( public DdiRootController(
@@ -110,7 +109,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
final ArtifactManagement artifactManagement, final ArtifactUrlResolver artifactUrlHandler, final ArtifactManagement artifactManagement, final ArtifactUrlResolver artifactUrlHandler,
final SystemManagement systemManagement, final SystemManagement systemManagement,
final ApplicationEventPublisher eventPublisher, final ApplicationEventPublisher eventPublisher,
final HawkbitSecurityProperties securityProperties, final TenantAware tenantAware) { final HawkbitSecurityProperties securityProperties) {
this.controllerManagement = controllerManagement; this.controllerManagement = controllerManagement;
this.confirmationManagement = confirmationManagement; this.confirmationManagement = confirmationManagement;
this.artifactManagement = artifactManagement; this.artifactManagement = artifactManagement;
@@ -118,7 +117,6 @@ public class DdiRootController implements DdiRootControllerRestApi {
this.systemManagement = systemManagement; this.systemManagement = systemManagement;
this.eventPublisher = eventPublisher; this.eventPublisher = eventPublisher;
this.securityProperties = securityProperties; this.securityProperties = securityProperties;
this.tenantAware = tenantAware;
} }
@Override @Override
@@ -155,7 +153,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
installedAction, activeAction, installedAction, activeAction,
activeAction == null activeAction == null
? controllerManagement.getPollingTime(target) ? controllerManagement.getPollingTime(target)
: controllerManagement.getPollingTimeForAction(target, activeAction), tenantAware), : controllerManagement.getPollingTimeForAction(target, activeAction)),
HttpStatus.OK); HttpStatus.OK);
} }
@@ -190,7 +188,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
(length, shippedSinceLastEvent, total) -> { (length, shippedSinceLastEvent, total) -> {
if (actionStatus != null) { if (actionStatus != null) {
eventPublisher.publishEvent(new DownloadProgressEvent( eventPublisher.publishEvent(new DownloadProgressEvent(
tenantAware.getCurrentTenant(), actionStatus.getId(), shippedSinceLastEvent)); AccessContext.tenant(), actionStatus.getId(), shippedSinceLastEvent));
} }
}); });
} }
@@ -352,14 +350,13 @@ public class DdiRootController implements DdiRootControllerRestApi {
@Override @Override
public ResponseEntity<DdiConfirmationBase> getConfirmationBase(final String tenant, final String controllerId) { public ResponseEntity<DdiConfirmationBase> getConfirmationBase(final String tenant, final String controllerId) {
log.debug("getConfirmationBase is called [controllerId={}].", controllerId); log.debug("getConfirmationBase is called [controllerId={}].", controllerId);
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist(controllerId, IpUtil final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist(
.getClientIpFromRequest(RequestResponseContextHolder.getHttpServletRequest(), securityProperties)); controllerId, IpUtil.getClientIpFromRequest(RequestResponseContextHolder.getHttpServletRequest(), securityProperties));
final Action activeAction = controllerManagement.findActiveActionWithHighestWeight(controllerId).orElse(null); final Action activeAction = controllerManagement.findActiveActionWithHighestWeight(controllerId).orElse(null);
final DdiAutoConfirmationState autoConfirmationState = getAutoConfirmationState(controllerId); final DdiAutoConfirmationState autoConfirmationState = getAutoConfirmationState(controllerId);
final DdiConfirmationBase confirmationBase = DataConversionHelper.createConfirmationBase( final DdiConfirmationBase confirmationBase = DataConversionHelper.createConfirmationBase(target, activeAction, autoConfirmationState);
target, activeAction, autoConfirmationState, tenantAware);
return new ResponseEntity<>(confirmationBase, HttpStatus.OK); return new ResponseEntity<>(confirmationBase, HttpStatus.OK);
} }

View File

@@ -32,6 +32,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.cbor.CBORFactory; import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
import com.fasterxml.jackson.dataformat.cbor.CBORGenerator; import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
import com.fasterxml.jackson.dataformat.cbor.CBORParser; import com.fasterxml.jackson.dataformat.cbor.CBORParser;
import org.eclipse.hawkbit.context.AccessContext;
import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback; import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback;
import org.eclipse.hawkbit.ddi.json.model.DdiAssignedVersion; import org.eclipse.hawkbit.ddi.json.model.DdiAssignedVersion;
import org.eclipse.hawkbit.ddi.json.model.DdiConfirmationFeedback; import org.eclipse.hawkbit.ddi.json.model.DdiConfirmationFeedback;
@@ -131,7 +132,7 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
protected ResultActions putInstalledBase(final String controllerId, final String content, final ResultMatcher statusMatcher) protected ResultActions putInstalledBase(final String controllerId, final String content, final ResultMatcher statusMatcher)
throws Exception { throws Exception {
return mvc.perform(put(INSTALLED_BASE_ROOT, tenantAware.getCurrentTenant(), controllerId) return mvc.perform(put(INSTALLED_BASE_ROOT, AccessContext.tenant(), controllerId)
.content(content.getBytes()).contentType(MediaType.APPLICATION_JSON)) .content(content.getBytes()).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(statusMatcher); .andExpect(statusMatcher);
@@ -141,7 +142,7 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
final MediaType mediaType, final String controllerId, final MediaType mediaType, final String controllerId,
final Long actionId, final byte[] content, final ResultMatcher statusMatcher) throws Exception { final Long actionId, final byte[] content, final ResultMatcher statusMatcher) throws Exception {
return mvc return mvc
.perform(post(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), controllerId, actionId) .perform(post(DEPLOYMENT_FEEDBACK, AccessContext.tenant(), controllerId, actionId)
.content(content).contentType(mediaType).accept(mediaType)) .content(content).contentType(mediaType).accept(mediaType))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(statusMatcher); .andExpect(statusMatcher);
@@ -157,7 +158,7 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
final MediaType mediaType, final String controllerId, final MediaType mediaType, final String controllerId,
final Long actionId, final byte[] content, final ResultMatcher statusMatcher) throws Exception { final Long actionId, final byte[] content, final ResultMatcher statusMatcher) throws Exception {
return mvc return mvc
.perform(post(CANCEL_FEEDBACK, tenantAware.getCurrentTenant(), controllerId, actionId).content(content) .perform(post(CANCEL_FEEDBACK, AccessContext.tenant(), controllerId, actionId).content(content)
.contentType(mediaType).accept(mediaType)) .contentType(mediaType).accept(mediaType))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(statusMatcher); .andExpect(statusMatcher);
@@ -177,7 +178,7 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
final DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId, final DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId,
final Long osModuleId, final String downloadType, final String updateType) throws Exception { final Long osModuleId, final String downloadType, final String updateType) throws Exception {
final ResultActions resultActions = performGet(DEPLOYMENT_BASE, mediaType, status().isOk(), final ResultActions resultActions = performGet(DEPLOYMENT_BASE, mediaType, status().isOk(),
tenantAware.getCurrentTenant(), controllerId, actionId.toString()); AccessContext.tenant(), controllerId, actionId.toString());
return verifyBasePayload( return verifyBasePayload(
"$.deployment", resultActions, controllerId, ds, artifact, artifactSignature, actionId, osModuleId, downloadType, updateType); "$.deployment", resultActions, controllerId, ds, artifact, artifactSignature, actionId, osModuleId, downloadType, updateType);
} }
@@ -194,18 +195,18 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
final DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId, final DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId,
final Long osModuleId, final Action.ActionType actionType) throws Exception { final Long osModuleId, final Action.ActionType actionType) throws Exception {
final ResultActions resultActions = performGet(INSTALLED_BASE, mediaType, status().isOk(), final ResultActions resultActions = performGet(INSTALLED_BASE, mediaType, status().isOk(),
tenantAware.getCurrentTenant(), controllerId, actionId.toString()); AccessContext.tenant(), controllerId, actionId.toString());
return verifyBasePayload("$.deployment", resultActions, controllerId, ds, artifact, artifactSignature, actionId, osModuleId, return verifyBasePayload("$.deployment", resultActions, controllerId, ds, artifact, artifactSignature, actionId, osModuleId,
getDownloadAndUploadType(actionType), getDownloadAndUploadType(actionType)); getDownloadAndUploadType(actionType), getDownloadAndUploadType(actionType));
} }
protected String installedBaseLink(final String controllerId, final String actionId) { protected String installedBaseLink(final String controllerId, final String actionId) {
return HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + return HTTP_LOCALHOST + AccessContext.tenant() + "/controller/v1/" +
controllerId + "/installedBase/" + actionId; controllerId + "/installedBase/" + actionId;
} }
protected String deploymentBaseLink(final String controllerId, final String actionId) { protected String deploymentBaseLink(final String controllerId, final String actionId) {
return HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + return HTTP_LOCALHOST + AccessContext.tenant() + "/controller/v1/" +
controllerId + "/deploymentBase/" + actionId; controllerId + "/deploymentBase/" + actionId;
} }
@@ -319,7 +320,7 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
final Long osModuleId, final String downloadType, final String updateType) throws Exception { final Long osModuleId, final String downloadType, final String updateType) throws Exception {
final ResultActions resultActions = performGet( final ResultActions resultActions = performGet(
CONFIRMATION_BASE_ACTION, mediaType, status().isOk(), CONFIRMATION_BASE_ACTION, mediaType, status().isOk(),
tenantAware.getCurrentTenant(), controllerId, actionId.toString()); AccessContext.tenant(), controllerId, actionId.toString());
return verifyBasePayload( return verifyBasePayload(
"$.confirmation", resultActions, controllerId, ds, artifact, artifactSignature, actionId, osModuleId, "$.confirmation", resultActions, controllerId, ds, artifact, artifactSignature, actionId, osModuleId,
downloadType, updateType); downloadType, updateType);
@@ -367,10 +368,10 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].hashes.sha256", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].hashes.sha256",
contains(artifact.getSha256Hash()))) contains(artifact.getSha256Hash())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.download-http.href", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.download-http.href",
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId + contains(HTTP_LOCALHOST + AccessContext.tenant() + "/controller/v1/" + controllerId +
"/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename()))) "/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.md5sum-http.href", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.md5sum-http.href",
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId + contains(HTTP_LOCALHOST + AccessContext.tenant() + "/controller/v1/" + controllerId +
"/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename() + ".MD5SUM"))) "/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename() + ".MD5SUM")))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].size", contains(ARTIFACT_SIZE))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].size", contains(ARTIFACT_SIZE)))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].filename", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].filename",
@@ -382,10 +383,10 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].hashes.sha256", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].hashes.sha256",
contains(artifactSignature.getSha256Hash()))) contains(artifactSignature.getSha256Hash())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.download-http.href", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.download-http.href",
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId + contains(HTTP_LOCALHOST + AccessContext.tenant() + "/controller/v1/" + controllerId +
"/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename()))) "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.md5sum-http.href", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.md5sum-http.href",
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId + contains(HTTP_LOCALHOST + AccessContext.tenant() + "/controller/v1/" + controllerId +
"/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename() + ".MD5SUM"))) "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename() + ".MD5SUM")))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].version", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].version",
contains(findFirstModuleByType(ds, appType).orElseThrow().getVersion()))) contains(findFirstModuleByType(ds, appType).orElseThrow().getVersion())))

View File

@@ -30,6 +30,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
import org.eclipse.hawkbit.context.AccessContext;
import org.eclipse.hawkbit.ddi.rest.resource.DdiArtifactDownloadTest.DownloadTestConfiguration; import org.eclipse.hawkbit.ddi.rest.resource.DdiArtifactDownloadTest.DownloadTestConfiguration;
import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent; import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent;
import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.Artifact;
@@ -106,55 +107,55 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
// test now consistent data to test allowed methods // test now consistent data to test allowed methods
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}", mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()) AccessContext.tenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
.header(HttpHeaders.IF_MATCH, artifact.getSha1Hash())) .header(HttpHeaders.IF_MATCH, artifact.getSha1Hash()))
.andExpect(status().isOk()); .andExpect(status().isOk());
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM", mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())) AccessContext.tenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
.andExpect(status().isOk()); .andExpect(status().isOk());
// test failed If-match // test failed If-match
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}", mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()) AccessContext.tenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
.header(HttpHeaders.IF_MATCH, "fsjkhgjfdhg")) .header(HttpHeaders.IF_MATCH, "fsjkhgjfdhg"))
.andExpect(status().isPreconditionFailed()); .andExpect(status().isPreconditionFailed());
// test invalid range // test invalid range
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}", mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()) AccessContext.tenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
.header("Range", "bytes=1-10,hdsfjksdh")) .header("Range", "bytes=1-10,hdsfjksdh"))
.andExpect(header().string("Content-Range", "bytes */" + 5 * 1024)) .andExpect(header().string("Content-Range", "bytes */" + 5 * 1024))
.andExpect(status().isRequestedRangeNotSatisfiable()); .andExpect(status().isRequestedRangeNotSatisfiable());
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}", mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()) AccessContext.tenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
.header("Range", "bytes=100-10")) .header("Range", "bytes=100-10"))
.andExpect(header().string("Content-Range", "bytes */" + 5 * 1024)) .andExpect(header().string("Content-Range", "bytes */" + 5 * 1024))
.andExpect(status().isRequestedRangeNotSatisfiable()); .andExpect(status().isRequestedRangeNotSatisfiable());
// not allowed methods // not allowed methods
mvc.perform(put("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}", mvc.perform(put("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())) AccessContext.tenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(delete("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}", mvc.perform(delete("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())) AccessContext.tenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(post("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}", mvc.perform(post("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())) AccessContext.tenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(put("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM", mvc.perform(put("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())) AccessContext.tenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(delete("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM", mvc.perform(delete("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())) AccessContext.tenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(post("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM", mvc.perform(post("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())) AccessContext.tenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
} }
@@ -193,7 +194,7 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
assignDistributionSet(ds, targets); assignDistributionSet(ds, targets);
final MvcResult result = mvc.perform(get( final MvcResult result = mvc.perform(get(
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}", "/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())) AccessContext.tenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)) .andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
.andExpect(header().string("Accept-Ranges", "bytes")) .andExpect(header().string("Accept-Ranges", "bytes"))
@@ -233,7 +234,7 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
// download // download
final MvcResult result = mvc.perform(get( final MvcResult result = mvc.perform(get(
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}.MD5SUM", "/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}.MD5SUM",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())) AccessContext.tenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(header().string("Content-Disposition", .andExpect(header().string("Content-Disposition",
"attachment;filename=" + artifact.getFilename() + ".MD5SUM")) "attachment;filename=" + artifact.getFilename() + ".MD5SUM"))
@@ -278,7 +279,7 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
final MvcResult result = mvc.perform(get( final MvcResult result = mvc.perform(get(
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}", "/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1").header("Range", AccessContext.tenant(), target.getControllerId(), getOsModule(ds), "file1").header("Range",
"bytes=" + rangeString)) "bytes=" + rangeString))
.andExpect(status().isPartialContent()) .andExpect(status().isPartialContent())
.andExpect(header().string("ETag", artifact.getSha1Hash())) .andExpect(header().string("ETag", artifact.getSha1Hash()))
@@ -298,7 +299,7 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
// return last 1000 Bytes // return last 1000 Bytes
MvcResult result = mvc.perform( MvcResult result = mvc.perform(
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}", get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1") AccessContext.tenant(), target.getControllerId(), getOsModule(ds), "file1")
.header("Range", "bytes=-1000")) .header("Range", "bytes=-1000"))
.andExpect(status().isPartialContent()) .andExpect(status().isPartialContent())
.andExpect(header().string("ETag", artifact.getSha1Hash())) .andExpect(header().string("ETag", artifact.getSha1Hash()))
@@ -317,7 +318,7 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
// skip first 1000 Bytes and return the rest // skip first 1000 Bytes and return the rest
result = mvc.perform( result = mvc.perform(
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}", get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1") AccessContext.tenant(), target.getControllerId(), getOsModule(ds), "file1")
.header("Range", "bytes=1000-")) .header("Range", "bytes=1000-"))
.andExpect(status().isPartialContent()) .andExpect(status().isPartialContent())
.andExpect(header().string("ETag", artifact.getSha1Hash())) .andExpect(header().string("ETag", artifact.getSha1Hash()))
@@ -335,7 +336,7 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
// Start download from file end fails // Start download from file end fails
mvc.perform( mvc.perform(
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}", get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1") AccessContext.tenant(), target.getControllerId(), getOsModule(ds), "file1")
.header("Range", "bytes=" + random.length + "-")) .header("Range", "bytes=" + random.length + "-"))
.andExpect(status().isRequestedRangeNotSatisfiable()) .andExpect(status().isRequestedRangeNotSatisfiable())
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)) .andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
@@ -347,7 +348,7 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
// multipart download - first 20 bytes in 2 parts // multipart download - first 20 bytes in 2 parts
result = mvc.perform( result = mvc.perform(
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}", get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1") AccessContext.tenant(), target.getControllerId(), getOsModule(ds), "file1")
.header("Range", "bytes=0-9,10-19")) .header("Range", "bytes=0-9,10-19"))
.andExpect(status().isPartialContent()) .andExpect(status().isPartialContent())
.andExpect(header().string("ETag", artifact.getSha1Hash())) .andExpect(header().string("ETag", artifact.getSha1Hash()))

View File

@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.context.AccessContext;
import org.eclipse.hawkbit.ddi.json.model.DdiResult; import org.eclipse.hawkbit.ddi.json.model.DdiResult;
import org.eclipse.hawkbit.ddi.json.model.DdiStatus; import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
@@ -66,7 +67,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// check that we can get the cancel action as CBOR // check that we can get the cancel action as CBOR
final byte[] result = mvc final byte[] result = mvc
.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" .perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId(), tenantAware.getCurrentTenant()) + cancelAction.getId(), AccessContext.tenant())
.accept(DdiRestConstants.MEDIA_TYPE_CBOR)) .accept(DdiRestConstants.MEDIA_TYPE_CBOR))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
@@ -80,7 +81,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// and submit feedback as CBOR // and submit feedback as CBOR
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", AccessContext.tenant())
.content(jsonToCbor(getJsonProceedingCancelActionFeedback())) .content(jsonToCbor(getJsonProceedingCancelActionFeedback()))
.contentType(DdiRestConstants.MEDIA_TYPE_CBOR).accept(DdiRestConstants.MEDIA_TYPE_CBOR)) .contentType(DdiRestConstants.MEDIA_TYPE_CBOR).accept(DdiRestConstants.MEDIA_TYPE_CBOR))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -104,7 +105,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// controller rejects cancellation // controller rejects cancellation
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", AccessContext.tenant())
.content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -115,7 +116,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// get update action anyway // get update action anyway
mvc.perform( mvc.perform(
get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId, get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId,
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)) AccessContext.tenant()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().contentType(MediaType.APPLICATION_JSON))
@@ -131,7 +132,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// and finish it // and finish it
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/"
+ actionId + "/feedback", tenantAware.getCurrentTenant()).content( + actionId + "/feedback", AccessContext.tenant()).content(
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE,
Collections.singletonList("message"))) Collections.singletonList("message")))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
@@ -161,14 +162,14 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
assignDistributionSet(ds.getId(), savedTarget.getControllerId())); assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
final long timeBeforeFirstPoll = System.currentTimeMillis(); final long timeBeforeFirstPoll = System.currentTimeMillis();
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(), mvc.perform(get("/{tenant}/controller/v1/{controller}", AccessContext.tenant(),
TestdataFactory.DEFAULT_CONTROLLER_ID).accept(MediaTypes.HAL_JSON)) TestdataFactory.DEFAULT_CONTROLLER_ID).accept(MediaTypes.HAL_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href", .andExpect(jsonPath("$._links.deploymentBase.href",
startsWith("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" startsWith("http://localhost/" + AccessContext.tenant() + "/controller/v1/"
+ TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId))); + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId)));
final long timeAfterFirstPoll = System.currentTimeMillis() + 1; final long timeAfterFirstPoll = System.currentTimeMillis() + 1;
assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).getLastTargetQuery()) assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).getLastTargetQuery())
@@ -192,21 +193,21 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
assertThat(activeActionsByTarget.get(0).getStatus()).isEqualTo(Status.CANCELING); assertThat(activeActionsByTarget.get(0).getStatus()).isEqualTo(Status.CANCELING);
final long timeBefore2ndPoll = System.currentTimeMillis(); final long timeBefore2ndPoll = System.currentTimeMillis();
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(), mvc.perform(get("/{tenant}/controller/v1/{controller}", AccessContext.tenant(),
TestdataFactory.DEFAULT_CONTROLLER_ID)) TestdataFactory.DEFAULT_CONTROLLER_ID))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.cancelAction.href", .andExpect(jsonPath("$._links.cancelAction.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" equalTo("http://localhost/" + AccessContext.tenant() + "/controller/v1/"
+ TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction.getId()))); + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction.getId())));
final long timeAfter2ndPoll = System.currentTimeMillis() + 1; final long timeAfter2ndPoll = System.currentTimeMillis() + 1;
assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).getLastTargetQuery()) assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).getLastTargetQuery())
.isBetween(timeBefore2ndPoll, timeAfter2ndPoll); .isBetween(timeBefore2ndPoll, timeAfter2ndPoll);
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)) + cancelAction.getId(), AccessContext.tenant()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().contentType(MediaType.APPLICATION_JSON))
@@ -217,7 +218,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// controller confirmed cancelled action, should not be active anymore // controller confirmed cancelled action, should not be active anymore
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON) + cancelAction.getId() + "/feedback", AccessContext.tenant()).accept(MediaType.APPLICATION_JSON)
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -240,22 +241,22 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// not allowed methods // not allowed methods
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1", mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
tenantAware.getCurrentTenant())) AccessContext.tenant()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(put("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1", mvc.perform(put("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
tenantAware.getCurrentTenant())) AccessContext.tenant()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1", mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
tenantAware.getCurrentTenant())) AccessContext.tenant()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
// non existing target // non existing target
mvc.perform(get("/{tenant}/controller/v1/34534543/cancelAction/1", tenantAware.getCurrentTenant()) mvc.perform(get("/{tenant}/controller/v1/34534543/cancelAction/1", AccessContext.tenant())
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
@@ -263,7 +264,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
createCancelAction("34534543"); createCancelAction("34534543");
// wrong media type // wrong media type
mvc.perform(get("/{tenant}/controller/v1/34534543/cancelAction/1", tenantAware.getCurrentTenant()) mvc.perform(get("/{tenant}/controller/v1/34534543/cancelAction/1", AccessContext.tenant())
.accept(MediaType.APPLICATION_ATOM_XML)) .accept(MediaType.APPLICATION_ATOM_XML))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotAcceptable()); .andExpect(status().isNotAcceptable());
@@ -289,7 +290,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE)).hasSize(1); assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE)).hasSize(1);
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", AccessContext.tenant())
.content(getJsonProceedingCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonProceedingCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -299,7 +300,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
assertThat(countActionStatusAll()).isEqualTo(3); assertThat(countActionStatusAll()).isEqualTo(3);
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", AccessContext.tenant())
.content(getJsonResumedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonResumedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -308,7 +309,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
assertThat(countActionStatusAll()).isEqualTo(4); assertThat(countActionStatusAll()).isEqualTo(4);
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", AccessContext.tenant())
.content(getJsonScheduledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonScheduledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -319,7 +320,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// cancellation canceled -> should remove the action from active // cancellation canceled -> should remove the action from active
assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE)).hasSize(1); assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE)).hasSize(1);
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", AccessContext.tenant())
.content(getJsonCanceledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonCanceledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -333,7 +334,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// error // error
assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE)).hasSize(1); assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE)).hasSize(1);
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", AccessContext.tenant())
.content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -343,7 +344,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// update closed -> should remove the action from active // update closed -> should remove the action from active
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", AccessContext.tenant())
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -383,7 +384,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3); assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
mvc.perform(get( mvc.perform(get(
"/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction.getId(), "/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction.getId(),
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)) AccessContext.tenant()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
@@ -391,19 +392,19 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId)))); .andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId))));
assertThat(countActionStatusAll()).isEqualTo(6); assertThat(countActionStatusAll()).isEqualTo(6);
mvc.perform(get("/{tenant}/controller/v1/{controllerId}", tenantAware.getCurrentTenant(), mvc.perform(get("/{tenant}/controller/v1/{controllerId}", AccessContext.tenant(),
TestdataFactory.DEFAULT_CONTROLLER_ID)) TestdataFactory.DEFAULT_CONTROLLER_ID))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.cancelAction.href", .andExpect(jsonPath("$._links.cancelAction.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" equalTo("http://localhost/" + AccessContext.tenant() + "/controller/v1/"
+ TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction.getId()))); + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction.getId())));
// now lets return feedback for the first cancelation // now lets return feedback for the first cancelation
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", AccessContext.tenant())
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -414,7 +415,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE)).hasSize(2); assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE)).hasSize(2);
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3); assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction2.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)) + cancelAction2.getId(), AccessContext.tenant()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().contentType(MediaType.APPLICATION_JSON))
@@ -422,19 +423,19 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId2)))); .andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId2))));
assertThat(countActionStatusAll()).isEqualTo(8); assertThat(countActionStatusAll()).isEqualTo(8);
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(), mvc.perform(get("/{tenant}/controller/v1/{controller}", AccessContext.tenant(),
TestdataFactory.DEFAULT_CONTROLLER_ID)) TestdataFactory.DEFAULT_CONTROLLER_ID))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.cancelAction.href", .andExpect(jsonPath("$._links.cancelAction.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" equalTo("http://localhost/" + AccessContext.tenant() + "/controller/v1/"
+ TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction2.getId()))); + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction2.getId())));
// now lets return feedback for the second cancelation // now lets return feedback for the second cancelation
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction2.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction2.getId() + "/feedback", AccessContext.tenant())
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -444,7 +445,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
assertThat(deploymentManagement.findAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).orElseThrow()).isEqualTo(ds3); assertThat(deploymentManagement.findAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).orElseThrow()).isEqualTo(ds3);
mvc.perform( mvc.perform(
get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId3, get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId3,
tenantAware.getCurrentTenant())) AccessContext.tenant()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
assertThat(countActionStatusAll()).isEqualTo(10); assertThat(countActionStatusAll()).isEqualTo(10);
@@ -461,7 +462,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
mvc.perform(get( mvc.perform(get(
"/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction3.getId(), "/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction3.getId(),
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)) AccessContext.tenant()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().contentType(MediaType.APPLICATION_JSON))
@@ -471,7 +472,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// now lets return feedback for the third cancelation // now lets return feedback for the third cancelation
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction3.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction3.getId() + "/feedback", AccessContext.tenant())
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -502,13 +503,13 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// only 97 action status left // only 97 action status left
for (int i = 0; i < 98; i++) { for (int i = 0; i < 98; i++) {
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(feedback) + cancelAction.getId() + "/feedback", AccessContext.tenant()).content(feedback)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()); .andExpect(status().isOk());
} }
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(feedback) + cancelAction.getId() + "/feedback", AccessContext.tenant()).content(feedback)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andExpect(status().isTooManyRequests()); .andExpect(status().isTooManyRequests());
} }
@@ -523,25 +524,25 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// not allowed methods // not allowed methods
mvc.perform(put("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(put("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", AccessContext.tenant())
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())) + cancelAction.getId() + "/feedback", AccessContext.tenant()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())) + cancelAction.getId() + "/feedback", AccessContext.tenant()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
// bad content type // bad content type
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", AccessContext.tenant())
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_ATOM_XML) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_ATOM_XML)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -550,14 +551,14 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// bad body // bad body
String invalidFeedback = "{\"status\":{\"execution\":\"546456456\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"none\"]}}"; String invalidFeedback = "{\"status\":{\"execution\":\"546456456\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"none\"]}}";
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(invalidFeedback) + cancelAction.getId() + "/feedback", AccessContext.tenant()).content(invalidFeedback)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest()); .andExpect(status().isBadRequest());
// non existing target // non existing target
mvc.perform(post("/{tenant}/controller/v1/12345/cancelAction/" + cancelAction.getId() + "/feedback", mvc.perform(post("/{tenant}/controller/v1/12345/cancelAction/" + cancelAction.getId() + "/feedback",
tenantAware.getCurrentTenant()).content(getJsonClosedCancelActionFeedback()) AccessContext.tenant()).content(getJsonClosedCancelActionFeedback())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
@@ -565,14 +566,14 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// invalid action // invalid action
invalidFeedback = "{\"id\":\"sdfsdfsdfs\",\"status\":{\"execution\":\"closed\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"details\"]}}"; invalidFeedback = "{\"id\":\"sdfsdfsdfs\",\"status\":{\"execution\":\"closed\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"details\"]}}";
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(invalidFeedback) + cancelAction.getId() + "/feedback", AccessContext.tenant()).content(invalidFeedback)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest()); .andExpect(status().isBadRequest());
// finaly, get it right :) // finaly, get it right :)
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", AccessContext.tenant())
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())

View File

@@ -27,6 +27,7 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.eclipse.hawkbit.context.AccessContext;
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
@@ -62,7 +63,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
final Map<String, String> attributes = new HashMap<>(); final Map<String, String> attributes = new HashMap<>();
attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID); attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID);
mvc.perform(put(TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(TARGET1_CONFIG_DATA_PATH, AccessContext.tenant())
.content(jsonToCbor(JsonBuilder.configData(attributes).toString())) .content(jsonToCbor(JsonBuilder.configData(attributes).toString()))
.contentType(DdiRestConstants.MEDIA_TYPE_CBOR)) .contentType(DdiRestConstants.MEDIA_TYPE_CBOR))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -80,13 +81,13 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
final Target savedTarget = testdataFactory.createTarget("4712"); final Target savedTarget = testdataFactory.createTarget("4712");
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(MediaTypes.HAL_JSON)) mvc.perform(get("/{tenant}/controller/v1/4712", AccessContext.tenant()).accept(MediaTypes.HAL_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.configData.href", equalTo( .andExpect(jsonPath("$._links.configData.href", equalTo(
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/4712/configData"))); "http://localhost/" + AccessContext.tenant() + "/controller/v1/4712/configData")));
Thread.sleep(1); // is required: otherwise processing the next line is Thread.sleep(1); // is required: otherwise processing the next line is
// often too fast and // the following assert will fail // often too fast and // the following assert will fail
assertThat(targetManagement.getByControllerId("4712") assertThat(targetManagement.getByControllerId("4712")
@@ -102,7 +103,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
// to request the controller attributes again // to request the controller attributes again
assertThat(updateControllerAttributes.isRequestControllerAttributes()).isFalse(); assertThat(updateControllerAttributes.isRequestControllerAttributes()).isFalse();
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(MediaTypes.HAL_JSON)) mvc.perform(get("/{tenant}/controller/v1/4712", AccessContext.tenant()).accept(MediaTypes.HAL_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
@@ -122,7 +123,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
final Map<String, String> attributes = new HashMap<>(); final Map<String, String> attributes = new HashMap<>();
attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID); attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID);
mvc.perform(put(TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(TARGET1_CONFIG_DATA_PATH, AccessContext.tenant())
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
@@ -130,7 +131,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
// update // update
attributes.put("sdsds", "123412"); attributes.put("sdsds", "123412");
mvc.perform(put(TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(TARGET1_CONFIG_DATA_PATH, AccessContext.tenant())
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
@@ -150,12 +151,12 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
for (int i = 0; i < quotaManagement.getMaxAttributeEntriesPerTarget(); i++) { for (int i = 0; i < quotaManagement.getMaxAttributeEntriesPerTarget(); i++) {
attributes.put("dsafsdf" + i, "sdsds" + i); attributes.put("dsafsdf" + i, "sdsds" + i);
} }
mvc.perform(put(TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(TARGET1_CONFIG_DATA_PATH, AccessContext.tenant())
.content(JsonBuilder.configData(attributes).toString()) .content(JsonBuilder.configData(attributes).toString())
.contentType(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()); .andExpect(status().isOk());
mvc.perform(put(TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(TARGET1_CONFIG_DATA_PATH, AccessContext.tenant())
.content(JsonBuilder.configData(Map.of("on too many", "sdsds")).toString()) .content(JsonBuilder.configData(Map.of("on too many", "sdsds")).toString())
.contentType(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isTooManyRequests()) .andExpect(status().isTooManyRequests())
@@ -172,33 +173,33 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
testdataFactory.createTarget("4712"); testdataFactory.createTarget("4712");
// not allowed methods // not allowed methods
mvc.perform(post("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant())) mvc.perform(post("/{tenant}/controller/v1/4712/configData", AccessContext.tenant()))
.andDo(MockMvcResultPrinter.print()).// .andDo(MockMvcResultPrinter.print()).//
andExpect(status().isMethodNotAllowed()); andExpect(status().isMethodNotAllowed());
mvc.perform(get("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant())) mvc.perform(get("/{tenant}/controller/v1/4712/configData", AccessContext.tenant()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(delete("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant())) mvc.perform(delete("/{tenant}/controller/v1/4712/configData", AccessContext.tenant()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
// bad content type // bad content type
final Map<String, String> attributes = Map.of("dsafsdf", "sdsds"); final Map<String, String> attributes = Map.of("dsafsdf", "sdsds");
mvc.perform(put("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant()) mvc.perform(put("/{tenant}/controller/v1/4712/configData", AccessContext.tenant())
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaTypes.HAL_JSON)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaTypes.HAL_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isUnsupportedMediaType()); .andExpect(status().isUnsupportedMediaType());
// non existing target // non existing target
mvc.perform(put("/{tenant}/controller/v1/456456/configData", tenantAware.getCurrentTenant()) mvc.perform(put("/{tenant}/controller/v1/456456/configData", AccessContext.tenant())
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
// bad body // bad body
mvc.perform(put("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant()) mvc.perform(put("/{tenant}/controller/v1/4712/configData", AccessContext.tenant())
.content("{\"id\": \"51659181\"}").contentType(MediaType.APPLICATION_JSON)) .content("{\"id\": \"51659181\"}").contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest()); .andExpect(status().isBadRequest());
@@ -241,7 +242,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
private void putAndVerifyConfigDataWithKeyTooLong() throws Exception { private void putAndVerifyConfigDataWithKeyTooLong() throws Exception {
final Map<String, String> attributes = Collections.singletonMap(ATTRIBUTE_KEY_TOO_LONG, ATTRIBUTE_VALUE_VALID); final Map<String, String> attributes = Collections.singletonMap(ATTRIBUTE_KEY_TOO_LONG, ATTRIBUTE_VALUE_VALID);
mvc.perform(put(DdiConfigDataTest.TARGET2_CONFIG_DATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(DdiConfigDataTest.TARGET2_CONFIG_DATA_PATH, AccessContext.tenant())
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
.andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName()))) .andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName())))
@@ -250,7 +251,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
private void putAndVerifyConfigDataWithValueTooLong() throws Exception { private void putAndVerifyConfigDataWithValueTooLong() throws Exception {
final Map<String, String> attributes = Collections.singletonMap(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_TOO_LONG); final Map<String, String> attributes = Collections.singletonMap(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_TOO_LONG);
mvc.perform(put(DdiConfigDataTest.TARGET2_CONFIG_DATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(DdiConfigDataTest.TARGET2_CONFIG_DATA_PATH, AccessContext.tenant())
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
.andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName()))) .andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName())))
@@ -264,7 +265,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
"k1", "v1"); "k1", "v1");
// use an invalid update mode // use an invalid update mode
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, AccessContext.tenant())
.content(JsonBuilder.configData(attributes, "KJHGKJHGKJHG").toString()) .content(JsonBuilder.configData(attributes, "KJHGKJHGKJHG").toString())
.contentType(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -280,7 +281,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
"k1", "foo", "k1", "foo",
"k3", "bar"); "k3", "bar");
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, AccessContext.tenant())
.content(JsonBuilder.configData(removeAttributes, "remove").toString()) .content(JsonBuilder.configData(removeAttributes, "remove").toString())
.contentType(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -302,7 +303,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
final Map<String, String> mergeAttributes = Map.of( final Map<String, String> mergeAttributes = Map.of(
"k1", "v1_modified_again", "k1", "v1_modified_again",
"k4", "v4"); "k4", "v4");
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, AccessContext.tenant())
.content(JsonBuilder.configData(mergeAttributes, "merge").toString()) .content(JsonBuilder.configData(mergeAttributes, "merge").toString())
.contentType(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -325,7 +326,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
"k1", "v1_modified", "k1", "v1_modified",
"k2", "v2", "k2", "v2",
"k3", "v3"); "k3", "v3");
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, AccessContext.tenant())
.content(JsonBuilder.configData(replacementAttributes, "replace").toString()) .content(JsonBuilder.configData(replacementAttributes, "replace").toString())
.contentType(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -346,7 +347,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
"k1", "v1"); "k1", "v1");
// set the initial attributes // set the initial attributes
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, AccessContext.tenant())
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());

View File

@@ -23,6 +23,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.eclipse.hawkbit.context.AccessContext;
import org.eclipse.hawkbit.ddi.json.model.DdiActivateAutoConfirmation; import org.eclipse.hawkbit.ddi.json.model.DdiActivateAutoConfirmation;
import org.eclipse.hawkbit.ddi.json.model.DdiConfirmationFeedback; import org.eclipse.hawkbit.ddi.json.model.DdiConfirmationFeedback;
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
@@ -106,9 +107,9 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
final String expectedConfirmationBaseLink = String.format( final String expectedConfirmationBaseLink = String.format(
"/%s/controller/v1/%s/confirmationBase/%d", "/%s/controller/v1/%s/confirmationBase/%d",
tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, uaction.getId()); AccessContext.tenant(), DEFAULT_CONTROLLER_ID, uaction.getId());
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID) performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), AccessContext.tenant(), DEFAULT_CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.confirmationBase.href", containsString(expectedConfirmationBaseLink))) .andExpect(jsonPath("$._links.confirmationBase.href", containsString(expectedConfirmationBaseLink)))
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()); .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
@@ -150,11 +151,11 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
// get confirmation base // get confirmation base
performGet(CONFIRMATION_BASE_ACTION, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), performGet(CONFIRMATION_BASE_ACTION, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR),
status().isOk(), tenantAware.getCurrentTenant(), target.getControllerId(), action.getId().toString()); status().isOk(), AccessContext.tenant(), target.getControllerId(), action.getId().toString());
// get artifacts // get artifacts
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR),
status().isOk(), tenantAware.getCurrentTenant(), target.getControllerId(), status().isOk(), AccessContext.tenant(), target.getControllerId(),
String.valueOf(softwareModuleId)); String.valueOf(softwareModuleId));
} }
@@ -170,12 +171,12 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
final String controllerId = savedTarget.getControllerId(); final String controllerId = savedTarget.getControllerId();
final Action savedAction = deploymentManagement.findActiveActionsByTarget(controllerId, PAGE).getContent().get(0); final Action savedAction = deploymentManagement.findActiveActionsByTarget(controllerId, PAGE).getContent().get(0);
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), controllerId).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$._links.confirmationBase.href").doesNotExist()); .andExpect(jsonPath("$._links.confirmationBase.href").doesNotExist());
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), controllerId, savedAction.getId()) mvc.perform(get(CONFIRMATION_BASE_ACTION, AccessContext.tenant(), controllerId, savedAction.getId())
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
@@ -195,18 +196,18 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
final String controllerId = savedTarget.getControllerId(); final String controllerId = savedTarget.getControllerId();
final Action savedAction = deploymentManagement.findActiveActionsByTarget(controllerId, PAGE).getContent().get(0); final Action savedAction = deploymentManagement.findActiveActionsByTarget(controllerId, PAGE).getContent().get(0);
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), controllerId).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$._links.confirmationBase.href").exists()) .andExpect(jsonPath("$._links.confirmationBase.href").exists())
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()); .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), controllerId, savedAction.getId()) mvc.perform(get(CONFIRMATION_BASE_ACTION, AccessContext.tenant(), controllerId, savedAction.getId())
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), controllerId, savedAction.getId()) mvc.perform(get(DEPLOYMENT_BASE, AccessContext.tenant(), controllerId, savedAction.getId())
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
@@ -300,13 +301,13 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
final String confirmationBaseActionLink = String.format( final String confirmationBaseActionLink = String.format(
"/%s/controller/v1/%s/confirmationBase/%d", "/%s/controller/v1/%s/confirmationBase/%d",
tenantAware.getCurrentTenant(), controllerId, actionId); AccessContext.tenant(), controllerId, actionId);
final String activateAutoConfLink = String.format( final String activateAutoConfLink = String.format(
"/%s/controller/v1/%s/confirmationBase/activateAutoConfirm", "/%s/controller/v1/%s/confirmationBase/activateAutoConfirm",
tenantAware.getCurrentTenant(), controllerId); AccessContext.tenant(), controllerId);
mvc.perform(get(CONFIRMATION_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON)) mvc.perform(get(CONFIRMATION_BASE, AccessContext.tenant(), controllerId).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("autoConfirm.active", equalTo(Boolean.FALSE))) .andExpect(jsonPath("autoConfirm.active", equalTo(Boolean.FALSE)))
@@ -327,9 +328,9 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
final String deactivateAutoConfLink = String.format( final String deactivateAutoConfLink = String.format(
"/%s/controller/v1/%s/confirmationBase/deactivateAutoConfirm", "/%s/controller/v1/%s/confirmationBase/deactivateAutoConfirm",
tenantAware.getCurrentTenant(), controllerId); AccessContext.tenant(), controllerId);
mvc.perform(get(CONFIRMATION_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON)) mvc.perform(get(CONFIRMATION_BASE, AccessContext.tenant(), controllerId).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("autoConfirm.active", equalTo(Boolean.TRUE))) .andExpect(jsonPath("autoConfirm.active", equalTo(Boolean.TRUE)))
@@ -353,7 +354,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
final DdiActivateAutoConfirmation body = new DdiActivateAutoConfirmation(initiator, remark); final DdiActivateAutoConfirmation body = new DdiActivateAutoConfirmation(initiator, remark);
mvc.perform(post(ACTIVATE_AUTO_CONFIRM, tenantAware.getCurrentTenant(), controllerId) mvc.perform(post(ACTIVATE_AUTO_CONFIRM, AccessContext.tenant(), controllerId)
.content(getMapper().writeValueAsString(body)).contentType(MediaType.APPLICATION_JSON)) .content(getMapper().writeValueAsString(body)).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
@@ -374,7 +375,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
confirmationManagement.activateAutoConfirmation(controllerId, null, null); confirmationManagement.activateAutoConfirmation(controllerId, null, null);
mvc.perform(post(DEACTIVATE_AUTO_CONFIRM, tenantAware.getCurrentTenant(), controllerId)) mvc.perform(post(DEACTIVATE_AUTO_CONFIRM, AccessContext.tenant(), controllerId))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
@@ -414,15 +415,15 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
// asserts that deployment link is not available // asserts that deployment link is not available
final String expectedConfirmationBaseLink = String.format( final String expectedConfirmationBaseLink = String.format(
"/%s/controller/v1/%s/confirmationBase/%d", "/%s/controller/v1/%s/confirmationBase/%d",
tenantAware.getCurrentTenant(), controllerId, savedAction.getId()); AccessContext.tenant(), controllerId, savedAction.getId());
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), controllerId).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()) .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
.andExpect(jsonPath("$._links.confirmationBase.href", containsString(expectedConfirmationBaseLink))); .andExpect(jsonPath("$._links.confirmationBase.href", containsString(expectedConfirmationBaseLink)));
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), controllerId, savedAction.getId()) mvc.perform(get(DEPLOYMENT_BASE, AccessContext.tenant(), controllerId, savedAction.getId())
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
@@ -460,14 +461,14 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
.andExpect(status().isOk()); .andExpect(status().isOk());
// confirmationBase not available in RUNNING state anymore // confirmationBase not available in RUNNING state anymore
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), savedTarget.getControllerId(), mvc.perform(get(CONFIRMATION_BASE_ACTION, AccessContext.tenant(), savedTarget.getControllerId(),
savedAction.getId()).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) savedAction.getId()).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
// assert confirmed message against deploymentBase endpoint // assert confirmed message against deploymentBase endpoint
// this call will update the action due to retrieved action status update // this call will update the action due to retrieved action status update
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), savedTarget.getControllerId(), mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=2", AccessContext.tenant(), savedTarget.getControllerId(),
savedAction.getId()).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) savedAction.getId()).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
@@ -487,9 +488,9 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
private void verifyActionInDeploymentBaseState(final String controllerId, final long actionId) throws Exception { private void verifyActionInDeploymentBaseState(final String controllerId, final long actionId) throws Exception {
final String expectedDeploymentBaseLink = String.format( final String expectedDeploymentBaseLink = String.format(
"/%s/controller/v1/%s/deploymentBase/%d", "/%s/controller/v1/%s/deploymentBase/%d",
tenantAware.getCurrentTenant(), controllerId, actionId); AccessContext.tenant(), controllerId, actionId);
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), controllerId).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$._links.deploymentBase.href", containsString(expectedDeploymentBaseLink))) .andExpect(jsonPath("$._links.deploymentBase.href", containsString(expectedDeploymentBaseLink)))
@@ -502,18 +503,18 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
} }
private void verifyActionInConfirmationBaseState(final String controllerId, final long actionId) throws Exception { private void verifyActionInConfirmationBaseState(final String controllerId, final long actionId) throws Exception {
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), controllerId).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$._links.confirmationBase.href").exists()) .andExpect(jsonPath("$._links.confirmationBase.href").exists())
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()); .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), controllerId, actionId) mvc.perform(get(CONFIRMATION_BASE_ACTION, AccessContext.tenant(), controllerId, actionId)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), controllerId, actionId) mvc.perform(get(DEPLOYMENT_BASE, AccessContext.tenant(), controllerId, actionId)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
@@ -528,7 +529,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
final String feedback = getJsonConfirmationFeedback(confirmation, code, Collections.singletonList(message)); final String feedback = getJsonConfirmationFeedback(confirmation, code, Collections.singletonList(message));
return mvc.perform( return mvc.perform(
post(CONFIRMATION_FEEDBACK, tenantAware.getCurrentTenant(), target.getControllerId(), action.getId()) post(CONFIRMATION_FEEDBACK, AccessContext.tenant(), target.getControllerId(), action.getId())
.content(feedback).contentType(MediaType.APPLICATION_JSON)); .content(feedback).contentType(MediaType.APPLICATION_JSON));
} }
} }

View File

@@ -27,6 +27,7 @@ import java.util.concurrent.TimeUnit;
import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.JsonPath;
import org.assertj.core.api.Condition; import org.assertj.core.api.Condition;
import org.eclipse.hawkbit.context.AccessContext;
import org.eclipse.hawkbit.ddi.json.model.DdiResult; import org.eclipse.hawkbit.ddi.json.model.DdiResult;
import org.eclipse.hawkbit.ddi.json.model.DdiStatus; import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
@@ -96,11 +97,11 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
// get deployment base // get deployment base
performGet(DEPLOYMENT_BASE, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), status().isOk(), performGet(DEPLOYMENT_BASE, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), status().isOk(),
tenantAware.getCurrentTenant(), target.getControllerId(), action.getId().toString()); AccessContext.tenant(), target.getControllerId(), action.getId().toString());
// get artifacts // get artifacts
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR),
status().isOk(), tenantAware.getCurrentTenant(), target.getControllerId(), status().isOk(), AccessContext.tenant(), target.getControllerId(),
String.valueOf(softwareModuleId)); String.valueOf(softwareModuleId));
final byte[] feedback = jsonToCbor(getJsonProceedingDeploymentActionFeedback()); final byte[] feedback = jsonToCbor(getJsonProceedingDeploymentActionFeedback());
@@ -115,7 +116,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
@Test @Test
void artifactsNotFound() throws Exception { void artifactsNotFound() throws Exception {
final Target target = testdataFactory.createTarget(); final Target target = testdataFactory.createTarget();
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isNotFound(), tenantAware.getCurrentTenant(), performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isNotFound(), AccessContext.tenant(),
target.getControllerId(), "1"); target.getControllerId(), "1");
} }
@@ -132,7 +133,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
assignDistributionSet(distributionSet.getId(), target.getName()); assignDistributionSet(distributionSet.getId(), target.getName());
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(), AccessContext.tenant(),
target.getControllerId(), softwareModuleId.toString()) target.getControllerId(), softwareModuleId.toString())
.andExpect(jsonPath("$", hasSize(3))) .andExpect(jsonPath("$", hasSize(3)))
.andExpect(jsonPath("$.[?(@.filename=='filename0')]", hasSize(1))) .andExpect(jsonPath("$.[?(@.filename=='filename0')]", hasSize(1)))
@@ -174,7 +175,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
// Run test // Run test
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), AccessContext.tenant(),
DEFAULT_CONTROLLER_ID) DEFAULT_CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath( .andExpect(jsonPath(
@@ -209,14 +210,14 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
ActionType.TIMEFORCED, System.currentTimeMillis() + 2_000)); ActionType.TIMEFORCED, System.currentTimeMillis() + 2_000));
MvcResult mvcResult = performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), MvcResult mvcResult = performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(),
tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID) AccessContext.tenant(), DEFAULT_CONTROLLER_ID)
.andReturn(); .andReturn();
final String urlBeforeSwitch = JsonPath.compile("_links.deploymentBase.href") final String urlBeforeSwitch = JsonPath.compile("_links.deploymentBase.href")
.read(mvcResult.getResponse().getContentAsString()).toString(); .read(mvcResult.getResponse().getContentAsString()).toString();
// Time is not yet over, so we should see the same URL // Time is not yet over, so we should see the same URL
mvcResult = performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), mvcResult = performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), AccessContext.tenant(),
DEFAULT_CONTROLLER_ID) DEFAULT_CONTROLLER_ID)
.andReturn(); .andReturn();
assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString()) assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
@@ -226,7 +227,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
// After the time is over we should see a new etag // After the time is over we should see a new etag
TimeUnit.MILLISECONDS.sleep(2_000); TimeUnit.MILLISECONDS.sleep(2_000);
mvcResult = performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), mvcResult = performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), AccessContext.tenant(),
DEFAULT_CONTROLLER_ID) DEFAULT_CONTROLLER_ID)
.andReturn(); .andReturn();
@@ -272,7 +273,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
// Run test // Run test
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), AccessContext.tenant(),
DEFAULT_CONTROLLER_ID) DEFAULT_CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href", .andExpect(jsonPath("$._links.deploymentBase.href",
@@ -326,7 +327,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
// Run test // Run test
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), AccessContext.tenant(),
DEFAULT_CONTROLLER_ID) DEFAULT_CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href", .andExpect(jsonPath("$._links.deploymentBase.href",
@@ -388,7 +389,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
// Run test // Run test
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID) performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), AccessContext.tenant(), DEFAULT_CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href", .andExpect(jsonPath("$._links.deploymentBase.href",
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString())))); startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
@@ -416,25 +417,25 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final Target target = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID); final Target target = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID);
// not allowed methods // not allowed methods
mvc.perform(post(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "1")) mvc.perform(post(DEPLOYMENT_BASE, AccessContext.tenant(), DEFAULT_CONTROLLER_ID, "1"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(put(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "1")) mvc.perform(put(DEPLOYMENT_BASE, AccessContext.tenant(), DEFAULT_CONTROLLER_ID, "1"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(delete(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "1")) mvc.perform(delete(DEPLOYMENT_BASE, AccessContext.tenant(), DEFAULT_CONTROLLER_ID, "1"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
// non existing target // non existing target
mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "not-existing", "1")) mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_BASE, AccessContext.tenant(), "not-existing", "1"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
// no deployment // no deployment
mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "1")) mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_BASE, AccessContext.tenant(), DEFAULT_CONTROLLER_ID, "1"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
@@ -443,12 +444,12 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final DistributionSet savedSet = testdataFactory.createDistributionSet(""); final DistributionSet savedSet = testdataFactory.createDistributionSet("");
final Long actionId = getFirstAssignedActionId(assignDistributionSet(savedSet, toAssign)); final Long actionId = getFirstAssignedActionId(assignDistributionSet(savedSet, toAssign));
mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_BASE, AccessContext.tenant(), DEFAULT_CONTROLLER_ID,
actionId)) actionId))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
mvc.perform(MockMvcRequestBuilders mvc.perform(MockMvcRequestBuilders
.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, actionId) .get(DEPLOYMENT_BASE, AccessContext.tenant(), DEFAULT_CONTROLLER_ID, actionId)
.accept(MediaType.APPLICATION_ATOM_XML)) .accept(MediaType.APPLICATION_ATOM_XML))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotAcceptable()); .andExpect(status().isNotAcceptable());
@@ -643,16 +644,16 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
DdiResult.FinalResult.NONE, Collections.singletonList("")), status().isNotFound()); DdiResult.FinalResult.NONE, Collections.singletonList("")), status().isNotFound());
// not allowed methods // not allowed methods
mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_FEEDBACK, AccessContext.tenant(),
DEFAULT_CONTROLLER_ID, "2")) DEFAULT_CONTROLLER_ID, "2"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(put(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "2")) mvc.perform(put(DEPLOYMENT_FEEDBACK, AccessContext.tenant(), DEFAULT_CONTROLLER_ID, "2"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(delete(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "2")) mvc.perform(delete(DEPLOYMENT_FEEDBACK, AccessContext.tenant(), DEFAULT_CONTROLLER_ID, "2"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
} }

View File

@@ -27,6 +27,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.eclipse.hawkbit.context.AccessContext;
import org.eclipse.hawkbit.ddi.json.model.DdiResult; import org.eclipse.hawkbit.ddi.json.model.DdiResult;
import org.eclipse.hawkbit.ddi.json.model.DdiStatus; import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
@@ -90,11 +91,11 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// get installed base // get installed base
performGet(INSTALLED_BASE, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), status().isOk(), performGet(INSTALLED_BASE, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), status().isOk(),
tenantAware.getCurrentTenant(), target.getControllerId(), actionId.toString()); AccessContext.tenant(), target.getControllerId(), actionId.toString());
// get artifacts // get artifacts
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR),
status().isOk(), tenantAware.getCurrentTenant(), target.getControllerId(), status().isOk(), AccessContext.tenant(), target.getControllerId(),
String.valueOf(softwareModuleId)); String.valueOf(softwareModuleId));
} }
@@ -153,7 +154,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// Run test with 1st action // Run test with 1st action
final Long actionId1 = getFirstAssignedActionId( final Long actionId1 = getFirstAssignedActionId(
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT)); assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), CONTROLLER_ID) performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), AccessContext.tenant(), CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist()) .andExpect(jsonPath("$._links.installedBase.href").doesNotExist())
.andExpect(jsonPath("$._links.deploymentBase.href", .andExpect(jsonPath("$._links.deploymentBase.href",
@@ -172,7 +173,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// Run test with 2nd action // Run test with 2nd action
final Long actionId2 = getFirstAssignedActionId( final Long actionId2 = getFirstAssignedActionId(
assignDistributionSet(ds2.getId(), target.getControllerId(), Action.ActionType.FORCED)); assignDistributionSet(ds2.getId(), target.getControllerId(), Action.ActionType.FORCED));
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), CONTROLLER_ID) performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), AccessContext.tenant(), CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.installedBase.href", .andExpect(jsonPath("$._links.installedBase.href",
startsWith(installedBaseLink(CONTROLLER_ID, actionId1.toString())))) startsWith(installedBaseLink(CONTROLLER_ID, actionId1.toString()))))
@@ -189,7 +190,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds2, artifact2, artifactSignature2, getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds2, artifact2, artifactSignature2,
actionId2, findFirstModuleByType(ds2, osType).orElseThrow().getId(), Action.ActionType.FORCED); actionId2, findFirstModuleByType(ds2, osType).orElseThrow().getId(), Action.ActionType.FORCED);
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), CONTROLLER_ID) performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), AccessContext.tenant(), CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.installedBase.href", .andExpect(jsonPath("$._links.installedBase.href",
startsWith(installedBaseLink(CONTROLLER_ID, actionId2.toString())))) startsWith(installedBaseLink(CONTROLLER_ID, actionId2.toString()))))
@@ -238,7 +239,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
status().isOk()); status().isOk());
// Test: latest succeeded action is returned in installedBase // Test: latest succeeded action is returned in installedBase
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), CONTROLLER_ID) performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), AccessContext.tenant(), CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.installedBase.href", .andExpect(jsonPath("$._links.installedBase.href",
startsWith(installedBaseLink(CONTROLLER_ID, actionId3.toString())))) startsWith(installedBaseLink(CONTROLLER_ID, actionId3.toString()))))
@@ -248,11 +249,11 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
actionId3, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT); actionId3, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT);
// cancelled action are not accessible // cancelled action are not accessible
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(), mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, AccessContext.tenant(), target.getControllerId(),
actionId1.toString())) actionId1.toString()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(), mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, AccessContext.tenant(), target.getControllerId(),
actionId2.toString())) actionId2.toString()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
@@ -297,7 +298,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// Test: the succeeded action is returned in installedBase instead of the latest // Test: the succeeded action is returned in installedBase instead of the latest
// cancelled action // cancelled action
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), CONTROLLER_ID) performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), AccessContext.tenant(), CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.installedBase.href", .andExpect(jsonPath("$._links.installedBase.href",
startsWith(installedBaseLink(CONTROLLER_ID, actionId1.toString())))) startsWith(installedBaseLink(CONTROLLER_ID, actionId1.toString()))))
@@ -307,11 +308,11 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
actionId1, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT); actionId1, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT);
// cancelled action are not accessible // cancelled action are not accessible
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(), mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, AccessContext.tenant(), target.getControllerId(),
actionId2.toString())) actionId2.toString()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(), mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, AccessContext.tenant(), target.getControllerId(),
actionId3.toString())) actionId3.toString()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
@@ -351,7 +352,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
status().isOk()); status().isOk());
// Test: the succeeded action is returned in installedBase instead of the latest cancelled action // Test: the succeeded action is returned in installedBase instead of the latest cancelled action
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), CONTROLLER_ID) performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), AccessContext.tenant(), CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.installedBase.href", .andExpect(jsonPath("$._links.installedBase.href",
startsWith(installedBaseLink(CONTROLLER_ID, actionId1.toString())))) startsWith(installedBaseLink(CONTROLLER_ID, actionId1.toString()))))
@@ -362,11 +363,11 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
actionId1, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT); actionId1, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT);
// cancelled action are not accessible // cancelled action are not accessible
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(), mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, AccessContext.tenant(), target.getControllerId(),
actionId2.toString())) actionId2.toString()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(), mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, AccessContext.tenant(), target.getControllerId(),
actionId3.toString())) actionId3.toString()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
@@ -382,16 +383,16 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds, target)); final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds, target));
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), CONTROLLER_ID) performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), AccessContext.tenant(), CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist()) .andExpect(jsonPath("$._links.installedBase.href").doesNotExist())
.andExpect(jsonPath("$._links.deploymentBase.href", .andExpect(jsonPath("$._links.deploymentBase.href",
startsWith(deploymentBaseLink(CONTROLLER_ID, actionId.toString())))); startsWith(deploymentBaseLink(CONTROLLER_ID, actionId.toString()))));
performGet(DEPLOYMENT_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(DEPLOYMENT_BASE, MediaType.APPLICATION_JSON, status().isOk(), AccessContext.tenant(),
target.getControllerId(), actionId.toString()); target.getControllerId(), actionId.toString());
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(), mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, AccessContext.tenant(), target.getControllerId(),
actionId.toString())) actionId.toString()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
@@ -413,7 +414,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
postDeploymentFeedback(target.getControllerId(), actionId, getJsonClosedDeploymentActionFeedback(), status().isOk()); postDeploymentFeedback(target.getControllerId(), actionId, getJsonClosedDeploymentActionFeedback(), status().isOk());
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(), performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(),
tenantAware.getCurrentTenant(), target.getControllerId(), softwareModuleId.toString()) AccessContext.tenant(), target.getControllerId(), softwareModuleId.toString())
.andExpect(jsonPath("$", hasSize(3))) .andExpect(jsonPath("$", hasSize(3)))
.andExpect(jsonPath("$.[?(@.filename=='filename0')]", hasSize(1))) .andExpect(jsonPath("$.[?(@.filename=='filename0')]", hasSize(1)))
.andExpect(jsonPath("$.[?(@.filename=='filename1')]", hasSize(1))) .andExpect(jsonPath("$.[?(@.filename=='filename1')]", hasSize(1)))
@@ -454,13 +455,13 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// Run test // Run test
final ResultActions resultActions = performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), final ResultActions resultActions = performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(),
tenantAware.getCurrentTenant(), target.getControllerId()); AccessContext.tenant(), target.getControllerId());
resultActions.andDo(MockMvcResultPrinter.print()) resultActions.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()) .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
.andExpect(jsonPath("$._links.installedBase.href", containsString(String.format( .andExpect(jsonPath("$._links.installedBase.href", containsString(String.format(
"/%s/controller/v1/%s/installedBase/%d", "/%s/controller/v1/%s/installedBase/%d",
tenantAware.getCurrentTenant(), target.getControllerId(), actionId)))); AccessContext.tenant(), target.getControllerId(), actionId))));
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, artifactSignature, getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, artifactSignature,
actionId, findFirstModuleByType(ds, osType).orElseThrow().getId(), actionType); actionId, findFirstModuleByType(ds, osType).orElseThrow().getId(), actionType);
@@ -499,7 +500,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
final Long actionId = getFirstAssignedActionId( final Long actionId = getFirstAssignedActionId(
assignDistributionSet(ds.getId(), target.getControllerId(), Action.ActionType.DOWNLOAD_ONLY)); assignDistributionSet(ds.getId(), target.getControllerId(), Action.ActionType.DOWNLOAD_ONLY));
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), AccessContext.tenant(),
target.getControllerId()) target.getControllerId())
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
@@ -510,7 +511,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
postDeploymentFeedback(target.getControllerId(), actionId, getJsonDownloadedDeploymentActionFeedback(), status().isOk()); postDeploymentFeedback(target.getControllerId(), actionId, getJsonDownloadedDeploymentActionFeedback(), status().isOk());
// Test // Test
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), AccessContext.tenant(),
target.getControllerId()) target.getControllerId())
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
@@ -530,7 +531,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
final Long actionId = getFirstAssignedActionId( final Long actionId = getFirstAssignedActionId(
assignDistributionSet(ds.getId(), target.getControllerId(), actionType)); assignDistributionSet(ds.getId(), target.getControllerId(), actionType));
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), AccessContext.tenant(),
target.getControllerId()) target.getControllerId())
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
@@ -546,7 +547,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
status().isOk()); status().isOk());
// Test // Test
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), AccessContext.tenant(),
target.getControllerId()) target.getControllerId())
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
@@ -581,14 +582,14 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// Test // Test
// for zero input no action history is returned // for zero input no action history is returned
mvc.perform(get(INSTALLED_BASE + "?actionHistory", tenantAware.getCurrentTenant(), 911, savedAction.getId()) mvc.perform(get(INSTALLED_BASE + "?actionHistory", AccessContext.tenant(), 911, savedAction.getId())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$.actionHistory.messages").doesNotExist()); .andExpect(jsonPath("$.actionHistory.messages").doesNotExist());
// depending on given query parameter value, only the latest messages are returned // depending on given query parameter value, only the latest messages are returned
mvc.perform(get(INSTALLED_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), 911, savedAction.getId()) mvc.perform(get(INSTALLED_BASE + "?actionHistory=2", AccessContext.tenant(), 911, savedAction.getId())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
@@ -598,7 +599,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
jsonPath("$.actionHistory.messages", not(hasItem(containsString("Installation scheduled"))))); jsonPath("$.actionHistory.messages", not(hasItem(containsString("Installation scheduled")))));
// for negative input the entire action history is returned // for negative input the entire action history is returned
mvc.perform(get(INSTALLED_BASE + "?actionHistory=-3", tenantAware.getCurrentTenant(), 911, savedAction.getId()) mvc.perform(get(INSTALLED_BASE + "?actionHistory=-3", AccessContext.tenant(), 911, savedAction.getId())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
@@ -615,25 +616,25 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
final Target target = testdataFactory.createTarget(CONTROLLER_ID); final Target target = testdataFactory.createTarget(CONTROLLER_ID);
// not allowed methods // not allowed methods
mvc.perform(post(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, "1")) mvc.perform(post(INSTALLED_BASE, AccessContext.tenant(), CONTROLLER_ID, "1"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(put(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, "1")) mvc.perform(put(INSTALLED_BASE, AccessContext.tenant(), CONTROLLER_ID, "1"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(delete(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, "1")) mvc.perform(delete(INSTALLED_BASE, AccessContext.tenant(), CONTROLLER_ID, "1"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
// non existing target // non existing target
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), "not-existing", "1")) mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, AccessContext.tenant(), "not-existing", "1"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
// no deployment // no deployment
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, "1")) mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, AccessContext.tenant(), CONTROLLER_ID, "1"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
@@ -643,10 +644,10 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
final Long actionId = getFirstAssignedActionId(assignDistributionSet(savedSet, toAssign)); final Long actionId = getFirstAssignedActionId(assignDistributionSet(savedSet, toAssign));
postDeploymentFeedback(CONTROLLER_ID, actionId, getJsonClosedCancelActionFeedback(), status().isOk()); postDeploymentFeedback(CONTROLLER_ID, actionId, getJsonClosedCancelActionFeedback(), status().isOk());
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, actionId)) mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, AccessContext.tenant(), CONTROLLER_ID, actionId))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, actionId) mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, AccessContext.tenant(), CONTROLLER_ID, actionId)
.accept(MediaType.APPLICATION_ATOM_XML)) .accept(MediaType.APPLICATION_ATOM_XML))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotAcceptable()); .andExpect(status().isNotAcceptable());

View File

@@ -10,8 +10,8 @@
package org.eclipse.hawkbit.ddi.rest.resource; package org.eclipse.hawkbit.ddi.rest.resource;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.hawkbit.im.authentication.SpPermission.TENANT_CONFIGURATION; import static org.eclipse.hawkbit.auth.SpPermission.TENANT_CONFIGURATION;
import static org.eclipse.hawkbit.im.authentication.SpRole.CONTROLLER_ROLE_ANONYMOUS; import static org.eclipse.hawkbit.auth.SpRole.CONTROLLER_ROLE_ANONYMOUS;
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.callAs; import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.callAs;
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.getAs; import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.getAs;
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.withController; import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.withController;
@@ -37,10 +37,11 @@ import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import org.eclipse.hawkbit.auth.SpPermission;
import org.eclipse.hawkbit.context.AccessContext;
import org.eclipse.hawkbit.ddi.json.model.DdiResult; import org.eclipse.hawkbit.ddi.json.model.DdiResult;
import org.eclipse.hawkbit.ddi.json.model.DdiStatus; import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent; import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent; import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetPollEvent; import org.eclipse.hawkbit.repository.event.remote.TargetPollEvent;
@@ -65,7 +66,7 @@ import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties; import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
import org.eclipse.hawkbit.util.IpUtil; import org.eclipse.hawkbit.utils.IpUtil;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.MediaTypes; import org.springframework.hateoas.MediaTypes;
@@ -93,7 +94,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
*/ */
@Test @Test
void rootPollResourceCbor() throws Exception { void rootPollResourceCbor() throws Exception {
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711).accept(DdiRestConstants.MEDIA_TYPE_CBOR)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), 4711).accept(DdiRestConstants.MEDIA_TYPE_CBOR))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(content().contentType(DdiRestConstants.MEDIA_TYPE_CBOR)) .andExpect(content().contentType(DdiRestConstants.MEDIA_TYPE_CBOR))
.andExpect(status().isOk()); .andExpect(status().isOk());
@@ -104,7 +105,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
*/ */
@Test @Test
void apiReturnsJSONByDefault() throws Exception { void apiReturnsJSONByDefault() throws Exception {
final MvcResult result = mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711)) final MvcResult result = mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), 4711))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
@@ -132,7 +133,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
// make a poll, audit information should not be changed, run as controller principal! // make a poll, audit information should not be changed, run as controller principal!
callAs(withController("controller", CONTROLLER_ROLE_ANONYMOUS), callAs(withController("controller", CONTROLLER_ROLE_ANONYMOUS),
() -> { () -> {
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownTargetControllerId)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), knownTargetControllerId))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
return null; return null;
@@ -205,7 +206,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
withPollingTime("00:02:00", () -> callAs( withPollingTime("00:02:00", () -> callAs(
withUser("controller", CONTROLLER_ROLE_ANONYMOUS), withUser("controller", CONTROLLER_ROLE_ANONYMOUS),
() -> { () -> {
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), 4711))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
@@ -226,7 +227,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1), @Expect(type = TenantConfigurationCreatedEvent.class, count = 1),
@Expect(type = TenantConfigurationDeletedEvent.class, count = 1) }) @Expect(type = TenantConfigurationDeletedEvent.class, count = 1) })
void pollWithModifiedWithOverridesGlobalPollingTime() throws Exception { void pollWithModifiedWithOverridesGlobalPollingTime() throws Exception {
SecurityContextSwitch.callAsPrivileged(() -> { SecurityContextSwitch.asPrivileged(() -> {
final Target target = testdataFactory.createTarget("not4711"); final Target target = testdataFactory.createTarget("not4711");
targetManagement.assignTargetsWithGroup("Europe", List.of(target.getControllerId())); targetManagement.assignTargetsWithGroup("Europe", List.of(target.getControllerId()));
return null; return null;
@@ -235,13 +236,13 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
withPollingTime("00:02:00, controllerid == 4711 -> 00:01:00, group == 'Europe' -> 00:05:05", () -> callAs( withPollingTime("00:02:00, controllerid == 4711 -> 00:01:00, group == 'Europe' -> 00:05:05", () -> callAs(
withUser("controller", CONTROLLER_ROLE_ANONYMOUS), withUser("controller", CONTROLLER_ROLE_ANONYMOUS),
() -> { () -> {
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), 4711))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))); .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")));
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), "not4711")) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), "not4711"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
@@ -268,7 +269,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
@Expect(type = TargetAttributesRequestedEvent.class, count = 1) }) @Expect(type = TargetAttributesRequestedEvent.class, count = 1) })
void rootRsNotModified() throws Exception { void rootRsNotModified() throws Exception {
final String controllerId = "4711"; final String controllerId = "4711";
final String etag = mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId)) final String etag = mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), controllerId))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
@@ -276,7 +277,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andReturn().getResponse() .andReturn().getResponse()
.getHeader("ETag"); .getHeader("ETag");
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).header("If-None-Match", etag)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), controllerId).header("If-None-Match", etag))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotModified()); .andExpect(status().isNotModified());
@@ -286,7 +287,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
final Action updateAction = deploymentManagement.findActiveActionsByTarget(target.getControllerId(), PAGE).getContent().get(0); final Action updateAction = deploymentManagement.findActiveActionsByTarget(target.getControllerId(), PAGE).getContent().get(0);
final String etagWithFirstUpdate = mvc final String etagWithFirstUpdate = mvc
.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId) .perform(get(CONTROLLER_BASE, AccessContext.tenant(), controllerId)
.header("If-None-Match", etag) .header("If-None-Match", etag)
.accept(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON)
.with(new RequestOnHawkbitDefaultPortPostProcessor())) .with(new RequestOnHawkbitDefaultPortPostProcessor()))
@@ -299,7 +300,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
startsWith(deploymentBaseLink("4711", updateAction.getId().toString())))) startsWith(deploymentBaseLink("4711", updateAction.getId().toString()))))
.andReturn().getResponse().getHeader("ETag"); .andReturn().getResponse().getHeader("ETag");
assertThat(etagWithFirstUpdate).isNotNull(); assertThat(etagWithFirstUpdate).isNotNull();
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).header("If-None-Match", mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), controllerId).header("If-None-Match",
etagWithFirstUpdate).with(new RequestOnHawkbitDefaultPortPostProcessor())) etagWithFirstUpdate).with(new RequestOnHawkbitDefaultPortPostProcessor()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotModified()); .andExpect(status().isNotModified());
@@ -311,7 +312,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
// as the update was installed, and we always receive the installed action, the // as the update was installed, and we always receive the installed action, the
// original state cannot be restored // original state cannot be restored
final String etagAfterInstallation = mvc final String etagAfterInstallation = mvc
.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId) .perform(get(CONTROLLER_BASE, AccessContext.tenant(), controllerId)
.header("If-None-Match", etag).accept(MediaType.APPLICATION_JSON) .header("If-None-Match", etag).accept(MediaType.APPLICATION_JSON)
.with(new RequestOnHawkbitDefaultPortPostProcessor())) .with(new RequestOnHawkbitDefaultPortPostProcessor()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -327,7 +328,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
final DistributionSet ds2 = testdataFactory.createDistributionSet("2"); final DistributionSet ds2 = testdataFactory.createDistributionSet("2");
assignDistributionSet(ds2.getId(), controllerId); assignDistributionSet(ds2.getId(), controllerId);
final Action updateAction2 = deploymentManagement.findActiveActionsByTarget(target.getControllerId(), PAGE).getContent().get(0); final Action updateAction2 = deploymentManagement.findActiveActionsByTarget(target.getControllerId(), PAGE).getContent().get(0);
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), controllerId)
.header("If-None-Match", etagAfterInstallation).accept(MediaType.APPLICATION_JSON) .header("If-None-Match", etagAfterInstallation).accept(MediaType.APPLICATION_JSON)
.with(new RequestOnHawkbitDefaultPortPostProcessor())) .with(new RequestOnHawkbitDefaultPortPostProcessor()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -355,7 +356,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
testdataFactory.createTarget(controllerId); testdataFactory.createTarget(controllerId);
assertThat(targetManagement.getByControllerId(controllerId).getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN); assertThat(targetManagement.getByControllerId(controllerId).getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN);
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), controllerId))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
@@ -382,7 +383,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
// make a poll, audit information should be set on plug and play // make a poll, audit information should be set on plug and play
callAs(withController("controller", CONTROLLER_ROLE_ANONYMOUS), callAs(withController("controller", CONTROLLER_ROLE_ANONYMOUS),
() -> { () -> {
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownControllerId1)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), knownControllerId1))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
return null; return null;
@@ -408,7 +409,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
securityProperties.getClients().setTrackRemoteIp(false); securityProperties.getClients().setTrackRemoteIp(false);
// test // test
final String knownControllerId1 = "0815"; final String knownControllerId1 = "0815";
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownControllerId1)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), knownControllerId1))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
// verify // verify
@@ -468,7 +469,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
final Target savedTarget = testdataFactory.createTarget("922"); final Target savedTarget = testdataFactory.createTarget("922");
final Map<String, String> attributes = Collections.singletonMap("AttributeKey", "AttributeValue"); final Map<String, String> attributes = Collections.singletonMap("AttributeKey", "AttributeValue");
assertThatAttributesUpdateIsRequested(savedTarget.getControllerId()); assertThatAttributesUpdateIsRequested(savedTarget.getControllerId());
mvc.perform(put(CONTROLLER_BASE + "/configData", tenantAware.getCurrentTenant(), savedTarget.getControllerId()) mvc.perform(put(CONTROLLER_BASE + "/configData", AccessContext.tenant(), savedTarget.getControllerId())
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()); .andExpect(status().isOk());
assertThatAttributesUpdateIsNotRequested(savedTarget.getControllerId()); assertThatAttributesUpdateIsNotRequested(savedTarget.getControllerId());
@@ -505,7 +506,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "success", TARGET_COMPLETED_INSTALLATION_MSG) sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "success", TARGET_COMPLETED_INSTALLATION_MSG)
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), 911, savedAction.getId()) mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=2", AccessContext.tenant(), 911, savedAction.getId())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
@@ -543,12 +544,12 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "success", TARGET_COMPLETED_INSTALLATION_MSG) sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "success", TARGET_COMPLETED_INSTALLATION_MSG)
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=0", tenantAware.getCurrentTenant(), 911, savedAction.getId()) mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=0", AccessContext.tenant(), 911, savedAction.getId())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$.actionHistory.messages").doesNotExist()); .andExpect(jsonPath("$.actionHistory.messages").doesNotExist());
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory", tenantAware.getCurrentTenant(), 911, savedAction.getId()) mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory", AccessContext.tenant(), 911, savedAction.getId())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
@@ -584,7 +585,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "success", TARGET_COMPLETED_INSTALLATION_MSG) sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "success", TARGET_COMPLETED_INSTALLATION_MSG)
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=-1", tenantAware.getCurrentTenant(), 911, savedAction.getId()) mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=-1", AccessContext.tenant(), 911, savedAction.getId())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
@@ -602,7 +603,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
getAs(withUser("tenantadmin", TENANT_CONFIGURATION), getAs(withUser("tenantadmin", TENANT_CONFIGURATION),
() -> { () -> {
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME, "00:05:00"); tenantConfigurationManagement().addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME, "00:05:00");
return null; return null;
}); });
@@ -657,7 +658,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
mvc.perform(get(CONTROLLER_BASE, "default-tenant", "1911")).andExpect(status().isOk()); mvc.perform(get(CONTROLLER_BASE, "default-tenant", "1911")).andExpect(status().isOk());
final Action action = deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE).getContent().get(0); final Action action = deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE).getContent().get(0);
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "1911", action.getId()).accept(MediaType.APPLICATION_JSON)) mvc.perform(get(DEPLOYMENT_BASE, AccessContext.tenant(), "1911", action.getId()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$.deployment.download", equalTo("forced"))) .andExpect(jsonPath("$.deployment.download", equalTo("forced")))
@@ -678,7 +679,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
mvc.perform(get(CONTROLLER_BASE, "default-tenant", "1911")).andExpect(status().isOk()); mvc.perform(get(CONTROLLER_BASE, "default-tenant", "1911")).andExpect(status().isOk());
final Action action = deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE).getContent().get(0); final Action action = deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE).getContent().get(0);
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "1911", action.getId()).accept(MediaType.APPLICATION_JSON)) mvc.perform(get(DEPLOYMENT_BASE, AccessContext.tenant(), "1911", action.getId()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$.deployment.download", equalTo("forced"))) .andExpect(jsonPath("$.deployment.download", equalTo("forced")))
@@ -709,7 +710,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
@Test @Test
void rootRsWithInvalidControllerId() throws Exception { void rootRsWithInvalidControllerId() throws Exception {
final String invalidControllerId = randomString(Target.CONTROLLER_ID_MAX_SIZE + 1); final String invalidControllerId = randomString(Target.CONTROLLER_ID_MAX_SIZE + 1);
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), invalidControllerId)).andExpect(status().isBadRequest()); mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), invalidControllerId)).andExpect(status().isBadRequest());
} }
private void assertAttributesUpdateNotRequestedAfterFailedDeployment(Target target, final DistributionSet ds) throws Exception { private void assertAttributesUpdateNotRequestedAfterFailedDeployment(Target target, final DistributionSet ds) throws Exception {
@@ -727,13 +728,13 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
} }
private void assertThatAttributesUpdateIsRequested(final String targetControllerId) throws Exception { private void assertThatAttributesUpdateIsRequested(final String targetControllerId) throws Exception {
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), targetControllerId).accept(MediaType.APPLICATION_JSON)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), targetControllerId).accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$._links.configData.href").isNotEmpty()); .andExpect(jsonPath("$._links.configData.href").isNotEmpty());
} }
private void assertThatAttributesUpdateIsNotRequested(final String targetControllerId) throws Exception { private void assertThatAttributesUpdateIsNotRequested(final String targetControllerId) throws Exception {
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), targetControllerId).accept(MediaType.APPLICATION_JSON)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), targetControllerId).accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$._links.configData").doesNotExist()); .andExpect(jsonPath("$._links.configData").doesNotExist());
} }
@@ -749,7 +750,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
final String feedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.valueOf(execution.toUpperCase()), final String feedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.valueOf(execution.toUpperCase()),
DdiResult.FinalResult.valueOf(finished.toUpperCase()), Collections.singletonList(message)); DdiResult.FinalResult.valueOf(finished.toUpperCase()), Collections.singletonList(message));
return mvc.perform(post(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), target.getControllerId(), action.getId()) return mvc.perform(post(DEPLOYMENT_FEEDBACK, AccessContext.tenant(), target.getControllerId(), action.getId())
.content(feedback).contentType(MediaType.APPLICATION_JSON)); .content(feedback).contentType(MediaType.APPLICATION_JSON));
} }
@@ -761,8 +762,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
private void assertDeploymentActionIsExposedToTarget(final String controllerId, final long expectedActionId) throws Exception { private void assertDeploymentActionIsExposedToTarget(final String controllerId, final long expectedActionId) throws Exception {
final String expectedDeploymentBaseLink = String.format( final String expectedDeploymentBaseLink = String.format(
"/%s/controller/v1/%s/deploymentBase/%d", "/%s/controller/v1/%s/deploymentBase/%d",
tenantAware.getCurrentTenant(), controllerId, expectedActionId); AccessContext.tenant(), controllerId, expectedActionId);
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON)) mvc.perform(get(CONTROLLER_BASE, AccessContext.tenant(), controllerId).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$._links.deploymentBase.href", containsString(expectedDeploymentBaseLink))); .andExpect(jsonPath("$._links.deploymentBase.href", containsString(expectedDeploymentBaseLink)));
@@ -771,7 +772,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
private void withPollingTime(final String pollingTime, final Callable<Void> runnable) throws Exception { private void withPollingTime(final String pollingTime, final Callable<Void> runnable) throws Exception {
getAs(withUser("tenantadmin", TENANT_CONFIGURATION), getAs(withUser("tenantadmin", TENANT_CONFIGURATION),
() -> { () -> {
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME, pollingTime); tenantConfigurationManagement().addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME, pollingTime);
return null; return null;
}); });
try { try {
@@ -779,7 +780,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
} finally { } finally {
getAs(withUser("tenantadmin", TENANT_CONFIGURATION), getAs(withUser("tenantadmin", TENANT_CONFIGURATION),
() -> { () -> {
tenantConfigurationManagement.deleteConfiguration(TenantConfigurationKey.POLLING_TIME); tenantConfigurationManagement().deleteConfiguration(TenantConfigurationKey.POLLING_TIME);
return null; return null;
}); });
} }

View File

@@ -17,6 +17,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.eclipse.hawkbit.context.AccessContext;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
@@ -53,7 +54,7 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
*/ */
@Test @Test
void blackListedClientIsForbidden() throws Exception { void blackListedClientIsForbidden() throws Exception {
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()) mvc.perform(get("/{tenant}/controller/v1/4711", AccessContext.tenant())
.header(X_FORWARDED_FOR, "192.168.0.4 , 10.0.0.1 ")) .header(X_FORWARDED_FOR, "192.168.0.4 , 10.0.0.1 "))
.andExpect(status().isForbidden()); .andExpect(status().isForbidden());
} }
@@ -66,7 +67,7 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
int requests = 0; int requests = 0;
MvcResult result; MvcResult result;
do { do {
result = mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()) result = mvc.perform(get("/{tenant}/controller/v1/4711", AccessContext.tenant())
.header(X_FORWARDED_FOR, "10.0.0.1")) .header(X_FORWARDED_FOR, "10.0.0.1"))
.andReturn(); .andReturn();
requests++; requests++;
@@ -85,7 +86,7 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
@Test @Test
void unacceptableGetLoadButOnWhitelistIPv4() throws Exception { void unacceptableGetLoadButOnWhitelistIPv4() throws Exception {
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()) mvc.perform(get("/{tenant}/controller/v1/4711", AccessContext.tenant())
.header(X_FORWARDED_FOR, "127.0.0.1")) .header(X_FORWARDED_FOR, "127.0.0.1"))
.andExpect(status().isOk()); .andExpect(status().isOk());
} }
@@ -97,7 +98,7 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
@Test @Test
void unacceptableGetLoadButOnWhitelistIPv6() throws Exception { void unacceptableGetLoadButOnWhitelistIPv6() throws Exception {
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()) mvc.perform(get("/{tenant}/controller/v1/4711", AccessContext.tenant())
.header(X_FORWARDED_FOR, "0:0:0:0:0:0:0:1")) .header(X_FORWARDED_FOR, "0:0:0:0:0:0:0:1"))
.andExpect(status().isOk()); .andExpect(status().isOk());
} }
@@ -114,7 +115,7 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
// sleep for one second // sleep for one second
Thread.sleep(1100); Thread.sleep(1100);
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++) {
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()) mvc.perform(get("/{tenant}/controller/v1/4711", AccessContext.tenant())
.header(X_FORWARDED_FOR, "10.0.0.1")) .header(X_FORWARDED_FOR, "10.0.0.1"))
.andExpect(status().isOk()); .andExpect(status().isOk());
} }
@@ -133,7 +134,7 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
MvcResult result; MvcResult result;
do { do {
result = mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback", result = mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback",
tenantAware.getCurrentTenant()).header(X_FORWARDED_FOR, "10.0.0.1").content(feedback) AccessContext.tenant()).header(X_FORWARDED_FOR, "10.0.0.1").content(feedback)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andReturn(); .andReturn();
requests++; requests++;
@@ -162,7 +163,7 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++) {
mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback", mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback",
tenantAware.getCurrentTenant()).header(X_FORWARDED_FOR, "10.0.0.1") AccessContext.tenant()).header(X_FORWARDED_FOR, "10.0.0.1")
.content(feedback).contentType(MediaType.APPLICATION_JSON) .content(feedback).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()); .andExpect(status().isOk());

View File

@@ -9,24 +9,13 @@
*/ */
package org.eclipse.hawkbit.ddi.rest.resource; package org.eclipse.hawkbit.ddi.rest.resource;
import static org.junit.jupiter.api.Assertions.fail;
import java.util.List;
import java.util.Map; import java.util.Map;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
import org.eclipse.hawkbit.repository.model.RolloutGroupConditions;
import org.eclipse.hawkbit.repository.model.Target;
import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import org.springframework.util.CollectionUtils;
/** /**
* Builder class for building certain json strings. * Builder class for building certain json strings.

View File

@@ -10,6 +10,7 @@
package org.eclipse.hawkbit.security.controller; package org.eclipse.hawkbit.security.controller;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -21,14 +22,13 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.util.UrlUtils;
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.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.context.SecurityContextHolderStrategy; import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.util.AntPathMatcher; import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.UriUtils;
/** /**
* An abstraction for all controller based security to parse the e.g. the tenant name from the URL and the controller ID from the URL to do * An abstraction for all controller based security to parse the e.g. the tenant name from the URL and the controller ID from the URL to do
@@ -119,8 +119,9 @@ public class AuthenticationFilters {
authenticator.log().debug("retrieving principal from URI request {}", requestURI); authenticator.log().debug("retrieving principal from URI request {}", requestURI);
final Map<String, String> extractUriTemplateVariables = pathExtractor final Map<String, String> extractUriTemplateVariables = pathExtractor
.extractUriTemplateVariables(request.getContextPath() + CONTROLLER_REQUEST_ANT_PATTERN, requestURI); .extractUriTemplateVariables(request.getContextPath() + CONTROLLER_REQUEST_ANT_PATTERN, requestURI);
final String controllerId = UrlUtils.decodeUriValue(extractUriTemplateVariables.get(CONTROLLER_ID_PLACE_HOLDER)); final String controllerId = UriUtils.decode(extractUriTemplateVariables.get(CONTROLLER_ID_PLACE_HOLDER),
final String tenant = UrlUtils.decodeUriValue(extractUriTemplateVariables.get(TENANT_PLACE_HOLDER)); StandardCharsets.UTF_8);
final String tenant = UriUtils.decode(extractUriTemplateVariables.get(TENANT_PLACE_HOLDER), StandardCharsets.UTF_8);
authenticator.log().trace("Parsed tenant {} and controllerId {} from path request {}", tenant, controllerId, requestURI); authenticator.log().trace("Parsed tenant {} and controllerId {} from path request {}", tenant, controllerId, requestURI);
return createTenantSecurityTokenVariables(request, tenant, controllerId); return createTenantSecurityTokenVariables(request, tenant, controllerId);
} else { } else {
@@ -147,8 +148,8 @@ public class AuthenticationFilters {
// source ip matches the given pattern -> authenticated // source ip matches the given pattern -> authenticated
return true; return true;
} else { } else {
authenticator.log().debug( authenticator.log().debug("The remote source IP address {} is not in the list of trusted IP addresses {}",
"The remote source IP address {} is not in the list of trusted IP addresses {}", remoteAddress, authorizedSourceIps); remoteAddress, authorizedSourceIps);
return false; return false;
} }
} }

View File

@@ -9,16 +9,15 @@
*/ */
package org.eclipse.hawkbit.security.controller; package org.eclipse.hawkbit.security.controller;
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.Callable;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.eclipse.hawkbit.im.authentication.SpRole; import org.eclipse.hawkbit.auth.SpRole;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails; import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.authentication.AbstractAuthenticationToken;
@@ -32,10 +31,10 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
public interface Authenticator { public interface Authenticator {
/** /**
* If the authentication mechanism is not enabled for the tenant - it just returns null. * If the auth mechanism is not enabled for the tenant - it just returns null.
* If the authentication mechanism is supported, the filter extracts from the security token the related credentials, * If the auth mechanism is supported, the filter extracts from the security token the related credentials,
* validate them (do authenticate the caller). * validate them (do authenticate the caller).
* If validation / authentication is successful returns an authenticated authentication object. Otherwise, * If validation / auth is successful returns an authenticated auth object. Otherwise,
* throws BadCredentialsException. * throws BadCredentialsException.
* *
* @param controllerSecurityToken the securityToken * @param controllerSecurityToken the securityToken
@@ -47,23 +46,10 @@ public interface Authenticator {
abstract class AbstractAuthenticator implements Authenticator { abstract class AbstractAuthenticator implements Authenticator {
protected final TenantConfigurationManagement tenantConfigurationManagement;
protected final TenantAware tenantAware;
protected final SystemSecurityContext systemSecurityContext;
private final Callable<Boolean> isEnabledGetter;
protected AbstractAuthenticator(
final TenantConfigurationManagement tenantConfigurationManagement,
final TenantAware tenantAware, final SystemSecurityContext systemSecurityContext) {
this.tenantConfigurationManagement = tenantConfigurationManagement;
this.tenantAware = tenantAware;
this.systemSecurityContext = systemSecurityContext;
isEnabledGetter = () -> systemSecurityContext.runAsSystem(
() -> tenantConfigurationManagement.getConfigurationValue(getTenantConfigurationKey(), Boolean.class).getValue());
}
protected boolean isEnabled(final ControllerSecurityToken securityToken) { protected boolean isEnabled(final ControllerSecurityToken securityToken) {
return tenantAware.runAsTenant(securityToken.getTenant(), isEnabledGetter); return asSystemAsTenant(
securityToken.getTenant(),
() -> TenantConfigHelper.getAsSystem(getTenantConfigurationKey(), Boolean.class));
} }
protected abstract String getTenantConfigurationKey(); protected abstract String getTenantConfigurationKey();

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.security; package org.eclipse.hawkbit.security.controller;
import java.util.List; import java.util.List;
@@ -56,7 +56,7 @@ public class DdiSecurityProperties {
private String sslIssuerHashHeader = "X-Ssl-Issuer-Hash-%d"; private String sslIssuerHashHeader = "X-Ssl-Issuer-Hash-%d";
/** /**
* List of trusted (reverse proxy) IP addresses for performing DDI * List of trusted (reverse proxy) IP addresses for performing DDI
* client certificate authentication. * client certificate auth.
*/ */
private List<String> trustedIPs; private List<String> trustedIPs;
} }
@@ -71,25 +71,25 @@ public class DdiSecurityProperties {
private final Gatewaytoken gatewaytoken = new Gatewaytoken(); private final Gatewaytoken gatewaytoken = new Gatewaytoken();
/** /**
* Target token authentication. Tokens are defined per target. * Target token auth. Tokens are defined per target.
*/ */
@Data @Data
public static class Targettoken { public static class Targettoken {
/** /**
* Set to true to enable target token authentication. * Set to true to enable target token auth.
*/ */
private boolean enabled = false; private boolean enabled = false;
} }
/** /**
* Gateway token authentication. Tokens are defined per tenant. Use with care! * Gateway token auth. Tokens are defined per tenant. Use with care!
*/ */
@Data @Data
public static class Gatewaytoken { public static class Gatewaytoken {
/** /**
* Gateway token based authentication enabled. * Gateway token based auth enabled.
*/ */
private boolean enabled = false; private boolean enabled = false;

View File

@@ -9,16 +9,12 @@
*/ */
package org.eclipse.hawkbit.security.controller; package org.eclipse.hawkbit.security.controller;
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_ENABLED; import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_ENABLED;
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY; import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY;
import java.util.concurrent.Callable;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@@ -35,22 +31,6 @@ public class GatewayTokenAuthenticator extends Authenticator.AbstractAuthenticat
public static final String GATEWAY_SECURITY_TOKEN_AUTH_SCHEME = "GatewayToken "; public static final String GATEWAY_SECURITY_TOKEN_AUTH_SCHEME = "GatewayToken ";
private static final int OFFSET_GATEWAY_TOKEN = GATEWAY_SECURITY_TOKEN_AUTH_SCHEME.length(); private static final int OFFSET_GATEWAY_TOKEN = GATEWAY_SECURITY_TOKEN_AUTH_SCHEME.length();
private final Callable<String> gatewaySecurityTokenKeyGetter;
public GatewayTokenAuthenticator(
final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware,
final SystemSecurityContext systemSecurityContext) {
super(tenantConfigurationManagement, tenantAware, systemSecurityContext);
gatewaySecurityTokenKeyGetter = () -> {
log.trace("retrieving configuration value for configuration key {}", AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY);
return systemSecurityContext
.runAsSystem(() -> tenantConfigurationManagement
.getConfigurationValue(AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class)
.getValue());
};
}
@Override @Override
public Authentication authenticate(final ControllerSecurityToken controllerSecurityToken) { public Authentication authenticate(final ControllerSecurityToken controllerSecurityToken) {
final String authHeader = controllerSecurityToken.getHeader(ControllerSecurityToken.AUTHORIZATION_HEADER); final String authHeader = controllerSecurityToken.getHeader(ControllerSecurityToken.AUTHORIZATION_HEADER);
@@ -63,7 +43,7 @@ public class GatewayTokenAuthenticator extends Authenticator.AbstractAuthenticat
} }
if (!isEnabled(controllerSecurityToken)) { if (!isEnabled(controllerSecurityToken)) {
log.debug("The gateway token authentication is disabled"); log.debug("The gateway token auth is disabled");
return null; return null;
} }
@@ -71,8 +51,14 @@ public class GatewayTokenAuthenticator extends Authenticator.AbstractAuthenticat
final String presentedToken = authHeader.substring(OFFSET_GATEWAY_TOKEN); final String presentedToken = authHeader.substring(OFFSET_GATEWAY_TOKEN);
// validate if the presented token is the same as the gateway token // validate if the presented token is the same as the gateway token
return presentedToken.equals(tenantAware.runAsTenant(controllerSecurityToken.getTenant(), gatewaySecurityTokenKeyGetter)) return presentedToken.equals(asSystemAsTenant(
? authenticatedController(controllerSecurityToken.getTenant(), controllerSecurityToken.getControllerId()) : null; controllerSecurityToken.getTenant(),
() -> {
log.trace("retrieving configuration value for configuration key {}", AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY);
return TenantConfigHelper.getAsSystem(AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class);
}))
? authenticatedController(controllerSecurityToken.getTenant(), controllerSecurityToken.getControllerId())
: null;
} }
@Override @Override

View File

@@ -9,14 +9,14 @@
*/ */
package org.eclipse.hawkbit.security.controller; package org.eclipse.hawkbit.security.controller;
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_HEADER_AUTHORITY_NAME;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -29,7 +29,7 @@ import org.springframework.security.core.Authentication;
@Slf4j @Slf4j
public class SecurityHeaderAuthenticator extends Authenticator.AbstractAuthenticator { public class SecurityHeaderAuthenticator extends Authenticator.AbstractAuthenticator {
private static final Logger LOG_SECURITY_AUTH = LoggerFactory.getLogger("server-security.authentication"); private static final Logger LOG_SECURITY_AUTH = LoggerFactory.getLogger("server-security.auth");
// Example Headers with Cert Information // Example Headers with Cert Information
// Clientip: 217.24.201.180 // Clientip: 217.24.201.180
@@ -48,18 +48,9 @@ public class SecurityHeaderAuthenticator extends Authenticator.AbstractAuthentic
// header exists multiple times in the request for all trusted chains. // header exists multiple times in the request for all trusted chains.
private final String sslIssuerHashBasicHeader; private final String sslIssuerHashBasicHeader;
private final Callable<String> sslIssuerNameConfigGetter; public SecurityHeaderAuthenticator(final String caCommonNameHeader, final String caAuthorityNameHeader) {
public SecurityHeaderAuthenticator(
final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware,
final SystemSecurityContext systemSecurityContext,
final String caCommonNameHeader, final String caAuthorityNameHeader) {
super(tenantConfigurationManagement, tenantAware, systemSecurityContext);
this.caCommonNameHeader = caCommonNameHeader; this.caCommonNameHeader = caCommonNameHeader;
this.sslIssuerHashBasicHeader = caAuthorityNameHeader; this.sslIssuerHashBasicHeader = caAuthorityNameHeader;
sslIssuerNameConfigGetter = () -> systemSecurityContext.runAsSystem(
() -> tenantConfigurationManagement.getConfigurationValue(
TenantConfigurationKey.AUTHENTICATION_HEADER_AUTHORITY_NAME, String.class).getValue());
} }
@Override @Override
@@ -76,13 +67,15 @@ public class SecurityHeaderAuthenticator extends Authenticator.AbstractAuthentic
} }
if (!isEnabled(controllerSecurityToken)) { if (!isEnabled(controllerSecurityToken)) {
log.debug("The gateway header authentication is disabled"); log.debug("The gateway header auth is disabled");
return null; return null;
} }
final String sslIssuerHashValue = getIssuerHashHeader( final String sslIssuerHashValue = getIssuerHashHeader(
controllerSecurityToken, controllerSecurityToken,
tenantAware.runAsTenant(controllerSecurityToken.getTenant(), sslIssuerNameConfigGetter)); asSystemAsTenant(
controllerSecurityToken.getTenant(),
() -> TenantConfigHelper.getAsSystem(AUTHENTICATION_HEADER_AUTHORITY_NAME, String.class)));
if (sslIssuerHashValue == null) { if (sslIssuerHashValue == null) {
log.debug("The request contains the 'common name' header but trusted hash is not found"); log.debug("The request contains the 'common name' header but trusted hash is not found");
return null; return null;
@@ -115,7 +108,8 @@ public class SecurityHeaderAuthenticator extends Authenticator.AbstractAuthentic
// iterate over the headers until we get a null header. // iterate over the headers until we get a null header.
String foundHash; String foundHash;
for (int iHeader = 1; (foundHash = controllerSecurityToken.getHeader(String.format(sslIssuerHashBasicHeader, iHeader))) != null; iHeader++) { for (int iHeader = 1; (foundHash = controllerSecurityToken.getHeader(
String.format(sslIssuerHashBasicHeader, iHeader))) != null; iHeader++) {
if (knownHashes.contains(foundHash.toLowerCase())) { if (knownHashes.contains(foundHash.toLowerCase())) {
if (log.isTraceEnabled()) { if (log.isTraceEnabled()) {
log.trace("Found matching ssl issuer hash at position {}", iHeader); log.trace("Found matching ssl issuer hash at position {}", iHeader);

View File

@@ -9,11 +9,10 @@
*/ */
package org.eclipse.hawkbit.security.controller; package org.eclipse.hawkbit.security.controller;
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@@ -32,11 +31,7 @@ public class SecurityTokenAuthenticator extends Authenticator.AbstractAuthentica
private final ControllerManagement controllerManagement; private final ControllerManagement controllerManagement;
public SecurityTokenAuthenticator( public SecurityTokenAuthenticator(final ControllerManagement controllerManagement) {
final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware,
final SystemSecurityContext systemSecurityContext,
final ControllerManagement controllerManagement) {
super(tenantConfigurationManagement, tenantAware, systemSecurityContext);
this.controllerManagement = controllerManagement; this.controllerManagement = controllerManagement;
} }
@@ -52,21 +47,20 @@ public class SecurityTokenAuthenticator extends Authenticator.AbstractAuthentica
} }
if (!isEnabled(controllerSecurityToken)) { if (!isEnabled(controllerSecurityToken)) {
log.debug("The target security token authentication is disabled"); log.debug("The target security token auth is disabled");
return null; return null;
} }
log.debug("Found 'authorization' header starting with '{}'", TARGET_SECURITY_TOKEN_AUTH_SCHEME); log.debug("Found 'authorization' header starting with '{}'", TARGET_SECURITY_TOKEN_AUTH_SCHEME);
final String presentedToken = authHeader.substring(OFFSET_TARGET_TOKEN); final String presentedToken = authHeader.substring(OFFSET_TARGET_TOKEN);
return systemSecurityContext.runAsSystemAsTenant(() -> controllerSecurityToken.getTargetId() != null final String tenant = controllerSecurityToken.getTenant();
return asSystemAsTenant(tenant, () -> controllerSecurityToken.getTargetId() != null
? controllerManagement.find(controllerSecurityToken.getTargetId()) ? controllerManagement.find(controllerSecurityToken.getTargetId())
: controllerManagement.findByControllerId(controllerSecurityToken.getControllerId()), : controllerManagement.findByControllerId(controllerSecurityToken.getControllerId()))
controllerSecurityToken.getTenant())
// validate if the presented token is the same as the one set for the target // validate if the presented token is the same as the one set for the target
.filter(target -> presentedToken.equals( .filter(target -> presentedToken.equals(asSystemAsTenant(tenant, target::getSecurityToken)))
systemSecurityContext.runAsSystemAsTenant(target::getSecurityToken, controllerSecurityToken.getTenant()))) .map(target -> authenticatedController(tenant, target.getControllerId()))
.map(target -> authenticatedController(controllerSecurityToken.getTenant(), target.getControllerId()))
.orElse(null); .orElse(null);
} }

View File

@@ -16,10 +16,8 @@ import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationPrope
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@@ -28,7 +26,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
/** /**
* Feature: Unit Tests - Security<br/> * Feature: Unit Tests - Security<br/>
* Story: Gateway token authentication * Story: Gateway token auth
*/ */
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class GatewayTokenAuthenticatorTest { class GatewayTokenAuthenticatorTest {
@@ -48,17 +46,15 @@ class GatewayTokenAuthenticatorTest {
@Mock @Mock
private TenantConfigurationManagement tenantConfigurationManagementMock; private TenantConfigurationManagement tenantConfigurationManagementMock;
@Mock
private UserAuthoritiesResolver authoritiesResolver;
@BeforeEach @BeforeEach
void before() { void before() {
final SecurityContextTenantAware tenantAware = new SecurityContextTenantAware(authoritiesResolver); TenantConfigHelper.setTenantConfigurationManagement(tenantConfigurationManagementMock);
authenticator = new GatewayTokenAuthenticator(tenantConfigurationManagementMock, tenantAware, new SystemSecurityContext(tenantAware)); authenticator = new GatewayTokenAuthenticator();
} }
/** /**
* Tests successful authentication with gateway token * Tests successful auth with gateway token
*/ */
@Test @Test
void testWithGwToken() { void testWithGwToken() {
@@ -74,7 +70,7 @@ class GatewayTokenAuthenticatorTest {
} }
/** /**
* Tests that if gateway token doesn't match, the authentication fails * Tests that if gateway token doesn't match, the auth fails
*/ */
@Test @Test
void testWithBadGwToken() { void testWithBadGwToken() {
@@ -88,7 +84,7 @@ class GatewayTokenAuthenticatorTest {
} }
/** /**
* Tests that if gateway token miss, the authentication fails * Tests that if gateway token miss, the auth fails
*/ */
@Test @Test
void testWithoutGwToken() { void testWithoutGwToken() {
@@ -96,7 +92,7 @@ class GatewayTokenAuthenticatorTest {
} }
/** /**
* Tests that if disabled, the authentication fails * Tests that if disabled, the auth fails
*/ */
@Test @Test
void testWithGwTokenButDisabled() { void testWithGwTokenButDisabled() {

View File

@@ -15,10 +15,8 @@ import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationPrope
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@@ -57,20 +55,15 @@ class SecurityHeaderAuthenticatorTest {
@Mock @Mock
private TenantConfigurationManagement tenantConfigurationManagementMock; private TenantConfigurationManagement tenantConfigurationManagementMock;
@Mock
private UserAuthoritiesResolver authoritiesResolver;
@BeforeEach @BeforeEach
void before() { void before() {
final SecurityContextTenantAware tenantAware = new SecurityContextTenantAware(authoritiesResolver); TenantConfigHelper.setTenantConfigurationManagement(tenantConfigurationManagementMock);
authenticator = new SecurityHeaderAuthenticator( authenticator = new SecurityHeaderAuthenticator(CA_COMMON_NAME, "X-Ssl-Issuer-Hash-%d");
tenantConfigurationManagementMock, tenantAware,
new SystemSecurityContext(tenantAware), CA_COMMON_NAME, "X-Ssl-Issuer-Hash-%d"
);
} }
/** /**
* Tests successful authentication with multiple a single hashes * Tests successful auth with multiple a single hashes
*/ */
@Test @Test
void testWithSingleKnownHash() { void testWithSingleKnownHash() {
@@ -86,7 +79,7 @@ class SecurityHeaderAuthenticatorTest {
} }
/** /**
* Tests successful authentication with multiple hashes * Tests successful auth with multiple hashes
*/ */
@Test @Test
void testWithMultipleKnownHashes() { void testWithMultipleKnownHashes() {
@@ -107,7 +100,7 @@ class SecurityHeaderAuthenticatorTest {
} }
/** /**
* Tests that if the hash is unknown, the authentication fails * Tests that if the hash is unknown, the auth fails
*/ */
@Test @Test
void testWithUnknownHash() { void testWithUnknownHash() {
@@ -121,7 +114,7 @@ class SecurityHeaderAuthenticatorTest {
} }
/** /**
* Tests that if CN doesn't match the CN in the security token, the authentication fails * Tests that if CN doesn't match the CN in the security token, the auth fails
*/ */
@Test @Test
void testWithNonMatchingCN() { void testWithNonMatchingCN() {
@@ -133,7 +126,7 @@ class SecurityHeaderAuthenticatorTest {
} }
/** /**
* Tests that if the hash miss, the authentication fails * Tests that if the hash miss, the auth fails
*/ */
@Test @Test
void testWithoutHash() { void testWithoutHash() {
@@ -141,7 +134,7 @@ class SecurityHeaderAuthenticatorTest {
} }
/** /**
* Tests that if disabled, the authentication fails * Tests that if disabled, the auth fails
*/ */
@Test @Test
void testWithSingleKnownHashButDisabled() { void testWithSingleKnownHashButDisabled() {

View File

@@ -17,11 +17,9 @@ import java.util.Optional;
import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@@ -31,7 +29,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
/** /**
* Feature: Unit Tests - Security<br/> * Feature: Unit Tests - Security<br/>
* Story: Gateway token authentication * Story: Gateway token auth
*/ */
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class SecurityTokenAuthenticatorTest { class SecurityTokenAuthenticatorTest {
@@ -51,19 +49,15 @@ class SecurityTokenAuthenticatorTest {
private TenantConfigurationManagement tenantConfigurationManagementMock; private TenantConfigurationManagement tenantConfigurationManagementMock;
@Mock @Mock
private ControllerManagement controllerManagementMock; private ControllerManagement controllerManagementMock;
@Mock
private UserAuthoritiesResolver authoritiesResolver;
@BeforeEach @BeforeEach
void before() { void before() {
final SecurityContextTenantAware tenantAware = new SecurityContextTenantAware(authoritiesResolver); TenantConfigHelper.setTenantConfigurationManagement(tenantConfigurationManagementMock);
authenticator = new SecurityTokenAuthenticator( authenticator = new SecurityTokenAuthenticator(controllerManagementMock);
tenantConfigurationManagementMock, tenantAware,
new SystemSecurityContext(tenantAware), controllerManagementMock);
} }
/** /**
* Tests successful authentication with gateway token * Tests successful auth with gateway token
*/ */
@Test @Test
void testWithSecToken() { void testWithSecToken() {
@@ -82,7 +76,7 @@ class SecurityTokenAuthenticatorTest {
} }
/** /**
* Tests that if gateway token doesn't match, the authentication fails * Tests that if gateway token doesn't match, the auth fails
*/ */
@Test @Test
void testWithBadSecToken() { void testWithBadSecToken() {
@@ -94,7 +88,7 @@ class SecurityTokenAuthenticatorTest {
} }
/** /**
* Tests that if gateway token miss, the authentication fails * Tests that if gateway token miss, the auth fails
*/ */
@Test @Test
void testWithoutSecToken() { void testWithoutSecToken() {
@@ -102,7 +96,7 @@ class SecurityTokenAuthenticatorTest {
} }
/** /**
* Tests that if disabled, the authentication fails * Tests that if disabled, the auth fails
*/ */
@Test @Test
void testWithSecTokenButDisabled() { void testWithSecTokenButDisabled() {

View File

@@ -30,7 +30,7 @@ server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true server.servlet.encoding.enabled=true
server.servlet.encoding.force=true server.servlet.encoding.force=true
# DDI authentication configuration # DDI auth configuration
hawkbit.server.ddi.security.authentication.targettoken.enabled=false hawkbit.server.ddi.security.authentication.targettoken.enabled=false
hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=false hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=false

View File

@@ -12,8 +12,8 @@ package org.eclipse.hawkbit.app.ddi;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.auth.SpPermission;
import org.eclipse.hawkbit.im.authentication.SpRole; import org.eclipse.hawkbit.auth.SpRole;
import org.eclipse.hawkbit.repository.test.util.WithUser; import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;

View File

@@ -12,20 +12,17 @@ package org.eclipse.hawkbit.autoconfigure.ddi;
import java.util.List; import java.util.List;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.context.Mdc;
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.rest.SecurityManagedConfiguration; import org.eclipse.hawkbit.rest.SecurityManagedConfiguration;
import org.eclipse.hawkbit.rest.security.DosFilter; import org.eclipse.hawkbit.rest.security.DosFilter;
import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties; import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.security.MdcHandler;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.security.controller.AuthenticationFilters; import org.eclipse.hawkbit.security.controller.AuthenticationFilters;
import org.eclipse.hawkbit.security.controller.DdiSecurityProperties;
import org.eclipse.hawkbit.security.controller.GatewayTokenAuthenticator; import org.eclipse.hawkbit.security.controller.GatewayTokenAuthenticator;
import org.eclipse.hawkbit.security.controller.SecurityHeaderAuthenticator; import org.eclipse.hawkbit.security.controller.SecurityHeaderAuthenticator;
import org.eclipse.hawkbit.security.controller.SecurityTokenAuthenticator; import org.eclipse.hawkbit.security.controller.SecurityTokenAuthenticator;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@@ -50,23 +47,15 @@ class ControllerDownloadSecurityConfiguration {
DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/*"; DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/*";
private final ControllerManagement controllerManagement; private final ControllerManagement controllerManagement;
private final TenantConfigurationManagement tenantConfigurationManagement;
private final TenantAware tenantAware;
private final DdiSecurityProperties ddiSecurityConfiguration; private final DdiSecurityProperties ddiSecurityConfiguration;
private final HawkbitSecurityProperties securityProperties; private final HawkbitSecurityProperties securityProperties;
private final SystemSecurityContext systemSecurityContext;
ControllerDownloadSecurityConfiguration( ControllerDownloadSecurityConfiguration(
final ControllerManagement controllerManagement, final ControllerManagement controllerManagement,
final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware, final DdiSecurityProperties ddiSecurityConfiguration, final HawkbitSecurityProperties securityProperties) {
final DdiSecurityProperties ddiSecurityConfiguration,
final HawkbitSecurityProperties securityProperties, final SystemSecurityContext systemSecurityContext) {
this.controllerManagement = controllerManagement; this.controllerManagement = controllerManagement;
this.tenantConfigurationManagement = tenantConfigurationManagement;
this.tenantAware = tenantAware;
this.ddiSecurityConfiguration = ddiSecurityConfiguration; this.ddiSecurityConfiguration = ddiSecurityConfiguration;
this.securityProperties = securityProperties; this.securityProperties = securityProperties;
this.systemSecurityContext = systemSecurityContext;
} }
/** /**
@@ -95,17 +84,13 @@ class ControllerDownloadSecurityConfiguration {
.csrf(AbstractHttpConfigurer::disable) .csrf(AbstractHttpConfigurer::disable)
.addFilterBefore(new AuthenticationFilters.SecurityHeaderAuthenticationFilter( .addFilterBefore(new AuthenticationFilters.SecurityHeaderAuthenticationFilter(
new SecurityHeaderAuthenticator( new SecurityHeaderAuthenticator(
tenantConfigurationManagement, tenantAware, systemSecurityContext,
ddiSecurityConfiguration.getRp().getCnHeader(), ddiSecurityConfiguration.getRp().getSslIssuerHashHeader()), ddiSecurityConfiguration.getRp().getCnHeader(), ddiSecurityConfiguration.getRp().getSslIssuerHashHeader()),
ddiSecurityConfiguration), AuthorizationFilter.class) ddiSecurityConfiguration), AuthorizationFilter.class)
.addFilterBefore(new AuthenticationFilters.SecurityTokenAuthenticationFilter( .addFilterBefore(new AuthenticationFilters.SecurityTokenAuthenticationFilter(
new SecurityTokenAuthenticator( new SecurityTokenAuthenticator(controllerManagement),
tenantConfigurationManagement, tenantAware, systemSecurityContext,
controllerManagement),
ddiSecurityConfiguration), AuthorizationFilter.class) ddiSecurityConfiguration), AuthorizationFilter.class)
.addFilterBefore(new AuthenticationFilters.GatewayTokenAuthenticationFilter( .addFilterBefore(new AuthenticationFilters.GatewayTokenAuthenticationFilter(
new GatewayTokenAuthenticator( new GatewayTokenAuthenticator(),
tenantConfigurationManagement, tenantAware, systemSecurityContext),
ddiSecurityConfiguration), AuthorizationFilter.class) ddiSecurityConfiguration), AuthorizationFilter.class)
.exceptionHandling(configurer -> configurer.authenticationEntryPoint( .exceptionHandling(configurer -> configurer.authenticationEntryPoint(
(request, response, authException) -> response.setStatus(HttpStatus.UNAUTHORIZED.value()))) (request, response, authException) -> response.setStatus(HttpStatus.UNAUTHORIZED.value())))
@@ -115,7 +100,7 @@ class ControllerDownloadSecurityConfiguration {
http.redirectToHttps(Customizer.withDefaults()); http.redirectToHttps(Customizer.withDefaults());
} }
MdcHandler.Filter.addMdcFilter(http); Mdc.Filter.addMdcFilter(http);
return http.build(); return http.build();
} }

View File

@@ -12,20 +12,17 @@ package org.eclipse.hawkbit.autoconfigure.ddi;
import java.util.List; import java.util.List;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.context.Mdc;
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.rest.SecurityManagedConfiguration; import org.eclipse.hawkbit.rest.SecurityManagedConfiguration;
import org.eclipse.hawkbit.rest.security.DosFilter; import org.eclipse.hawkbit.rest.security.DosFilter;
import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties; import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.security.MdcHandler;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.security.controller.AuthenticationFilters; import org.eclipse.hawkbit.security.controller.AuthenticationFilters;
import org.eclipse.hawkbit.security.controller.DdiSecurityProperties;
import org.eclipse.hawkbit.security.controller.GatewayTokenAuthenticator; import org.eclipse.hawkbit.security.controller.GatewayTokenAuthenticator;
import org.eclipse.hawkbit.security.controller.SecurityHeaderAuthenticator; import org.eclipse.hawkbit.security.controller.SecurityHeaderAuthenticator;
import org.eclipse.hawkbit.security.controller.SecurityTokenAuthenticator; import org.eclipse.hawkbit.security.controller.SecurityTokenAuthenticator;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -52,23 +49,16 @@ class ControllerSecurityConfiguration {
private static final String[] DDI_ANT_MATCHERS = { DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/**" }; private static final String[] DDI_ANT_MATCHERS = { DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/**" };
private final ControllerManagement controllerManagement; private final ControllerManagement controllerManagement;
private final TenantConfigurationManagement tenantConfigurationManagement;
private final TenantAware tenantAware;
private final DdiSecurityProperties ddiSecurityConfiguration; private final DdiSecurityProperties ddiSecurityConfiguration;
private final HawkbitSecurityProperties securityProperties; private final HawkbitSecurityProperties securityProperties;
private final SystemSecurityContext systemSecurityContext;
@Autowired @Autowired
ControllerSecurityConfiguration(final ControllerManagement controllerManagement, ControllerSecurityConfiguration(
final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware, final ControllerManagement controllerManagement, final DdiSecurityProperties ddiSecurityConfiguration,
final DdiSecurityProperties ddiSecurityConfiguration, final HawkbitSecurityProperties securityProperties) {
final HawkbitSecurityProperties securityProperties, final SystemSecurityContext systemSecurityContext) {
this.controllerManagement = controllerManagement; this.controllerManagement = controllerManagement;
this.tenantConfigurationManagement = tenantConfigurationManagement;
this.tenantAware = tenantAware;
this.ddiSecurityConfiguration = ddiSecurityConfiguration; this.ddiSecurityConfiguration = ddiSecurityConfiguration;
this.securityProperties = securityProperties; this.securityProperties = securityProperties;
this.systemSecurityContext = systemSecurityContext;
} }
/** /**
@@ -89,7 +79,6 @@ class ControllerSecurityConfiguration {
return filterRegBean; return filterRegBean;
} }
@Bean @Bean
@Order(301) @Order(301)
protected SecurityFilterChain filterChainDDI( protected SecurityFilterChain filterChainDDI(
@@ -100,24 +89,23 @@ class ControllerSecurityConfiguration {
.authorizeHttpRequests(amrmRegistry -> amrmRegistry.anyRequest().authenticated()) .authorizeHttpRequests(amrmRegistry -> amrmRegistry.anyRequest().authenticated())
.anonymous(AbstractHttpConfigurer::disable) .anonymous(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable) .csrf(AbstractHttpConfigurer::disable)
.addFilterBefore(new AuthenticationFilters.SecurityHeaderAuthenticationFilter( .addFilterBefore(
new AuthenticationFilters.SecurityHeaderAuthenticationFilter(
new SecurityHeaderAuthenticator( new SecurityHeaderAuthenticator(
tenantConfigurationManagement, tenantAware, ddiSecurityConfiguration.getRp().getCnHeader(),
systemSecurityContext, ddiSecurityConfiguration.getRp().getCnHeader(), ddiSecurityConfiguration.getRp().getSslIssuerHashHeader() ddiSecurityConfiguration.getRp().getSslIssuerHashHeader()), ddiSecurityConfiguration),
), ddiSecurityConfiguration), AuthorizationFilter.class) AuthorizationFilter.class)
.addFilterBefore(new AuthenticationFilters.SecurityTokenAuthenticationFilter( .addFilterBefore(
new SecurityTokenAuthenticator( new AuthenticationFilters.SecurityTokenAuthenticationFilter(
tenantConfigurationManagement, tenantAware, new SecurityTokenAuthenticator(controllerManagement), ddiSecurityConfiguration),
systemSecurityContext, controllerManagement), ddiSecurityConfiguration), AuthorizationFilter.class) AuthorizationFilter.class)
.addFilterBefore(new AuthenticationFilters.GatewayTokenAuthenticationFilter( .addFilterBefore(
new GatewayTokenAuthenticator( new AuthenticationFilters.GatewayTokenAuthenticationFilter(new GatewayTokenAuthenticator(), ddiSecurityConfiguration),
tenantConfigurationManagement, tenantAware, AuthorizationFilter.class)
systemSecurityContext), ddiSecurityConfiguration), AuthorizationFilter.class)
.exceptionHandling(configurer -> configurer.authenticationEntryPoint( .exceptionHandling(configurer -> configurer.authenticationEntryPoint(
(request, response, authException) -> response.setStatus(HttpStatus.UNAUTHORIZED.value()))) (request, response, authException) -> response.setStatus(HttpStatus.UNAUTHORIZED.value())))
.sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); .sessionManagement(configurer -> configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
if (securityProperties.getCors().isEnabled() && !disableCorsForDdiApi) { if (securityProperties.getCors().isEnabled() && !disableCorsForDdiApi) {
http.cors(configurer -> configurer.configurationSource(securityProperties.getCors().toCorsConfigurationSource())); http.cors(configurer -> configurer.configurationSource(securityProperties.getCors().toCorsConfigurationSource()));
} }
@@ -126,7 +114,7 @@ class ControllerSecurityConfiguration {
http.requiresChannel(crmRegistry -> crmRegistry.anyRequest().requiresSecure()); http.requiresChannel(crmRegistry -> crmRegistry.anyRequest().requiresSecure());
} }
MdcHandler.Filter.addMdcFilter(http); Mdc.Filter.addMdcFilter(http);
return http.build(); return http.build();
} }

View File

@@ -10,7 +10,7 @@
package org.eclipse.hawkbit.autoconfigure.ddi; package org.eclipse.hawkbit.autoconfigure.ddi;
import org.eclipse.hawkbit.ddi.rest.resource.DdiApiConfiguration; import org.eclipse.hawkbit.ddi.rest.resource.DdiApiConfiguration;
import org.eclipse.hawkbit.security.DdiSecurityProperties; import org.eclipse.hawkbit.security.controller.DdiSecurityProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;

View File

@@ -32,11 +32,6 @@
<artifactId>hawkbit-core</artifactId> <artifactId>hawkbit-core</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-security-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.eclipse.hawkbit</groupId> <groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-dmf-api</artifactId> <artifactId>hawkbit-dmf-api</artifactId>

View File

@@ -9,6 +9,7 @@
*/ */
package org.eclipse.hawkbit.amqp; package org.eclipse.hawkbit.amqp;
import static org.eclipse.hawkbit.context.AccessContext.asSystem;
import static org.eclipse.hawkbit.repository.RepositoryConstants.MAX_ACTION_COUNT; import static org.eclipse.hawkbit.repository.RepositoryConstants.MAX_ACTION_COUNT;
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.BATCH_ASSIGNMENTS_ENABLED; import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.BATCH_ASSIGNMENTS_ENABLED;
@@ -51,7 +52,6 @@ import org.eclipse.hawkbit.repository.RepositoryProperties;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent; import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent;
import org.eclipse.hawkbit.repository.event.remote.MultiActionAssignEvent; import org.eclipse.hawkbit.repository.event.remote.MultiActionAssignEvent;
import org.eclipse.hawkbit.repository.event.remote.MultiActionCancelEvent; import org.eclipse.hawkbit.repository.event.remote.MultiActionCancelEvent;
@@ -64,6 +64,7 @@ import org.eclipse.hawkbit.repository.event.remote.service.MultiActionCancelServ
import org.eclipse.hawkbit.repository.event.remote.service.TargetAssignDistributionSetServiceEvent; import org.eclipse.hawkbit.repository.event.remote.service.TargetAssignDistributionSetServiceEvent;
import org.eclipse.hawkbit.repository.event.remote.service.TargetAttributesRequestedServiceEvent; import org.eclipse.hawkbit.repository.event.remote.service.TargetAttributesRequestedServiceEvent;
import org.eclipse.hawkbit.repository.event.remote.service.TargetDeletedServiceEvent; import org.eclipse.hawkbit.repository.event.remote.service.TargetDeletedServiceEvent;
import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.ActionProperties; import org.eclipse.hawkbit.repository.model.ActionProperties;
import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.Artifact;
@@ -71,8 +72,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TenantMetaData; import org.eclipse.hawkbit.repository.model.TenantMetaData;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.utils.IpUtil;
import org.eclipse.hawkbit.util.IpUtil;
import org.springframework.amqp.core.Message; import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder; import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageProperties; import org.springframework.amqp.core.MessageProperties;
@@ -94,43 +94,36 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
private final ArtifactUrlResolver artifactUrlHandler; private final ArtifactUrlResolver artifactUrlHandler;
private final AmqpMessageSenderService amqpSenderService; private final AmqpMessageSenderService amqpSenderService;
private final SystemSecurityContext systemSecurityContext;
private final SystemManagement systemManagement; private final SystemManagement systemManagement;
private final TargetManagement<? extends Target> targetManagement; private final TargetManagement<? extends Target> targetManagement;
private final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement; private final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement;
private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement; private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement;
private final DeploymentManagement deploymentManagement; private final DeploymentManagement deploymentManagement;
private final TenantConfigurationManagement tenantConfigurationManagement;
private final RepositoryProperties repositoryProperties; private final RepositoryProperties repositoryProperties;
@SuppressWarnings("java:S107") @SuppressWarnings("java:S107")
protected AmqpMessageDispatcherService( protected AmqpMessageDispatcherService(
final RabbitTemplate rabbitTemplate, final RabbitTemplate rabbitTemplate,
final AmqpMessageSenderService amqpSenderService, final ArtifactUrlResolver artifactUrlHandler, final AmqpMessageSenderService amqpSenderService, final ArtifactUrlResolver artifactUrlHandler,
final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement, final SystemManagement systemManagement,
final TargetManagement<? extends Target> targetManagement, final TargetManagement<? extends Target> targetManagement,
final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement, final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement,
final DistributionSetManagement<? extends DistributionSet> distributionSetManagement, final DistributionSetManagement<? extends DistributionSet> distributionSetManagement,
final DeploymentManagement deploymentManagement, final DeploymentManagement deploymentManagement,
final TenantConfigurationManagement tenantConfigurationManagement,
final RepositoryProperties repositoryProperties) { final RepositoryProperties repositoryProperties) {
super(rabbitTemplate); super(rabbitTemplate);
this.artifactUrlHandler = artifactUrlHandler; this.artifactUrlHandler = artifactUrlHandler;
this.amqpSenderService = amqpSenderService; this.amqpSenderService = amqpSenderService;
this.systemSecurityContext = systemSecurityContext;
this.systemManagement = systemManagement; this.systemManagement = systemManagement;
this.targetManagement = targetManagement; this.targetManagement = targetManagement;
this.softwareModuleManagement = softwareModuleManagement; this.softwareModuleManagement = softwareModuleManagement;
this.distributionSetManagement = distributionSetManagement; this.distributionSetManagement = distributionSetManagement;
this.deploymentManagement = deploymentManagement; this.deploymentManagement = deploymentManagement;
this.tenantConfigurationManagement = tenantConfigurationManagement;
this.repositoryProperties = repositoryProperties; this.repositoryProperties = repositoryProperties;
} }
public boolean isBatchAssignmentsEnabled() { public boolean isBatchAssignmentsEnabled() {
return systemSecurityContext.runAsSystem(() -> return TenantConfigHelper.getAsSystem(BATCH_ASSIGNMENTS_ENABLED, Boolean.class);
tenantConfigurationManagement
.getConfigurationValue(BATCH_ASSIGNMENTS_ENABLED, Boolean.class).getValue());
} }
/** /**
@@ -184,9 +177,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
protected DmfDownloadAndUpdateRequest createDownloadAndUpdateRequest( protected DmfDownloadAndUpdateRequest createDownloadAndUpdateRequest(
final Target target, final Long actionId, final Map<SoftwareModule, Map<String, String>> softwareModules) { final Target target, final Long actionId, final Map<SoftwareModule, Map<String, String>> softwareModules) {
return new DmfDownloadAndUpdateRequest( return new DmfDownloadAndUpdateRequest(
actionId, actionId, asSystem(target::getSecurityToken), convertToAmqpSoftwareModules(target, softwareModules));
systemSecurityContext.runAsSystem(target::getSecurityToken),
convertToAmqpSoftwareModules(target, softwareModules));
} }
/** /**
@@ -227,7 +218,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
protected void sendPingResponseToDmfReceiver(final Message ping, final String tenant, final String virtualHost) { protected void sendPingResponseToDmfReceiver(final Message ping, final String tenant, final String virtualHost) {
final Message message = MessageBuilder final Message message = MessageBuilder
.withBody(String.valueOf(System.currentTimeMillis()).getBytes()) .withBody(String.valueOf(java.lang.System.currentTimeMillis()).getBytes())
.setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN) .setContentType(MessageProperties.CONTENT_TYPE_TEXT_PLAIN)
.setCorrelationId(ping.getMessageProperties().getCorrelationId()) .setCorrelationId(ping.getMessageProperties().getCorrelationId())
.setHeader(MessageHeaderKey.TYPE, MessageType.PING_RESPONSE) .setHeader(MessageHeaderKey.TYPE, MessageType.PING_RESPONSE)
@@ -251,16 +242,9 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
amqpSenderService.sendMessage(message, address); amqpSenderService.sendMessage(message, address);
} }
protected DmfTarget convertToDmfTarget(final Target target, final Long actionId) {
return new DmfTarget(actionId, target.getControllerId(), systemSecurityContext.runAsSystem(target::getSecurityToken));
}
protected DmfConfirmRequest createConfirmRequest( protected DmfConfirmRequest createConfirmRequest(
final Target target, final Long actionId, final Map<SoftwareModule, Map<String, String>> softwareModules) { final Target target, final Long actionId, final Map<SoftwareModule, Map<String, String>> softwareModules) {
return new DmfConfirmRequest( return new DmfConfirmRequest(actionId, asSystem(target::getSecurityToken), convertToAmqpSoftwareModules(target, softwareModules));
actionId,
systemSecurityContext.runAsSystem(target::getSecurityToken),
convertToAmqpSoftwareModules(target, softwareModules));
} }
void sendMultiActionRequestToTarget( void sendMultiActionRequestToTarget(
@@ -580,13 +564,14 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
final Map<SoftwareModule, Map<String, String>> modules) { final Map<SoftwareModule, Map<String, String>> modules) {
final List<DmfTarget> dmfTargets = targets.stream() final List<DmfTarget> dmfTargets = targets.stream()
.filter(target -> IpUtil.isAmqpUri(IpUtil.addressToUri(target.getAddress()))) .filter(target -> IpUtil.isAmqpUri(IpUtil.addressToUri(target.getAddress())))
.map(t -> convertToDmfTarget(t, actions.get(t.getControllerId()).getId())) // as system - the security token is sent to DMF receiver
.map(t -> new DmfTarget(actions.get(t.getControllerId()).getId(), t.getControllerId(), asSystem(t::getSecurityToken)))
.toList(); .toList();
// due to the fact that all targets in a batch use the same set of software modules we don't generate target-specific urls // due to the fact that all targets in a batch use the same set of software modules we don't generate target-specific urls
final Target firstTarget = targets.get(0); final Target firstTarget = targets.get(0);
final DmfBatchDownloadAndUpdateRequest batchRequest = new DmfBatchDownloadAndUpdateRequest( final DmfBatchDownloadAndUpdateRequest batchRequest = new DmfBatchDownloadAndUpdateRequest(
System.currentTimeMillis(), java.lang.System.currentTimeMillis(),
dmfTargets, dmfTargets,
Optional.ofNullable(modules) Optional.ofNullable(modules)
.map(Map::entrySet) .map(Map::entrySet)
@@ -594,7 +579,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
.map(stream -> stream.map(entry -> convertToAmqpSoftwareModule(firstTarget, entry)).toList()) .map(stream -> stream.map(entry -> convertToAmqpSoftwareModule(firstTarget, entry)).toList())
.orElse(null)); .orElse(null));
// we use only the first action when constructing message as Tenant and action type are the same // we use only the first action when constructing message as AccessContext and action type are the same
// since all actions have the same trigger // since all actions have the same trigger
final ActionProperties firstAction = actions.values().iterator().next(); final ActionProperties firstAction = actions.values().iterator().next();
final Message message = getMessageConverter().toMessage( final Message message = getMessageConverter().toMessage(

View File

@@ -10,9 +10,7 @@
package org.eclipse.hawkbit.amqp; package org.eclipse.hawkbit.amqp;
import static org.eclipse.hawkbit.repository.RepositoryConstants.MAX_ACTION_COUNT; import static org.eclipse.hawkbit.repository.RepositoryConstants.MAX_ACTION_COUNT;
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.MULTI_ASSIGNMENTS_ENABLED;
import java.io.Serializable;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@@ -28,6 +26,7 @@ import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.audit.AuditLog; import org.eclipse.hawkbit.audit.AuditLog;
import org.eclipse.hawkbit.auth.SpRole;
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic; import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey; import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
import org.eclipse.hawkbit.dmf.amqp.api.MessageType; import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
@@ -37,14 +36,13 @@ import org.eclipse.hawkbit.dmf.json.model.DmfAttributeUpdate;
import org.eclipse.hawkbit.dmf.json.model.DmfAutoConfirmation; import org.eclipse.hawkbit.dmf.json.model.DmfAutoConfirmation;
import org.eclipse.hawkbit.dmf.json.model.DmfCreateThing; import org.eclipse.hawkbit.dmf.json.model.DmfCreateThing;
import org.eclipse.hawkbit.dmf.json.model.DmfUpdateMode; import org.eclipse.hawkbit.dmf.json.model.DmfUpdateMode;
import org.eclipse.hawkbit.im.authentication.SpRole;
import org.eclipse.hawkbit.repository.ConfirmationManagement; import org.eclipse.hawkbit.repository.ConfirmationManagement;
import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.RepositoryConstants;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.UpdateMode; import org.eclipse.hawkbit.repository.UpdateMode;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate; import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate;
import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate.ActionStatusCreateBuilder; import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate.ActionStatusCreateBuilder;
@@ -53,9 +51,9 @@ import org.eclipse.hawkbit.repository.model.ActionProperties;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails; import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
import org.eclipse.hawkbit.util.IpUtil; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
import org.eclipse.hawkbit.utils.IpUtil;
import org.springframework.amqp.AmqpRejectAndDontRequeueException; import org.springframework.amqp.AmqpRejectAndDontRequeueException;
import org.springframework.amqp.core.Message; import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.amqp.rabbit.annotation.RabbitListener;
@@ -82,30 +80,16 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
private final AmqpMessageDispatcherService amqpMessageDispatcherService; private final AmqpMessageDispatcherService amqpMessageDispatcherService;
private final ConfirmationManagement confirmationManagement; private final ConfirmationManagement confirmationManagement;
private final TenantConfigurationManagement tenantConfigurationManagement;
private final SystemSecurityContext systemSecurityContext;
private ControllerManagement controllerManagement; private ControllerManagement controllerManagement;
/**
* Constructor.
*
* @param rabbitTemplate for converting messages
* @param amqpMessageDispatcherService to sending events to DMF client
* @param controllerManagement for target repo access
* @param systemSecurityContext the system Security Context
* @param tenantConfigurationManagement the tenant configuration Management
* @param confirmationManagement the confirmation management
*/
public AmqpMessageHandlerService( public AmqpMessageHandlerService(
final RabbitTemplate rabbitTemplate, final RabbitTemplate rabbitTemplate,
final AmqpMessageDispatcherService amqpMessageDispatcherService, final AmqpMessageDispatcherService amqpMessageDispatcherService,
final ControllerManagement controllerManagement, final SystemSecurityContext systemSecurityContext, final ControllerManagement controllerManagement,
final TenantConfigurationManagement tenantConfigurationManagement, final ConfirmationManagement confirmationManagement) { final ConfirmationManagement confirmationManagement) {
super(rabbitTemplate); super(rabbitTemplate);
this.amqpMessageDispatcherService = amqpMessageDispatcherService; this.amqpMessageDispatcherService = amqpMessageDispatcherService;
this.controllerManagement = controllerManagement; this.controllerManagement = controllerManagement;
this.systemSecurityContext = systemSecurityContext;
this.tenantConfigurationManagement = tenantConfigurationManagement;
this.confirmationManagement = confirmationManagement; this.confirmationManagement = confirmationManagement;
} }
@@ -331,7 +315,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
} }
private void sendUpdateCommandToTarget(final Target target) { private void sendUpdateCommandToTarget(final Target target) {
if (isMultiAssignmentsEnabled()) { if (TenantConfigHelper.getAsSystem(TenantConfigurationProperties.TenantConfigurationKey.MULTI_ASSIGNMENTS_ENABLED, Boolean.class)) {
sendCurrentActionsAsMultiActionToTarget(target); sendCurrentActionsAsMultiActionToTarget(target);
} else { } else {
sendOldestActionToTarget(target); sendOldestActionToTarget(target);
@@ -456,8 +440,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
} else if (actionUpdateStatus.getActionStatus() == DmfActionStatus.DENIED) { } else if (actionUpdateStatus.getActionStatus() == DmfActionStatus.DENIED) {
updatedAction = confirmationManagement.denyAction(action.getId(), actionUpdateStatus.getCode(), messages); updatedAction = confirmationManagement.denyAction(action.getId(), actionUpdateStatus.getCode(), messages);
} else { } else {
final ActionStatusCreateBuilder actionStatus = ActionStatusCreate.builder().actionId(action.getId()) final ActionStatusCreateBuilder actionStatus = ActionStatusCreate.builder().actionId(action.getId()).status(status);
.status(status);
Optional.ofNullable(actionUpdateStatus.getCode()).ifPresentOrElse( Optional.ofNullable(actionUpdateStatus.getCode()).ifPresentOrElse(
code -> { code -> {
actionStatus.code(code); actionStatus.code(code);
@@ -491,12 +474,4 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
return findActionWithDetails.get(); return findActionWithDetails.get();
} }
private boolean isMultiAssignmentsEnabled() {
return getConfigValue(MULTI_ASSIGNMENTS_ENABLED, Boolean.class);
}
private <T extends Serializable> T getConfigValue(final String key, final Class<T> valueType) {
return systemSecurityContext.runAsSystem(() -> tenantConfigurationManagement.getConfigurationValue(key, valueType).getValue());
}
} }

View File

@@ -13,7 +13,7 @@ import java.net.URI;
import java.util.UUID; import java.util.UUID;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.util.IpUtil; import org.eclipse.hawkbit.utils.IpUtil;
import org.springframework.amqp.core.Message; import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData; import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.rabbit.core.RabbitTemplate;

View File

@@ -28,11 +28,9 @@ import org.eclipse.hawkbit.repository.RepositoryProperties;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder; import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange; import org.springframework.amqp.core.FanoutExchange;
@@ -150,7 +148,7 @@ public class DmfApiConfiguration {
} }
/** /**
* Create the DMF API receiver queue for authentication requests called by 3rd * Create the DMF API receiver queue for auth requests called by 3rd
* party artifact storages for download authorization by devices. * party artifact storages for download authorization by devices.
* *
* @return the receiver queue * @return the receiver queue
@@ -227,12 +225,10 @@ public class DmfApiConfiguration {
public AmqpMessageHandlerService amqpMessageHandlerService( public AmqpMessageHandlerService amqpMessageHandlerService(
final RabbitTemplate rabbitTemplate, final RabbitTemplate rabbitTemplate,
final AmqpMessageDispatcherService amqpMessageDispatcherService, final AmqpMessageDispatcherService amqpMessageDispatcherService,
final ControllerManagement controllerManagement, final SystemSecurityContext systemSecurityContext, final ControllerManagement controllerManagement,
final TenantConfigurationManagement tenantConfigurationManagement,
final ConfirmationManagement confirmationManagement) { final ConfirmationManagement confirmationManagement) {
return new AmqpMessageHandlerService( return new AmqpMessageHandlerService(
rabbitTemplate, amqpMessageDispatcherService, controllerManagement, rabbitTemplate, amqpMessageDispatcherService, controllerManagement, confirmationManagement);
systemSecurityContext, tenantConfigurationManagement, confirmationManagement);
} }
/** /**
@@ -266,14 +262,14 @@ public class DmfApiConfiguration {
AmqpMessageDispatcherService amqpMessageDispatcherService( AmqpMessageDispatcherService amqpMessageDispatcherService(
final RabbitTemplate rabbitTemplate, final RabbitTemplate rabbitTemplate,
final AmqpMessageSenderService amqpSenderService, final ArtifactUrlResolver artifactUrlHandler, final AmqpMessageSenderService amqpSenderService, final ArtifactUrlResolver artifactUrlHandler,
final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement, final SystemManagement systemManagement,
final TargetManagement<? extends Target> targetManagement, final TargetManagement<? extends Target> targetManagement,
final DistributionSetManagement<? extends DistributionSet> distributionSetManagement, final DistributionSetManagement<? extends DistributionSet> distributionSetManagement,
final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement, final DeploymentManagement deploymentManagement, final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement, final DeploymentManagement deploymentManagement,
final TenantConfigurationManagement tenantConfigurationManagement, final RepositoryProperties repositoryProperties) { final RepositoryProperties repositoryProperties) {
return new AmqpMessageDispatcherService(rabbitTemplate, amqpSenderService, artifactUrlHandler, return new AmqpMessageDispatcherService(rabbitTemplate, amqpSenderService, artifactUrlHandler,
systemSecurityContext, systemManagement, targetManagement, softwareModuleManagement, distributionSetManagement, systemManagement, targetManagement, softwareModuleManagement, distributionSetManagement,
deploymentManagement, tenantConfigurationManagement, repositoryProperties); deploymentManagement, repositoryProperties);
} }
private static Map<String, Object> getTTLMaxArgsAuthenticationQueue() { private static Map<String, Object> getTTLMaxArgsAuthenticationQueue() {

View File

@@ -52,7 +52,7 @@ import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TenantMetaData; import org.eclipse.hawkbit.repository.model.TenantMetaData;
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest; import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.eclipse.hawkbit.util.IpUtil; import org.eclipse.hawkbit.utils.IpUtil;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
@@ -116,8 +116,8 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
when(systemManagement.getTenantMetadataWithoutDetails()).thenReturn(tenantMetaData); when(systemManagement.getTenantMetadataWithoutDetails()).thenReturn(tenantMetaData);
amqpMessageDispatcherService = new AmqpMessageDispatcherService(rabbitTemplate, senderService, amqpMessageDispatcherService = new AmqpMessageDispatcherService(rabbitTemplate, senderService,
artifactUrlHandlerMock, systemSecurityContext, systemManagement, targetManagement, artifactUrlHandlerMock, systemManagement, targetManagement,
softwareModuleManagement, distributionSetManagement, deploymentManagement, tenantConfigurationManagement, repositoryProperties); softwareModuleManagement, distributionSetManagement, deploymentManagement, repositoryProperties);
} }

View File

@@ -21,7 +21,6 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.lang.reflect.Field;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@@ -40,16 +39,12 @@ import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.UpdateMode; import org.eclipse.hawkbit.repository.UpdateMode;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.SecurityTokenGeneratorHolder; import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.ActionProperties; import org.eclipse.hawkbit.repository.model.ActionProperties;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
import org.eclipse.hawkbit.security.SecurityTokenGenerator;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@@ -93,8 +88,6 @@ class AmqpMessageHandlerServiceTest {
private TenantConfigurationManagement tenantConfigurationManagement; private TenantConfigurationManagement tenantConfigurationManagement;
@Mock @Mock
private RabbitTemplate rabbitTemplate; private RabbitTemplate rabbitTemplate;
@Mock
private UserAuthoritiesResolver authoritiesResolver;
@Captor @Captor
private ArgumentCaptor<Map<String, String>> attributesCaptor; private ArgumentCaptor<Map<String, String>> attributesCaptor;
@@ -116,6 +109,7 @@ class AmqpMessageHandlerServiceTest {
@BeforeEach @BeforeEach
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
void before() { void before() {
TenantConfigHelper.setTenantConfigurationManagement(tenantConfigurationManagement);
messageConverter = new Jackson2JsonMessageConverter(); messageConverter = new Jackson2JsonMessageConverter();
lenient().when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter); lenient().when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter);
final TenantConfigurationValue multiAssignmentConfig = TenantConfigurationValue.builder().value(Boolean.FALSE) final TenantConfigurationValue multiAssignmentConfig = TenantConfigurationValue.builder().value(Boolean.FALSE)
@@ -123,12 +117,8 @@ class AmqpMessageHandlerServiceTest {
lenient().when(tenantConfigurationManagement.getConfigurationValue(MULTI_ASSIGNMENTS_ENABLED, Boolean.class)) lenient().when(tenantConfigurationManagement.getConfigurationValue(MULTI_ASSIGNMENTS_ENABLED, Boolean.class))
.thenReturn(multiAssignmentConfig); .thenReturn(multiAssignmentConfig);
final SecurityContextTenantAware tenantAware = new SecurityContextTenantAware(authoritiesResolver); amqpMessageHandlerService = new AmqpMessageHandlerService(
final SystemSecurityContext systemSecurityContext = new SystemSecurityContext(tenantAware); rabbitTemplate, amqpMessageDispatcherServiceMock, controllerManagementMock, confirmationManagementMock);
amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate, amqpMessageDispatcherServiceMock,
controllerManagementMock, systemSecurityContext, tenantConfigurationManagement,
confirmationManagementMock);
} }
/** /**
@@ -442,7 +432,7 @@ class AmqpMessageHandlerServiceTest {
* Test next update is provided on finished action * Test next update is provided on finished action
*/ */
@Test @Test
void lookupNextUpdateActionAfterFinished() throws IllegalAccessException { void lookupNextUpdateActionAfterFinished() {
// Mock // Mock
final Action action = createActionWithTarget(22L); final Action action = createActionWithTarget(22L);
@@ -655,10 +645,7 @@ class AmqpMessageHandlerServiceTest {
return messageProperties; return messageProperties;
} }
private Action createActionWithTarget(final Long targetId) throws IllegalAccessException { private Action createActionWithTarget(final Long targetId) {
// is needed for the creation of targets
initializeSecurityTokenGenerator();
// Mock // Mock
final Action actionMock = mock(Action.class); final Action actionMock = mock(Action.class);
final Target targetMock = mock(Target.class); final Target targetMock = mock(Target.class);
@@ -673,17 +660,6 @@ class AmqpMessageHandlerServiceTest {
return actionMock; return actionMock;
} }
private void initializeSecurityTokenGenerator() throws IllegalAccessException {
final SecurityTokenGeneratorHolder instance = SecurityTokenGeneratorHolder.getInstance();
final Field[] fields = instance.getClass().getDeclaredFields();
for (final Field field : fields) {
if (field.getType().isAssignableFrom(SecurityTokenGenerator.class)) {
field.setAccessible(true);
field.set(instance, new SecurityTokenGenerator());
}
}
}
private MessageProperties getThingCreatedMessageProperties(final String thingId) { private MessageProperties getThingCreatedMessageProperties(final String thingId) {
final MessageProperties messageProperties = createMessageProperties(MessageType.THING_CREATED); final MessageProperties messageProperties = createMessageProperties(MessageType.THING_CREATED);
messageProperties.setHeader(MessageHeaderKey.THING_ID, thingId); messageProperties.setHeader(MessageHeaderKey.THING_ID, thingId);

View File

@@ -51,7 +51,7 @@ import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch; import org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.eclipse.hawkbit.util.IpUtil; import org.eclipse.hawkbit.utils.IpUtil;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.springframework.amqp.core.Message; import org.springframework.amqp.core.Message;
@@ -93,9 +93,9 @@ abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpIntegratio
} }
protected <T> T waitUntilIsPresent(final Callable<Optional<T>> callable) { protected <T> T waitUntilIsPresent(final Callable<Optional<T>> callable) {
await().until(() -> SecurityContextSwitch.callAsPrivileged(() -> callable.call().isPresent())); await().until(() -> SecurityContextSwitch.asPrivileged(() -> callable.call().isPresent()));
try { try {
return SecurityContextSwitch.callAsPrivileged(() -> callable.call().get()); return SecurityContextSwitch.asPrivileged(() -> callable.call().get());
} catch (final Exception e) { } catch (final Exception e) {
return null; return null;
} }
@@ -368,7 +368,7 @@ abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpIntegratio
waitUntilIsPresent(() -> controllerManagement.findByControllerId(controllerId)); waitUntilIsPresent(() -> controllerManagement.findByControllerId(controllerId));
await().untilAsserted(() -> { await().untilAsserted(() -> {
try { try {
final Map<String, String> controllerAttributes = SecurityContextSwitch.callAsPrivileged( final Map<String, String> controllerAttributes = SecurityContextSwitch.asPrivileged(
() -> targetManagement.getControllerAttributes(controllerId)); () -> targetManagement.getControllerAttributes(controllerId));
assertThat(controllerAttributes).hasSameSizeAs(attributes); assertThat(controllerAttributes).hasSameSizeAs(attributes);
assertThat(controllerAttributes).containsAllEntriesOf(attributes); assertThat(controllerAttributes).containsAllEntriesOf(attributes);

View File

@@ -793,7 +793,7 @@ class AmqpMessageDispatcherServiceIntegrationTest extends AbstractAmqpServiceInt
} }
private void waitUntil(final Callable<Boolean> callable) { private void waitUntil(final Callable<Boolean> callable) {
await().until(() -> SecurityContextSwitch.callAsPrivileged(callable)); await().until(() -> SecurityContextSwitch.asPrivileged(callable));
} }
private void assertLatestMultiActionMessageContainsInstallMessages(final String controllerId, private void assertLatestMultiActionMessageContainsInstallMessages(final String controllerId,

View File

@@ -1231,7 +1231,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
private void assertAction(final Long actionId, final int messages, final Status... expectedActionStates) { private void assertAction(final Long actionId, final int messages, final Status... expectedActionStates) {
await().untilAsserted(() -> { await().untilAsserted(() -> {
try { try {
SecurityContextSwitch.callAsPrivileged(() -> { SecurityContextSwitch.asPrivileged(() -> {
final List<ActionStatus> actionStatusList = deploymentManagement.findActionStatusByAction(actionId, PAGE).getContent(); final List<ActionStatus> actionStatusList = deploymentManagement.findActionStatusByAction(actionId, PAGE).getContent();
// Check correlation ID // Check correlation ID
@@ -1265,7 +1265,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
final Status... expectedActionStates) { final Status... expectedActionStates) {
await().untilAsserted(() -> { await().untilAsserted(() -> {
try { try {
SecurityContextSwitch.callAsPrivileged(() -> { SecurityContextSwitch.asPrivileged(() -> {
final List<ActionStatus> actionStatusList = deploymentManagement final List<ActionStatus> actionStatusList = deploymentManagement
.findActionStatusByAction(actionId, PAGE).getContent(); .findActionStatusByAction(actionId, PAGE).getContent();
assertThat(actionStatusList).hasSize(statusListCount); assertThat(actionStatusList).hasSize(statusListCount);

View File

@@ -14,7 +14,6 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.eclipse.hawkbit.repository.helper.SystemSecurityContextHolder;
import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
@@ -39,11 +38,6 @@ public class AmqpTestConfiguration {
return rabbitTemplate; return rabbitTemplate;
} }
@Bean
SystemSecurityContextHolder systemSecurityContextHolder() {
return SystemSecurityContextHolder.getInstance();
}
@Bean @Bean
Executor asyncExecutor() { Executor asyncExecutor() {
return new DelegatingSecurityContextExecutorService(Executors.newSingleThreadExecutor()); return new DelegatingSecurityContextExecutorService(Executors.newSingleThreadExecutor());

View File

@@ -11,6 +11,8 @@ package org.eclipse.hawkbit.mgmt.rest.api;
import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.ACTION_ORDER; import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.ACTION_ORDER;
import java.util.List;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.Extension;
import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
@@ -32,8 +34,6 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
/** /**
* REST API providing (read-only) access to actions. * REST API providing (read-only) access to actions.
*/ */
@@ -60,7 +60,7 @@ public interface MgmtActionRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -116,7 +116,7 @@ public interface MgmtActionRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "404", description = "Target not found.", @ApiResponse(responseCode = "404", description = "Target not found.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@@ -140,7 +140,7 @@ public interface MgmtActionRestApi {
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), @ApiResponse(responseCode = "401", description = "The request requires user auth.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or data volume restriction applies.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or data volume restriction applies.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "404", description = "Action not found.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), @ApiResponse(responseCode = "404", description = "Action not found.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@@ -160,7 +160,7 @@ public interface MgmtActionRestApi {
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), @ApiResponse(responseCode = "401", description = "The request requires user auth.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or data volume restriction applies.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or data volume restriction applies.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "406", description = "In case accept header is specified and not application/json.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), @ApiResponse(responseCode = "406", description = "In case accept header is specified and not application/json.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),

View File

@@ -76,7 +76,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -126,7 +126,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -159,7 +159,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -195,7 +195,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -226,7 +226,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -272,7 +272,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -331,7 +331,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -390,7 +390,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -448,7 +448,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully assigned"), @ApiResponse(responseCode = "200", description = "Successfully assigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -488,7 +488,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -527,7 +527,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -559,7 +559,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -593,7 +593,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully updated"), @ApiResponse(responseCode = "200", description = "Successfully updated"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -633,7 +633,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -668,7 +668,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "204", description = "Successfully assigned"), @ApiResponse(responseCode = "204", description = "Successfully assigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -709,7 +709,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -747,7 +747,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -796,7 +796,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -829,7 +829,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -861,7 +861,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -894,7 +894,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -930,7 +930,7 @@ public interface MgmtDistributionSetRestApi {
@ApiResponse(responseCode = "204", description = "Successfully invalidated distribution set"), @ApiResponse(responseCode = "204", description = "Successfully invalidated distribution set"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",

View File

@@ -64,7 +64,7 @@ public interface MgmtDistributionSetTagRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -115,7 +115,7 @@ public interface MgmtDistributionSetTagRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -148,7 +148,7 @@ public interface MgmtDistributionSetTagRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -186,7 +186,7 @@ public interface MgmtDistributionSetTagRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -227,7 +227,7 @@ public interface MgmtDistributionSetTagRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -269,7 +269,7 @@ public interface MgmtDistributionSetTagRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -324,7 +324,7 @@ public interface MgmtDistributionSetTagRestApi {
@ApiResponse(responseCode = "204", description = "Successfully assigned"), @ApiResponse(responseCode = "204", description = "Successfully assigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -362,7 +362,7 @@ public interface MgmtDistributionSetTagRestApi {
@ApiResponse(responseCode = "204", description = "Successfully assigned"), @ApiResponse(responseCode = "204", description = "Successfully assigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -404,7 +404,7 @@ public interface MgmtDistributionSetTagRestApi {
@ApiResponse(responseCode = "204", description = "Successfully unassigned"), @ApiResponse(responseCode = "204", description = "Successfully unassigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -439,7 +439,7 @@ public interface MgmtDistributionSetTagRestApi {
@ApiResponse(responseCode = "204", description = "Successfully unassigned"), @ApiResponse(responseCode = "204", description = "Successfully unassigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +

View File

@@ -66,7 +66,7 @@ public interface MgmtDistributionSetTypeRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -117,7 +117,7 @@ public interface MgmtDistributionSetTypeRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -150,7 +150,7 @@ public interface MgmtDistributionSetTypeRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -182,7 +182,7 @@ public interface MgmtDistributionSetTypeRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -225,7 +225,7 @@ public interface MgmtDistributionSetTypeRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -264,7 +264,7 @@ public interface MgmtDistributionSetTypeRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -301,7 +301,7 @@ public interface MgmtDistributionSetTypeRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -338,7 +338,7 @@ public interface MgmtDistributionSetTypeRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -374,7 +374,7 @@ public interface MgmtDistributionSetTypeRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -410,7 +410,7 @@ public interface MgmtDistributionSetTypeRestApi {
@ApiResponse(responseCode = "204", description = "Successfully removed"), @ApiResponse(responseCode = "204", description = "Successfully removed"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -447,7 +447,7 @@ public interface MgmtDistributionSetTypeRestApi {
@ApiResponse(responseCode = "204", description = "Successfully removed"), @ApiResponse(responseCode = "204", description = "Successfully removed"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -484,7 +484,7 @@ public interface MgmtDistributionSetTypeRestApi {
@ApiResponse(responseCode = "204", description = "Successfully added"), @ApiResponse(responseCode = "204", description = "Successfully added"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -528,7 +528,7 @@ public interface MgmtDistributionSetTypeRestApi {
@ApiResponse(responseCode = "204", description = "Successfully added"), @ApiResponse(responseCode = "204", description = "Successfully added"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +

View File

@@ -81,7 +81,7 @@ public final class MgmtRestConstants {
*/ */
public static final String ROLLOUT_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING + "/rollouts"; public static final String ROLLOUT_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING + "/rollouts";
/** /**
* The basic authentication validation mapping * The basic auth validation mapping
*/ */
public static final String AUTH_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING + "/userinfo"; public static final String AUTH_V1_REQUEST_MAPPING = BASE_V1_REQUEST_MAPPING + "/userinfo";
/** /**

View File

@@ -65,7 +65,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -119,7 +119,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -152,7 +152,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -191,7 +191,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -234,7 +234,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "204", description = "Successfully approved"), @ApiResponse(responseCode = "204", description = "Successfully approved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -268,7 +268,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "204", description = "Successfully denied"), @ApiResponse(responseCode = "204", description = "Successfully denied"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -300,7 +300,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "204", description = "Successfully started"), @ApiResponse(responseCode = "204", description = "Successfully started"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -330,7 +330,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "204", description = "Successfully paused"), @ApiResponse(responseCode = "204", description = "Successfully paused"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -361,7 +361,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "204", description = "Successfully stopped"), @ApiResponse(responseCode = "204", description = "Successfully stopped"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -394,7 +394,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -426,7 +426,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "204", description = "Successfully resumed"), @ApiResponse(responseCode = "204", description = "Successfully resumed"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -462,7 +462,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -520,7 +520,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -561,7 +561,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -616,7 +616,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "204", description = "Successfully triggered"), @ApiResponse(responseCode = "204", description = "Successfully triggered"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -646,7 +646,7 @@ public interface MgmtRolloutRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +

View File

@@ -71,7 +71,7 @@ public interface MgmtSoftwareModuleRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -113,7 +113,7 @@ public interface MgmtSoftwareModuleRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -148,7 +148,7 @@ public interface MgmtSoftwareModuleRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -183,7 +183,7 @@ public interface MgmtSoftwareModuleRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -220,7 +220,7 @@ public interface MgmtSoftwareModuleRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -270,7 +270,7 @@ public interface MgmtSoftwareModuleRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -302,7 +302,7 @@ public interface MgmtSoftwareModuleRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -336,7 +336,7 @@ public interface MgmtSoftwareModuleRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -375,7 +375,7 @@ public interface MgmtSoftwareModuleRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -405,7 +405,7 @@ public interface MgmtSoftwareModuleRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -441,7 +441,7 @@ public interface MgmtSoftwareModuleRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -473,7 +473,7 @@ public interface MgmtSoftwareModuleRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -507,7 +507,7 @@ public interface MgmtSoftwareModuleRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -539,7 +539,7 @@ public interface MgmtSoftwareModuleRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +

View File

@@ -65,7 +65,7 @@ public interface MgmtSoftwareModuleTypeRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -116,7 +116,7 @@ public interface MgmtSoftwareModuleTypeRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -149,7 +149,7 @@ public interface MgmtSoftwareModuleTypeRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -182,7 +182,7 @@ public interface MgmtSoftwareModuleTypeRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -225,7 +225,7 @@ public interface MgmtSoftwareModuleTypeRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +

View File

@@ -59,7 +59,7 @@ public interface MgmtTargetFilterQueryRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -95,7 +95,7 @@ public interface MgmtTargetFilterQueryRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -147,7 +147,7 @@ public interface MgmtTargetFilterQueryRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -187,7 +187,7 @@ public interface MgmtTargetFilterQueryRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -227,7 +227,7 @@ public interface MgmtTargetFilterQueryRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -257,7 +257,7 @@ public interface MgmtTargetFilterQueryRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -289,7 +289,7 @@ public interface MgmtTargetFilterQueryRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -331,7 +331,7 @@ public interface MgmtTargetFilterQueryRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +

View File

@@ -9,6 +9,10 @@
*/ */
package org.eclipse.hawkbit.mgmt.rest.api; package org.eclipse.hawkbit.mgmt.rest.api;
import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.TARGET_GROUP_ORDER;
import java.util.List;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.extensions.Extension; import io.swagger.v3.oas.annotations.extensions.Extension;
import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
@@ -31,10 +35,6 @@ import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
import static org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants.TARGET_GROUP_ORDER;
@Tag( @Tag(
name = "Target Groups", description = "REST API for Target Groups operations.", name = "Target Groups", description = "REST API for Target Groups operations.",
extensions = @Extension(name = OpenApi.X_HAWKBIT, properties = @ExtensionProperty(name = "order", value = TARGET_GROUP_ORDER))) extensions = @Extension(name = OpenApi.X_HAWKBIT, properties = @ExtensionProperty(name = "order", value = TARGET_GROUP_ORDER)))
@@ -60,7 +60,7 @@ public interface MgmtTargetGroupRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."), @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."),
@@ -113,7 +113,7 @@ public interface MgmtTargetGroupRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."), @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."),
@@ -163,7 +163,7 @@ public interface MgmtTargetGroupRestApi {
@ApiResponse(responseCode = "204", description = "Successfully assigned"), @ApiResponse(responseCode = "204", description = "Successfully assigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."), @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."),
@@ -199,7 +199,7 @@ public interface MgmtTargetGroupRestApi {
@ApiResponse(responseCode = "204", description = "Successfully assigned"), @ApiResponse(responseCode = "204", description = "Successfully assigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."), @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."),
@@ -235,7 +235,7 @@ public interface MgmtTargetGroupRestApi {
@ApiResponse(responseCode = "204", description = "Successfully assigned"), @ApiResponse(responseCode = "204", description = "Successfully assigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."), @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."),
@@ -268,7 +268,7 @@ public interface MgmtTargetGroupRestApi {
@ApiResponse(responseCode = "204", description = "Successfully unassigned"), @ApiResponse(responseCode = "204", description = "Successfully unassigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."), @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."),
@@ -295,7 +295,7 @@ public interface MgmtTargetGroupRestApi {
@ApiResponse(responseCode = "204", description = "Successfully unassigned"), @ApiResponse(responseCode = "204", description = "Successfully unassigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."), @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."),
@@ -320,7 +320,7 @@ public interface MgmtTargetGroupRestApi {
description = "Handles the GET request of retrieving a list of all target groups.") description = "Handles the GET request of retrieving a list of all target groups.")
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."), @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."),
@@ -345,7 +345,7 @@ public interface MgmtTargetGroupRestApi {
@ApiResponse(responseCode = "204", description = "Successfully assigned"), @ApiResponse(responseCode = "204", description = "Successfully assigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."), @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."),

View File

@@ -43,7 +43,6 @@ import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTargetRequestBody;
import org.eclipse.hawkbit.rest.OpenApi; import org.eclipse.hawkbit.rest.OpenApi;
import org.eclipse.hawkbit.rest.json.model.ExceptionInfo; import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
import org.springframework.hateoas.MediaTypes; import org.springframework.hateoas.MediaTypes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
@@ -53,7 +52,6 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
/** /**
* API for handling target operations. * API for handling target operations.
@@ -76,7 +74,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -112,7 +110,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -163,7 +161,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -202,7 +200,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -242,7 +240,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -272,7 +270,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "204", description = "Successfully unassigned"), @ApiResponse(responseCode = "204", description = "Successfully unassigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -299,7 +297,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "204", description = "Successfully assigned"), @ApiResponse(responseCode = "204", description = "Successfully assigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -326,7 +324,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -362,7 +360,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -418,7 +416,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted."), @ApiResponse(responseCode = "204", description = "Successfully deleted."),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -453,7 +451,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -487,7 +485,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "204", description = "Success"), @ApiResponse(responseCode = "204", description = "Success"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -521,7 +519,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully updated"), @ApiResponse(responseCode = "200", description = "Successfully updated"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -564,7 +562,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "204", description = "Successfully updated confirmation status of the action"), @ApiResponse(responseCode = "204", description = "Successfully updated confirmation status of the action"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies.", "changed (i.e. read-only) or data volume restriction applies.",
@@ -612,7 +610,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -647,7 +645,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -680,7 +678,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully assigned"), @ApiResponse(responseCode = "200", description = "Successfully assigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -726,7 +724,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -753,7 +751,7 @@ public interface MgmtTargetRestApi {
@Operation(summary = "Return tags for specific target", description = "Get a paged list of tags for a target. Required permission: READ_REPOSITORY") @Operation(summary = "Return tags for specific target", description = "Get a paged list of tags for a target. Required permission: READ_REPOSITORY")
@ApiResponses(value = { @ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -783,7 +781,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -819,7 +817,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -850,7 +848,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -883,7 +881,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "204", description = "Successfully updated"), @ApiResponse(responseCode = "204", description = "Successfully updated"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or data volume restriction applies.", description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or data volume restriction applies.",
@@ -921,7 +919,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -950,7 +948,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or data volume restriction applies.", description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or data volume restriction applies.",
@@ -980,7 +978,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "204", description = "Successfully activated auto-confirm"), @ApiResponse(responseCode = "204", description = "Successfully activated auto-confirm"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -1017,7 +1015,7 @@ public interface MgmtTargetRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deactivated auto-confirm"), @ApiResponse(responseCode = "204", description = "Successfully deactivated auto-confirm"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +

View File

@@ -64,7 +64,7 @@ public interface MgmtTargetTagRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."), @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."),
@@ -109,7 +109,7 @@ public interface MgmtTargetTagRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "404", description = "Target tag not found.", @ApiResponse(responseCode = "404", description = "Target tag not found.",
@@ -136,7 +136,7 @@ public interface MgmtTargetTagRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."), @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."),
@@ -165,7 +165,7 @@ public interface MgmtTargetTagRestApi {
@ApiResponse(responseCode = "200", description = "Successfully updated"), @ApiResponse(responseCode = "200", description = "Successfully updated"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "404", description = "Target tag not found.", @ApiResponse(responseCode = "404", description = "Target tag not found.",
@@ -198,7 +198,7 @@ public interface MgmtTargetTagRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "404", description = "Target tag not found.", @ApiResponse(responseCode = "404", description = "Target tag not found.",
@@ -228,7 +228,7 @@ public interface MgmtTargetTagRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "404", description = "Target tag not found", @ApiResponse(responseCode = "404", description = "Target tag not found",
@@ -277,7 +277,7 @@ public interface MgmtTargetTagRestApi {
@ApiResponse(responseCode = "204", description = "Successfully assigned"), @ApiResponse(responseCode = "204", description = "Successfully assigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."), @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource."),
@@ -308,7 +308,7 @@ public interface MgmtTargetTagRestApi {
@ApiResponse(responseCode = "204", description = "Successfully assigned"), @ApiResponse(responseCode = "204", description = "Successfully assigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "404", description = "Not Found - e.g. target tag not found. Contains info about not found.", @ApiResponse(responseCode = "404", description = "Not Found - e.g. target tag not found. Contains info about not found.",
@@ -344,7 +344,7 @@ public interface MgmtTargetTagRestApi {
@ApiResponse(responseCode = "204", description = "Successfully unassigned"), @ApiResponse(responseCode = "204", description = "Successfully unassigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "404", description = "Target not found.", @ApiResponse(responseCode = "404", description = "Target not found.",
@@ -373,7 +373,7 @@ public interface MgmtTargetTagRestApi {
@ApiResponse(responseCode = "204", description = "Successfully unassigned"), @ApiResponse(responseCode = "204", description = "Successfully unassigned"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication."), @ApiResponse(responseCode = "401", description = "The request requires user auth."),
@ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be " +
"changed (i.e. read-only) or data volume restriction applies."), "changed (i.e. read-only) or data volume restriction applies."),
@ApiResponse(responseCode = "404", description = "Not Found - e.g. target tag not found. Contains info about not found.", @ApiResponse(responseCode = "404", description = "Not Found - e.g. target tag not found. Contains info about not found.",

View File

@@ -65,7 +65,7 @@ public interface MgmtTargetTypeRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -116,7 +116,7 @@ public interface MgmtTargetTypeRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -148,7 +148,7 @@ public interface MgmtTargetTypeRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -180,7 +180,7 @@ public interface MgmtTargetTypeRestApi {
@ApiResponse(responseCode = "200", description = "Successfully updated"), @ApiResponse(responseCode = "200", description = "Successfully updated"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -222,7 +222,7 @@ public interface MgmtTargetTypeRestApi {
@ApiResponse(responseCode = "201", description = "Successfully created"), @ApiResponse(responseCode = "201", description = "Successfully created"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -262,7 +262,7 @@ public interface MgmtTargetTypeRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -297,7 +297,7 @@ public interface MgmtTargetTypeRestApi {
@ApiResponse(responseCode = "204", description = "Successfully removed"), @ApiResponse(responseCode = "204", description = "Successfully removed"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -333,7 +333,7 @@ public interface MgmtTargetTypeRestApi {
@ApiResponse(responseCode = "204", description = "Successfully added"), @ApiResponse(responseCode = "204", description = "Successfully added"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +

View File

@@ -56,7 +56,7 @@ public interface MgmtTenantManagementRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -88,7 +88,7 @@ public interface MgmtTenantManagementRestApi {
@ApiResponse(responseCode = "204", description = "Successfully deleted"), @ApiResponse(responseCode = "204", description = "Successfully deleted"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -120,7 +120,7 @@ public interface MgmtTenantManagementRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -156,7 +156,7 @@ public interface MgmtTenantManagementRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +
@@ -198,7 +198,7 @@ public interface MgmtTenantManagementRestApi {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"), @ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))),
@ApiResponse(responseCode = "401", description = "The request requires user authentication.", @ApiResponse(responseCode = "401", description = "The request requires user auth.",
content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))),
@ApiResponse(responseCode = "403", @ApiResponse(responseCode = "403",
description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " + description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or " +

View File

@@ -11,6 +11,8 @@ package org.eclipse.hawkbit.mgmt.rest.resource;
import static org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility.sanitizeActionSortParam; import static org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility.sanitizeActionSortParam;
import java.util.List;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.audit.AuditLog; import org.eclipse.hawkbit.audit.AuditLog;
import org.eclipse.hawkbit.mgmt.json.model.PagedList; import org.eclipse.hawkbit.mgmt.json.model.PagedList;
@@ -29,8 +31,6 @@ import org.springframework.http.ResponseEntity;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Slf4j @Slf4j
@RestController @RestController
@ConditionalOnProperty(name = "hawkbit.rest.MgmtActionResource.enabled", matchIfMissing = true) @ConditionalOnProperty(name = "hawkbit.rest.MgmtActionResource.enabled", matchIfMissing = true)

View File

@@ -10,9 +10,9 @@
package org.eclipse.hawkbit.mgmt.rest.resource; package org.eclipse.hawkbit.mgmt.rest.resource;
import org.eclipse.hawkbit.audit.AuditLog; import org.eclipse.hawkbit.audit.AuditLog;
import org.eclipse.hawkbit.context.AccessContext;
import org.eclipse.hawkbit.mgmt.json.model.auth.MgmtUserInfo; import org.eclipse.hawkbit.mgmt.json.model.auth.MgmtUserInfo;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtBasicAuthRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtBasicAuthRestApi;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
@@ -25,18 +25,12 @@ import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
public class MgmtBasicAuthResource implements MgmtBasicAuthRestApi { public class MgmtBasicAuthResource implements MgmtBasicAuthRestApi {
private final TenantAware tenantAware;
public MgmtBasicAuthResource(final TenantAware tenantAware) {
this.tenantAware = tenantAware;
}
@Override @Override
@AuditLog(entity = "BasicAuth", type = AuditLog.Type.READ, description = "Validate Basic Auth") @AuditLog(entity = "BasicAuth", type = AuditLog.Type.READ, description = "Validate Basic Auth")
public ResponseEntity<MgmtUserInfo> validateBasicAuth() { public ResponseEntity<MgmtUserInfo> validateBasicAuth() {
final MgmtUserInfo userInfo = new MgmtUserInfo(); final MgmtUserInfo userInfo = new MgmtUserInfo();
userInfo.setTenant(tenantAware.getCurrentTenant()); userInfo.setTenant(AccessContext.tenant());
userInfo.setUsername(tenantAware.getCurrentUsername()); userInfo.setUsername(AccessContext.actor());
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) { if (authentication != null) {
userInfo.setPermissions(authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).toArray(String[]::new)); userInfo.setPermissions(authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).toArray(String[]::new));

View File

@@ -55,8 +55,8 @@ import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.repository.model.DeploymentRequest; import org.eclipse.hawkbit.repository.model.DeploymentRequest;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult; import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
@@ -65,8 +65,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@@ -89,7 +87,6 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
private final DeploymentManagement deployManagement; private final DeploymentManagement deployManagement;
private final SystemManagement systemManagement; private final SystemManagement systemManagement;
private final MgmtDistributionSetMapper mgmtDistributionSetMapper; private final MgmtDistributionSetMapper mgmtDistributionSetMapper;
private final TenantConfigHelper tenantConfigHelper;
@SuppressWarnings("java:S107") @SuppressWarnings("java:S107")
MgmtDistributionSetResource( MgmtDistributionSetResource(
@@ -99,9 +96,9 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
final DistributionSetInvalidationManagement distributionSetInvalidationManagement, final DistributionSetInvalidationManagement distributionSetInvalidationManagement,
final TargetManagement<? extends Target> targetManagement, final TargetManagement<? extends Target> targetManagement,
final TargetFilterQueryManagement<? extends TargetFilterQuery> targetFilterQueryManagement, final TargetFilterQueryManagement<? extends TargetFilterQuery> targetFilterQueryManagement,
final DeploymentManagement deployManagement, final TenantConfigurationManagement tenantConfigurationManagement, final DeploymentManagement deployManagement,
final MgmtDistributionSetMapper mgmtDistributionSetMapper, final MgmtDistributionSetMapper mgmtDistributionSetMapper,
final SystemManagement systemManagement, final SystemSecurityContext systemSecurityContext) { final SystemManagement systemManagement) {
this.softwareModuleManagement = softwareModuleManagement; this.softwareModuleManagement = softwareModuleManagement;
this.distributionSetManagement = distributionSetManagement; this.distributionSetManagement = distributionSetManagement;
this.distributionSetTypeManagement = distributionSetTypeManagement; this.distributionSetTypeManagement = distributionSetTypeManagement;
@@ -109,7 +106,6 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
this.targetManagement = targetManagement; this.targetManagement = targetManagement;
this.targetFilterQueryManagement = targetFilterQueryManagement; this.targetFilterQueryManagement = targetFilterQueryManagement;
this.deployManagement = deployManagement; this.deployManagement = deployManagement;
this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
this.mgmtDistributionSetMapper = mgmtDistributionSetMapper; this.mgmtDistributionSetMapper = mgmtDistributionSetMapper;
this.systemManagement = systemManagement; this.systemManagement = systemManagement;
} }
@@ -209,7 +205,7 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
} }
return ResponseEntity.ok(new PagedList<>( return ResponseEntity.ok(new PagedList<>(
MgmtTargetMapper.toResponse(targetsAssignedDS.getContent(), tenantConfigHelper), targetsAssignedDS.getTotalElements())); MgmtTargetMapper.toResponse(targetsAssignedDS.getContent()), targetsAssignedDS.getTotalElements()));
} }
@Override @Override
@@ -227,7 +223,7 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
} }
return ResponseEntity.ok(new PagedList<>( return ResponseEntity.ok(new PagedList<>(
MgmtTargetMapper.toResponse(targetsInstalledDS.getContent(), tenantConfigHelper), targetsInstalledDS.getTotalElements())); MgmtTargetMapper.toResponse(targetsInstalledDS.getContent()), targetsInstalledDS.getTotalElements()));
} }
@Override @Override
@@ -239,7 +235,8 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
.findByAutoAssignDSAndRsql(distributionSetId, rsqlParam, pageable); .findByAutoAssignDSAndRsql(distributionSetId, rsqlParam, pageable);
return ResponseEntity.ok(new PagedList<>( return ResponseEntity.ok(new PagedList<>(
MgmtTargetFilterQueryMapper.toResponse(targetFilterQueries.getContent(), tenantConfigHelper.isConfirmationFlowEnabled(), false), MgmtTargetFilterQueryMapper.toResponse(
targetFilterQueries.getContent(), TenantConfigHelper.isUserConfirmationFlowEnabled(), false),
targetFilterQueries.getTotalElements())); targetFilterQueries.getTotalElements()));
} }
@@ -256,13 +253,13 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
final List<DeploymentRequest> deploymentRequests = assignments.stream().map(dsAssignment -> { final List<DeploymentRequest> deploymentRequests = assignments.stream().map(dsAssignment -> {
final boolean isConfirmationRequired = dsAssignment.getConfirmationRequired() == null final boolean isConfirmationRequired = dsAssignment.getConfirmationRequired() == null
? tenantConfigHelper.isConfirmationFlowEnabled() ? TenantConfigHelper.isUserConfirmationFlowEnabled()
: dsAssignment.getConfirmationRequired(); : dsAssignment.getConfirmationRequired();
return MgmtDeploymentRequestMapper.createAssignmentRequestBuilder(dsAssignment, distributionSetId) return MgmtDeploymentRequestMapper.createAssignmentRequestBuilder(dsAssignment, distributionSetId)
.confirmationRequired(isConfirmationRequired).build(); .confirmationRequired(isConfirmationRequired).build();
}).toList(); }).toList();
final List<DistributionSetAssignmentResult> assignmentResults = deployManagement.assignDistributionSets(deploymentRequests); final List<DistributionSetAssignmentResult> assignmentResults = deployManagement.assignDistributionSets(deploymentRequests, null);
return ResponseEntity.ok(mgmtDistributionSetMapper.toResponse(assignmentResults)); return ResponseEntity.ok(mgmtDistributionSetMapper.toResponse(assignmentResults));
} }

View File

@@ -80,7 +80,7 @@ public class MgmtOpenApiConfiguration {
private static ServerVariable tenantSeverVariable() { private static ServerVariable tenantSeverVariable() {
final ServerVariable tenantServerVariable = new ServerVariable(); final ServerVariable tenantServerVariable = new ServerVariable();
tenantServerVariable.setDescription("Tenant identifier"); tenantServerVariable.setDescription("AccessContext identifier");
tenantServerVariable.setDefault("DEFAULT"); tenantServerVariable.setDefault("DEFAULT");
return tenantServerVariable; return tenantServerVariable;
} }

View File

@@ -37,9 +37,9 @@ import org.eclipse.hawkbit.repository.RolloutManagement;
import org.eclipse.hawkbit.repository.RolloutManagement.Create; import org.eclipse.hawkbit.repository.RolloutManagement.Create;
import org.eclipse.hawkbit.repository.RolloutManagement.GroupCreate; import org.eclipse.hawkbit.repository.RolloutManagement.GroupCreate;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException; import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup;
@@ -47,8 +47,6 @@ import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
import org.eclipse.hawkbit.repository.model.RolloutGroupConditions; import org.eclipse.hawkbit.repository.model.RolloutGroupConditions;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@@ -66,19 +64,15 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
private final RolloutGroupManagement rolloutGroupManagement; private final RolloutGroupManagement rolloutGroupManagement;
private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement; private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement;
private final TargetFilterQueryManagement<? extends TargetFilterQuery> targetFilterQueryManagement; private final TargetFilterQueryManagement<? extends TargetFilterQuery> targetFilterQueryManagement;
private final TenantConfigHelper tenantConfigHelper;
MgmtRolloutResource( MgmtRolloutResource(
final RolloutManagement rolloutManagement, final RolloutGroupManagement rolloutGroupManagement, final RolloutManagement rolloutManagement, final RolloutGroupManagement rolloutGroupManagement,
final DistributionSetManagement<? extends DistributionSet> distributionSetManagement, final DistributionSetManagement<? extends DistributionSet> distributionSetManagement,
final TargetFilterQueryManagement<? extends TargetFilterQuery> targetFilterQueryManagement, final TargetFilterQueryManagement<? extends TargetFilterQuery> targetFilterQueryManagement) {
final SystemSecurityContext systemSecurityContext,
final TenantConfigurationManagement tenantConfigurationManagement) {
this.rolloutManagement = rolloutManagement; this.rolloutManagement = rolloutManagement;
this.rolloutGroupManagement = rolloutGroupManagement; this.rolloutGroupManagement = rolloutGroupManagement;
this.distributionSetManagement = distributionSetManagement; this.distributionSetManagement = distributionSetManagement;
this.targetFilterQueryManagement = targetFilterQueryManagement; this.targetFilterQueryManagement = targetFilterQueryManagement;
this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
} }
@Override @Override
@@ -121,7 +115,7 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
final DistributionSet distributionSet = distributionSetManagement.getValidAndComplete(rolloutRequestBody.getDistributionSetId()); final DistributionSet distributionSet = distributionSetManagement.getValidAndComplete(rolloutRequestBody.getDistributionSetId());
final RolloutGroupConditions rolloutGroupConditions = MgmtRolloutMapper.fromRequest(rolloutRequestBody, true); final RolloutGroupConditions rolloutGroupConditions = MgmtRolloutMapper.fromRequest(rolloutRequestBody, true);
final Create create = MgmtRolloutMapper.fromRequest(rolloutRequestBody, distributionSet); final Create create = MgmtRolloutMapper.fromRequest(rolloutRequestBody, distributionSet);
final boolean confirmationFlowActive = tenantConfigHelper.isConfirmationFlowEnabled(); final boolean confirmationFlowActive = TenantConfigHelper.isUserConfirmationFlowEnabled();
final Rollout rollout; final Rollout rollout;
if (rolloutRequestBody.getGroups() != null) { if (rolloutRequestBody.getGroups() != null) {
@@ -226,7 +220,7 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
} }
final List<MgmtRolloutGroupResponseBody> rest = MgmtRolloutMapper.toResponseRolloutGroup( final List<MgmtRolloutGroupResponseBody> rest = MgmtRolloutMapper.toResponseRolloutGroup(
rolloutGroups.getContent(), tenantConfigHelper.isConfirmationFlowEnabled(), isFullMode); rolloutGroups.getContent(), TenantConfigHelper.isUserConfirmationFlowEnabled(), isFullMode);
return ResponseEntity.ok(new PagedList<>(rest, rolloutGroups.getTotalElements())); return ResponseEntity.ok(new PagedList<>(rest, rolloutGroups.getTotalElements()));
} }
@@ -240,7 +234,7 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
} }
return ResponseEntity.ok(MgmtRolloutMapper.toResponseRolloutGroup( return ResponseEntity.ok(MgmtRolloutMapper.toResponseRolloutGroup(
rolloutGroup, true, tenantConfigHelper.isConfirmationFlowEnabled())); rolloutGroup, true, TenantConfigHelper.isUserConfirmationFlowEnabled()));
} }
@Override @Override
@@ -255,7 +249,7 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
} else { } else {
rolloutGroupTargets = this.rolloutGroupManagement.findTargetsOfRolloutGroupByRsql(groupId, rsqlParam, pageable); rolloutGroupTargets = this.rolloutGroupManagement.findTargetsOfRolloutGroupByRsql(groupId, rsqlParam, pageable);
} }
final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(rolloutGroupTargets.getContent(), tenantConfigHelper); final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(rolloutGroupTargets.getContent());
return ResponseEntity.ok(new PagedList<>(rest, rolloutGroupTargets.getTotalElements())); return ResponseEntity.ok(new PagedList<>(rest, rolloutGroupTargets.getTotalElements()));
} }

View File

@@ -22,6 +22,8 @@ import java.util.Optional;
import jakarta.validation.ValidationException; import jakarta.validation.ValidationException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.artifact.model.ArtifactHashes;
import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver;
import org.eclipse.hawkbit.audit.AuditLog; import org.eclipse.hawkbit.audit.AuditLog;
import org.eclipse.hawkbit.mgmt.json.model.PagedList; import org.eclipse.hawkbit.mgmt.json.model.PagedList;
import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact; import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact;
@@ -38,8 +40,6 @@ import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement; import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.artifact.model.ArtifactHashes;
import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.ArtifactUpload; import org.eclipse.hawkbit.repository.model.ArtifactUpload;

View File

@@ -27,12 +27,10 @@ import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtTargetFilterQueryMapper
import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility; import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate; import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@@ -47,14 +45,9 @@ import org.springframework.web.bind.annotation.RestController;
public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestApi { public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestApi {
private final TargetFilterQueryManagement<? extends TargetFilterQuery> filterManagement; private final TargetFilterQueryManagement<? extends TargetFilterQuery> filterManagement;
private final TenantConfigHelper tenantConfigHelper;
MgmtTargetFilterQueryResource( MgmtTargetFilterQueryResource(final TargetFilterQueryManagement<? extends TargetFilterQuery> filterManagement) {
final TargetFilterQueryManagement<? extends TargetFilterQuery> filterManagement,
final SystemSecurityContext systemSecurityContext,
final TenantConfigurationManagement tenantConfigurationManagement) {
this.filterManagement = filterManagement; this.filterManagement = filterManagement;
this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
} }
@Override @Override
@@ -62,7 +55,7 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
final TargetFilterQuery findTarget = findFilterWithExceptionIfNotFound(filterId); final TargetFilterQuery findTarget = findFilterWithExceptionIfNotFound(filterId);
// to single response include poll status // to single response include poll status
final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(findTarget, final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(findTarget,
tenantConfigHelper.isConfirmationFlowEnabled(), true); TenantConfigHelper.isUserConfirmationFlowEnabled(), true);
MgmtTargetFilterQueryMapper.addLinks(response); MgmtTargetFilterQueryMapper.addLinks(response);
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
@@ -82,8 +75,8 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
final boolean isRepresentationFull = parseRepresentationMode(representationModeParam) == MgmtRepresentationMode.FULL; final boolean isRepresentationFull = parseRepresentationMode(representationModeParam) == MgmtRepresentationMode.FULL;
final List<MgmtTargetFilterQuery> rest = MgmtTargetFilterQueryMapper final List<MgmtTargetFilterQuery> rest = MgmtTargetFilterQueryMapper.toResponse(
.toResponse(findTargetFiltersAll.getContent(), tenantConfigHelper.isConfirmationFlowEnabled(), isRepresentationFull); findTargetFiltersAll.getContent(), TenantConfigHelper.isUserConfirmationFlowEnabled(), isRepresentationFull);
return ResponseEntity.ok(new PagedList<>(rest, filterManagement.count())); return ResponseEntity.ok(new PagedList<>(rest, filterManagement.count()));
} }
@@ -92,7 +85,7 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
final TargetFilterQuery createdTarget = filterManagement.create(MgmtTargetFilterQueryMapper.fromRequest(filter)); final TargetFilterQuery createdTarget = filterManagement.create(MgmtTargetFilterQueryMapper.fromRequest(filter));
final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse( final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(
createdTarget, tenantConfigHelper.isConfirmationFlowEnabled(), false); createdTarget, TenantConfigHelper.isUserConfirmationFlowEnabled(), false);
MgmtTargetFilterQueryMapper.addLinks(response); MgmtTargetFilterQueryMapper.addLinks(response);
return new ResponseEntity<>(response, HttpStatus.CREATED); return new ResponseEntity<>(response, HttpStatus.CREATED);
@@ -108,7 +101,7 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
.build()); .build());
final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(updateFilter, final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(updateFilter,
tenantConfigHelper.isConfirmationFlowEnabled(), false); TenantConfigHelper.isUserConfirmationFlowEnabled(), false);
MgmtTargetFilterQueryMapper.addLinks(response); MgmtTargetFilterQueryMapper.addLinks(response);
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
@@ -141,7 +134,7 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
public ResponseEntity<MgmtTargetFilterQuery> postAssignedDistributionSet( public ResponseEntity<MgmtTargetFilterQuery> postAssignedDistributionSet(
final Long filterId, final MgmtDistributionSetAutoAssignment autoAssignRequest) { final Long filterId, final MgmtDistributionSetAutoAssignment autoAssignRequest) {
final boolean confirmationRequired = autoAssignRequest.getConfirmationRequired() == null final boolean confirmationRequired = autoAssignRequest.getConfirmationRequired() == null
? tenantConfigHelper.isConfirmationFlowEnabled() ? TenantConfigHelper.isUserConfirmationFlowEnabled()
: autoAssignRequest.getConfirmationRequired(); : autoAssignRequest.getConfirmationRequired();
final AutoAssignDistributionSetUpdate update = MgmtTargetFilterQueryMapper final AutoAssignDistributionSetUpdate update = MgmtTargetFilterQueryMapper
@@ -150,7 +143,7 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
final TargetFilterQuery updateFilter = filterManagement.updateAutoAssignDS(update); final TargetFilterQuery updateFilter = filterManagement.updateAutoAssignDS(update);
final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(updateFilter, final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(updateFilter,
tenantConfigHelper.isConfirmationFlowEnabled(), false); TenantConfigHelper.isUserConfirmationFlowEnabled(), false);
MgmtTargetFilterQueryMapper.addLinks(response); MgmtTargetFilterQueryMapper.addLinks(response);
return ResponseEntity.ok(response); return ResponseEntity.ok(response);

View File

@@ -9,6 +9,10 @@
*/ */
package org.eclipse.hawkbit.mgmt.rest.resource; package org.eclipse.hawkbit.mgmt.rest.resource;
import static org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility.sanitizeTargetSortParam;
import java.util.List;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.mgmt.json.model.PagedList; import org.eclipse.hawkbit.mgmt.json.model.PagedList;
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget; import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget;
@@ -16,31 +20,21 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetGroupRestApi;
import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtTargetMapper; import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtTargetMapper;
import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility; import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility.sanitizeTargetSortParam;
@Slf4j @Slf4j
@RestController @RestController
public class MgmtTargetGroupResource implements MgmtTargetGroupRestApi { public class MgmtTargetGroupResource implements MgmtTargetGroupRestApi {
private final TargetManagement<? extends Target> targetManagement; private final TargetManagement<? extends Target> targetManagement;
private final TenantConfigHelper tenantConfigHelper;
public MgmtTargetGroupResource( public MgmtTargetGroupResource(
final TargetManagement <? extends Target>targetManagement, final TargetManagement <? extends Target>targetManagement) {
final TenantConfigurationManagement tenantConfigurationManagement, final SystemSecurityContext systemSecurityContext) {
this.targetManagement = targetManagement; this.targetManagement = targetManagement;
this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
} }
@Override @Override
@@ -50,7 +44,7 @@ public class MgmtTargetGroupResource implements MgmtTargetGroupRestApi {
final Page<Target> targets = targetManagement.findTargetsByGroup(group, false, pageable); final Page<Target> targets = targetManagement.findTargetsByGroup(group, false, pageable);
final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(targets.getContent(), tenantConfigHelper); final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(targets.getContent());
return ResponseEntity.ok(new PagedList<>(rest, targets.getTotalElements())); return ResponseEntity.ok(new PagedList<>(rest, targets.getTotalElements()));
} }
@@ -61,7 +55,7 @@ public class MgmtTargetGroupResource implements MgmtTargetGroupRestApi {
final Page<Target> targets = targetManagement.findTargetsByGroup(groupFilter, subgroups, pageable); final Page<Target> targets = targetManagement.findTargetsByGroup(groupFilter, subgroups, pageable);
final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(targets.getContent(), tenantConfigHelper); final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(targets.getContent());
return ResponseEntity.ok(new PagedList<>(rest, targets.getTotalElements())); return ResponseEntity.ok(new PagedList<>(rest, targets.getTotalElements()));
} }

View File

@@ -56,9 +56,9 @@ import org.eclipse.hawkbit.repository.ConfirmationManagement;
import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.InvalidConfirmationFeedbackException; import org.eclipse.hawkbit.repository.exception.InvalidConfirmationFeedbackException;
import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.DeploymentRequest; import org.eclipse.hawkbit.repository.model.DeploymentRequest;
@@ -66,8 +66,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
@@ -91,27 +89,24 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
private final DeploymentManagement deploymentManagement; private final DeploymentManagement deploymentManagement;
private final MgmtTargetMapper mgmtTargetMapper; private final MgmtTargetMapper mgmtTargetMapper;
private final MgmtDistributionSetMapper mgmtDistributionSetMapper; private final MgmtDistributionSetMapper mgmtDistributionSetMapper;
private final TenantConfigHelper tenantConfigHelper;
MgmtTargetResource( MgmtTargetResource(
final TargetManagement<? extends Target> targetManagement, final TargetTypeManagement<? extends TargetType> targetTypeManagement, final TargetManagement<? extends Target> targetManagement, final TargetTypeManagement<? extends TargetType> targetTypeManagement,
final DeploymentManagement deploymentManagement, final ConfirmationManagement confirmationManagement, final DeploymentManagement deploymentManagement, final ConfirmationManagement confirmationManagement,
final MgmtTargetMapper mgmtTargetMapper, final MgmtDistributionSetMapper mgmtDistributionSetMapper, final MgmtTargetMapper mgmtTargetMapper, final MgmtDistributionSetMapper mgmtDistributionSetMapper) {
final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement) {
this.targetManagement = targetManagement; this.targetManagement = targetManagement;
this.targetTypeManagement = targetTypeManagement; this.targetTypeManagement = targetTypeManagement;
this.deploymentManagement = deploymentManagement; this.deploymentManagement = deploymentManagement;
this.confirmationManagement = confirmationManagement; this.confirmationManagement = confirmationManagement;
this.mgmtTargetMapper = mgmtTargetMapper; this.mgmtTargetMapper = mgmtTargetMapper;
this.mgmtDistributionSetMapper = mgmtDistributionSetMapper; this.mgmtDistributionSetMapper = mgmtDistributionSetMapper;
this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
} }
@Override @Override
public ResponseEntity<MgmtTarget> getTarget(final String targetId) { public ResponseEntity<MgmtTarget> getTarget(final String targetId) {
final Target findTarget = targetManagement.getByControllerId(targetId); final Target findTarget = targetManagement.getByControllerId(targetId);
// to single response include poll status // to single response include poll status
final MgmtTarget response = MgmtTargetMapper.toResponse(findTarget, tenantConfigHelper, null); final MgmtTarget response = MgmtTargetMapper.toResponse(findTarget, null);
MgmtTargetMapper.addTargetLinks(response); MgmtTargetMapper.addTargetLinks(response);
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
@@ -128,7 +123,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
findTargetsAll = targetManagement.findAll(pageable); findTargetsAll = targetManagement.findAll(pageable);
} }
final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(findTargetsAll.getContent(), tenantConfigHelper); final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(findTargetsAll.getContent());
return ResponseEntity.ok(new PagedList<>(rest, findTargetsAll.getTotalElements())); return ResponseEntity.ok(new PagedList<>(rest, findTargetsAll.getTotalElements()));
} }
@@ -137,7 +132,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
log.debug("creating {} targets", targets.size()); log.debug("creating {} targets", targets.size());
final Collection<? extends Target> createdTargets = this.targetManagement.create(mgmtTargetMapper.fromRequest(targets)); final Collection<? extends Target> createdTargets = this.targetManagement.create(mgmtTargetMapper.fromRequest(targets));
log.debug("{} targets created, return status {}", targets.size(), HttpStatus.CREATED); log.debug("{} targets created, return status {}", targets.size(), HttpStatus.CREATED);
return new ResponseEntity<>(MgmtTargetMapper.toResponse(createdTargets, tenantConfigHelper), HttpStatus.CREATED); return new ResponseEntity<>(MgmtTargetMapper.toResponse(createdTargets), HttpStatus.CREATED);
} }
@Override @Override
@@ -166,7 +161,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
.requestControllerAttributes(targetRest.getRequestAttributes()) .requestControllerAttributes(targetRest.getRequestAttributes())
.build()); .build());
final MgmtTarget response = MgmtTargetMapper.toResponse(updateTarget, tenantConfigHelper, null); final MgmtTarget response = MgmtTargetMapper.toResponse(updateTarget, null);
MgmtTargetMapper.addTargetLinks(response); MgmtTargetMapper.addTargetLinks(response);
return ResponseEntity.ok(response); return ResponseEntity.ok(response);
@@ -399,14 +394,13 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
final List<DeploymentRequest> deploymentRequests = dsAssignments.stream().map(dsAssignment -> { final List<DeploymentRequest> deploymentRequests = dsAssignments.stream().map(dsAssignment -> {
final boolean isConfirmationRequired = dsAssignment.getConfirmationRequired() == null final boolean isConfirmationRequired = dsAssignment.getConfirmationRequired() == null
? tenantConfigHelper.isConfirmationFlowEnabled() ? TenantConfigHelper.isUserConfirmationFlowEnabled()
: dsAssignment.getConfirmationRequired(); : dsAssignment.getConfirmationRequired();
return MgmtDeploymentRequestMapper.createAssignmentRequestBuilder(dsAssignment, targetId) return MgmtDeploymentRequestMapper.createAssignmentRequestBuilder(dsAssignment, targetId)
.confirmationRequired(isConfirmationRequired).build(); .confirmationRequired(isConfirmationRequired).build();
}).toList(); }).toList();
final List<DistributionSetAssignmentResult> assignmentResults = deploymentManagement final List<DistributionSetAssignmentResult> assignmentResults = deploymentManagement.assignDistributionSets(deploymentRequests, null);
.assignDistributionSets(deploymentRequests);
return ResponseEntity.ok(mgmtDistributionSetMapper.toResponse(assignmentResults)); return ResponseEntity.ok(mgmtDistributionSetMapper.toResponse(assignmentResults));
} }
@@ -486,6 +480,6 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
} }
private <T, R> R getNullIfEmpty(final T object, final Function<T, R> extractMethod) { private <T, R> R getNullIfEmpty(final T object, final Function<T, R> extractMethod) {
return object == null ? null : extractMethod.apply(object); return ObjectUtils.isEmpty(object) ? null : extractMethod.apply(object);
} }
} }

View File

@@ -27,12 +27,9 @@ import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtTargetMapper;
import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility; import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility;
import org.eclipse.hawkbit.repository.TargetManagement; import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TargetTagManagement; import org.eclipse.hawkbit.repository.TargetTagManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@@ -48,14 +45,11 @@ public class MgmtTargetTagResource implements MgmtTargetTagRestApi {
private final TargetTagManagement<? extends TargetTag> tagManagement; private final TargetTagManagement<? extends TargetTag> tagManagement;
private final TargetManagement<? extends Target> targetManagement; private final TargetManagement<? extends Target> targetManagement;
private final TenantConfigHelper tenantConfigHelper;
MgmtTargetTagResource( MgmtTargetTagResource(
final TargetTagManagement<? extends TargetTag> tagManagement, final TargetManagement<? extends Target> targetManagement, final TargetTagManagement<? extends TargetTag> tagManagement, final TargetManagement<? extends Target> targetManagement) {
final SystemSecurityContext securityContext, final TenantConfigurationManagement configurationManagement) {
this.tagManagement = tagManagement; this.tagManagement = tagManagement;
this.targetManagement = targetManagement; this.targetManagement = targetManagement;
tenantConfigHelper = TenantConfigHelper.usingContext(securityContext, configurationManagement);
} }
@Override @Override
@@ -129,7 +123,7 @@ public class MgmtTargetTagResource implements MgmtTargetTagRestApi {
findTargetsAll = targetManagement.findByRsqlAndTag(rsqlParam, targetTagId, pageable); findTargetsAll = targetManagement.findByRsqlAndTag(rsqlParam, targetTagId, pageable);
} }
final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(findTargetsAll.getContent(), tenantConfigHelper); final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(findTargetsAll.getContent());
return ResponseEntity.ok(new PagedList<>(rest, findTargetsAll.getTotalElements())); return ResponseEntity.ok(new PagedList<>(rest, findTargetsAll.getTotalElements()));
} }

View File

@@ -33,7 +33,6 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
/** /**

View File

@@ -22,9 +22,9 @@ import org.eclipse.hawkbit.mgmt.json.model.system.MgmtSystemTenantConfigurationV
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTenantManagementRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtTenantManagementRestApi;
import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtTenantManagementMapper; import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtTenantManagementMapper;
import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.exception.TenantConfigurationValidatorException; import org.eclipse.hawkbit.repository.exception.TenantConfigurationValidatorException;
import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@@ -38,22 +38,19 @@ import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
public class MgmtTenantManagementResource implements MgmtTenantManagementRestApi { public class MgmtTenantManagementResource implements MgmtTenantManagementRestApi {
private final TenantConfigurationManagement tenantConfigurationManagement;
private final TenantConfigurationProperties tenantConfigurationProperties; private final TenantConfigurationProperties tenantConfigurationProperties;
private final SystemManagement systemManagement; private final SystemManagement systemManagement;
MgmtTenantManagementResource( MgmtTenantManagementResource(
final TenantConfigurationManagement tenantConfigurationManagement,
final TenantConfigurationProperties tenantConfigurationProperties, final TenantConfigurationProperties tenantConfigurationProperties,
final SystemManagement systemManagement) { final SystemManagement systemManagement) {
this.tenantConfigurationManagement = tenantConfigurationManagement;
this.tenantConfigurationProperties = tenantConfigurationProperties; this.tenantConfigurationProperties = tenantConfigurationProperties;
this.systemManagement = systemManagement; this.systemManagement = systemManagement;
} }
@Override @Override
public ResponseEntity<Map<String, MgmtSystemTenantConfigurationValue>> getTenantConfiguration() { public ResponseEntity<Map<String, MgmtSystemTenantConfigurationValue>> getTenantConfiguration() {
// Load and Construct default Tenant Configuration // Load and Construct default AccessContext Configuration
final Map<String, MgmtSystemTenantConfigurationValue> tenantConfigurationValueMap = new HashMap<>(); final Map<String, MgmtSystemTenantConfigurationValue> tenantConfigurationValueMap = new HashMap<>();
tenantConfigurationProperties.getConfigurationKeys().forEach(key -> { tenantConfigurationProperties.getConfigurationKeys().forEach(key -> {
try { try {
@@ -74,14 +71,14 @@ public class MgmtTenantManagementResource implements MgmtTenantManagementRestApi
} }
@Override @Override
@AuditLog(entity = "TenantConfiguration", type = AuditLog.Type.DELETE, description = "Delete Tenant Configuration Value") @AuditLog(entity = "TenantConfiguration", type = AuditLog.Type.DELETE, description = "Delete AccessContext Configuration Value")
public ResponseEntity<Void> deleteTenantConfigurationValue(final String keyName) { public ResponseEntity<Void> deleteTenantConfigurationValue(final String keyName) {
//Default DistributionSet Type cannot be deleted as is part of TenantMetadata // Default DistributionSet Type cannot be deleted as is part of TenantMetadata
if (isDefaultDistributionSetTypeKey(keyName)) { if (isDefaultDistributionSetTypeKey(keyName)) {
return ResponseEntity.badRequest().build(); return ResponseEntity.badRequest().build();
} }
tenantConfigurationManagement.deleteConfiguration(keyName); TenantConfigHelper.getTenantConfigurationManagement().deleteConfiguration(keyName);
log.debug("{} config value deleted, return status {}", keyName, HttpStatus.OK); log.debug("{} config value deleted, return status {}", keyName, HttpStatus.OK);
return ResponseEntity.noContent().build(); return ResponseEntity.noContent().build();
@@ -93,7 +90,7 @@ public class MgmtTenantManagementResource implements MgmtTenantManagementRestApi
} }
@Override @Override
@AuditLog(entity = "TenantConfiguration", type = AuditLog.Type.UPDATE, description = "Update Tenant Configuration Value") @AuditLog(entity = "TenantConfiguration", type = AuditLog.Type.UPDATE, description = "Update AccessContext Configuration Value")
public ResponseEntity<MgmtSystemTenantConfigurationValue> updateTenantConfigurationValue( public ResponseEntity<MgmtSystemTenantConfigurationValue> updateTenantConfigurationValue(
final String keyName, final MgmtSystemTenantConfigurationValueRequest configurationValueRest) { final String keyName, final MgmtSystemTenantConfigurationValueRequest configurationValueRest) {
Serializable configurationValue = configurationValueRest.getValue(); Serializable configurationValue = configurationValueRest.getValue();
@@ -101,7 +98,8 @@ public class MgmtTenantManagementResource implements MgmtTenantManagementRestApi
if (isDefaultDistributionSetTypeKey(keyName)) { if (isDefaultDistributionSetTypeKey(keyName)) {
responseUpdatedValue = updateDefaultDsType(configurationValue); responseUpdatedValue = updateDefaultDsType(configurationValue);
} else { } else {
final TenantConfigurationValue<? extends Serializable> updatedTenantConfigurationValue = tenantConfigurationManagement final TenantConfigurationValue<? extends Serializable> updatedTenantConfigurationValue = TenantConfigHelper
.getTenantConfigurationManagement()
.addOrUpdateConfiguration(keyName, configurationValueRest.getValue()); .addOrUpdateConfiguration(keyName, configurationValueRest.getValue());
responseUpdatedValue = MgmtTenantManagementMapper.toResponseTenantConfigurationValue(keyName, updatedTenantConfigurationValue); responseUpdatedValue = MgmtTenantManagementMapper.toResponseTenantConfigurationValue(keyName, updatedTenantConfigurationValue);
} }
@@ -110,7 +108,7 @@ public class MgmtTenantManagementResource implements MgmtTenantManagementRestApi
} }
@Override @Override
@AuditLog(entity = "TenantConfiguration", type = AuditLog.Type.UPDATE, description = "Update Tenant Configuration") @AuditLog(entity = "TenantConfiguration", type = AuditLog.Type.UPDATE, description = "Update AccessContext Configuration")
public ResponseEntity<List<MgmtSystemTenantConfigurationValue>> updateTenantConfiguration( public ResponseEntity<List<MgmtSystemTenantConfigurationValue>> updateTenantConfiguration(
final Map<String, Serializable> configurationValueMap) { final Map<String, Serializable> configurationValueMap) {
final boolean containsNull = configurationValueMap.keySet().stream().anyMatch(Objects::isNull); final boolean containsNull = configurationValueMap.keySet().stream().anyMatch(Objects::isNull);
@@ -130,7 +128,7 @@ public class MgmtTenantManagementResource implements MgmtTenantManagementRestApi
//try update TenantConfiguration, in case of Error -> rollback TenantMetadata //try update TenantConfiguration, in case of Error -> rollback TenantMetadata
final Map<String, TenantConfigurationValue<Serializable>> tenantConfigurationValues; final Map<String, TenantConfigurationValue<Serializable>> tenantConfigurationValues;
try { try {
tenantConfigurationValues = tenantConfigurationManagement.addOrUpdateConfiguration(configurationValueMap); tenantConfigurationValues = TenantConfigHelper.getTenantConfigurationManagement().addOrUpdateConfiguration(configurationValueMap);
} catch (Exception ex) { } catch (Exception ex) {
//if DefaultDsType was updated, rollback it in case of TenantConfiguration update. //if DefaultDsType was updated, rollback it in case of TenantConfiguration update.
if (updatedDefaultDsType != null) { if (updatedDefaultDsType != null) {
@@ -155,13 +153,13 @@ public class MgmtTenantManagementResource implements MgmtTenantManagementRestApi
} }
private MgmtSystemTenantConfigurationValue loadTenantConfigurationValueBy(final String keyName) { private MgmtSystemTenantConfigurationValue loadTenantConfigurationValueBy(final String keyName) {
//Check if requested key is TenantConfiguration or TenantMetadata, load it and return it as rest response // Check if requested key is TenantConfiguration or TenantMetadata, load it and return it as rest response
final MgmtSystemTenantConfigurationValue response; final MgmtSystemTenantConfigurationValue response;
if (isDefaultDistributionSetTypeKey(keyName)) { if (isDefaultDistributionSetTypeKey(keyName)) {
response = MgmtTenantManagementMapper.toResponseDefaultDsType(systemManagement.getTenantMetadata().getDefaultDsType().getId()); response = MgmtTenantManagementMapper.toResponseDefaultDsType(systemManagement.getTenantMetadata().getDefaultDsType().getId());
} else { } else {
response = MgmtTenantManagementMapper.toResponseTenantConfigurationValue( response = MgmtTenantManagementMapper.toResponseTenantConfigurationValue(
keyName, tenantConfigurationManagement.getConfigurationValue(keyName)); keyName, TenantConfigHelper.getTenantConfigurationManagement().getConfigurationValue(keyName));
} }
return response; return response;
} }

View File

@@ -33,7 +33,6 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleTypeRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleTypeRestApi;
import org.eclipse.hawkbit.mgmt.rest.resource.MgmtDownloadArtifactResource; import org.eclipse.hawkbit.mgmt.rest.resource.MgmtDownloadArtifactResource;
import org.eclipse.hawkbit.mgmt.rest.resource.MgmtSoftwareModuleResource; import org.eclipse.hawkbit.mgmt.rest.resource.MgmtSoftwareModuleResource;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement.Create; import org.eclipse.hawkbit.repository.SoftwareModuleManagement.Create;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement; import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.SystemManagement;

View File

@@ -39,12 +39,11 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtRolloutRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTypeRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTypeRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.SortDirection; import org.eclipse.hawkbit.mgmt.rest.api.SortDirection;
import org.eclipse.hawkbit.repository.qfields.ActionFields;
import org.eclipse.hawkbit.repository.qfields.ActionStatusFields;
import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.TargetManagement.Create; import org.eclipse.hawkbit.repository.TargetManagement.Create;
import org.eclipse.hawkbit.repository.TargetTypeManagement; import org.eclipse.hawkbit.repository.TargetTypeManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.helper.TenantConfigHelper;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.ActionStatus;
@@ -54,9 +53,10 @@ import org.eclipse.hawkbit.repository.model.PollStatus;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.qfields.ActionFields;
import org.eclipse.hawkbit.repository.qfields.ActionStatusFields;
import org.eclipse.hawkbit.rest.json.model.ResponseList; import org.eclipse.hawkbit.rest.json.model.ResponseList;
import org.eclipse.hawkbit.util.IpUtil; import org.eclipse.hawkbit.utils.IpUtil;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
@@ -119,30 +119,16 @@ public final class MgmtTargetMapper {
return response; return response;
} }
/** public static List<MgmtTarget> toResponse(final Collection<? extends Target> targets) {
* Create a response for targets.
*
* @param targets list of targets
* @return the response
*/
public static List<MgmtTarget> toResponse(final Collection<? extends Target> targets, final TenantConfigHelper configHelper) {
if (targets == null) { if (targets == null) {
return Collections.emptyList(); return Collections.emptyList();
} }
final Function<Target, PollStatus> pollStatusResolver = configHelper.pollStatusResolver(); final Function<Target, PollStatus> pollStatusResolver = TenantConfigHelper.pollStatusResolver();
return new ResponseList<>( return new ResponseList<>(targets.stream().map(target -> toResponse(target, pollStatusResolver)).toList());
targets.stream().map(target -> toResponse(target, configHelper, pollStatusResolver)).toList());
} }
/** public static MgmtTarget toResponse(final Target target, final Function<Target, PollStatus> pollStatusResolver) {
* Create a response for target.
*
* @param target the target
* @return the response
*/
public static MgmtTarget toResponse(
final Target target, final TenantConfigHelper configHelper, final Function<Target, PollStatus> pollStatusResolver) {
if (target == null) { if (target == null) {
return null; return null;
} }
@@ -189,13 +175,14 @@ public final class MgmtTargetMapper {
targetRest.setTargetType(target.getTargetType().getId()); targetRest.setTargetType(target.getTargetType().getId());
targetRest.setTargetTypeName(target.getTargetType().getName()); targetRest.setTargetTypeName(target.getTargetType().getName());
} }
if (configHelper.isConfirmationFlowEnabled()) {
if (TenantConfigHelper.isUserConfirmationFlowEnabled()) {
targetRest.setAutoConfirmActive(target.getAutoConfirmationStatus() != null); targetRest.setAutoConfirmActive(target.getAutoConfirmationStatus() != null);
} }
targetRest.add(linkTo(methodOn(MgmtTargetRestApi.class).getTarget(target.getControllerId())).withSelfRel().expand()); targetRest.add(linkTo(methodOn(MgmtTargetRestApi.class).getTarget(target.getControllerId())).withSelfRel().expand());
addPollStatus(target, targetRest, pollStatusResolver == null ? configHelper.pollStatusResolver() : pollStatusResolver); addPollStatus(target, targetRest, pollStatusResolver == null ? TenantConfigHelper.pollStatusResolver() : pollStatusResolver);
return targetRest; return targetRest;
} }

View File

@@ -12,11 +12,11 @@ package org.eclipse.hawkbit.mgmt.rest.resource.util;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
import org.eclipse.hawkbit.repository.qfields.ActionFields; import org.eclipse.hawkbit.repository.qfields.ActionFields;
import org.eclipse.hawkbit.repository.qfields.ActionStatusFields; import org.eclipse.hawkbit.repository.qfields.ActionStatusFields;
import org.eclipse.hawkbit.repository.qfields.DistributionSetFields; import org.eclipse.hawkbit.repository.qfields.DistributionSetFields;
import org.eclipse.hawkbit.repository.qfields.DistributionSetTypeFields; import org.eclipse.hawkbit.repository.qfields.DistributionSetTypeFields;
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
import org.eclipse.hawkbit.repository.qfields.RolloutFields; import org.eclipse.hawkbit.repository.qfields.RolloutFields;
import org.eclipse.hawkbit.repository.qfields.RolloutGroupFields; import org.eclipse.hawkbit.repository.qfields.RolloutGroupFields;
import org.eclipse.hawkbit.repository.qfields.SoftwareModuleFields; import org.eclipse.hawkbit.repository.qfields.SoftwareModuleFields;

View File

@@ -24,8 +24,8 @@ import org.eclipse.hawkbit.repository.jpa.JpaRepositoryConfiguration;
import org.eclipse.hawkbit.repository.test.TestConfiguration; import org.eclipse.hawkbit.repository.test.TestConfiguration;
import org.eclipse.hawkbit.repository.test.matcher.EventVerifier; import org.eclipse.hawkbit.repository.test.matcher.EventVerifier;
import org.eclipse.hawkbit.repository.test.util.CleanupTestExecutionListener; import org.eclipse.hawkbit.repository.test.util.CleanupTestExecutionListener;
import org.eclipse.hawkbit.repository.test.util.TestLoggerExtension;
import org.eclipse.hawkbit.repository.test.util.SharedSqlTestDatabaseExtension; import org.eclipse.hawkbit.repository.test.util.SharedSqlTestDatabaseExtension;
import org.eclipse.hawkbit.repository.test.util.TestLoggerExtension;
import org.eclipse.hawkbit.repository.test.util.WithUser; import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.rest.RestConfiguration; import org.eclipse.hawkbit.rest.RestConfiguration;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;

View File

@@ -1954,13 +1954,13 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest {
private void awaitRunningState(final Long rolloutId) { private void awaitRunningState(final Long rolloutId) {
awaitRollout().until(() -> SecurityContextSwitch awaitRollout().until(() -> SecurityContextSwitch
.callAsPrivileged(() -> rolloutManagement.get(rolloutId)) .asPrivileged(() -> rolloutManagement.get(rolloutId))
.getStatus().equals(RolloutStatus.RUNNING)); .getStatus().equals(RolloutStatus.RUNNING));
} }
private void awaitActionStatus(final Long actionId, final Status status) { private void awaitActionStatus(final Long actionId, final Status status) {
awaitRollout().until(() -> SecurityContextSwitch awaitRollout().until(() -> SecurityContextSwitch
.callAsPrivileged(() -> deploymentManagement.findAction(actionId).orElseThrow(NoSuchElementException::new)) .asPrivileged(() -> deploymentManagement.findAction(actionId).orElseThrow(NoSuchElementException::new))
.getStatus().equals(status)); .getStatus().equals(status));
} }

View File

@@ -9,22 +9,22 @@
*/ */
package org.eclipse.hawkbit.mgmt.rest.resource; package org.eclipse.hawkbit.mgmt.rest.resource;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import static org.eclipse.hawkbit.repository.TargetManagement.Create.builder;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.eclipse.hawkbit.repository.TargetManagement.Create.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
public class MgmtTargetGroupResourceTest extends AbstractManagementApiIntegrationTest { public class MgmtTargetGroupResourceTest extends AbstractManagementApiIntegrationTest {

Some files were not shown because too many files have changed in this diff Show More