You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by ah...@apache.org on 2024/03/20 14:18:58 UTC
(causeway-app-helloworld) branch jpa3-SNAPSHOT created (now 8067a41)
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a change to branch jpa3-SNAPSHOT
in repository https://gitbox.apache.org/repos/asf/causeway-app-helloworld.git
at 8067a41 use SimpleAuth as Shiro replacement
This branch includes the following new commits:
new 8067a41 use SimpleAuth as Shiro replacement
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(causeway-app-helloworld) 01/01: use SimpleAuth as Shiro replacement
Posted by ah...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch jpa3-SNAPSHOT
in repository https://gitbox.apache.org/repos/asf/causeway-app-helloworld.git
commit 8067a41e4da743d2df7569e9dd07b0b5f47f0bab
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Mar 20 15:18:53 2024 +0100
use SimpleAuth as Shiro replacement
---
pom.xml | 11 +--
.../modules/hello/dom/hwo/HelloWorldObject.java | 28 +++---
.../modules/hello/dom/hwo/HelloWorldObjects.java | 6 +-
src/main/java/domainapp/webapp/AppManifest.java | 3 +-
src/main/java/domainapp/webapp/HelloWorldApp.java | 51 +++++++++-
src/main/java/domainapp/webapp/SimpleAuth.java | 106 +++++++++++++++++++++
src/main/resources/shiro.ini | 49 ----------
7 files changed, 179 insertions(+), 75 deletions(-)
diff --git a/pom.xml b/pom.xml
index cad7745..51818b9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,20 +7,19 @@
<parent>
<groupId>org.apache.causeway.app</groupId>
<artifactId>causeway-app-starter-parent</artifactId>
- <version>2.0.0-SNAPSHOT</version>
+ <version>3.0.0-SNAPSHOT</version>
<relativePath/>
</parent>
<artifactId>helloworld-jpa</artifactId>
<groupId>org.apache.causeway.starters</groupId>
- <version>2.0.0-SNAPSHOT</version>
<name>HelloWorld (JPA)</name>
<packaging>jar</packaging>
<properties>
- <java.version>11</java.version>
+ <java.version>21</java.version>
<!-- https://stackoverflow.com/questions/38983934/cannot-get-maven-project-version-property-in-a-spring-application-with-value/38983935#38983935 -->
<resource.delimiter>^</resource.delimiter>
</properties>
@@ -88,7 +87,7 @@
<dependency>
<groupId>org.apache.causeway.security</groupId>
- <artifactId>causeway-security-shiro</artifactId>
+ <artifactId>causeway-security-bypass</artifactId>
</dependency>
<dependency>
@@ -115,7 +114,7 @@
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
</dependency>
-
+
</dependencies>
<profiles>
@@ -133,7 +132,7 @@
<artifactId>jib-maven-plugin</artifactId>
<configuration>
<from>
- <image>adoptopenjdk/openjdk11:x86_64-alpine-jre-11.0.10_9</image>
+ <image>openjdk:21-jdk-bookworm</image>
</from>
<container>
<jvmFlags>
diff --git a/src/main/java/domainapp/modules/hello/dom/hwo/HelloWorldObject.java b/src/main/java/domainapp/modules/hello/dom/hwo/HelloWorldObject.java
index b93ae56..2d96194 100644
--- a/src/main/java/domainapp/modules/hello/dom/hwo/HelloWorldObject.java
+++ b/src/main/java/domainapp/modules/hello/dom/hwo/HelloWorldObject.java
@@ -2,18 +2,18 @@ package domainapp.modules.hello.dom.hwo;
import java.util.Comparator;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EntityListeners;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.Table;
-import javax.persistence.Transient;
-import javax.persistence.UniqueConstraint;
-import javax.persistence.Version;
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EntityListeners;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import jakarta.persistence.Transient;
+import jakarta.persistence.UniqueConstraint;
+import jakarta.persistence.Version;
import org.apache.causeway.applib.annotation.Action;
import org.apache.causeway.applib.annotation.ActionLayout;
@@ -73,7 +73,7 @@ public class HelloWorldObject implements Comparable<HelloWorldObject> {
public String getName() {
return name;
}
- public void setName(String name) {
+ public void setName(final String name) {
this.name = name;
}
@@ -86,7 +86,7 @@ public class HelloWorldObject implements Comparable<HelloWorldObject> {
public String getNotes() {
return notes;
}
- public void setNotes(String notes) {
+ public void setNotes(final String notes) {
this.notes = notes;
}
diff --git a/src/main/java/domainapp/modules/hello/dom/hwo/HelloWorldObjects.java b/src/main/java/domainapp/modules/hello/dom/hwo/HelloWorldObjects.java
index b155532..8e2bc7e 100644
--- a/src/main/java/domainapp/modules/hello/dom/hwo/HelloWorldObjects.java
+++ b/src/main/java/domainapp/modules/hello/dom/hwo/HelloWorldObjects.java
@@ -2,9 +2,9 @@ package domainapp.modules.hello.dom.hwo;
import java.util.List;
-import javax.annotation.Priority;
-import javax.inject.Inject;
-import javax.inject.Named;
+import jakarta.annotation.Priority;
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
import org.apache.causeway.applib.annotation.Action;
import org.apache.causeway.applib.annotation.ActionLayout;
diff --git a/src/main/java/domainapp/webapp/AppManifest.java b/src/main/java/domainapp/webapp/AppManifest.java
index 1ad5341..0e5fb3a 100644
--- a/src/main/java/domainapp/webapp/AppManifest.java
+++ b/src/main/java/domainapp/webapp/AppManifest.java
@@ -10,7 +10,6 @@ import org.apache.causeway.applib.CausewayModuleApplibMixins;
import org.apache.causeway.core.config.presets.CausewayPresets;
import org.apache.causeway.core.runtimeservices.CausewayModuleCoreRuntimeServices;
import org.apache.causeway.persistence.jpa.eclipselink.CausewayModulePersistenceJpaEclipselink;
-import org.apache.causeway.security.shiro.CausewayModuleSecurityShiro;
import org.apache.causeway.testing.h2console.ui.CausewayModuleTestingH2ConsoleUi;
import org.apache.causeway.viewer.restfulobjects.jaxrsresteasy.CausewayModuleViewerRestfulObjectsJaxrsResteasy;
import org.apache.causeway.viewer.wicket.applib.CausewayModuleViewerWicketApplibMixins;
@@ -24,7 +23,7 @@ import domainapp.modules.hello.HelloWorldModule;
CausewayModuleApplibChangeAndExecutionLoggers.class,
CausewayModuleCoreRuntimeServices.class,
- CausewayModuleSecurityShiro.class,
+ //CausewayModuleSecurityXxx.class,
CausewayModulePersistenceJpaEclipselink.class,
CausewayModuleViewerRestfulObjectsJaxrsResteasy.class,
CausewayModuleViewerWicketApplibMixins.class,
diff --git a/src/main/java/domainapp/webapp/HelloWorldApp.java b/src/main/java/domainapp/webapp/HelloWorldApp.java
index 9ad441f..a67f5fa 100644
--- a/src/main/java/domainapp/webapp/HelloWorldApp.java
+++ b/src/main/java/domainapp/webapp/HelloWorldApp.java
@@ -1,19 +1,68 @@
package domainapp.webapp;
+import java.util.List;
+
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.apache.causeway.core.config.presets.CausewayPresets;
+import domainapp.webapp.HelloWorldApp.SimpleAuthSetup;
+import domainapp.webapp.SimpleAuth.Realm;
+
@SpringBootApplication
@Import({
+ SimpleAuthSetup.class,
+ SimpleAuth.class,
AppManifest.class,
})
public class HelloWorldApp extends SpringBootServletInitializer {
- public static void main(String[] args) {
+ @Configuration
+ static class SimpleAuthSetup {
+
+ /* migrated from shiro.ini
+ [users]
+ sven = pass, admin_role
+ dick = pass, hello_role, default_role
+ bob = pass, hello_role, default_role, fixtures_role
+ joe = pass, hello_role, default_role
+
+ [roles]
+ hello_role = *:HelloWorldObjects:*:*,\
+ *:HelloWorldObject:*:*
+ admin_role = *
+ default_role = causeway.applib,\
+ causeway.security
+ fixtures_role = causeway.testing.fixtures
+ features_role = causeway.feat
+ metamodel_role = causeway.metamodel
+ h2_role = causeway.ext.h2Console
+ jdo_role = causeway.persistence.jdo
+ swagger_role = causeway.viewer.restfulobjects
+ conf_role = causeway.conf
+ sudo_role = causeway.sudo
+ */
+ @Bean
+ public SimpleAuth.Realm simpleAuthRealm() {
+ return new Realm()
+ .addRole("hello_role", id->id.getFullIdentityString().contains("HelloWorldObject"))
+ .addRole("admin_role", id->true)
+ .addRole("default_role", id->id.getFullIdentityString().startsWith("causeway.applib")
+ || id.getFullIdentityString().startsWith("causeway.security"))
+ .addRole("fixtures_role", id->id.getFullIdentityString().startsWith("causeway..testing.fixtures"))
+ .addUser("sven", "pass", List.of("admin_role"))
+ .addUser("dick", "pass", List.of("hello_role", "default_role"))
+ .addUser("bob", "pass", List.of("hello_role", "default_role", "fixtures_role"))
+ .addUser("joe", "pass", List.of("hello_role", "default_role"));
+ }
+ }
+
+ public static void main(final String[] args) {
CausewayPresets.prototyping(); // or run with use -DPROTOTYPING=true
SpringApplication.run(new Class[] { HelloWorldApp.class }, args);
}
diff --git a/src/main/java/domainapp/webapp/SimpleAuth.java b/src/main/java/domainapp/webapp/SimpleAuth.java
new file mode 100644
index 0000000..dd52a4a
--- /dev/null
+++ b/src/main/java/domainapp/webapp/SimpleAuth.java
@@ -0,0 +1,106 @@
+package domainapp.webapp;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import jakarta.inject.Inject;
+
+import org.springframework.stereotype.Component;
+
+import org.apache.causeway.applib.Identifier;
+import org.apache.causeway.applib.services.iactnlayer.InteractionContext;
+import org.apache.causeway.applib.services.user.UserMemento;
+import org.apache.causeway.core.security.authentication.AuthenticationRequest;
+import org.apache.causeway.core.security.authentication.AuthenticationRequestPassword;
+import org.apache.causeway.core.security.authentication.Authenticator;
+import org.apache.causeway.core.security.authorization.Authorizor;
+
+@Component
+public class SimpleAuth implements Authenticator, Authorizor {
+
+ static class Realm {
+ static record Role(String name, Predicate<Identifier> grantsRead, Predicate<Identifier> grantsChange) {
+ }
+ static record User(String name, String pass, List<Role> roles) {
+ }
+ final Map<String, Role> roles = new HashMap<>();
+ final Map<String, User> users = new HashMap<>();
+ public Realm addRole(final String name, final Predicate<Identifier> grants) {
+ roles.put(name, new Role(name, grants, grants));
+ return this;
+ }
+ public Realm addUser(final String name, final String pass, final List<String> roleNames) {
+ users.put(name, new User(name, pass, roleNames.stream().map(roles::get).toList()));
+ return this;
+ }
+ }
+
+ @Inject Realm realm;
+
+ /**
+ * Default implementation returns a validated {@link InteractionContext}; can be overridden
+ * if required.
+ */
+ @Override
+ public final InteractionContext authenticate(
+ final AuthenticationRequest request,
+ final String validationCode) {
+
+ if(request instanceof AuthenticationRequestPassword pwdRequest) {
+ if (!isValid(pwdRequest)) {
+ return null;
+ }
+ }
+
+ var user = UserMemento.ofNameAndRoleNames(request.getName(), Stream.concat(
+ request.streamRoles(),
+ realm.users.get(request.getName())
+ .roles()
+ .stream()
+ .map(Realm.Role::name))
+ )
+ .withAuthenticationCode(validationCode);
+ return InteractionContext.ofUserWithSystemDefaults(user);
+ }
+
+ @Override
+ public final void logout() {
+ // no-op
+ }
+
+ @Override
+ public boolean isVisible(final InteractionContext ctx, final Identifier identifier) {
+ return roles(ctx.getUser()).stream()
+ .anyMatch(role->role.grantsRead().test(identifier));
+ }
+
+ @Override
+ public boolean isUsable(final InteractionContext ctx, final Identifier identifier) {
+ return roles(ctx.getUser()).stream()
+ .anyMatch(role->role.grantsChange().test(identifier));
+ }
+
+ @Override
+ public final boolean canAuthenticate(final Class<? extends AuthenticationRequest> authenticationRequestClass) {
+ return AuthenticationRequestPassword.class.isAssignableFrom(authenticationRequestClass);
+ }
+
+ protected boolean isValid(final AuthenticationRequestPassword request) {
+ return Optional.ofNullable(realm.users.get(request.getName()))
+ .map(Realm.User::pass)
+ .map(pass->pass.equals(request.getPassword()))
+ .orElse(false);
+ }
+
+ protected List<Realm.Role> roles(final UserMemento userMemento){
+ var roles = Optional.ofNullable(realm.users.get(userMemento.getName()))
+ .map(Realm.User::roles)
+ .orElseGet(List::of);
+ return roles;
+ }
+
+}
diff --git a/src/main/resources/shiro.ini b/src/main/resources/shiro.ini
deleted file mode 100644
index 30faa89..0000000
--- a/src/main/resources/shiro.ini
+++ /dev/null
@@ -1,49 +0,0 @@
-[main]
-
-# to use .ini file
-securityManager.realms = $iniRealm
-
-
-
-# -----------------------------------------------------------------------------
-# Users and their assigned roles
-#
-# Each line conforms to the format defined in the
-# org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions JavaDoc
-# -----------------------------------------------------------------------------
-
-[users]
-# user = password, role1, role2, role3, ...
-
-
-sven = pass, admin_role
-dick = pass, hello_role, default_role
-bob = pass, hello_role, default_role, fixtures_role
-joe = pass, hello_role, default_role
-
-
-
-# -----------------------------------------------------------------------------
-# Roles with assigned permissions
-#
-# Each line conforms to the format defined in the
-# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc
-# -----------------------------------------------------------------------------
-
-[roles]
-# role = perm1, perm2, perm3, ...
-# perm in format: logicalTypeNamespace:logicalTypeSimpleName:memberName:r,w
-
-hello_role = *:HelloWorldObjects:*:*,\
- *:HelloWorldObject:*:*
-admin_role = *
-default_role = causeway.applib,\
- causeway.security
-fixtures_role = causeway.testing.fixtures
-features_role = causeway.feat
-metamodel_role = causeway.metamodel
-h2_role = causeway.ext.h2Console
-jdo_role = causeway.persistence.jdo
-swagger_role = causeway.viewer.restfulobjects
-conf_role = causeway.conf
-sudo_role = causeway.sudo