You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by da...@apache.org on 2023/07/23 11:40:25 UTC
[causeway] 01/05: CAUSEWAY-3524: introduce ApplicationFeatureIdTransformer for secman
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch CAUSEWAY-3524
in repository https://gitbox.apache.org/repos/asf/causeway.git
commit 3746c62ae520829c7ba5dfed201be0cbc25eb39c
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Jul 7 19:02:13 2023 +0200
CAUSEWAY-3524: introduce ApplicationFeatureIdTransformer for secman
to provide an SPI allowing backward compatibility of security perms
---
antora/supplemental-ui/index.html | 59 +++++++++---------
.../permission/dom/ApplicationPermissionValue.java | 4 ++
.../CausewayModuleExtSecmanIntegration.java | 3 +
.../ApplicationFeatureIdTransformer.java | 72 ++++++++++++++++++++++
.../PermissionsEvaluationServiceForSecman.java | 18 +++++-
5 files changed, 124 insertions(+), 32 deletions(-)
diff --git a/antora/supplemental-ui/index.html b/antora/supplemental-ui/index.html
index d0892f3889..f7bea3b86f 100644
--- a/antora/supplemental-ui/index.html
+++ b/antora/supplemental-ui/index.html
@@ -72,8 +72,8 @@
<i class="fa fa-envelope-o"></i> <a href="mailto:users@causeway.apache.org">users@causeway.apache.org</a>
</div>
<div class="social-links float-right">
- <a title="Mailing List" href="docs/2.0.0-RC2/support/mailing-list.html" class="email"><i class="fa fa-at"></i></a>
- <a title="Slack Channel" href="docs/2.0.0-RC2/support/slack-channel.html" class="slack"><i class="fa fa-slack"></i></a>
+ <a title="Mailing List" href="docs/latest/support/mailing-list.html" class="email"><i class="fa fa-at"></i></a>
+ <a title="Slack Channel" href="docs/latest/support/slack-channel.html" class="slack"><i class="fa fa-slack"></i></a>
<a title="Bug Reports (Jira)" href="https://issues.apache.org/jira/secure/RapidBoard.jspa?rapidView=87" class="bug"><i class="fa fa-bug"></i></a>
<a title="Stackoverflow" href="https://stackoverflow.com/questions/tagged/causeway" class="stackoverflow"><i class="fa fa-stack-overflow"></i></a>
<a title="Twitter" href="https://twitter.com/ApacheCauseway" class="twitter"><i class="fa fa-twitter"></i></a>
@@ -112,23 +112,23 @@
</li>
<li><a href="#call-to-action">Quick Start</a></li>
<li class="menu-has-children">
- <a href="docs/2.0.0-RC2/about.html">Docs</a>
+ <a href="docs/latest/about.html">Docs</a>
<ul>
- <li><a href="docs/2.0.0-RC2/about.html">Table of Contents</a></li>
+ <li><a href="docs/latest/about.html">Table of Contents</a></li>
<li><hr/></li>
- <li><a href="docs/2.0.0-RC2/landing-page/guides.html">Guides</a></li>
- <li><a href="docs/2.0.0-RC2/landing-page/components.html">Components</a></li>
- <li><a href="extensions/2.0.0-RC2/about.html">Extensions</a></li>
- <li><a href="valuetypes/2.0.0-RC2/about.html">Value Types</a></li>
+ <li><a href="docs/latest/landing-page/guides.html">Guides</a></li>
+ <li><a href="docs/latest/landing-page/components.html">Components</a></li>
+ <li><a href="extensions/latest/about.html">Extensions</a></li>
+ <li><a href="valuetypes/latest/about.html">Value Types</a></li>
</ul>
</li>
<li class="menu-has-children">
<a href="#">Download</a>
<ul>
- <li><a href="docs/2.0.0-RC2/starters/about.html">Starter Apps</a></li>
- <li><a href="docs/2.0.0-RC2/downloads/how-to#formal-releases">Source Releases</a></li>
- <li><a href="docs/2.0.0-RC2/landing-page/releases.html">Binary Releases</a></li>
- <li><a href="docs/2.0.0-RC2/downloads/how-to#source-code">Source @ Github</a></li>
+ <li><a href="docs/latest/starters/about.html">Starter Apps</a></li>
+ <li><a href="docs/latest/downloads/how-to#formal-releases">Source Releases</a></li>
+ <li><a href="docs/latest/landing-page/releases.html">Binary Releases</a></li>
+ <li><a href="docs/latest/downloads/how-to#source-code">Source @ Github</a></li>
</ul>
</li>
<li class="menu-has-children">
@@ -162,7 +162,7 @@
<p>
<a href="#testimonials" class="btn-projects scrollto"> Reviews </a>
<a href="#call-to-action" class="btn-get-started scrollto">Quick Start</a>
- <a href="docs/2.0.0-RC2/about.html" class="btn-docs"> Docs </a>
+ <a href="docs/latest/about.html" class="btn-docs"> Docs </a>
</p>
<p>
<div class="nav-panel-search hide-for-print">
@@ -218,7 +218,7 @@
<div class="container">
<div class="section-header">
<h2>Quotes</h2>
- <p>We gathered together some quotes from current users of the framework. You can find out who said what <a href="docs/2.0.0-RC2/quotes/quotes.html">here</a>.</p>
+ <p>We gathered together some quotes from current users of the framework. You can find out who said what <a href="docs/latest/quotes/quotes.html">here</a>.</p>
</div>
<div class="owl-carousel testimonials-carousel">
@@ -561,7 +561,7 @@
<div class="col-lg-6 text-left text-lg-left">
<h4 class="cta-text">Try out ...</h4>
<p class="cta-text text-left" style="margin-block-end: 0; ">
- Try out the framework with the minimal <a href="docs/2.0.0-RC2/starters/helloworld.html">helloworld</a> starter app.
+ Try out the framework with the minimal <a href="docs/latest/starters/helloworld.html">helloworld</a> starter app.
<p>
<p class="cta-text text-left" style="margin-block-end: 0; ">
Run it locally (JPA or JDO) using:
@@ -586,7 +586,7 @@ mvn spring-boot:run</pre>
<div class="col-lg-6 text-left text-lg-left">
<h4 class="cta-text">Develop your own ...</h4>
<p class="cta-text text-left" style="margin-block-end: 0; ">
- Develop your own app with the structured <a href="docs/2.0.0-RC2/starters/simpleapp.html">simpleapp</a> starter app.
+ Develop your own app with the structured <a href="docs/latest/starters/simpleapp.html">simpleapp</a> starter app.
<p>
<p class="cta-text text-left" style="margin-block-end: 0; ">
Run it locally (JPA or JDO) using:
@@ -656,7 +656,7 @@ docker run -p 8080:8080 apache/causeway-app-demo-jdo:latest</pre>
<div class="contact-email">
<i class="ion-ios-filing-outline"></i>
<h3>Slack</h3>
- <p><a href="docs/2.0.0-RC2/support/slack-channel.html">Join #apache-causeway <br/>(on the ASF slack workspace)</a></p>
+ <p><a href="docs/latest/support/slack-channel.html">Join #apache-causeway <br/>(on the ASF slack workspace)</a></p>
</div>
</div>
@@ -793,18 +793,18 @@ docker run -p 8080:8080 apache/causeway-app-demo-jdo:latest</pre>
<script src="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js"></script>
<script>
- function focusSearchInput () { document.querySelector('#algolia-search-input').focus() }
- var search = docsearch({
- appId: '5ISP5TFAEN',
- apiKey: '0fc51c28b4ad46e7318e96d4e97fab7c',
- indexName: 'causeway-apache-org',
- inputSelector: '#algolia-search-input',
- autocompleteOptions: { hint: false, keyboardShortcuts: ['s'] },
- debug: false,
- }).autocomplete
- search.on('autocomplete:closed', function () { search.autocomplete.setVal() })
- focusSearchInput()
- window.addEventListener('load', focusSearchInput);
+ function focusSearchInput () { document.querySelector('#algolia-search-input').focus() }
+ var search = docsearch({
+ appId: '5ISP5TFAEN',
+ apiKey: '0fc51c28b4ad46e7318e96d4e97fab7c',
+ indexName: 'causeway-apache-org',
+ inputSelector: '#algolia-search-input',
+ autocompleteOptions: { hint: false, keyboardShortcuts: ['s'] },
+ debug: false,
+ }).autocomplete
+ search.on('autocomplete:closed', function () { search.autocomplete.setVal() })
+ focusSearchInput()
+ window.addEventListener('load', focusSearchInput);
</script>
<!--
@@ -816,6 +816,5 @@ docker run -p 8080:8080 apache/causeway-app-demo-jdo:latest</pre>
algoliaOptions: { hitsPerPage: 6 },
-->
-
</body>
</html>
diff --git a/extensions/security/secman/applib/src/main/java/org/apache/causeway/extensions/secman/applib/permission/dom/ApplicationPermissionValue.java b/extensions/security/secman/applib/src/main/java/org/apache/causeway/extensions/secman/applib/permission/dom/ApplicationPermissionValue.java
index 3aff46724d..77ed07c631 100644
--- a/extensions/security/secman/applib/src/main/java/org/apache/causeway/extensions/secman/applib/permission/dom/ApplicationPermissionValue.java
+++ b/extensions/security/secman/applib/src/main/java/org/apache/causeway/extensions/secman/applib/permission/dom/ApplicationPermissionValue.java
@@ -117,6 +117,10 @@ public class ApplicationPermissionValue implements Comparable<ApplicationPermiss
return false;
}
+ @Programmatic
+ public ApplicationPermissionValue withFeatureId(ApplicationFeatureId applicationFeatureId) {
+ return new ApplicationPermissionValue(applicationFeatureId, this.rule, this.mode);
+ }
// -- Comparators
diff --git a/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/CausewayModuleExtSecmanIntegration.java b/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/CausewayModuleExtSecmanIntegration.java
index 6e45015dcd..b8c8bb0ef3 100644
--- a/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/CausewayModuleExtSecmanIntegration.java
+++ b/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/CausewayModuleExtSecmanIntegration.java
@@ -18,6 +18,8 @@
*/
package org.apache.causeway.extensions.secman.integration;
+import org.apache.causeway.extensions.secman.integration.permissions.ApplicationFeatureIdTransformer;
+
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -44,6 +46,7 @@ import org.apache.causeway.extensions.secman.integration.userreg.UserRegistratio
TableColumnVisibilityServiceForSecman.class,
ImpersonateMenuAdvisorForSecman.class, //not activated by default yet
PermissionsEvaluationServiceForSecman.class,
+ ApplicationFeatureIdTransformer.Identity.class,
UserRegistrationServiceForSecman.class,
UserMementoRefinerFromApplicationUser.class,
diff --git a/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/permissions/ApplicationFeatureIdTransformer.java b/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/permissions/ApplicationFeatureIdTransformer.java
new file mode 100644
index 0000000000..a843a19710
--- /dev/null
+++ b/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/permissions/ApplicationFeatureIdTransformer.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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
+ *
+ * http://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 org.apache.causeway.extensions.secman.integration.permissions;
+
+import org.apache.causeway.applib.annotation.PriorityPrecedence;
+import org.apache.causeway.applib.annotation.Programmatic;
+import org.apache.causeway.applib.services.appfeat.ApplicationFeatureId;
+
+import org.apache.causeway.extensions.secman.applib.permission.dom.ApplicationPermissionValue;
+
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Priority;
+
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+/**
+ * Provides an SPI used by {@link PermissionsEvaluationServiceForSecman} that
+ * pre-processes {@link ApplicationFeatureId}s before evaluating them.
+ *
+ * <p>
+ * The primary use case is to enable backward compatibility; rather than evaluating using the
+ * logicalTypeName#memberId, an alternative transformer could use the packageName#memberId (as was done in v1).
+ * </p>
+ *
+ */
+public interface ApplicationFeatureIdTransformer {
+
+ @Programmatic
+ ApplicationFeatureId transform(ApplicationFeatureId applicationFeatureId);
+
+ @Programmatic
+ default Collection<ApplicationPermissionValue> transform(Collection<ApplicationPermissionValue> permissionValues) {
+ return permissionValues.stream()
+ .map(apv -> apv.withFeatureId(transform(apv.getFeatureId())))
+ .collect(Collectors.toList());
+ }
+
+ @Service
+ @Priority(PriorityPrecedence.LATE)
+ class Identity implements ApplicationFeatureIdTransformer {
+
+ @Programmatic
+ @Override
+ public ApplicationFeatureId transform(ApplicationFeatureId applicationFeatureId) {
+ return applicationFeatureId;
+ }
+
+ @Programmatic
+ @Override
+ public Collection<ApplicationPermissionValue> transform(Collection<ApplicationPermissionValue> permissionValues) {
+ return permissionValues;
+ }
+ }
+}
diff --git a/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/permissions/PermissionsEvaluationServiceForSecman.java b/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/permissions/PermissionsEvaluationServiceForSecman.java
index 3496bb1b6a..b0991ec9fc 100644
--- a/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/permissions/PermissionsEvaluationServiceForSecman.java
+++ b/extensions/security/secman/integration/src/main/java/org/apache/causeway/extensions/secman/integration/permissions/PermissionsEvaluationServiceForSecman.java
@@ -20,6 +20,7 @@ package org.apache.causeway.extensions.secman.integration.permissions;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import java.util.Optional;
import javax.inject.Inject;
@@ -71,9 +72,12 @@ implements PermissionsEvaluationService {
@Override
public ApplicationPermissionValueSet.Evaluation evaluate(
- final ApplicationFeatureId targetMemberId,
+ final ApplicationFeatureId targetMemberIdInput,
final ApplicationPermissionMode mode,
- final Collection<ApplicationPermissionValue> permissionValues) {
+ final Collection<ApplicationPermissionValue> permissionValuesInput) {
+
+ final ApplicationFeatureId targetMemberId = applicationFeatureIdTransformer().transform(targetMemberIdInput);
+ final Collection<ApplicationPermissionValue> permissionValues = applicationFeatureIdTransformer().transform(permissionValuesInput);
if(_NullSafe.isEmpty(permissionValues)) {
return null;
@@ -112,4 +116,14 @@ implements PermissionsEvaluationService {
throw _Exceptions.illegalArgument("PermissionsEvaluationPolicy '%s' not recognised", policy);
}
+ private ApplicationFeatureIdTransformer applicationFeatureIdTransformerCached;
+ ApplicationFeatureIdTransformer applicationFeatureIdTransformer() {
+ if (applicationFeatureIdTransformerCached == null) {
+ applicationFeatureIdTransformerCached = applicationFeatureIdTransformers == null || applicationFeatureIdTransformers.isEmpty() ? new ApplicationFeatureIdTransformer.Identity() : applicationFeatureIdTransformers.get(0);
+ }
+ return applicationFeatureIdTransformerCached;
+ };
+
+ @Inject List<ApplicationFeatureIdTransformer> applicationFeatureIdTransformers;
+
}