You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2021/05/25 18:09:28 UTC
[isis] 03/03: ISIS-2697: simplifies secman's support for user
registration
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch ISIS-2697
in repository https://gitbox.apache.org/repos/asf/isis.git
commit 69e68922147605c4ceca0e19510aa26c9ce65252
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Tue May 25 19:05:04 2021 +0100
ISIS-2697: simplifies secman's support for user registration
---
...UserRegistrationService_010-implementation.adoc | 26 +-------
.../apache/isis/core/config/IsisConfiguration.java | 19 ++++++
.../adoc/modules/secman/pages/setting-up.adoc | 20 ++++++
.../secman/model/IsisModuleExtSecmanModel.java | 4 +-
....java => UserRegistrationServiceForSecman.java} | 71 +++++++++++-----------
5 files changed, 79 insertions(+), 61 deletions(-)
diff --git a/antora/components/refguide-index/modules/applib/pages/index/services/userreg/hooks/UserRegistrationService_010-implementation.adoc b/antora/components/refguide-index/modules/applib/pages/index/services/userreg/hooks/UserRegistrationService_010-implementation.adoc
index 66c8c0b..243bc20 100644
--- a/antora/components/refguide-index/modules/applib/pages/index/services/userreg/hooks/UserRegistrationService_010-implementation.adoc
+++ b/antora/components/refguide-index/modules/applib/pages/index/services/userreg/hooks/UserRegistrationService_010-implementation.adoc
@@ -10,28 +10,6 @@ Rather, the implementation will depend on the security mechanism being used.
=== SecMan
-If you have configured your app to use the xref:security:ROOT:about.adoc[SecMan extension] then note that it _does_ provide an abstract implementation (`SecurityModuleAppUserRegistrationServiceAbstract`) of the `UserRegistrationService`.
-You will need to extend that service and provide implementation for the two abstract methods: `getInitialRole()` and `getAdditionalInitialRoles()`.
-This is needed so that the self-registered users are assigned automatically to your application role(s) and be able to use the application.
-Without any role such user will be able only to see/use the logout link of the application.
-
-For example:
-
-[source,java]
-----
-@Service
-public class AppUserRegistrationService
- extends SecurityModuleAppUserRegistrationServiceAbstract {
-
- protected ApplicationRole getInitialRole() {
- return applicationRoles.findRoleByName("regular-user");
- }
- protected Set<ApplicationRole> getAdditionalInitialRoles() {
- return Collections.singleton(
- applicationRoles.findRoleByName("self-registered-user"));
- }
-
- @Inject ApplicationRoles applicationRoles;
-}
-----
+If you have configured your app to use the xref:security:ROOT:about.adoc[SecMan extension] then note that it _does_ provide an implementation (`UserRegistrationServiceForSecman`) of this `UserRegistrationService`.
+This can be configured to set up initial roles; see xref:security:secman:setting-up.adoc#user-registration-aka-sign-up[secman docs] for details.
diff --git a/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java b/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
index 835280f..aab2e3a 100644
--- a/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
+++ b/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
@@ -2947,7 +2947,26 @@ public class IsisConfiguration {
}
}
+ private final Secman secman = new Secman();
+ @Data
+ public static class Secman {
+ private final UserRegistration userRegistration = new UserRegistration();
+ @Data
+ public static class UserRegistration {
+ /**
+ * The set of roles that users registering with the app are granted
+ * automatically.
+ *
+ * <p>
+ * If using the wicket viewer, also requires
+ * {@link Viewer.Wicket#isSuppressSignUp() isis.viewer.wicket.suppress-signup} to be set
+ * <code>false</code>, along with any other of its other prereqs.
+ * </p>
+ */
+ private final List<String> initialRoleNames = new ArrayList<>();
+ }
+ }
}
private static List<String> listOf(final String ...values) {
diff --git a/extensions/security/secman/adoc/modules/secman/pages/setting-up.adoc b/extensions/security/secman/adoc/modules/secman/pages/setting-up.adoc
index 02d7b1e..670ced5 100644
--- a/extensions/security/secman/adoc/modules/secman/pages/setting-up.adoc
+++ b/extensions/security/secman/adoc/modules/secman/pages/setting-up.adoc
@@ -371,4 +371,24 @@ isisModuleSecurityRealm.delegateAuthenticationRealm=$ldapRealm #<.
<.> specify the LDAP realm as the delegate realm for SecMan's own realm.
+[#user-registration-aka-sign-up]
+== User registration (aka Sign-up)
+
+Secman provides an implementation of the xref:refguide:applib:index/services/userreg/UserRegistrationService.adoc[UserRegistrationService] SPI.
+This means, if the viewer supports it (eg the Wicket viewer's xref:vw::features/user-registration.adoc[sign-up support]), then end-users can sign-up to create an account via email.
+The Secman implementation sets up the user with appropriate initial roles.
+
+The exact roles to setup are specified using configuration property:
+
+[source,yaml]
+.application.yaml
+----
+isis:
+ extensions:
+ secman:
+ user-registration:
+ initial-roles:
+ - "self-registered-user-role"
+ - "regular-user-role"
+----
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/IsisModuleExtSecmanModel.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/IsisModuleExtSecmanModel.java
index 23c9624..197836f 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/IsisModuleExtSecmanModel.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/IsisModuleExtSecmanModel.java
@@ -26,6 +26,7 @@ import org.apache.isis.extensions.secman.model.facets.TenantedAuthorizationPostP
import org.apache.isis.extensions.secman.model.seed.SeedSecurityModuleService;
import org.apache.isis.extensions.secman.model.spiimpl.ImpersonateMenuAdvisorForSecman;
import org.apache.isis.extensions.secman.model.spiimpl.TableColumnVisibilityServiceForSecman;
+import org.apache.isis.extensions.secman.model.userreg.UserRegistrationServiceForSecman;
/**
* @since 2.0 {@index}
@@ -35,10 +36,11 @@ import org.apache.isis.extensions.secman.model.spiimpl.TableColumnVisibilityServ
// Module
IsisModuleExtSecmanApi.class,
- // @Component
+ // @Component or @Service
TenantedAuthorizationPostProcessor.Register.class,
TableColumnVisibilityServiceForSecman.class,
ImpersonateMenuAdvisorForSecman.class, //not activated by default yet
+ UserRegistrationServiceForSecman.class,
SeedSecurityModuleService.class,
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/userreg/SecurityModuleAppUserRegistrationServiceAbstract.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/userreg/UserRegistrationServiceForSecman.java
similarity index 58%
rename from extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/userreg/SecurityModuleAppUserRegistrationServiceAbstract.java
rename to extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/userreg/UserRegistrationServiceForSecman.java
index 7c38f95..a2cd8f0 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/userreg/SecurityModuleAppUserRegistrationServiceAbstract.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/userreg/UserRegistrationServiceForSecman.java
@@ -18,30 +18,46 @@
*/
package org.apache.isis.extensions.secman.model.userreg;
-import java.util.Set;
+import java.util.Optional;
import javax.inject.Inject;
+import javax.inject.Named;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Service;
+
+import org.apache.isis.applib.annotation.OrderPrecedence;
import org.apache.isis.applib.services.userreg.UserDetails;
import org.apache.isis.applib.services.userreg.UserRegistrationService;
import org.apache.isis.applib.value.Password;
import org.apache.isis.commons.internal.base._Strings;
-import org.apache.isis.extensions.secman.api.role.dom.ApplicationRole;
+import org.apache.isis.core.config.IsisConfiguration;
import org.apache.isis.extensions.secman.api.role.dom.ApplicationRoleRepository;
import org.apache.isis.extensions.secman.api.user.dom.ApplicationUser;
import org.apache.isis.extensions.secman.api.user.dom.ApplicationUserRepository;
import org.apache.isis.extensions.secman.api.user.dom.ApplicationUserStatus;
+import lombok.RequiredArgsConstructor;
+import lombok.val;
+
/**
- * An abstract implementation of {@link org.apache.isis.applib.services.userreg.UserRegistrationService}
- * with a single abstract method for the initial role of newly created local users
+ * An implementation of {@link org.apache.isis.applib.services.userreg.UserRegistrationService}
+ * to allow users to be automatically created with the configured initial
+ * role(s).
*
* @since 2.0 {@index}
*/
-public abstract class SecurityModuleAppUserRegistrationServiceAbstract implements UserRegistrationService {
+@Service
+@Named("isis.ext.secman.UserRegistrationServiceForSecman")
+@Order(OrderPrecedence.MIDPOINT)
+@Qualifier("SecMan")
+@RequiredArgsConstructor(onConstructor_ = {@Inject})
+public class UserRegistrationServiceForSecman implements UserRegistrationService {
- @Inject private ApplicationUserRepository applicationUserRepository;
- @Inject private ApplicationRoleRepository applicationRoleRepository;
+ private final ApplicationUserRepository applicationUserRepository;
+ private final ApplicationRoleRepository applicationRoleRepository;
+ private final IsisConfiguration isisConfiguration;
@Override
public boolean usernameExists(final String username) {
@@ -53,27 +69,21 @@ public abstract class SecurityModuleAppUserRegistrationServiceAbstract implement
final UserDetails userDetails) {
final Password password = new Password(userDetails.getPassword());
- final ApplicationRole initialRole = getInitialRole();
final String username = userDetails.getUsername();
final String emailAddress = userDetails.getEmailAddress();
- final ApplicationUser applicationUser = (ApplicationUser) applicationUserRepository
+ final ApplicationUser applicationUser = applicationUserRepository
.newLocalUser(username, password, ApplicationUserStatus.UNLOCKED);
if(_Strings.isNotEmpty(emailAddress)) {
applicationUser.setEmailAddress(emailAddress);
}
- if(initialRole!=null) {
- applicationRoleRepository.addRoleToUser(initialRole, applicationUser);
- }
-
- final Set<ApplicationRole> additionalRoles = getAdditionalInitialRoles();
- if(additionalRoles != null) {
- for (final ApplicationRole additionalRole : additionalRoles) {
- applicationRoleRepository.addRoleToUser(additionalRole, applicationUser);
- }
- }
+ isisConfiguration.getExtensions().getSecman().getUserRegistration().getInitialRoleNames().stream()
+ .map(applicationRoleRepository::findByName)
+ .filter(Optional::isPresent)
+ .map(Optional::get)
+ .forEach(role -> applicationRoleRepository.addRoleToUser(role, applicationUser));
}
@Override
@@ -83,23 +93,12 @@ public abstract class SecurityModuleAppUserRegistrationServiceAbstract implement
@Override
public boolean updatePasswordByEmail(final String emailAddress, final String password) {
- boolean passwordUpdated = false;
- final ApplicationUser user = applicationUserRepository.findByEmailAddress(emailAddress)
- .orElse(null);
- if (user != null) {
- passwordUpdated = applicationUserRepository.updatePassword(user, password);;
- }
- return passwordUpdated;
+ return applicationUserRepository.findByEmailAddress(emailAddress)
+ .map(user -> {
+ val passwordWasUpdated = applicationUserRepository.updatePassword(user, password);
+ return passwordWasUpdated;
+ })
+ .orElse(false);
}
- /**
- * @return The role to use for newly created local users
- */
- protected abstract ApplicationRole getInitialRole();
-
- /**
- * @return Additional roles for newly created local users
- */
- protected abstract Set<ApplicationRole> getAdditionalInitialRoles();
-
}