generated from micronaut-projects/micronaut-project-template
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Expose tenantId via EL with new annotation module (#255)
* Expose tenantId via EL with new annotation module This PR adds a new ExpressionEvaluationContext which allows us to use tenantId in EL expressions. Added test-suite in all 3 languages to allow documenting it's usage and validating the docs source * Unused dependency * Appease sonar's nonsense * Catch the exception when there's no tenant header/cookie/etc and resolve to null * Remove unrequired dependency * use properties configuration * use StringUtils constant * remove junit jupiter engine * more javadoc * use HttpClient as method parameter * Update src/main/docs/guide/multitenancy/tenantexpression.adoc * Update src/main/docs/guide/multitenancy/tenantexpression.adoc --------- Co-authored-by: Sergio del Amo <[email protected]>
- Loading branch information
Showing
30 changed files
with
597 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,12 @@ | ||
plugins { | ||
id 'groovy-gradle-plugin' | ||
} | ||
|
||
repositories { | ||
gradlePluginPortal() | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
implementation(libs.gradle.kotlin) | ||
} |
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,7 @@ | ||
dependencyResolutionManagement { | ||
versionCatalogs { | ||
libs { | ||
from(files("../gradle/libs.versions.toml")) | ||
} | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
|
||
plugins { | ||
id("io.micronaut.build.internal.multitenancy-module") | ||
} | ||
|
||
description = "Expression language support for multi-tenancy" | ||
|
||
dependencies { | ||
compileOnly(mn.micronaut.core.processor) | ||
} | ||
|
||
micronautBuild { | ||
binaryCompatibility { | ||
enabled = false | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
.../src/main/java/io/micronaut/multitenancy/expression/TenantEvaluationContextRegistrar.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 @@ | ||
/* | ||
* Copyright 2017-2023 original authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.micronaut.multitenancy.expression; | ||
|
||
import io.micronaut.expressions.context.ExpressionEvaluationContextRegistrar; | ||
|
||
/** | ||
* Registers the `TenantEvaluationContext` from the main module as an Evaluation context. | ||
* | ||
* @since 5.2.0 | ||
* @author Tim Yates | ||
*/ | ||
public class TenantEvaluationContextRegistrar implements ExpressionEvaluationContextRegistrar { | ||
|
||
@Override | ||
public String getContextClassName() { | ||
return "io.micronaut.multitenancy.expression.TenantEvaluationContext"; | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
...tions/src/main/resources/META-INF/services/io.micronaut.inject.visitor.TypeElementVisitor
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 @@ | ||
io.micronaut.multitenancy.expression.TenantEvaluationContextRegistrar |
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
76 changes: 76 additions & 0 deletions
76
multitenancy/src/main/java/io/micronaut/multitenancy/expression/TenantEvaluationContext.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,76 @@ | ||
/* | ||
* Copyright 2017-2023 original authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.micronaut.multitenancy.expression; | ||
|
||
import io.micronaut.context.annotation.Requires; | ||
import io.micronaut.core.annotation.Internal; | ||
import io.micronaut.core.annotation.Nullable; | ||
import io.micronaut.multitenancy.exceptions.TenantNotFoundException; | ||
import io.micronaut.multitenancy.tenantresolver.TenantResolver; | ||
import jakarta.inject.Singleton; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.io.Serializable; | ||
|
||
/** | ||
* Context for supporting annotation expressions with tenant id. | ||
* | ||
* @since 5.2.0 | ||
* @author Tim Yates | ||
*/ | ||
@Internal | ||
@Singleton | ||
@Requires(beans = {TenantResolver.class}) | ||
public final class TenantEvaluationContext { | ||
|
||
private static final Logger LOG = LoggerFactory.getLogger(TenantEvaluationContext.class); | ||
|
||
private final TenantResolver tenantResolver; | ||
|
||
/** | ||
* @param tenantResolver The enabled and configured TenantResolver | ||
*/ | ||
public TenantEvaluationContext(TenantResolver tenantResolver) { | ||
this.tenantResolver = tenantResolver; | ||
} | ||
|
||
/** | ||
* Resolves and returns the Tenant ID with {@link TenantResolver#resolveTenantIdentifier()}. | ||
* @return the tenant id or {@literal null}. | ||
*/ | ||
@Nullable | ||
public String getTenantId() { | ||
try { | ||
Serializable tenant = tenantResolver.resolveTenantIdentifier(); | ||
if (tenant instanceof CharSequence charSequenceTenant) { | ||
if (LOG.isDebugEnabled()) { | ||
LOG.debug("Resolved tenant: {}", tenant); | ||
} | ||
return charSequenceTenant.toString(); | ||
} | ||
if (LOG.isDebugEnabled()) { | ||
LOG.debug("Tenant not resolvable to a String: {}", tenant); | ||
} | ||
return null; | ||
} catch (TenantNotFoundException ex) { | ||
if (LOG.isDebugEnabled()) { | ||
LOG.debug("Tenant not found: {}", ex.getMessage()); | ||
} | ||
return null; | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
multitenancy/src/main/java/io/micronaut/multitenancy/expression/package-info.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,22 @@ | ||
/* | ||
* Copyright 2017-2023 original authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
/** | ||
* Expression Language support for multi-tenancy. | ||
* | ||
* @since 5.2.0 | ||
* @author Tim Yates | ||
*/ | ||
package io.micronaut.multitenancy.expression; |
78 changes: 78 additions & 0 deletions
78
...y/src/test/groovy/io/micronaut/multitenancy/expression/TenantEvaluationContextSpec.groovy
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,78 @@ | ||
package io.micronaut.multitenancy.expression | ||
|
||
import io.micronaut.context.BeanContext | ||
import io.micronaut.context.annotation.Bean | ||
import io.micronaut.context.annotation.Factory | ||
import io.micronaut.context.annotation.Property | ||
import io.micronaut.context.annotation.Requires | ||
import io.micronaut.context.annotation.Value | ||
import io.micronaut.core.annotation.Nullable | ||
import io.micronaut.core.util.StringUtils | ||
import io.micronaut.http.HttpRequest | ||
import io.micronaut.http.MediaType | ||
import io.micronaut.http.annotation.Controller | ||
import io.micronaut.http.annotation.Get | ||
import io.micronaut.http.annotation.Produces | ||
import io.micronaut.http.client.HttpClient | ||
import io.micronaut.http.client.annotation.Client | ||
import io.micronaut.multitenancy.tenantresolver.HttpHeaderTenantResolverConfiguration | ||
import io.micronaut.test.extensions.spock.annotation.MicronautTest | ||
import jakarta.inject.Inject | ||
import spock.lang.Specification | ||
|
||
@MicronautTest | ||
@Property(name = "spec.name", value = "TenantEvaluationContextSpec") | ||
@Property(name = "micronaut.multitenancy.tenantresolver.httpheader.enabled", value = StringUtils.TRUE) | ||
class TenantEvaluationContextSpec extends Specification { | ||
|
||
@Inject | ||
@Client("/") | ||
HttpClient client | ||
|
||
void "test tenant evaluation context"() { | ||
when: | ||
def request = HttpRequest.GET("/tenant/expression").header(HttpHeaderTenantResolverConfiguration.DEFAULT_HEADER_NAME, "allowed") | ||
def response = client.toBlocking().retrieve(request) | ||
|
||
then: | ||
response == "allowed" | ||
|
||
when: | ||
request = HttpRequest.GET("/tenant/expression") | ||
response = client.toBlocking().retrieve(request) | ||
|
||
then: | ||
response == "none" | ||
} | ||
|
||
@Controller("/tenant") | ||
@Requires(property = "spec.name", value = "TenantEvaluationContextSpec") | ||
static class TestTenantResolver { | ||
|
||
final BeanContext beanContext | ||
|
||
TestTenantResolver(BeanContext beanContext) { | ||
this.beanContext = beanContext | ||
} | ||
|
||
@Get("/expression") | ||
@Produces(MediaType.TEXT_PLAIN) | ||
String expression() { | ||
beanContext.createBean(Holder).value | ||
} | ||
} | ||
|
||
@Factory | ||
@Requires(property = "spec.name", value = "TenantEvaluationContextSpec") | ||
static class TestFactory { | ||
|
||
@Bean | ||
Holder holder(@Value("#{ tenantId }") @Nullable String tenantId) { | ||
new Holder(value: tenantId ?: 'none') | ||
} | ||
} | ||
|
||
static class Holder { | ||
String value | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
To allow using the current request tenant Id in the https://docs.micronaut.io/latest/guide/#evaluatedExpressions[Micronaut Expression Language], you need to include the multitenancy-annotation as an annotation processor dependency. | ||
|
||
dependency:io.micronaut.multitenancy:micronaut-multitenancy-annotation[scope="annotationProcessor"] | ||
|
||
snippet::io.micronaut.multitenancy.TenantCheckingSecuredController[tags="clazz"] | ||
|
||
<1> If `tenantId` (provided by the configured TenantResolver) is equal to `'allowed'` then allow the request. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
plugins { | ||
id("groovy") | ||
} | ||
|
||
description = "Test Suite for testing and documenting the Multitenancy features" | ||
|
||
repositories { | ||
mavenCentral() | ||
} | ||
|
||
dependencies { | ||
testImplementation(projects.micronautMultitenancyAnnotations) | ||
testImplementation(projects.micronautMultitenancy) | ||
|
||
testImplementation(mn.micronaut.inject.groovy) | ||
testImplementation(mnSecurity.micronaut.security.annotations) | ||
|
||
testImplementation(mn.micronaut.http.client) | ||
testImplementation(mn.micronaut.http.server.netty) | ||
testImplementation(mn.micronaut.jackson.databind) | ||
|
||
testImplementation(mnSecurity.micronaut.security) | ||
testImplementation(mnTest.micronaut.test.spock) | ||
|
||
testRuntimeOnly(mnLogging.logback.classic) | ||
} | ||
|
||
tasks.withType<Test>().configureEach { | ||
useJUnitPlatform() | ||
} |
Oops, something went wrong.