From ad21f708ad26db1eef9d8698bef9eb561869deab Mon Sep 17 00:00:00 2001 From: OZGCloud <ozgcloud@mgm-tp.com> Date: Thu, 5 May 2022 15:44:12 +0200 Subject: [PATCH] OZG-1527 add currentuserservice to get active user from --- pluto-server/pom.xml | 5 ++ .../ozg/pluto/PlutoServerApplication.java | 8 ++++ .../CallContextHandleInterceptor.java | 2 +- .../common/callcontext/CallContextUser.java | 3 +- .../callcontext/CurrentUserService.java | 43 +++++++++++++++++ .../CallContextUserTestFactory.java | 2 +- .../callcontext/CurrentUserServiceITCase.java | 47 +++++++++++++++++++ 7 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserService.java create mode 100644 pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserServiceITCase.java diff --git a/pluto-server/pom.xml b/pluto-server/pom.xml index 099275d17..2c899e3df 100644 --- a/pluto-server/pom.xml +++ b/pluto-server/pom.xml @@ -168,6 +168,11 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>org.springframework.security</groupId> + <artifactId>spring-security-test</artifactId> + </dependency> + <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java index 77094c837..c3e9cbd21 100644 --- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java @@ -5,9 +5,12 @@ import java.util.TimeZone; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.security.authentication.AuthenticationTrustResolver; +import org.springframework.security.authentication.AuthenticationTrustResolverImpl; import io.mongock.runner.springboot.EnableMongock; @@ -23,4 +26,9 @@ public class PlutoServerApplication { TimeZone.setDefault(TimeZone.getTimeZone("UTC")); SpringApplication.run(PlutoServerApplication.class, args); } + + @Bean + public AuthenticationTrustResolver trustResolver() { + return new AuthenticationTrustResolverImpl(); + } } \ No newline at end of file diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextHandleInterceptor.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextHandleInterceptor.java index 6342d627c..68c6072e3 100644 --- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextHandleInterceptor.java +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextHandleInterceptor.java @@ -94,12 +94,12 @@ class CallContextHandleInterceptor implements ServerInterceptor { CallContextUser createUser() { var builder = CallContextUser.builder() + .userId(getFromHeaders(KEY_USER_ID, headers)) .userName(getFromHeaders(KEY_USER_NAME, headers)) .organisatorischeEinheitenIds(getCollection(KEY_ACCESS_LIMITED_ORGAID, headers)); // TODO throw exception if missing required data as soon all clients are fine // with using headers for auth data. - getFromHeaders(KEY_USER_ID, headers).ifPresentOrElse(builder::userId, () -> LOG.warn("Missing user id in grpc header.")); getFromHeaders(KEY_CLIENT_NAME, headers).ifPresentOrElse(builder::clientName, () -> LOG.warn("Missing client name in grpc header.")); return builder.build(); diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextUser.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextUser.java index 7a37d14d0..6f1b4b5a0 100644 --- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextUser.java +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CallContextUser.java @@ -18,7 +18,8 @@ public class CallContextUser implements AuthenticatedPrincipal, Serializable { private final String clientName; - private final String userId; + @Builder.Default + private final transient Optional<String> userId = Optional.empty(); @Builder.Default private final transient Optional<String> userName = Optional.empty(); @Singular diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserService.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserService.java new file mode 100644 index 000000000..d6b15332f --- /dev/null +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserService.java @@ -0,0 +1,43 @@ +package de.itvsh.ozg.pluto.common.callcontext; + +import java.util.Optional; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationTrustResolver; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; + +@Service +public class CurrentUserService { + + @Autowired + private AuthenticationTrustResolver trustResolver; + + public CallContextUser getUser() { + var auth = getAuthentication(); + + if (auth instanceof CallContextAuthenticationToken) { + return (CallContextUser) auth.getPrincipal(); + } else { + return CallContextUser.builder() + .clientName(auth.getName()) + .organisatorischeEinheitenIds( + auth.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toUnmodifiableSet())) + .build(); + } + + } + + public Authentication getAuthentication() { + return findTrustedAuthentication().orElseThrow(() -> new IllegalStateException("No authenticated User found")); + } + + Optional<Authentication> findTrustedAuthentication() { + return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()) + .filter(auth -> !trustResolver.isAnonymous(auth)) + .filter(Authentication::isAuthenticated); + } +} diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CallContextUserTestFactory.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CallContextUserTestFactory.java index 4aeb8415b..68de875e1 100644 --- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CallContextUserTestFactory.java +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CallContextUserTestFactory.java @@ -13,7 +13,7 @@ public class CallContextUserTestFactory { static CallContextUser.CallContextUserBuilder createBuilder() { return CallContextUser.builder() .clientName(CallContextTestFactory.CLIENT) - .userId(UserTestFactory.ID) + .userId(Optional.of(UserTestFactory.ID)) .userName(Optional.of(UserTestFactory.NAME)) .organisatorischeEinheitenId(UserTestFactory.ORGANISATORISCHE_EINHEITEN_ID); } diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserServiceITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserServiceITCase.java new file mode 100644 index 000000000..66bca90a4 --- /dev/null +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/common/callcontext/CurrentUserServiceITCase.java @@ -0,0 +1,47 @@ +package de.itvsh.ozg.pluto.common.callcontext; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.test.context.support.WithAnonymousUser; +import org.springframework.security.test.context.support.WithMockUser; + +import de.itvsh.kop.common.test.ITCase; + +@ITCase +class CurrentUserServiceITCase { + + @Autowired + private CurrentUserService service; + + @Test + void shouldThrowExceptionIfUserIsMissing() { + assertThatThrownBy(() -> service.getUser()).isInstanceOf(IllegalStateException.class); + } + + @Test + @WithAnonymousUser + void shouldThrowExceptionIfAnonymouse() { + assertThatThrownBy(() -> service.getUser()).isInstanceOf(IllegalStateException.class); + } + + @Test + @WithMockUser + void shouldReturnUser() { + var user = service.getUser(); + + assertThat(user.getName()).isEqualTo("user"); + } + + @Test + void shouldReturnUserFromToken() { + var inUser = CallContextUserTestFactory.create(); + SecurityContextHolder.getContext().setAuthentication(CallContextAuthenticationToken.authenticate(inUser)); + + var user = service.getUser(); + + assertThat(user).isSameAs(inUser); + } +} -- GitLab