From 79eb5c64f2a3136a088f0c763b111dcfc1795c49 Mon Sep 17 00:00:00 2001 From: m-rudyk <121865672+m-rudyk@users.noreply.github.com> Date: Tue, 24 Oct 2023 12:24:06 +0300 Subject: [PATCH] Add unit tests for auth feature (#259) * refactor: move auth feature, remove unnecessary class * test: add unit tests for auth feature * fix: suppress unsafe cast in order to avoid build errors * fix: fix changes after review comment --- .../auth/MyAuthenticationSuccessHandler.java | 41 ----------- .../lpvs/{ => entity}/auth/MemberProfile.java | 2 +- .../{ => entity}/auth/OAuthAttributes.java | 3 +- .../lpvs/{ => entity}/auth/OAuthService.java | 15 +++- .../{ => entity}/auth/SecurityConfig.java | 32 ++++++++- .../lpvs/entity/auth/MemberProfileTest.java | 41 +++++++++++ .../lpvs/entity/auth/OAuthAttributesTest.java | 40 +++++++++++ .../lpvs/entity/auth/OAuthServiceTest.java | 68 +++++++++++++++++++ 8 files changed, 195 insertions(+), 47 deletions(-) delete mode 100644 src/main/java/com/lpvs/auth/MyAuthenticationSuccessHandler.java rename src/main/java/com/lpvs/{ => entity}/auth/MemberProfile.java (95%) rename src/main/java/com/lpvs/{ => entity}/auth/OAuthAttributes.java (97%) rename src/main/java/com/lpvs/{ => entity}/auth/OAuthService.java (84%) rename src/main/java/com/lpvs/{ => entity}/auth/SecurityConfig.java (61%) create mode 100644 src/test/java/com/lpvs/entity/auth/MemberProfileTest.java create mode 100644 src/test/java/com/lpvs/entity/auth/OAuthAttributesTest.java create mode 100644 src/test/java/com/lpvs/entity/auth/OAuthServiceTest.java diff --git a/src/main/java/com/lpvs/auth/MyAuthenticationSuccessHandler.java b/src/main/java/com/lpvs/auth/MyAuthenticationSuccessHandler.java deleted file mode 100644 index aa91ba14..00000000 --- a/src/main/java/com/lpvs/auth/MyAuthenticationSuccessHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright 2023 Basaeng, kyudori, hwan5180, quswjdgma83 - * - * Use of this source code is governed by a MIT license that can be - * found in the LICENSE file. - */ - -package com.lpvs.auth; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.core.user.OAuth2User; -import org.springframework.security.web.authentication.AuthenticationSuccessHandler; -import org.springframework.stereotype.Component; -import org.springframework.web.util.UriComponentsBuilder; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -@Component -public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler { - @Value("${frontend.main-page.url:}") - private String frontendMainPageUrl; - - private String REDIRECT_URI = frontendMainPageUrl+"/login/callback"; - - @Override - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { - OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal(); - System.out.println("oAuth2User = " + oAuth2User); - - response.sendRedirect(UriComponentsBuilder.fromUriString(REDIRECT_URI) - .queryParam("accessToken", "accessToken") - .queryParam("refreshToken", "refreshToken") - .build().encode(StandardCharsets.UTF_8).toUriString()); - } - -} diff --git a/src/main/java/com/lpvs/auth/MemberProfile.java b/src/main/java/com/lpvs/entity/auth/MemberProfile.java similarity index 95% rename from src/main/java/com/lpvs/auth/MemberProfile.java rename to src/main/java/com/lpvs/entity/auth/MemberProfile.java index fc2c6bc2..2c66c3c3 100644 --- a/src/main/java/com/lpvs/auth/MemberProfile.java +++ b/src/main/java/com/lpvs/entity/auth/MemberProfile.java @@ -5,7 +5,7 @@ * found in the LICENSE file. */ -package com.lpvs.auth; +package com.lpvs.entity.auth; import com.lpvs.entity.LPVSMember; import lombok.Getter; diff --git a/src/main/java/com/lpvs/auth/OAuthAttributes.java b/src/main/java/com/lpvs/entity/auth/OAuthAttributes.java similarity index 97% rename from src/main/java/com/lpvs/auth/OAuthAttributes.java rename to src/main/java/com/lpvs/entity/auth/OAuthAttributes.java index 9c120fc8..01aff4b6 100644 --- a/src/main/java/com/lpvs/auth/OAuthAttributes.java +++ b/src/main/java/com/lpvs/entity/auth/OAuthAttributes.java @@ -5,12 +5,13 @@ * found in the LICENSE file. */ -package com.lpvs.auth; +package com.lpvs.entity.auth; import java.util.Arrays; import java.util.Map; import java.util.function.Function; +@SuppressWarnings("unchecked") public enum OAuthAttributes { GOOGLE("google", (attributes) -> { MemberProfile memberProfile = new MemberProfile(); diff --git a/src/main/java/com/lpvs/auth/OAuthService.java b/src/main/java/com/lpvs/entity/auth/OAuthService.java similarity index 84% rename from src/main/java/com/lpvs/auth/OAuthService.java rename to src/main/java/com/lpvs/entity/auth/OAuthService.java index dab0c394..38fb8b0b 100644 --- a/src/main/java/com/lpvs/auth/OAuthService.java +++ b/src/main/java/com/lpvs/entity/auth/OAuthService.java @@ -5,11 +5,13 @@ * found in the LICENSE file. */ -package com.lpvs.auth; +package com.lpvs.entity.auth; import com.lpvs.entity.LPVSMember; import com.lpvs.repository.LPVSMemberRepository; import lombok.RequiredArgsConstructor; + +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; @@ -28,10 +30,18 @@ public class OAuthService implements OAuth2UserService { private final LPVSMemberRepository lpvsMemberRepository; + + private DefaultOAuth2UserService oAuth2UserService = null; + + @Autowired + public OAuthService(LPVSMemberRepository lpvsMemberRepository, DefaultOAuth2UserService oAuth2UserService) { + this.lpvsMemberRepository = lpvsMemberRepository; + this.oAuth2UserService = oAuth2UserService; + } @Override public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { - OAuth2UserService delegate = new DefaultOAuth2UserService(); + OAuth2UserService delegate = (null != oAuth2UserService)? oAuth2UserService : new DefaultOAuth2UserService(); OAuth2User oAuth2User = delegate.loadUser(userRequest); String registrationId = userRequest.getClientRegistration().getRegistrationId(); @@ -49,6 +59,7 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2Authentic Map customAttribute = customAttribute(attributes, userNameAttributeName, memberProfile, registrationId); + return new DefaultOAuth2User(Collections.singleton(new SimpleGrantedAuthority("USER")), customAttribute, diff --git a/src/main/java/com/lpvs/auth/SecurityConfig.java b/src/main/java/com/lpvs/entity/auth/SecurityConfig.java similarity index 61% rename from src/main/java/com/lpvs/auth/SecurityConfig.java rename to src/main/java/com/lpvs/entity/auth/SecurityConfig.java index 7a672f34..b43c2a48 100644 --- a/src/main/java/com/lpvs/auth/SecurityConfig.java +++ b/src/main/java/com/lpvs/entity/auth/SecurityConfig.java @@ -5,18 +5,30 @@ * found in the LICENSE file. */ -package com.lpvs.auth; +package com.lpvs.entity.auth; import lombok.RequiredArgsConstructor; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.util.UriComponentsBuilder; @EnableWebSecurity @RequiredArgsConstructor @@ -48,7 +60,23 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .anyRequest().permitAll() .and() .oauth2Login() - .successHandler(new MyAuthenticationSuccessHandler()) + .successHandler(new AuthenticationSuccessHandler() { + @Value("${frontend.main-page.url:}") + private String frontendMainPageUrl; + + private String REDIRECT_URI = frontendMainPageUrl+"/login/callback"; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal(); + System.out.println("oAuth2User = " + oAuth2User); + + response.sendRedirect(UriComponentsBuilder.fromUriString(REDIRECT_URI) + .queryParam("accessToken", "accessToken") + .queryParam("refreshToken", "refreshToken") + .build().encode(StandardCharsets.UTF_8).toUriString()); + } + }) .defaultSuccessUrl(frontendMainPageUrl, true) .userInfoEndpoint() .userService(oAuthService); diff --git a/src/test/java/com/lpvs/entity/auth/MemberProfileTest.java b/src/test/java/com/lpvs/entity/auth/MemberProfileTest.java new file mode 100644 index 00000000..fc2550b5 --- /dev/null +++ b/src/test/java/com/lpvs/entity/auth/MemberProfileTest.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2023, Samsung Electronics Co., Ltd. All rights reserved. + *

+ * Use of this source code is governed by a MIT license that can be + * found in the LICENSE file. + */ + +package com.lpvs.entity.auth; + +import org.junit.jupiter.api.Test; + +import com.lpvs.entity.LPVSMember; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + + +public class MemberProfileTest { + + @Test + public void testConstructor() { + MemberProfile profile = new MemberProfile(); + assertNull(profile.getName()); + assertNull(profile.getEmail()); + assertNull(profile.getProvider()); + assertNull(profile.getNickname()); + } + + @Test + public void testToMember() { + MemberProfile profile = new MemberProfile(); + profile.setName("John"); + profile.setEmail("john@example.com"); + profile.setProvider("OAuth2"); + LPVSMember member = profile.toMember(); + + assertEquals("John", member.getName()); + assertEquals("john@example.com", member.getEmail()); + assertEquals("OAuth2", member.getProvider()); + } +} diff --git a/src/test/java/com/lpvs/entity/auth/OAuthAttributesTest.java b/src/test/java/com/lpvs/entity/auth/OAuthAttributesTest.java new file mode 100644 index 00000000..b0e928e1 --- /dev/null +++ b/src/test/java/com/lpvs/entity/auth/OAuthAttributesTest.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2023, Samsung Electronics Co., Ltd. All rights reserved. + *

+ * Use of this source code is governed by a MIT license that can be + * found in the LICENSE file. + */ + +package com.lpvs.entity.auth; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.HashMap; +import java.util.Map; + +public class OAuthAttributesTest { + + @Test + public void testExtractOAuthAttributes() { + Map attributes = new HashMap() {{ + put("name", "testName"); + put("email", "testEmail"); + }};; + MemberProfile profile = OAuthAttributes.extract("google", attributes); + assertEquals("testName", profile.getName()); + assertEquals("testEmail", profile.getEmail()); + } + + @Test + public void testExtractOAuthAttributesUnknownProvider() { + Map attributes = new HashMap() {{ + put("name", "testName"); + put("email", "testEmail"); + }};; + assertThrows(IllegalArgumentException.class, () -> { + OAuthAttributes.extract("unknown", attributes); + }); + } +} diff --git a/src/test/java/com/lpvs/entity/auth/OAuthServiceTest.java b/src/test/java/com/lpvs/entity/auth/OAuthServiceTest.java new file mode 100644 index 00000000..e5542b2e --- /dev/null +++ b/src/test/java/com/lpvs/entity/auth/OAuthServiceTest.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2023, Samsung Electronics Co., Ltd. All rights reserved. + *

+ * Use of this source code is governed by a MIT license that can be + * found in the LICENSE file. + */ + +package com.lpvs.entity.auth; + +import com.lpvs.repository.LPVSMemberRepository; + +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.user.DefaultOAuth2User; +import org.springframework.security.oauth2.core.user.OAuth2User; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class OAuthServiceTest { + + @Test + public void testLoadUser() throws OAuth2AuthenticationException { + + // Create a mock LPVSMemberRepository + LPVSMemberRepository lpvsMemberRepository = mock(LPVSMemberRepository.class); + + // Create a sample OAuth2UserRequest + ClientRegistration clientRegistration = ClientRegistration + .withRegistrationId("google") + .userInfoUri("https://example.com/userinfo") + .userNameAttributeName("email") + .authorizationGrantType(AuthorizationGrantType.PASSWORD) + .clientId("id") + .tokenUri("https://example.com/tokenuri") + .build(); + OAuth2UserRequest userRequest = new OAuth2UserRequest( + clientRegistration, + new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "access-token", null, null)); + + Map attributes = new LinkedHashMap<>(); + attributes.put("email", "testEmail"); + attributes.put("name", "testName"); + OAuth2User oAuth2User = new DefaultOAuth2User(Collections.singleton(new SimpleGrantedAuthority("USER")), attributes, "email"); + + // Mock the behavior of DefaultOAuth2UserService + DefaultOAuth2UserService defaultUserService = Mockito.mock(DefaultOAuth2UserService.class); + when(defaultUserService.loadUser(userRequest)).thenReturn(oAuth2User); + + // Create an instance of your OAuthService with the mocked DefaultOAuth2UserService + OAuthService oAuthService = new OAuthService(lpvsMemberRepository, defaultUserService); + + OAuth2User loadedUser = oAuthService.loadUser(userRequest); + + assertEquals("testEmail", loadedUser.getAttribute("email")); + assertEquals("testName", loadedUser.getAttribute("name")); + assertEquals("google", loadedUser.getAttribute("provider")); + } +}