-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Tenant details enhanced config and validation
Signed-off-by: Thomas Vitale <[email protected]>
- Loading branch information
1 parent
c2c6e56
commit ec1101a
Showing
22 changed files
with
345 additions
and
165 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
...ava/io/arconia/core/multitenancy/context/events/ValidatingTenantContextEventListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package io.arconia.core.multitenancy.context.events; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import io.arconia.core.multitenancy.events.TenantEvent; | ||
import io.arconia.core.multitenancy.events.TenantEventListener; | ||
import io.arconia.core.multitenancy.exceptions.TenantResolutionException; | ||
import io.arconia.core.multitenancy.tenantdetails.TenantDetailsService; | ||
|
||
/** | ||
* A {@link TenantEventListener} that validates the tenant for the current context. | ||
*/ | ||
public final class ValidatingTenantContextEventListener implements TenantEventListener { | ||
|
||
private static final Logger logger = LoggerFactory.getLogger(ValidatingTenantContextEventListener.class); | ||
|
||
private final TenantDetailsService tenantDetailsService; | ||
|
||
public ValidatingTenantContextEventListener(TenantDetailsService tenantDetailsService) { | ||
this.tenantDetailsService = tenantDetailsService; | ||
} | ||
|
||
@Override | ||
public void onApplicationEvent(TenantEvent tenantEvent) { | ||
if (tenantEvent instanceof TenantContextAttachedEvent event) { | ||
logger.trace("Validating tenant {}", event.getTenantIdentifier()); | ||
var tenant = tenantDetailsService.loadTenantByIdentifier(event.getTenantIdentifier()); | ||
if (tenant == null || !tenant.isEnabled()) { | ||
throw new TenantResolutionException("The resolved tenant is invalid or disabled"); | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
...o/arconia/core/multitenancy/context/events/ValidatingTenantContextEventListenerTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package io.arconia.core.multitenancy.context.events; | ||
|
||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.InjectMocks; | ||
import org.mockito.Mock; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
|
||
import io.arconia.core.multitenancy.exceptions.TenantResolutionException; | ||
import io.arconia.core.multitenancy.tenantdetails.Tenant; | ||
import io.arconia.core.multitenancy.tenantdetails.TenantDetailsService; | ||
|
||
import static org.assertj.core.api.Assertions.assertThatThrownBy; | ||
import static org.mockito.ArgumentMatchers.anyString; | ||
import static org.mockito.Mockito.when; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
class ValidatingTenantContextEventListenerTests { | ||
|
||
@Mock | ||
TenantDetailsService tenantDetailsService; | ||
|
||
@InjectMocks | ||
ValidatingTenantContextEventListener validatingTenantContextEventListener; | ||
|
||
@Test | ||
void whenTenantExistsThenOk() { | ||
var tenantIdentifier = "acme"; | ||
when(tenantDetailsService.loadTenantByIdentifier(anyString())) | ||
.thenReturn(Tenant.create().identifier(tenantIdentifier).build()); | ||
|
||
validatingTenantContextEventListener.onApplicationEvent(new TenantContextAttachedEvent(tenantIdentifier, this)); | ||
} | ||
|
||
@Test | ||
void whenTenantDoesNotExistThenThrow() { | ||
var tenantIdentifier = "acme"; | ||
when(tenantDetailsService.loadTenantByIdentifier(anyString())).thenReturn(null); | ||
|
||
assertThatThrownBy(() -> validatingTenantContextEventListener | ||
.onApplicationEvent(new TenantContextAttachedEvent(tenantIdentifier, this))) | ||
.isInstanceOf(TenantResolutionException.class) | ||
.hasMessageContaining("The resolved tenant is invalid or disabled"); | ||
} | ||
|
||
@Test | ||
void whenTenantDisabledThenThrow() { | ||
var tenantIdentifier = "acme"; | ||
when(tenantDetailsService.loadTenantByIdentifier(anyString())) | ||
.thenReturn(Tenant.create().identifier(tenantIdentifier).enabled(false).build()); | ||
|
||
assertThatThrownBy(() -> validatingTenantContextEventListener | ||
.onApplicationEvent(new TenantContextAttachedEvent(tenantIdentifier, this))) | ||
.isInstanceOf(TenantResolutionException.class) | ||
.hasMessageContaining("The resolved tenant is invalid or disabled"); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
.../io/arconia/autoconfigure/multitenancy/core/tenantdetails/TenantDetailsConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package io.arconia.autoconfigure.multitenancy.core.tenantdetails; | ||
|
||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
import io.arconia.core.multitenancy.context.events.ValidatingTenantContextEventListener; | ||
import io.arconia.core.multitenancy.tenantdetails.TenantDetailsService; | ||
|
||
@Configuration(proxyBeanMethods = false) | ||
@EnableConfigurationProperties(TenantDetailsProperties.class) | ||
public class TenantDetailsConfiguration { | ||
|
||
@Bean | ||
@ConditionalOnMissingBean | ||
@ConditionalOnProperty(prefix = TenantDetailsProperties.CONFIG_PREFIX, name = "source", havingValue = "properties") | ||
TenantDetailsService tenantDetailsService(TenantDetailsProperties tenantDetailsProperties) { | ||
return new PropertiesTenantDetailsService(tenantDetailsProperties); | ||
} | ||
|
||
@Bean | ||
@ConditionalOnMissingBean | ||
@ConditionalOnBean(TenantDetailsService.class) | ||
ValidatingTenantContextEventListener validatingTenantContextEventListener( | ||
TenantDetailsService tenantDetailsService) { | ||
return new ValidatingTenantContextEventListener(tenantDetailsService); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.