diff --git a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultRealmRunner.java b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultRealmRunner.java index cc5f733ec2e..e116d4dc74d 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultRealmRunner.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultRealmRunner.java @@ -21,12 +21,14 @@ public class DefaultRealmRunner implements ApplicationEngineStartupRunner { @Override public void run(ApplicationArguments args) throws Exception { - if (realmService.getDefaultRealm().isEmpty()) { - Realm createRequest = new com.netgrif.application.engine.adapter.spring.auth.domain.Realm("Default"); - createRequest.setDescription("Default realm"); - createRequest.setAdminRealm(true); - createRequest.setDefaultRealm(true); - realmService.createRealm(createRequest); + if (realmService.getDefaultRealm().isPresent()) { + return; } + + Realm createRequest = new com.netgrif.application.engine.adapter.spring.auth.domain.Realm("Default"); + createRequest.setDescription("Default realm"); + createRequest.setAdminRealm(true); + createRequest.setDefaultRealm(true); + realmService.createRealm(createRequest); } } diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/Realm.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/Realm.java index ddb37c48cf6..8720102d5c2 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/Realm.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/Realm.java @@ -2,6 +2,7 @@ import com.netgrif.application.engine.objects.auth.provider.AuthMethodConfig; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; import lombok.Data; import java.io.Serial; @@ -89,6 +90,19 @@ public abstract class Realm implements Serializable { */ private Duration publicSessionTimeout = Duration.ofHours(2); + /** + * If true, the realm has enabled limit of maximum allowed sessions + * per user + */ + private boolean enableLimitSessions = false; + + /** + * Maximum allowed sessions per user. Attribute {@link #enableLimitSessions} + * must be enabled. + */ + @Positive + private int maxSessionsAllowed = 1; + /** * Constructs a new Realm instance with the specified name. * diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/provider/AuthMethodConfig.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/provider/AuthMethodConfig.java index 321d1e5758c..4b9a9b3eb05 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/provider/AuthMethodConfig.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/provider/AuthMethodConfig.java @@ -17,6 +17,8 @@ public class AuthMethodConfig implements Serializable { private boolean enabled; private T configuration; private String realmId; + /// lower number has bigger priority + private int order; public AuthMethodConfig() { if (this.id == null) { diff --git a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java index 0876a494e56..191a77c5355 100644 --- a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java +++ b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/RealmServiceImpl.java @@ -132,18 +132,15 @@ public Optional getRealmByName(String name) { } @Override - public > T addProvider(String realmId, AuthMethodConfig config) { + public Realm addProvider(String realmId, AuthMethodConfig config) { AuthMethodProvider provider = (AuthMethodProvider) providerRegistry.getProvider(config.getType()); if (provider == null) { throw new IllegalArgumentException("Provider type " + config.getType() + " not found"); } - AuthMethod authMethod = provider.createAuthMethod(config); Realm realm = getRealmById(realmId).orElseThrow(() -> new IllegalArgumentException("Realm with id " + realmId + " not found")); realm.addAuthMethod(config); - realmRepository.save((com.netgrif.application.engine.adapter.spring.auth.domain.Realm) realm); - - return (T) authMethod; + return realmRepository.save((com.netgrif.application.engine.adapter.spring.auth.domain.Realm) realm); } @Override @@ -173,6 +170,33 @@ public Realm updateRealm(String realmId, Realm update) { return realmRepository.save((com.netgrif.application.engine.adapter.spring.auth.domain.Realm) realm); } + @Override + public AuthMethodConfig updateConfigInRealm(String realmId, AuthMethodConfig config) { + if (config == null) { + throw new IllegalArgumentException("Authentication config not provided"); + } + + Realm realm = getRealmById(realmId).orElseThrow(() -> new IllegalArgumentException("Realm with id " + realmId + " not found")); + Optional> configToUpdateOpt = realm.getAuthMethods().stream() + .filter(realmConfig -> realmConfig.getId().equals(config.getId())) + .findFirst(); + + if (configToUpdateOpt.isEmpty()) { + throw new IllegalArgumentException("Authentication config with id " + config.getId() + " not found in realm " + realmId); + } + + AuthMethodConfig configToUpdate = configToUpdateOpt.get(); + configToUpdate.setName(config.getName()); + configToUpdate.setDescription(config.getDescription()); + configToUpdate.setEnabled(config.isEnabled()); + configToUpdate.setOrder(config.getOrder()); + configToUpdate.setConfiguration(config.getConfiguration()); + + realmRepository.save((com.netgrif.application.engine.adapter.spring.auth.domain.Realm) realm); + + return configToUpdate; + } + @Override public void deleteRealm(String realmId) { if (!realmRepository.existsById(realmId)) { diff --git a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java index 40954e98248..1fa89a13d23 100644 --- a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java +++ b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/UserServiceImpl.java @@ -141,9 +141,9 @@ public Optional findUserByUsername(String username, String realmId String collectionName = collectionNameProvider.getCollectionNameForRealm(realmId); Optional userOpt = userRepository.findByUsername(username, mongoTemplate, collectionName).map(user -> (AbstractUser) user); if (userOpt.isPresent()) { - log.debug("User [{}] found in realm [{}]", username, collectionName); + log.debug("User [{}] found in realm [{}]", username, realmId); } else { - log.warn("User [{}] not found in realm [{}]", username, collectionName); + log.warn("User [{}] not found in realm [{}]", username, realmId); } return userOpt; } diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/domain/NetgrifAuthenticationToken.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/domain/NetgrifAuthenticationToken.java index 37569f17303..b1c17d21013 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/domain/NetgrifAuthenticationToken.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/domain/NetgrifAuthenticationToken.java @@ -1,17 +1,26 @@ package com.netgrif.application.engine.auth.domain; +import com.netgrif.application.engine.objects.auth.domain.Realm; import lombok.Getter; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @Getter public class NetgrifAuthenticationToken extends UsernamePasswordAuthenticationToken { - private final String realmId; + private final String realmName; + private final Realm realm; - public NetgrifAuthenticationToken(Object principal, Object credentials, String realmId) { + public NetgrifAuthenticationToken(Object principal, Object credentials, String realmName) { super(principal, credentials); - this.realmId = realmId; + this.realmName = realmName; + this.realm = null; + } + + public NetgrifAuthenticationToken(Object principal, Object credentials, Realm realm) { + super(principal, credentials); + this.realm = realm; + this.realmName = realm != null ? realm.getName() : null; } } diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodConfigDeserializer.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodConfigDeserializer.java index 6aa3f7d727d..b137422890c 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodConfigDeserializer.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodConfigDeserializer.java @@ -54,6 +54,16 @@ public AuthMethodConfig deserialize(JsonParser jp, DeserializationContext ctx config.setEnabled(enabledNode.asBoolean()); } + JsonNode descNode = node.get("description"); + if (descNode != null) { + config.setDescription(descNode.asText()); + } + + JsonNode orderNode = node.get("order"); + if (orderNode != null) { + config.setOrder(orderNode.asInt()); + } + config.setType(type); config.setRealmId(realmID); diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodProvider.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodProvider.java index d5a06866bec..9f73db553e3 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodProvider.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/AuthMethodProvider.java @@ -1,14 +1,11 @@ package com.netgrif.application.engine.auth.provider; import com.netgrif.application.engine.objects.auth.provider.AuthMethod; -import com.netgrif.application.engine.objects.auth.provider.AuthMethodConfig; public interface AuthMethodProvider { String getProviderType(); - AuthMethod createAuthMethod(AuthMethodConfig authMethodConfig); - Class getConfigClass(); Class> getAuthMethodClass(); diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/ProviderRegistry.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/ProviderRegistry.java index 7163fdaed32..75cab02d73c 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/ProviderRegistry.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/provider/ProviderRegistry.java @@ -4,19 +4,26 @@ import org.springframework.stereotype.Component; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; @Slf4j @Component public class ProviderRegistry { - protected final Map> configClasses = new HashMap<>(); + protected final Map> configClasses = new ConcurrentHashMap<>(); - protected final Map> providers = new HashMap<>(); + protected final Map> providers = new ConcurrentHashMap<>(); + /** + * Registers provider into this bean + * + * @param type type of the provider. It's used as a key in the map registry + * @param provider provider instance to register. It's used as a value in the map registry + * */ public void registerProvider(String type, AuthMethodProvider provider) { providers.put(type.toLowerCase(), provider); configClasses.put(type.toLowerCase(), provider.getConfigClass()); - log.info("Registered provider for type: " + type); + log.info("Registered provider for type: {}", type); } public Class getConfigClass(String type) { diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/RealmDto.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/RealmDto.java index 3a045ed71b9..ac514eacc75 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/RealmDto.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/RealmDto.java @@ -6,5 +6,7 @@ public record RealmDto(String name, Boolean adminRealm, Boolean enableBlocking, Integer maxFailedAttempts, - Integer blockDurationMinutes) { + Integer blockDurationMinutes, + Boolean enableLimitSessions, + Integer maxSessionsAllowed) { } diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/request/RealmSearch.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/request/RealmSearch.java index f548f9c0021..67d3f6f3998 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/request/RealmSearch.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/realm/request/RealmSearch.java @@ -7,5 +7,7 @@ public record RealmSearch(String id, Boolean adminRealm, Boolean enableBlocking, Integer maxFailedAttempts, - Integer blockDurationMinutes) { + Integer blockDurationMinutes, + Boolean enableLimitSessions, + Integer maxSessionsAllowed) { } diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/RealmService.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/RealmService.java index ecfac324ba7..28083bf7575 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/RealmService.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/RealmService.java @@ -32,11 +32,13 @@ public interface RealmService { Optional getRealmByName(String name); - > T addProvider(String realmId, AuthMethodConfig config); + Realm addProvider(String realmId, AuthMethodConfig config); void removeProvider(String realmId, String providerId); Realm updateRealm(String realmId, Realm update); + AuthMethodConfig updateConfigInRealm(String realmId, AuthMethodConfig config); + void deleteRealm(String realmId); }