remove google and oauth login

This commit is contained in:
Krrish Ghimire
2026-07-06 23:13:47 +05:45
parent 708cac6848
commit 212785725f
30 changed files with 10 additions and 696 deletions

View File

@@ -34,7 +34,6 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'

View File

@@ -1,7 +1,5 @@
package com.krrishg.config;
import com.krrishg.service.OAuth2SuccessHandler;
import com.krrishg.service.OAuth2UserService;
import io.jsonwebtoken.Claims;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
@@ -34,23 +32,12 @@ import java.util.UUID;
public class SecurityConfig {
private final JwtConfig jwtConfig;
private final OAuth2UserService oAuth2UserService;
private final OAuth2SuccessHandler oAuth2SuccessHandler;
@Value("${indie.cors.allowed-origins:http://localhost:4200}")
private String[] allowedOrigins;
@Value("${spring.security.oauth2.client.registration.google.client-id:}")
private String googleClientId;
@Value("${spring.security.oauth2.client.registration.github.client-id:}")
private String githubClientId;
public SecurityConfig(JwtConfig jwtConfig, OAuth2UserService oAuth2UserService,
OAuth2SuccessHandler oAuth2SuccessHandler) {
public SecurityConfig(JwtConfig jwtConfig) {
this.jwtConfig = jwtConfig;
this.oAuth2UserService = oAuth2UserService;
this.oAuth2SuccessHandler = oAuth2SuccessHandler;
}
@Bean
@@ -72,25 +59,11 @@ public class SecurityConfig {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Forbidden"))
);
if (isOAuth2Configured()) {
http.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.userService(oAuth2UserService)
)
.successHandler(oAuth2SuccessHandler)
);
}
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
private boolean isOAuth2Configured() {
return (googleClientId != null && !googleClientId.isBlank())
|| (githubClientId != null && !githubClientId.isBlank());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();

View File

@@ -1,6 +1,5 @@
package com.krrishg.dto;
import com.krrishg.model.AuthProvider;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -32,6 +31,5 @@ public class AuthResponse {
private String email;
private String name;
private String avatarUrl;
private AuthProvider provider;
}
}

View File

@@ -1,5 +1,5 @@
package com.krrishg.model;
public enum AuthProvider {
LOCAL, GOOGLE, GITHUB, OPENID
LOCAL
}

View File

