From 364c8a039ebaedeafe4b88df194903f129e9531f Mon Sep 17 00:00:00 2001 From: marwanehcine Date: Wed, 29 Nov 2023 13:23:13 +0100 Subject: [PATCH] first code refactor to be updated --- .../admin/AbstractAccountsManager.java | 5 ++-- .../admin/CreateAccountUserCustomizer.java | 5 +++- .../admin/ldap/LdapAccountsManager.java | 10 +++++-- .../security/GeorchestraUserMapper.java | 7 +++-- .../ResolveGeorchestraUserGlobalFilter.java | 28 +++++++++++++++++-- .../DuplicatedEmailFoundException.java | 13 +++++++++ .../DuplicatedUsernameFoundException.java | 13 +++++++++ 7 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 gateway/src/main/java/org/georchestra/gateway/security/exceptions/DuplicatedEmailFoundException.java create mode 100644 gateway/src/main/java/org/georchestra/gateway/security/exceptions/DuplicatedUsernameFoundException.java diff --git a/gateway/src/main/java/org/georchestra/gateway/accounts/admin/AbstractAccountsManager.java b/gateway/src/main/java/org/georchestra/gateway/accounts/admin/AbstractAccountsManager.java index 5e384f38..154e4f4f 100644 --- a/gateway/src/main/java/org/georchestra/gateway/accounts/admin/AbstractAccountsManager.java +++ b/gateway/src/main/java/org/georchestra/gateway/accounts/admin/AbstractAccountsManager.java @@ -23,6 +23,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Consumer; +import org.georchestra.gateway.security.exceptions.DuplicatedEmailFoundException; import org.georchestra.security.model.GeorchestraUser; import lombok.NonNull; @@ -36,7 +37,7 @@ public abstract class AbstractAccountsManager implements AccountManager { protected final ReadWriteLock lock = new ReentrantReadWriteLock(); @Override - public GeorchestraUser getOrCreate(@NonNull GeorchestraUser mappedUser) { + public GeorchestraUser getOrCreate(@NonNull GeorchestraUser mappedUser) throws DuplicatedEmailFoundException { return find(mappedUser).orElseGet(() -> createIfMissing(mappedUser)); } @@ -56,7 +57,7 @@ protected Optional findInternal(GeorchestraUser mappedUser) { return findByUsername(mappedUser.getUsername()); } - GeorchestraUser createIfMissing(GeorchestraUser mapped) { + GeorchestraUser createIfMissing(GeorchestraUser mapped) throws DuplicatedEmailFoundException { lock.writeLock().lock(); try { GeorchestraUser existing = findInternal(mapped).orElse(null); diff --git a/gateway/src/main/java/org/georchestra/gateway/accounts/admin/CreateAccountUserCustomizer.java b/gateway/src/main/java/org/georchestra/gateway/accounts/admin/CreateAccountUserCustomizer.java index 04d8bd5a..4f72f9ec 100644 --- a/gateway/src/main/java/org/georchestra/gateway/accounts/admin/CreateAccountUserCustomizer.java +++ b/gateway/src/main/java/org/georchestra/gateway/accounts/admin/CreateAccountUserCustomizer.java @@ -20,7 +20,9 @@ import java.util.Objects; +import org.georchestra.ds.users.DuplicatedEmailException; import org.georchestra.gateway.security.GeorchestraUserCustomizerExtension; +import org.georchestra.gateway.security.exceptions.DuplicatedEmailFoundException; import org.georchestra.security.model.GeorchestraUser; import org.springframework.core.Ordered; import org.springframework.security.core.Authentication; @@ -57,7 +59,8 @@ public class CreateAccountUserCustomizer implements GeorchestraUserCustomizerExt * otherwise. */ @Override - public @NonNull GeorchestraUser apply(@NonNull Authentication auth, @NonNull GeorchestraUser mappedUser) { + public @NonNull GeorchestraUser apply(@NonNull Authentication auth, @NonNull GeorchestraUser mappedUser) + throws DuplicatedEmailFoundException { final boolean isOauth2 = auth instanceof OAuth2AuthenticationToken; final boolean isPreAuth = auth instanceof PreAuthenticatedAuthenticationToken; if (isOauth2) { diff --git a/gateway/src/main/java/org/georchestra/gateway/accounts/admin/ldap/LdapAccountsManager.java b/gateway/src/main/java/org/georchestra/gateway/accounts/admin/ldap/LdapAccountsManager.java index 688edd2b..8741ecd7 100644 --- a/gateway/src/main/java/org/georchestra/gateway/accounts/admin/ldap/LdapAccountsManager.java +++ b/gateway/src/main/java/org/georchestra/gateway/accounts/admin/ldap/LdapAccountsManager.java @@ -40,6 +40,8 @@ import org.georchestra.gateway.accounts.admin.AbstractAccountsManager; import org.georchestra.gateway.accounts.admin.AccountCreated; import org.georchestra.gateway.accounts.admin.AccountManager; +import org.georchestra.gateway.security.exceptions.DuplicatedEmailFoundException; +import org.georchestra.gateway.security.exceptions.DuplicatedUsernameFoundException; import org.georchestra.security.api.UsersApi; import org.georchestra.security.model.GeorchestraUser; import org.springframework.ldap.NameNotFoundException; @@ -88,12 +90,16 @@ private GeorchestraUser ensureRolesPrefixed(GeorchestraUser user) { } @Override - protected void createInternal(GeorchestraUser mapped) { + protected void createInternal(GeorchestraUser mapped) throws DuplicatedEmailFoundException { Account newAccount = mapToAccountBrief(mapped); try { accountDao.insert(newAccount); - } catch (DataServiceException | DuplicatedUidException | DuplicatedEmailException accountError) { + } catch (DataServiceException accountError) { throw new IllegalStateException(accountError); + } catch (DuplicatedEmailException accountError) { + throw new DuplicatedEmailFoundException(accountError.getMessage()); + } catch (DuplicatedUidException accountError) { + throw new DuplicatedUsernameFoundException(accountError.getMessage()); } ensureOrgExists(newAccount); diff --git a/gateway/src/main/java/org/georchestra/gateway/security/GeorchestraUserMapper.java b/gateway/src/main/java/org/georchestra/gateway/security/GeorchestraUserMapper.java index 352f9ab8..d24d2947 100644 --- a/gateway/src/main/java/org/georchestra/gateway/security/GeorchestraUserMapper.java +++ b/gateway/src/main/java/org/georchestra/gateway/security/GeorchestraUserMapper.java @@ -21,7 +21,9 @@ import java.util.List; import java.util.Optional; +import org.georchestra.ds.users.DuplicatedEmailException; import org.georchestra.gateway.model.GeorchestraUsers; +import org.georchestra.gateway.security.exceptions.DuplicatedEmailFoundException; import org.georchestra.security.model.GeorchestraUser; import org.springframework.core.Ordered; import org.springframework.security.core.Authentication; @@ -77,7 +79,7 @@ public class GeorchestraUserMapper { * {@link Optional#empty()} if no extension point implementation can * handle the auth token. */ - public Optional resolve(@NonNull Authentication authToken) { + public Optional resolve(@NonNull Authentication authToken) throws DuplicatedEmailFoundException { return resolvers.stream()// .map(resolver -> resolver.resolve(authToken))// .filter(Optional::isPresent)// @@ -85,7 +87,8 @@ public Optional resolve(@NonNull Authentication authToken) { .map(mapped -> customize(authToken, mapped)).findFirst(); } - private GeorchestraUser customize(@NonNull Authentication authToken, GeorchestraUser mapped) { + private GeorchestraUser customize(@NonNull Authentication authToken, GeorchestraUser mapped) + throws DuplicatedEmailFoundException { GeorchestraUser customized = mapped; for (GeorchestraUserCustomizerExtension customizer : customizers) { customized = customizer.apply(authToken, customized); diff --git a/gateway/src/main/java/org/georchestra/gateway/security/ResolveGeorchestraUserGlobalFilter.java b/gateway/src/main/java/org/georchestra/gateway/security/ResolveGeorchestraUserGlobalFilter.java index 474a9fbf..e00c2759 100644 --- a/gateway/src/main/java/org/georchestra/gateway/security/ResolveGeorchestraUserGlobalFilter.java +++ b/gateway/src/main/java/org/georchestra/gateway/security/ResolveGeorchestraUserGlobalFilter.java @@ -21,6 +21,7 @@ import org.georchestra.gateway.model.GeorchestraOrganizations; import org.georchestra.gateway.model.GeorchestraTargetConfig; import org.georchestra.gateway.model.GeorchestraUsers; +import org.georchestra.gateway.security.exceptions.DuplicatedEmailFoundException; import org.georchestra.gateway.security.ldap.extended.ExtendedGeorchestraUser; import org.georchestra.security.model.GeorchestraUser; import org.georchestra.security.model.Organization; @@ -30,6 +31,8 @@ import org.springframework.cloud.gateway.route.Route; import org.springframework.core.Ordered; import org.springframework.security.core.Authentication; +import org.springframework.security.web.server.DefaultServerRedirectStrategy; +import org.springframework.security.web.server.ServerRedirectStrategy; import org.springframework.web.server.ServerWebExchange; import lombok.NonNull; @@ -37,6 +40,9 @@ import lombok.extern.slf4j.Slf4j; import reactor.core.publisher.Mono; +import java.net.URI; +import java.util.Optional; + /** * A {@link GlobalFilter} that resolves the {@link GeorchestraUser} from the * request's {@link Authentication} so it can be {@link GeorchestraUsers#resolve @@ -56,6 +62,10 @@ public class ResolveGeorchestraUserGlobalFilter implements GlobalFilter, Ordered private final @NonNull GeorchestraUserMapper resolver; + private ServerRedirectStrategy redirectStrategy = new DefaultServerRedirectStrategy(); + + private static String EXPIRED_PASSWORD = "expired_password"; + /** * @return a lower precedence than {@link RouteToRequestUrlFilter}'s, in order * to make sure the matched {@link Route} has been set as a @@ -73,12 +83,20 @@ public class ResolveGeorchestraUserGlobalFilter implements GlobalFilter, Ordered */ public @Override Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { - return exchange.getPrincipal()// + Mono res = exchange.getPrincipal()// .doOnNext(p -> log.debug("resolving user from {}", p.getClass().getName()))// .filter(Authentication.class::isInstance)// .map(Authentication.class::cast)// - .map(resolver::resolve)// - .map(user -> { + .map(auth -> { + try { + return resolver.resolve(auth); + } catch (DuplicatedEmailFoundException exp) { + GeorchestraUser user = new GeorchestraUser(); + user.setId("0"); + return Optional.of(user); + } + })// + .filter(user -> !((GeorchestraUser) user.get()).getId().equals("0")).map(user -> { GeorchestraUser usr = user.orElse(null); GeorchestraUsers.store(exchange, usr); if (usr != null && usr instanceof ExtendedGeorchestraUser) { @@ -90,6 +108,10 @@ public class ResolveGeorchestraUserGlobalFilter implements GlobalFilter, Ordered })// .defaultIfEmpty(exchange)// .flatMap(chain::filter); + + System.out.println(res); + return res; + return this.redirectStrategy.sendRedirect(exchange, URI.create("login?error=" + EXPIRED_PASSWORD)); } } \ No newline at end of file diff --git a/gateway/src/main/java/org/georchestra/gateway/security/exceptions/DuplicatedEmailFoundException.java b/gateway/src/main/java/org/georchestra/gateway/security/exceptions/DuplicatedEmailFoundException.java new file mode 100644 index 00000000..675eaf74 --- /dev/null +++ b/gateway/src/main/java/org/georchestra/gateway/security/exceptions/DuplicatedEmailFoundException.java @@ -0,0 +1,13 @@ +package org.georchestra.gateway.security.exceptions; + +public class DuplicatedEmailFoundException extends RuntimeException { + private String message; + + public DuplicatedEmailFoundException(String message) { + super(message); + this.message = message; + } + + public DuplicatedEmailFoundException() { + } +} diff --git a/gateway/src/main/java/org/georchestra/gateway/security/exceptions/DuplicatedUsernameFoundException.java b/gateway/src/main/java/org/georchestra/gateway/security/exceptions/DuplicatedUsernameFoundException.java new file mode 100644 index 00000000..4e3faf69 --- /dev/null +++ b/gateway/src/main/java/org/georchestra/gateway/security/exceptions/DuplicatedUsernameFoundException.java @@ -0,0 +1,13 @@ +package org.georchestra.gateway.security.exceptions; + +public class DuplicatedUsernameFoundException extends RuntimeException { + private String message; + + public DuplicatedUsernameFoundException(String message) { + super(message); + this.message = message; + } + + public DuplicatedUsernameFoundException() { + } +}