172 lines
6.5 KiB
Java
172 lines
6.5 KiB
Java
package net.siegeln.cameleer.saas.auth;
|
|
|
|
import net.siegeln.cameleer.saas.audit.AuditAction;
|
|
import net.siegeln.cameleer.saas.audit.AuditService;
|
|
import net.siegeln.cameleer.saas.auth.dto.LoginRequest;
|
|
import net.siegeln.cameleer.saas.auth.dto.RegisterRequest;
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.junit.jupiter.api.extension.ExtendWith;
|
|
import org.mockito.ArgumentCaptor;
|
|
import org.mockito.Mock;
|
|
import org.mockito.junit.jupiter.MockitoExtension;
|
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
|
|
import java.util.Optional;
|
|
import java.util.UUID;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.ArgumentMatchers.eq;
|
|
import static org.mockito.Mockito.never;
|
|
import static org.mockito.Mockito.verify;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
@ExtendWith(MockitoExtension.class)
|
|
class AuthServiceTest {
|
|
|
|
@Mock
|
|
private UserRepository userRepository;
|
|
@Mock
|
|
private RoleRepository roleRepository;
|
|
@Mock
|
|
private PasswordEncoder passwordEncoder;
|
|
@Mock
|
|
private JwtService jwtService;
|
|
@Mock
|
|
private AuditService auditService;
|
|
|
|
private AuthService authService;
|
|
|
|
@BeforeEach
|
|
void setUp() {
|
|
authService = new AuthService(userRepository, roleRepository,
|
|
passwordEncoder, jwtService, auditService);
|
|
}
|
|
|
|
@Test
|
|
void register_createsUserAndReturnsToken() {
|
|
var request = new RegisterRequest("user@example.com", "Test User", "password123");
|
|
var ownerRole = new RoleEntity();
|
|
ownerRole.setName("OWNER");
|
|
|
|
when(userRepository.existsByEmail("user@example.com")).thenReturn(false);
|
|
when(passwordEncoder.encode("password123")).thenReturn("encoded-password");
|
|
when(roleRepository.findByName("OWNER")).thenReturn(Optional.of(ownerRole));
|
|
when(userRepository.save(any(UserEntity.class))).thenAnswer(invocation -> {
|
|
UserEntity user = invocation.getArgument(0);
|
|
// simulate ID assignment by persistence
|
|
try {
|
|
var idField = UserEntity.class.getDeclaredField("id");
|
|
idField.setAccessible(true);
|
|
idField.set(user, java.util.UUID.randomUUID());
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
return user;
|
|
});
|
|
when(jwtService.generateToken(any(UserEntity.class))).thenReturn("test-jwt-token");
|
|
|
|
var response = authService.register(request, "127.0.0.1");
|
|
|
|
assertNotNull(response);
|
|
assertEquals("test-jwt-token", response.token());
|
|
assertEquals("user@example.com", response.email());
|
|
assertEquals("Test User", response.name());
|
|
|
|
// Verify audit was logged
|
|
verify(auditService).log(
|
|
any(), eq("user@example.com"), eq(null),
|
|
eq(AuditAction.AUTH_REGISTER), eq(null),
|
|
eq(null), eq("127.0.0.1"),
|
|
eq("SUCCESS"), eq(null)
|
|
);
|
|
}
|
|
|
|
@Test
|
|
void register_rejectsDuplicateEmail() {
|
|
var request = new RegisterRequest("existing@example.com", "Test User", "password123");
|
|
when(userRepository.existsByEmail("existing@example.com")).thenReturn(true);
|
|
|
|
var exception = assertThrows(IllegalArgumentException.class,
|
|
() -> authService.register(request, "127.0.0.1"));
|
|
|
|
assertEquals("Email already registered", exception.getMessage());
|
|
verify(userRepository, never()).save(any());
|
|
verify(auditService, never()).log(any(), any(), any(), any(), any(), any(), any(), any(), any());
|
|
}
|
|
|
|
@Test
|
|
void login_returnsTokenForValidCredentials() {
|
|
var request = new LoginRequest("user@example.com", "password123");
|
|
var user = createUserWithId("user@example.com", "encoded-password");
|
|
|
|
when(userRepository.findByEmail("user@example.com")).thenReturn(Optional.of(user));
|
|
when(passwordEncoder.matches("password123", "encoded-password")).thenReturn(true);
|
|
when(jwtService.generateToken(user)).thenReturn("login-jwt-token");
|
|
|
|
var response = authService.login(request, "192.168.1.1");
|
|
|
|
assertNotNull(response);
|
|
assertEquals("login-jwt-token", response.token());
|
|
assertEquals("user@example.com", response.email());
|
|
|
|
verify(auditService).log(
|
|
any(), eq("user@example.com"), eq(null),
|
|
eq(AuditAction.AUTH_LOGIN), eq(null),
|
|
eq(null), eq("192.168.1.1"),
|
|
eq("SUCCESS"), eq(null)
|
|
);
|
|
}
|
|
|
|
@Test
|
|
void login_rejectsInvalidPassword() {
|
|
var request = new LoginRequest("user@example.com", "wrong-password");
|
|
var user = createUserWithId("user@example.com", "encoded-password");
|
|
|
|
when(userRepository.findByEmail("user@example.com")).thenReturn(Optional.of(user));
|
|
when(passwordEncoder.matches("wrong-password", "encoded-password")).thenReturn(false);
|
|
|
|
assertThrows(IllegalArgumentException.class,
|
|
() -> authService.login(request, "192.168.1.1"));
|
|
|
|
// Verify AUTH_LOGIN_FAILED audit was logged
|
|
verify(auditService).log(
|
|
any(), eq("user@example.com"), eq(null),
|
|
eq(AuditAction.AUTH_LOGIN_FAILED), eq(null),
|
|
eq(null), eq("192.168.1.1"),
|
|
eq("FAILURE"), eq(null)
|
|
);
|
|
}
|
|
|
|
@Test
|
|
void login_rejectsUnknownEmail() {
|
|
var request = new LoginRequest("unknown@example.com", "password123");
|
|
|
|
when(userRepository.findByEmail("unknown@example.com")).thenReturn(Optional.empty());
|
|
|
|
var exception = assertThrows(IllegalArgumentException.class,
|
|
() -> authService.login(request, "192.168.1.1"));
|
|
|
|
assertEquals("Invalid credentials", exception.getMessage());
|
|
verify(auditService, never()).log(any(), any(), any(), any(), any(), any(), any(), any(), any());
|
|
}
|
|
|
|
private UserEntity createUserWithId(String email, String password) {
|
|
var user = new UserEntity();
|
|
user.setEmail(email);
|
|
user.setName("Test User");
|
|
user.setPassword(password);
|
|
try {
|
|
var idField = UserEntity.class.getDeclaredField("id");
|
|
idField.setAccessible(true);
|
|
idField.set(user, UUID.randomUUID());
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
return user;
|
|
}
|
|
}
|