@@ -35,13 +35,6 @@ public class User {
@Column(name = "avatar_url")
private String avatarUrl;
@Enumerated(EnumType.STRING)
@Column(name = "provider", nullable = false)
private AuthProvider provider;
@Column(name = "provider_id")
private String providerId;
@Column(name = "email_verified")
@Builder.Default
private boolean emailVerified = false;

View File

@@ -1,6 +1,5 @@
package com.krrishg.repository;
import com.krrishg.model.AuthProvider;
import com.krrishg.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
@@ -11,7 +10,5 @@ public interface UserRepository extends JpaRepository<User, UUID> {
Optional<User> findByEmail(String email);
Optional<User> findByProviderAndProviderId(AuthProvider provider, String providerId);
boolean existsByEmail(String email);
}

View File

@@ -5,7 +5,6 @@ import com.krrishg.dto.AuthResponse;
import com.krrishg.dto.LoginRequest;
import com.krrishg.dto.RefreshTokenRequest;
import com.krrishg.dto.RegisterRequest;
import com.krrishg.model.AuthProvider;
import com.krrishg.model.User;
import com.krrishg.repository.UserRepository;
import io.jsonwebtoken.Claims;
@@ -36,7 +35,6 @@ public class AuthService {
.email(email)
.password(passwordEncoder.encode(request.getPassword()))
.name(request.getName())
.provider(AuthProvider.LOCAL)
.emailVerified(false)
.build();
@@ -49,10 +47,6 @@ public class AuthService {
User user = userRepository.findByEmail(email)
.orElseThrow(() -> new IllegalArgumentException("Invalid email or password"));
if (user.getProvider() != AuthProvider.LOCAL) {
throw new IllegalArgumentException("Please sign in with " + user.getProvider().name().toLowerCase());
}
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
throw new IllegalArgumentException("Invalid email or password");
}
@@ -83,7 +77,6 @@ public class AuthService {
.email(user.getEmail())
.name(user.getName())
.avatarUrl(user.getAvatarUrl())
.provider(user.getProvider())
.build();
return AuthResponse.builder()

View File

@@ -1,40 +0,0 @@
package com.krrishg.service;
import com.krrishg.model.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.core.user.OAuth2User;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class CustomOAuth2User implements OAuth2User {
private final User user;
private final Map<String, Object> attributes;
public CustomOAuth2User(User user, Map<String, Object> attributes) {
this.user = user;
this.attributes = attributes;
}
@Override
public Map<String, Object> getAttributes() {
return attributes;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of(new SimpleGrantedAuthority("ROLE_USER"));
}
@Override
public String getName() {
return user.getId().toString();
}
public User getUser() {
return user;
}
}

View File

@@ -1,42 +0,0 @@
package com.krrishg.service;
import com.krrishg.config.JwtConfig;
import com.krrishg.model.User;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class OAuth2SuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
private final JwtConfig jwtConfig;
public OAuth2SuccessHandler(JwtConfig jwtConfig) {
this.jwtConfig = jwtConfig;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
if (authentication.getPrincipal() instanceof CustomOAuth2User oAuth2User) {
User user = oAuth2User.getUser();
String accessToken = jwtConfig.generateAccessToken(user);
String refreshToken = jwtConfig.generateRefreshToken(user);
String redirectUrl = "http://localhost:4200/oauth2/callback"
+ "?accessToken=" + accessToken
+ "&refreshToken=" + refreshToken;
getRedirectStrategy().sendRedirect(request, response, redirectUrl);
} else {
super.onAuthenticationSuccess(request, response, authentication);
}
}
}

View File

@@ -1,110 +0,0 @@
package com.krrishg.service;
import com.krrishg.model.AuthProvider;
import com.krrishg.model.User;
import com.krrishg.repository.UserRepository;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
@Service
public class OAuth2UserService extends DefaultOAuth2UserService {
private final UserRepository userRepository;
public OAuth2UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
@Transactional
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = super.loadUser(userRequest);
String registrationId = userRequest.getClientRegistration().getRegistrationId();
AuthProvider provider = switch (registrationId) {
case "google" -> AuthProvider.GOOGLE;
case "github" -> AuthProvider.GITHUB;
default -> AuthProvider.OPENID;
};
String providerId = getProviderId(oAuth2User, provider);
String email = getAttribute(oAuth2User, "email");
if (email != null) {
email = email.toLowerCase().strip();
}
String name = getAttribute(oAuth2User, "name");
String avatarUrl = getAvatarUrl(oAuth2User, provider);
User user = findOrCreateUser(provider, providerId, email, name, avatarUrl);
return new CustomOAuth2User(user, oAuth2User.getAttributes());
}
String getProviderId(OAuth2User oAuth2User, AuthProvider provider) {
return switch (provider) {
case GOOGLE -> oAuth2User.getAttribute("sub");
case GITHUB -> oAuth2User.getAttribute("id").toString();
default -> oAuth2User.getName();
};
}
String getAttribute(OAuth2User oAuth2User, String key) {
Object value = oAuth2User.getAttribute(key);
return value != null ? value.toString() : null;
}
String getAvatarUrl(OAuth2User oAuth2User, AuthProvider provider) {
return switch (provider) {
case GOOGLE -> oAuth2User.getAttribute("picture");
case GITHUB -> oAuth2User.getAttribute("avatar_url");
default -> null;
};
}
User findOrCreateUser(AuthProvider provider, String providerId,
String email, String name, String avatarUrl) {
Optional<User> existing = userRepository.findByProviderAndProviderId(provider, providerId);
if (existing.isPresent()) {
User user = existing.get();
user.setName(name);
if (avatarUrl != null) {
user.setAvatarUrl(avatarUrl);
}
if (email != null && !email.equals(user.getEmail())) {
user.setEmail(email);
}
return userRepository.save(user);
}
if (email != null) {
Optional<User> emailUser = userRepository.findByEmail(email);
if (emailUser.isPresent()) {
User user = emailUser.get();
user.setProvider(provider);
user.setProviderId(providerId);
user.setEmailVerified(true);
if (avatarUrl != null) {
user.setAvatarUrl(avatarUrl);
}
return userRepository.save(user);
}
}
User newUser = User.builder()
.email(email != null ? email : providerId + "@" + provider.name().toLowerCase() + ".indie")
.name(name != null ? name : "User")
.avatarUrl(avatarUrl)
.provider(provider)
.providerId(providerId)
.emailVerified(true)
.build();
return userRepository.save(newUser);
}
}

View File

@@ -6,7 +6,6 @@ import com.krrishg.dto.AuthResponse.UserInfo;
import com.krrishg.dto.LoginRequest;
import com.krrishg.dto.RefreshTokenRequest;
import com.krrishg.dto.RegisterRequest;
import com.krrishg.model.AuthProvider;
import com.krrishg.service.AuthService;
import com.krrishg.support.TestSecurityConfig;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -46,7 +45,7 @@ class AuthControllerTest {
.accessToken("at-123")
.refreshToken("rt-456")
.tokenType("Bearer")
.user(new UserInfo(UUID.randomUUID(), "test@example.com", "Test", null, AuthProvider.LOCAL))
.user(new UserInfo(UUID.randomUUID(), "test@example.com", "Test", null))
.build();
when(authService.register(any(RegisterRequest.class))).thenReturn(response);
@@ -81,7 +80,7 @@ class AuthControllerTest {
.accessToken("at-123")
.refreshToken("rt-456")
.tokenType("Bearer")
.user(new UserInfo(UUID.randomUUID(), "login@example.com", "Login User", null, AuthProvider.LOCAL))
.user(new UserInfo(UUID.randomUUID(), "login@example.com", "Login User", null))
.build();
when(authService.login(any(LoginRequest.class))).thenReturn(response);
@@ -119,7 +118,7 @@ class AuthControllerTest {
.accessToken("new-at")
.refreshToken("new-rt")
.tokenType("Bearer")
.user(new UserInfo(UUID.randomUUID(), "user@example.com", "User", null, AuthProvider.LOCAL))
.user(new UserInfo(UUID.randomUUID(), "user@example.com", "User", null))
.build();
when(authService.refreshToken(any(RefreshTokenRequest.class))).thenReturn(response);

View File

@@ -4,7 +4,6 @@ import com.krrishg.config.EncryptionService;
import com.krrishg.config.GlobalExceptionHandler;
import com.krrishg.config.JwtAuthenticationToken;
import com.krrishg.config.UserPrincipal;
import com.krrishg.model.AuthProvider;
import com.krrishg.model.User;
import com.krrishg.repository.UserRepository;
import com.krrishg.support.TestSecurityConfig;
@@ -61,7 +60,6 @@ class UserSettingsControllerTest {
.id(userId)
.email("user@test.com")
.name("Test User")
.provider(AuthProvider.LOCAL)
.build();
}

View File

@@ -1,6 +1,5 @@
package com.krrishg.dto;
import com.krrishg.model.AuthProvider;
import org.junit.jupiter.api.Test;
import java.util.UUID;
@@ -12,7 +11,7 @@ class AuthResponseTest {
@Test
void constructorSetsBearerTokenType() {
AuthResponse.UserInfo userInfo = new AuthResponse.UserInfo(
UUID.randomUUID(), "test@example.com", "Test", null, AuthProvider.LOCAL);
UUID.randomUUID(), "test@example.com", "Test", null);
AuthResponse response = new AuthResponse("access-token", "refresh-token", userInfo);
@@ -28,7 +27,6 @@ class AuthResponseTest {
.id(UUID.randomUUID())
.email("user@example.com")
.name("User")
.provider(AuthProvider.GOOGLE)
.build();
AuthResponse response = AuthResponse.builder()
@@ -50,13 +48,11 @@ class AuthResponseTest {
.email("avatar@example.com")
.name("Avatar User")
.avatarUrl("https://example.com/avatar.png")
.provider(AuthProvider.GITHUB)
.build();
assertEquals(id, userInfo.getId());
assertEquals("avatar@example.com", userInfo.getEmail());
assertEquals("Avatar User", userInfo.getName());
assertEquals("https://example.com/avatar.png", userInfo.getAvatarUrl());
assertEquals(AuthProvider.GITHUB, userInfo.getProvider());
}
}

View File

@@ -9,7 +9,7 @@ class AuthProviderTest {
@Test
void enumValues() {
assertArrayEquals(
new AuthProvider[]{AuthProvider.LOCAL, AuthProvider.GOOGLE, AuthProvider.GITHUB, AuthProvider.OPENID},
new AuthProvider[]{AuthProvider.LOCAL},
AuthProvider.values()
);
}

View File

@@ -14,7 +14,6 @@ class UserTest {
User user = new User();
user.setEmail("test@example.com");
user.setName("Test User");
user.setProvider(AuthProvider.LOCAL);
assertNull(user.getId());
assertNull(user.getCreatedAt());
@@ -33,7 +32,6 @@ class UserTest {
.id(UUID.randomUUID())
.email("test@example.com")
.name("Test")
.provider(AuthProvider.LOCAL)
.build();
UUID existingId = user.getId();
@@ -47,7 +45,6 @@ class UserTest {
User user = User.builder()
.email("test@example.com")
.name("Test")
.provider(AuthProvider.LOCAL)
.build();
user.onCreate();
@@ -63,7 +60,6 @@ class UserTest {
User user = User.builder()
.email("test@example.com")
.name("Test")
.provider(AuthProvider.LOCAL)
.build();
assertFalse(user.isEmailVerified());

View File

@@ -1,6 +1,5 @@
package com.krrishg.repository;
import com.krrishg.model.AuthProvider;
import com.krrishg.model.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -25,7 +24,6 @@ class UserRepositoryTest {
User user = User.builder()
.email("test@example.com")
.name("Test User")
.provider(AuthProvider.LOCAL)
.build();
User saved = userRepository.save(user);
@@ -42,7 +40,6 @@ class UserRepositoryTest {
User user = User.builder()
.email("find@example.com")
.name("Find Me")
.provider(AuthProvider.LOCAL)
.build();
userRepository.save(user);
@@ -57,27 +54,11 @@ class UserRepositoryTest {
assertTrue(found.isEmpty());
}
@Test
void findByProviderAndProviderId() {
User user = User.builder()
.email("oauth@example.com")
.name("OAuth User")
.provider(AuthProvider.GOOGLE)
.providerId("google-123")
.build();
userRepository.save(user);
Optional<User> found = userRepository.findByProviderAndProviderId(AuthProvider.GOOGLE, "google-123");
assertTrue(found.isPresent());
assertEquals("oauth@example.com", found.get().getEmail());
}
@Test
void existsByEmail() {
User user = User.builder()
.email("exists@example.com")
.name("Exists")
.provider(AuthProvider.LOCAL)
.build();
userRepository.save(user);

View File

@@ -4,7 +4,6 @@ import com.krrishg.dto.AuthResponse;
import com.krrishg.dto.LoginRequest;
import com.krrishg.dto.RefreshTokenRequest;
import com.krrishg.dto.RegisterRequest;
import com.krrishg.model.AuthProvider;
import com.krrishg.model.User;
import com.krrishg.support.FakeJwtConfig;
import com.krrishg.support.FakeUserRepository;
@@ -39,7 +38,6 @@ class AuthServiceTest {
assertEquals("Bearer", response.getTokenType());
assertEquals("new@example.com", response.getUser().getEmail());
assertEquals("New User", response.getUser().getName());
assertEquals(AuthProvider.LOCAL, response.getUser().getProvider());
}
@Test
@@ -119,25 +117,6 @@ class AuthServiceTest {
assertEquals("Invalid email or password", ex.getMessage());
}
@Test
void loginThrowsOnOAuthUserTryingPasswordLogin() {
User oauthUser = User.builder()
.email("oauth@example.com")
.name("OAuth User")
.provider(AuthProvider.GOOGLE)
.providerId("google-123")
.build();
userRepository.save(oauthUser);
LoginRequest login = new LoginRequest();
login.setEmail("oauth@example.com");
login.setPassword("anypassword");
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
() -> authService.login(login));
assertEquals("Please sign in with google", ex.getMessage());
}
@Test
void refreshTokenReturnsNewTokens() {
RegisterRequest reg = new RegisterRequest();
@@ -171,7 +150,6 @@ class AuthServiceTest {
User user = User.builder()
.email("deleted@example.com")
.name("Deleted")
.provider(AuthProvider.LOCAL)
.build();
userRepository.save(user);

View File

@@ -1,47 +0,0 @@
package com.krrishg.service;
import com.krrishg.model.AuthProvider;
import com.krrishg.model.User;
import org.junit.jupiter.api.Test;
import java.util.Map;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.*;
class CustomOAuth2UserTest {
private final User user = User.builder()
.id(UUID.randomUUID())
.email("user@example.com")
.name("Test User")
.provider(AuthProvider.GOOGLE)
.providerId("google-123")
.build();
private final Map<String, Object> attributes = Map.of("sub", "google-123", "email", "user@example.com");
private final CustomOAuth2User oAuth2User = new CustomOAuth2User(user, attributes);
@Test
void getNameReturnsUserId() {
assertEquals(user.getId().toString(), oAuth2User.getName());
}
@Test
void getAttributesReturnsProvidedMap() {
assertEquals(attributes, oAuth2User.getAttributes());
}
@Test
void getAuthoritiesContainsRoleUser() {
var authorities = oAuth2User.getAuthorities();
assertEquals(1, authorities.size());
assertEquals("ROLE_USER", authorities.iterator().next().getAuthority());
}
@Test
void getUserReturnsTheUser() {
assertSame(user, oAuth2User.getUser());
}
}

View File

@@ -1,76 +0,0 @@
package com.krrishg.service;
import com.krrishg.config.JwtConfig;
import com.krrishg.model.AuthProvider;
import com.krrishg.model.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.RedirectStrategy;
import java.util.UUID;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class OAuth2SuccessHandlerTest {
@Mock
private JwtConfig jwtConfig;
@Mock
private HttpServletRequest request;
@Mock
private HttpServletResponse response;
@Mock
private Authentication authentication;
@Mock
private RedirectStrategy redirectStrategy;
private OAuth2SuccessHandler handler;
@BeforeEach
void setUp() {
handler = new OAuth2SuccessHandler(jwtConfig);
handler.setRedirectStrategy(redirectStrategy);
}
@Test
void onAuthenticationSuccessWithOAuth2UserRedirectsWithTokens() throws Exception {
CustomOAuth2User oAuth2User = mock(CustomOAuth2User.class);
User user = User.builder()
.id(UUID.randomUUID())
.email("user@example.com")
.name("User")
.provider(AuthProvider.GOOGLE)
.build();
when(authentication.getPrincipal()).thenReturn(oAuth2User);
when(oAuth2User.getUser()).thenReturn(user);
when(jwtConfig.generateAccessToken(user)).thenReturn("access-token-value");
when(jwtConfig.generateRefreshToken(user)).thenReturn("refresh-token-value");
handler.onAuthenticationSuccess(request, response, authentication);
String expectedRedirect = "http://localhost:4200/oauth2/callback"
+ "?accessToken=access-token-value&refreshToken=refresh-token-value";
verify(redirectStrategy).sendRedirect(request, response, expectedRedirect);
}
@Test
void onAuthenticationSuccessWithNonOAuth2UserCallsSuper() throws Exception {
when(authentication.getPrincipal()).thenReturn("plain principal");
handler.onAuthenticationSuccess(request, response, authentication);
verify(redirectStrategy).sendRedirect(eq(request), eq(response), anyString());
}
}

View File

@@ -1,129 +0,0 @@
package com.krrishg.service;
import com.krrishg.model.AuthProvider;
import com.krrishg.model.User;
import com.krrishg.support.FakeUserRepository;
import com.krrishg.support.TestOAuth2User;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
class OAuth2UserServiceTest {
private FakeUserRepository userRepository;
private OAuth2UserService oAuth2UserService;
@BeforeEach
void setUp() {
userRepository = new FakeUserRepository();
oAuth2UserService = new OAuth2UserService(userRepository);
}
@Test
void getProviderIdForGoogleReturnsSub() {
TestOAuth2User oAuth2User = new TestOAuth2User(Map.of("sub", "google-123"));
assertEquals("google-123", oAuth2UserService.getProviderId(oAuth2User, AuthProvider.GOOGLE));
}
@Test
void getProviderIdForGitHubReturnsId() {
TestOAuth2User oAuth2User = new TestOAuth2User(Map.of("id", 456));
assertEquals("456", oAuth2UserService.getProviderId(oAuth2User, AuthProvider.GITHUB));
}
@Test
void getAvatarUrlForGoogleReturnsPicture() {
TestOAuth2User oAuth2User = new TestOAuth2User(Map.of("picture", "https://example.com/avatar.jpg"));
assertEquals("https://example.com/avatar.jpg",
oAuth2UserService.getAvatarUrl(oAuth2User, AuthProvider.GOOGLE));
}
@Test
void getAvatarUrlForGitHubReturnsAvatarUrl() {
TestOAuth2User oAuth2User = new TestOAuth2User(Map.of("avatar_url", "https://github.com/avatar.png"));
assertEquals("https://github.com/avatar.png",
oAuth2UserService.getAvatarUrl(oAuth2User, AuthProvider.GITHUB));
}
@Test
void getAvatarUrlForOpenIdReturnsNull() {
TestOAuth2User oAuth2User = new TestOAuth2User(Map.of());
assertNull(oAuth2UserService.getAvatarUrl(oAuth2User, AuthProvider.OPENID));
}
@Test
void getAttributeReturnsStringValue() {
TestOAuth2User oAuth2User = new TestOAuth2User(Map.of("email", "test@example.com"));
assertEquals("test@example.com", oAuth2UserService.getAttribute(oAuth2User, "email"));
}
@Test
void getAttributeReturnsNullWhenMissing() {
TestOAuth2User oAuth2User = new TestOAuth2User(Map.of());
assertNull(oAuth2UserService.getAttribute(oAuth2User, "missing"));
}
@Test
void findOrCreateUserCreatesNewUser() {
User user = oAuth2UserService.findOrCreateUser(
AuthProvider.GOOGLE, "google-789",
"new@example.com", "New User", "https://example.com/avatar.jpg");
assertNotNull(user.getId());
assertEquals("new@example.com", user.getEmail());
assertEquals("New User", user.getName());
assertEquals(AuthProvider.GOOGLE, user.getProvider());
assertEquals("google-789", user.getProviderId());
assertTrue(user.isEmailVerified());
}
@Test
void findOrCreateUserUpdatesExistingOAuthUser() {
User existing = User.builder()
.email("existing@example.com")
.name("Old Name")
.provider(AuthProvider.GOOGLE)
.providerId("google-456")
.build();
userRepository.save(existing);
User updated = oAuth2UserService.findOrCreateUser(
AuthProvider.GOOGLE, "google-456",
"existing@example.com", "Updated Name", "https://example.com/new-avatar.jpg");
assertEquals("Updated Name", updated.getName());
assertEquals("https://example.com/new-avatar.jpg", updated.getAvatarUrl());
}
@Test
void findOrCreateUserLinksLocalUserToOAuth() {
User localUser = User.builder()
.email("link@example.com")
.name("Link User")
.provider(AuthProvider.LOCAL)
.password("hashedpw")
.build();
userRepository.save(localUser);
User linked = oAuth2UserService.findOrCreateUser(
AuthProvider.GITHUB, "github-789",
"link@example.com", "Link User", "https://github.com/avatar.png");
assertEquals(AuthProvider.GITHUB, linked.getProvider());
assertEquals("github-789", linked.getProviderId());
assertTrue(linked.isEmailVerified());
}
@Test
void findOrCreateUserGeneratesEmailWhenMissing() {
User user = oAuth2UserService.findOrCreateUser(
AuthProvider.GITHUB, "github-nomail",
null, "No Email", null);
assertTrue(user.getEmail().contains("github-nomail"));
assertTrue(user.getEmail().endsWith("@github.indie"));
}
}

View File

@@ -1,6 +1,5 @@
package com.krrishg.support;
import com.krrishg.model.AuthProvider;
import com.krrishg.model.User;
import com.krrishg.repository.UserRepository;
@@ -32,13 +31,6 @@ public class FakeUserRepository extends InMemoryRepository<User, UUID> implement
.findFirst();
}
@Override
public Optional<User> findByProviderAndProviderId(AuthProvider provider, String providerId) {
return store.values().stream()
.filter(u -> u.getProvider() == provider && providerId.equals(u.getProviderId()))
.findFirst();
}
@Override
public boolean existsByEmail(String email) {
return store.values().stream()

View File

@@ -1,38 +0,0 @@
package com.krrishg.support;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.core.user.OAuth2User;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class TestOAuth2User implements OAuth2User {
private final Map<String, Object> attributes;
public TestOAuth2User(Map<String, Object> attributes) {
this.attributes = attributes;
}
@Override
public Map<String, Object> getAttributes() {
return attributes;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of(new SimpleGrantedAuthority("ROLE_USER"));
}
@Override
public String getName() {
Object sub = attributes.get("sub");
if (sub != null) return sub.toString();
Object id = attributes.get("id");
if (id != null) return id.toString();
return "test-user";
}
}