Fix AmqpMessageDispatcherServiceTest.testSendCancelRequest - set action tenant (#2098)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -72,8 +72,7 @@ public class EventPublisherAutoConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return default {@link ApplicationEventFilter} that does not filter any
|
* @return default {@link ApplicationEventFilter} that does not filter any events
|
||||||
* events
|
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public class BaseAmqpService {
|
|||||||
return ObjectUtils.isEmpty(message.getBody());
|
return ObjectUtils.isEmpty(message.getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static final void logAndThrowMessageError(final Message message, final String error) {
|
protected static void logAndThrowMessageError(final Message message, final String error) {
|
||||||
log.debug("Warning! \"{}\" reported by message: {}", error, message);
|
log.debug("Warning! \"{}\" reported by message: {}", error, message);
|
||||||
throw new AmqpRejectAndDontRequeueException(error);
|
throw new AmqpRejectAndDontRequeueException(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,7 @@ public class MessageConversionExceptionHandler extends AbstractAmqpErrorHandler<
|
|||||||
@Override
|
@Override
|
||||||
public String getErrorMessage(Throwable throwable) {
|
public String getErrorMessage(Throwable throwable) {
|
||||||
final String errorMessage = super.getErrorMessage(throwable);
|
final String errorMessage = super.getErrorMessage(throwable);
|
||||||
//since the detailed error message lies in the first parent of current throwable we retrieve it
|
// since the detailed error message lies in the first parent of current throwable we retrieve it and append it to the errorMessage
|
||||||
// and append it to the errorMessage
|
|
||||||
final Optional<String> detailedErrorMessage = getFirstAncestralErrorMessage(throwable.getCause());
|
final Optional<String> detailedErrorMessage = getFirstAncestralErrorMessage(throwable.getCause());
|
||||||
return detailedErrorMessage.isPresent() ? (detailedErrorMessage.get() + errorMessage) : errorMessage;
|
return detailedErrorMessage.isPresent() ? (detailedErrorMessage.get() + errorMessage) : errorMessage;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
|||||||
void testSendCancelRequest() {
|
void testSendCancelRequest() {
|
||||||
final Action action = mock(Action.class);
|
final Action action = mock(Action.class);
|
||||||
when(action.getId()).thenReturn(1L);
|
when(action.getId()).thenReturn(1L);
|
||||||
|
when(action.getTenant()).thenReturn(TENANT);
|
||||||
when(action.getTarget()).thenReturn(testTarget);
|
when(action.getTarget()).thenReturn(testTarget);
|
||||||
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent = new CancelTargetAssignmentEvent(
|
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent = new CancelTargetAssignmentEvent(
|
||||||
action, serviceMatcher.getBusId());
|
action, serviceMatcher.getBusId());
|
||||||
|
|||||||
@@ -31,6 +31,5 @@ public class CancelTargetAssignmentEvent extends AbstractAssignmentEvent {
|
|||||||
|
|
||||||
public CancelTargetAssignmentEvent(final String tenant, final List<Action> a, final String applicationId) {
|
public CancelTargetAssignmentEvent(final String tenant, final List<Action> a, final String applicationId) {
|
||||||
super(applicationId, tenant, a, applicationId);
|
super(applicationId, tenant, a, applicationId);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,8 +57,7 @@ public class RemoteEntityEvent<E extends TenantAwareBaseEntity> extends RemoteId
|
|||||||
private E reloadEntityFromRepository() {
|
private E reloadEntityFromRepository() {
|
||||||
try {
|
try {
|
||||||
final Class<E> clazz = (Class<E>) Class.forName(getEntityClass());
|
final Class<E> clazz = (Class<E>) Class.forName(getEntityClass());
|
||||||
return EventEntityManagerHolder.getInstance().getEventEntityManager().findEntity(
|
return EventEntityManagerHolder.getInstance().getEventEntityManager().findEntity(getTenant(), getEntityId(), clazz);
|
||||||
getTenant(), getEntityId(), clazz);
|
|
||||||
} catch (final ClassNotFoundException e) {
|
} catch (final ClassNotFoundException e) {
|
||||||
log.error("Cannot reload entity because class is not found", e);
|
log.error("Cannot reload entity because class is not found", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,24 +22,19 @@ import org.springframework.messaging.converter.MessageConversionException;
|
|||||||
import org.springframework.util.MimeType;
|
import org.springframework.util.MimeType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A customize message converter for the spring cloud events. The converter is
|
* A customize message converter for the spring cloud events. The converter is registered for the application/binary+protostuff type.
|
||||||
* registered for the application/binary+protostuff type.
|
* <p/>
|
||||||
*
|
* The clazz-type-information is encoded into the message payload infront with a length of {@link #EVENT_TYPE_LENGTH}. This is necessary
|
||||||
* The clazz-type-information is encoded into the message payload infront with a
|
* due in case of rabbitMQ batching the message headers will be merged together and custom message header information will get lost.
|
||||||
* length of {@link #EVENT_TYPE_LENGTH}. This is necessary due in case of
|
* So in this implementation the information about the event-type is encoded in the payload of the message directly using the encoded
|
||||||
* rabbitMQ batching the message headers will be merged together and custom
|
* values of {@link EventType}.
|
||||||
* message header information will get lost. So in this implementation the
|
|
||||||
* information about the event-type is encoded in the payload of the message
|
|
||||||
* directly using the encoded values of {@link EventType}.
|
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class BusProtoStuffMessageConverter extends AbstractMessageConverter {
|
public class BusProtoStuffMessageConverter extends AbstractMessageConverter {
|
||||||
|
|
||||||
public static final MimeType APPLICATION_BINARY_PROTOSTUFF = new MimeType("application", "binary+protostuff");
|
public static final MimeType APPLICATION_BINARY_PROTOSTUFF = new MimeType("application", "binary+protostuff");
|
||||||
|
|
||||||
/**
|
/** The length of the class type length of the payload. */
|
||||||
* The length of the class type length of the payload.
|
|
||||||
*/
|
|
||||||
private static final byte EVENT_TYPE_LENGTH = 2;
|
private static final byte EVENT_TYPE_LENGTH = 2;
|
||||||
|
|
||||||
public BusProtoStuffMessageConverter() {
|
public BusProtoStuffMessageConverter() {
|
||||||
@@ -52,8 +47,7 @@ public class BusProtoStuffMessageConverter extends AbstractMessageConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object convertFromInternal(final Message<?> message, final Class<?> targetClass,
|
public Object convertFromInternal(final Message<?> message, final Class<?> targetClass, final Object conversionHint) {
|
||||||
final Object conversionHint) {
|
|
||||||
final Object objectPayload = message.getPayload();
|
final Object objectPayload = message.getPayload();
|
||||||
if (objectPayload instanceof byte[] payload) {
|
if (objectPayload instanceof byte[] payload) {
|
||||||
final byte[] clazzHeader = extractClazzHeader(payload);
|
final byte[] clazzHeader = extractClazzHeader(payload);
|
||||||
@@ -66,13 +60,9 @@ public class BusProtoStuffMessageConverter extends AbstractMessageConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object convertToInternal(final Object payload, final MessageHeaders headers,
|
protected Object convertToInternal(final Object payload, final MessageHeaders headers, final Object conversionHint) {
|
||||||
final Object conversionHint) {
|
|
||||||
|
|
||||||
final byte[] clazzHeader = writeClassHeader(payload.getClass());
|
final byte[] clazzHeader = writeClassHeader(payload.getClass());
|
||||||
|
|
||||||
final byte[] writeContent = writeContent(payload);
|
final byte[] writeContent = writeContent(payload);
|
||||||
|
|
||||||
return mergeClassHeaderAndContent(clazzHeader, writeContent);
|
return mergeClassHeaderAndContent(clazzHeader, writeContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,10 +86,8 @@ public class EventType {
|
|||||||
|
|
||||||
private int value;
|
private int value;
|
||||||
|
|
||||||
/**
|
// The associated event-type-value must remain the same as initially
|
||||||
* The associated event-type-value must remain the same as initially
|
// declared. Otherwise, messages cannot correctly de-serialized.
|
||||||
* declared. Otherwise, messages cannot correctly de-serialized.
|
|
||||||
*/
|
|
||||||
static {
|
static {
|
||||||
// target
|
// target
|
||||||
TYPES.put(1, TargetCreatedEvent.class);
|
TYPES.put(1, TargetCreatedEvent.class);
|
||||||
@@ -190,10 +188,12 @@ public class EventType {
|
|||||||
* does not have a {@link EventType}.
|
* does not have a {@link EventType}.
|
||||||
*/
|
*/
|
||||||
public static EventType from(final Class<?> clazz) {
|
public static EventType from(final Class<?> clazz) {
|
||||||
final Optional<Integer> foundEventType = TYPES.entrySet().stream()
|
return TYPES.entrySet().stream()
|
||||||
.filter(entry -> entry.getValue().equals(clazz)).map(Entry::getKey).findAny();
|
.filter(entry -> entry.getValue().equals(clazz))
|
||||||
|
.map(Entry::getKey)
|
||||||
return foundEventType.map(EventType::new).orElse(null);
|
.findAny()
|
||||||
|
.map(EventType::new)
|
||||||
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> getTargetClass() {
|
public Class<?> getTargetClass() {
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ import org.eclipse.hawkbit.tenancy.TenantAware;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A TenantAwareEvent entity manager, which loads an entity by id and type for
|
* A TenantAwareEvent entity manager, which loads an entity by id and type for remote events.
|
||||||
* remote events.
|
|
||||||
*/
|
*/
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public class JpaEventEntityManager implements EventEntityManager {
|
public class JpaEventEntityManager implements EventEntityManager {
|
||||||
@@ -38,8 +37,7 @@ public class JpaEventEntityManager implements EventEntityManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <E extends TenantAwareBaseEntity> E findEntity(final String tenant, final Long id,
|
public <E extends TenantAwareBaseEntity> E findEntity(final String tenant, final Long id, final Class<E> entityType) {
|
||||||
final Class<E> entityType) {
|
|
||||||
return tenantAware.runAsTenant(tenant, () -> entityManager.find(entityType, id));
|
return tenantAware.runAsTenant(tenant, () -> entityManager.find(entityType, id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,9 +165,8 @@ public class SecurityContextTenantAware implements ContextAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link Authentication} implementation to delegate to an existing
|
* An {@link Authentication} implementation to delegate to an existing {@link Authentication} object except setting the details
|
||||||
* {@link Authentication} object except setting the details specifically for
|
* specifically for a specific tenant and user.
|
||||||
* a specific tenant and user.
|
|
||||||
*/
|
*/
|
||||||
private static final class AuthenticationDelegate implements Authentication {
|
private static final class AuthenticationDelegate implements Authentication {
|
||||||
|
|
||||||
|
|||||||
@@ -65,14 +65,14 @@ public class SystemSecurityContext {
|
|||||||
/**
|
/**
|
||||||
* Runs a given {@link Callable} within a system security context, which is
|
* Runs a given {@link Callable} within a system security context, which is
|
||||||
* permitted to call secured system code. Often the system needs to call
|
* permitted to call secured system code. Often the system needs to call
|
||||||
* secured methods by it's own without relying on the current security
|
* secured methods by its own without relying on the current security
|
||||||
* context e.g. if the current security context does not contain the
|
* context e.g. if the current security context does not contain the
|
||||||
* necessary permission it's necessary to execute code as system code to
|
* necessary permission it's necessary to execute code as system code to
|
||||||
* execute necessary methods and functionality.
|
* execute necessary methods and functionality.
|
||||||
*
|
* <br/>
|
||||||
* The security context will be switched to the system code and back after
|
* The security context will be switched to the system code and back after
|
||||||
* the callable is called.
|
* the callable is called.
|
||||||
*
|
* <br/>
|
||||||
* The system code is executed for a current tenant by using the
|
* The system code is executed for a current tenant by using the
|
||||||
* {@link TenantAware#getCurrentTenant()}.
|
* {@link TenantAware#getCurrentTenant()}.
|
||||||
*
|
*
|
||||||
@@ -88,7 +88,7 @@ public class SystemSecurityContext {
|
|||||||
/**
|
/**
|
||||||
* Runs a given {@link Callable} within a system security context, which is
|
* Runs a given {@link Callable} within a system security context, which is
|
||||||
* permitted to call secured system code. Often the system needs to call
|
* permitted to call secured system code. Often the system needs to call
|
||||||
* secured methods by it's own without relying on the current security
|
* secured methods by its own without relying on the current security
|
||||||
* context e.g. if the current security context does not contain the
|
* context e.g. if the current security context does not contain the
|
||||||
* necessary permission it's necessary to execute code as system code to
|
* necessary permission it's necessary to execute code as system code to
|
||||||
* execute necessary methods and functionality.
|
* execute necessary methods and functionality.
|
||||||
@@ -120,12 +120,10 @@ public class SystemSecurityContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs a given {@link Callable} within a system security context, which has
|
* Runs a given {@link Callable} within a system security context, which has the provided {@link GrantedAuthority}s to successfully
|
||||||
* the provided {@link GrantedAuthority}s to successfully run the
|
* run the {@link Callable}.
|
||||||
* {@link Callable}.
|
* <br/>
|
||||||
*
|
* The security context will be switched to a new {@link SecurityContext} and back after the callable is called.
|
||||||
* The security context will be switched to the a new
|
|
||||||
* {@link SecurityContext} and back after the callable is called.
|
|
||||||
*
|
*
|
||||||
* @param tenant under which the {@link Callable#call()} must be executed.
|
* @param tenant under which the {@link Callable#call()} must be executed.
|
||||||
* @param callable to call within the security context
|
* @param callable to call within the security context
|
||||||
@@ -193,18 +191,17 @@ public class SystemSecurityContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of the Spring's {@link Authentication} object which is
|
* An implementation of the Spring's {@link Authentication} object which is used within a system security code block and
|
||||||
* used within a system security code block and wraps the original
|
* wraps the original authentication object. The wrapped object contains the necessary {@link SpringEvalExpressions#SYSTEM_ROLE}
|
||||||
* authentication object. The wrapped object contains the necessary
|
* which is allowed to execute all secured methods.
|
||||||
* {@link SpringEvalExpressions#SYSTEM_ROLE} which is allowed to execute all
|
|
||||||
* secured methods.
|
|
||||||
*/
|
*/
|
||||||
public static final class SystemCodeAuthentication implements Authentication {
|
public static final class SystemCodeAuthentication implements Authentication {
|
||||||
|
|
||||||
@Serial
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private static final List<SimpleGrantedAuthority> AUTHORITIES = Collections
|
|
||||||
.singletonList(new SimpleGrantedAuthority(SpringEvalExpressions.SYSTEM_ROLE));
|
private static final List<SimpleGrantedAuthority> AUTHORITIES =
|
||||||
|
Collections.singletonList(new SimpleGrantedAuthority(SpringEvalExpressions.SYSTEM_ROLE));
|
||||||
private final Authentication oldAuthentication;
|
private final Authentication oldAuthentication;
|
||||||
|
|
||||||
private SystemCodeAuthentication(final Authentication oldAuthentication) {
|
private SystemCodeAuthentication(final Authentication oldAuthentication) {
|
||||||
|
|||||||
Reference in New Issue
Block a user