diff --git a/src/main/java/com/jnz/teamManager/config/ApplicationConfig.java b/src/main/java/com/jnz/teamManager/config/ApplicationConfig.java index 6f24eb0..55c5600 100644 --- a/src/main/java/com/jnz/teamManager/config/ApplicationConfig.java +++ b/src/main/java/com/jnz/teamManager/config/ApplicationConfig.java @@ -1,6 +1,5 @@ package com.jnz.teamManager.config; -import com.jnz.teamManager.exception.controller.RestResponseEntityExceptionHandler; import com.jnz.teamManager.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; @@ -12,7 +11,12 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.cors.reactive.CorsWebFilter; + +import java.util.Arrays; @Configuration public class ApplicationConfig { @@ -42,6 +46,15 @@ public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } + @Bean + CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration configuration = new CorsConfiguration(); + configuration.setAllowedOrigins(Arrays.asList("https://team-manager-front.vercel.app", "http://localhost")); + configuration.setAllowedMethods(Arrays.asList("GET","POST", "DELETE", "PUT")); + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", configuration); + return source; + } diff --git a/src/main/java/com/jnz/teamManager/config/SecurityConfiguration.java b/src/main/java/com/jnz/teamManager/config/SecurityConfiguration.java index 61bf6af..4747b47 100644 --- a/src/main/java/com/jnz/teamManager/config/SecurityConfiguration.java +++ b/src/main/java/com/jnz/teamManager/config/SecurityConfiguration.java @@ -4,13 +4,16 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.logout.LogoutHandler; +import org.springframework.web.cors.CorsConfigurationSource; @Configuration @EnableWebSecurity @@ -28,10 +31,10 @@ public class SecurityConfiguration { @Autowired private ExceptionFilterHandler exceptionFilterHandler; - @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - http.csrf().disable().authorizeHttpRequests().requestMatchers("/auth/**").permitAll() + http.cors(AbstractHttpConfigurer::disable) + .csrf().disable().authorizeHttpRequests().requestMatchers("/auth/**").permitAll() .anyRequest().authenticated() .and().sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 1107825..1741368 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,6 @@ spring.datasource.url=${MYSQL_URL} spring.datasource.username=${MYSQLUSER} spring.datasource.password=${MYSQLPASSWORD} +server.port=${PORT} spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.hibernate.ddl-auto = update \ No newline at end of file diff --git a/src/test/java/com/jnz/teamManager/AuthenticationServiceEncoderTest.java b/src/test/java/com/jnz/teamManager/AuthenticationServiceEncoderTest.java new file mode 100644 index 0000000..3de2337 --- /dev/null +++ b/src/test/java/com/jnz/teamManager/AuthenticationServiceEncoderTest.java @@ -0,0 +1,26 @@ +package com.jnz.teamManager; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.crypto.password.PasswordEncoder; + +@SpringBootTest +public class AuthenticationServiceEncoderTest { + + @Autowired + private PasswordEncoder passwordEncoder; + + @Test + void testPasswordEncoder() { + String password = "password123"; + String encodedPassword = passwordEncoder.encode(password); + + Assertions.assertNotEquals(password, encodedPassword); + Assertions.assertTrue(passwordEncoder.matches(password, encodedPassword)); + } + + + +} diff --git a/src/test/java/com/jnz/teamManager/AuthenticationServiceTest.java b/src/test/java/com/jnz/teamManager/AuthenticationServiceTest.java new file mode 100644 index 0000000..31e4eeb --- /dev/null +++ b/src/test/java/com/jnz/teamManager/AuthenticationServiceTest.java @@ -0,0 +1,50 @@ +package com.jnz.teamManager; + +import com.jnz.teamManager.auth.dto.RegisterRequest; +import com.jnz.teamManager.entity.User; +import com.jnz.teamManager.service.UserService; +import com.jnz.teamManager.service.auth.AuthenticationService; +import com.jnz.teamManager.service.auth.JwtService; + +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.crypto.password.PasswordEncoder; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@SpringBootTest +public class AuthenticationServiceTest { + + @Mock + private UserService userService; + + @Mock + private PasswordEncoder passwordEncoder; + + @Mock + private JwtService jwtService; + + @InjectMocks + private AuthenticationService authenticationService; + + @Test + public void register_shouldCreateUser() { + // given + RegisterRequest registerRequest = new RegisterRequest(); + registerRequest.setUsername("testuser"); + registerRequest.setEmail("testuser@test.com"); + registerRequest.setPassword("password123"); + + when(passwordEncoder.encode(registerRequest.getPassword())).thenReturn("encodedpassword"); + + // when + authenticationService.register(registerRequest); + + // then + verify(userService).addUser(any(User.class)); + } +} \ No newline at end of file diff --git a/src/test/java/com/jnz/teamManager/InvitationServiceTest.java b/src/test/java/com/jnz/teamManager/InvitationServiceTest.java new file mode 100644 index 0000000..834d9b0 --- /dev/null +++ b/src/test/java/com/jnz/teamManager/InvitationServiceTest.java @@ -0,0 +1,132 @@ +package com.jnz.teamManager; + +import com.jnz.teamManager.entity.Invitation; +import com.jnz.teamManager.entity.Team; +import com.jnz.teamManager.entity.User; +import com.jnz.teamManager.exception.error.InvitationAlreadyExistsException; +import com.jnz.teamManager.repository.InvitationsRepository; +import com.jnz.teamManager.service.InvitationsService; +import com.jnz.teamManager.service.TeamService; +import com.jnz.teamManager.service.UserService; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import static org.mockito.ArgumentMatchers.anyLong; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.StreamSupport; + +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.Mockito.*; + +@SpringBootTest +public class InvitationServiceTest { + + @Mock + private InvitationsRepository invitationsRepository; + + @Mock + private UserService userService; + + @Mock + private TeamService teamService; + + private InvitationsService invitationsService; + + @BeforeEach + public void setUp() { + MockitoAnnotations.initMocks(this); + invitationsService = new InvitationsService(); + invitationsService.invitationsRepository = invitationsRepository; + invitationsService.userService = userService; + invitationsService.teamService = teamService; + } + + @Test + public void testAddInvitation() { + // Mock de datos de entrada + Map invitation = new HashMap<>(); + invitation.put("userReceiverId", "1"); + invitation.put("userOwnerId", "2"); + invitation.put("teamId", "3"); + invitation.put("message", "Test invitation"); + + // Mock de servicio de usuario + when(userService.getUserById(1L)).thenReturn(new User()); + when(userService.getUserById(2L)).thenReturn(new User()); + + // Mock de servicio de equipo + when(teamService.getTeamById(3L)).thenReturn(new Team()); + + // Mock de repositorio de invitaciones + when(invitationsRepository.findAll()).thenReturn(Collections.emptyList()); + + // Ejecución de método a probar + invitationsService.addInvitation(invitation); + + // Verificación de llamadas a métodos + verify(userService, times(1)).getUserById(1L); + verify(userService, times(1)).getUserById(2L); + verify(teamService, times(1)).getTeamById(3L); + verify(invitationsRepository, times(1)).save(any(Invitation.class)); + } + + @Test + public void testAddInvitation_DuplicateInvitation() { + // Mock de datos de entrada + Map invitation = new HashMap<>(); + invitation.put("userReceiverId", "1"); + invitation.put("userOwnerId", "2"); + invitation.put("teamId", "3"); + invitation.put("message", "Test invitation"); + + // Mock de servicio de usuario + when(userService.getUserById(1L)).thenReturn(new User()); + when(userService.getUserById(2L)).thenReturn(new User()); + + // Mock de servicio de equipo + when(teamService.getTeamById(3L)).thenReturn(new Team()); + + // Mock de repositorio de invitaciones con una invitación existente + Invitation existingInvitation = new Invitation(); + existingInvitation.setUser(new User()); + existingInvitation.setTeamId(new Team()); + when(invitationsRepository.findAll()).thenReturn(Collections.singletonList(existingInvitation)); + + // Ejecución de método a probar y verificación de excepción + assertThrows(InvitationAlreadyExistsException.class, () -> invitationsService.addInvitation(invitation)); + + // Verificación de llamadas a métodos + verify(userService, times(1)).getUserById(1L); + verify(userService, times(1)).getUserById(2L); + verify(teamService, times(1)).getTeamById(3L); + verify(invitationsRepository, never()).save(any(Invitation.class)); + } + + @Test + public void testDeleteInvitation() { + // Mock de datos de entrada + Invitation invitation = new Invitation(); + invitation.setUser(new User()); + invitation.setTeamId(new Team()); + + // Ejecución de método a probar + invitationsService.deleteInvitation(invitation); + + // Verificación de llamadas a métodos + verify(invitationsRepository, times(1)).delete(any(Invitation.class)); + } + + + +} \ No newline at end of file diff --git a/src/test/java/com/jnz/teamManager/JwtServiceTest.java b/src/test/java/com/jnz/teamManager/JwtServiceTest.java new file mode 100644 index 0000000..1f4d9b9 --- /dev/null +++ b/src/test/java/com/jnz/teamManager/JwtServiceTest.java @@ -0,0 +1,40 @@ +package com.jnz.teamManager; + +import com.jnz.teamManager.entity.User; +import com.jnz.teamManager.service.UserService; +import com.jnz.teamManager.service.auth.JwtService; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.core.userdetails.UserDetails; + +@SpringBootTest +public class JwtServiceTest { + + @Autowired + private JwtService jwtService; + + @Autowired + private UserService userService; + + @Test + public void testGenerateAndValidateToken() { + // Creamos un nuevo usuario + User user = User.builder() + .username("testUser") + .email("test@example.com") + .password("password123") + .build(); + userService.addUser(user); + + // Generamos un token para el usuario + UserDetails userDetails = userService.getUserByUsername(user.getUsername()); + String token = jwtService.generateToken(userDetails); + + // Verificamos si el token es válido + boolean isTokenValid = jwtService.isTokenValid(token, userDetails); + Assertions.assertTrue(isTokenValid); + } +} \ No newline at end of file diff --git a/src/test/java/com/jnz/teamManager/TeamServiceTest.java b/src/test/java/com/jnz/teamManager/TeamServiceTest.java new file mode 100644 index 0000000..ba4cde9 --- /dev/null +++ b/src/test/java/com/jnz/teamManager/TeamServiceTest.java @@ -0,0 +1,176 @@ +package com.jnz.teamManager; + +import com.jnz.teamManager.entity.Team; +import com.jnz.teamManager.entity.User; +import com.jnz.teamManager.exception.error.TeamNotExistsException; +import com.jnz.teamManager.repository.TeamRepository; +import com.jnz.teamManager.service.TeamService; +import com.jnz.teamManager.service.UserService; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.List; + + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class TeamServiceTest { + + @Mock + private TeamRepository teamRepository; + + @Mock + private UserService userService; + + @InjectMocks + private TeamService teamService; + + private User user; + private Team team; + + @BeforeEach + void setUp() { + user = new User(); + user.setId(1L); + user.setUsername("usertest"); + + team = new Team(); + team.setId(1L); + team.setName("Team A"); + team.setPlayers(Set.of(user)); + } + + @AfterEach + void tearDown() { + teamRepository.deleteAll(); + userService.deleteUser(user.getId()); + } + + + @Test + void testGetTeamById() { + when(teamRepository.findById(1L)).thenReturn(Optional.of(team)); + + Team result = teamService.getTeamById(1L); + + assertNotNull(result); + assertEquals(team, result); + } + + @Test + void testGetTeamByIdThrowsExceptionWhenTeamNotExists() { + when(teamRepository.findById(1L)).thenReturn(Optional.empty()); + + assertThrows(TeamNotExistsException.class, () -> teamService.getTeamById(1L)); + } + + @Test + void testFindAll() { + when(teamRepository.findAll()).thenReturn(Arrays.asList(team)); + + Iterable result = teamService.findAll(); + + assertNotNull(result); + assertEquals(1, ((List) result).size()); + assertEquals(team, ((List) result).get(0)); + } + + @Test + void testAddTeam() { + when(teamRepository.save(any(Team.class))).thenReturn(team); + + teamService.addTeam(team, user.getId()); + + verify(teamRepository, times(1)).save(any(Team.class)); + verify(userService, times(1)).addTeamToUser(eq(user.getId()), eq(team.getId())); + } + + @Test + void testDeleteTeam() { + when(teamRepository.findById(1L)).thenReturn(Optional.of(team)); + + teamService.deleteTeam(1L); + + verify(teamRepository, times(1)).delete(team); + assertTrue(user.getUserTeams().isEmpty()); + } + + @Test + void testGetUsersByTeamId() { + when(teamRepository.findById(1L)).thenReturn(Optional.of(team)); + + Iterable result = teamService.getUsersByTeamId(1L); + + assertNotNull(result); + assertEquals(1, ((List) result).size()); + assertEquals(user, ((List) result).get(0)); + } + + public void testUpdateTeam() { + Team team = new Team(); + team.setName("Team A"); + teamRepository.save(team); + + team.setName("Team B"); + + teamService.updateTeam(team); + + Team updatedTeam = teamService.getTeamById(team.getId()); + + assertEquals("Team B", updatedTeam.getName()); + } + + @Test + public void testGetTeamsWhereUserIsNotAt() { + Team team1 = new Team(); + team1.setName("Team A"); + teamRepository.save(team1); + + Team team2 = new Team(); + team2.setName("Team B"); + teamRepository.save(team2); + + User user1 = new User(); + user1.setUsername("test1"); + user1.setId(2L); + user1.setEmail("test1@test.com"); + user1.setPassword("test1"); + userService.addUser(user1); + + User user2 = new User(); + user2.setUsername("test"); + user2.setId(1L); + user2.setEmail("test@test.com"); + user2.setPassword("test"); + userService.addUser(user2); + + user1 = userService.getUserById(user1.getId()); + user2 = userService.getUserById(user2.getId()); + + // add user1 to team1 + userService.addTeamToUser(user1.getId(), team1.getId()); + + // get teams where user2 is not at + Iterable teams = teamService.getTeamsWhereUserIsNotAt(user2.getId()); + + Set teamIds = new HashSet<>(); + for (Team team : teams) { + teamIds.add(team.getId()); + } + + assertTrue(teamIds.contains(team1.getId())); + assertTrue(teamIds.contains(team2.getId())); + } +} \ No newline at end of file diff --git a/src/test/java/com/jnz/teamManager/UserServiceTest.java b/src/test/java/com/jnz/teamManager/UserServiceTest.java new file mode 100644 index 0000000..7aa46f9 --- /dev/null +++ b/src/test/java/com/jnz/teamManager/UserServiceTest.java @@ -0,0 +1,132 @@ +package com.jnz.teamManager; + +import com.jnz.teamManager.auth.dto.AuthenticationRequest; +import com.jnz.teamManager.auth.dto.RegisterRequest; +import com.jnz.teamManager.entity.Role; +import com.jnz.teamManager.entity.User; +import com.jnz.teamManager.exception.error.EmailAlreadyExistsException; +import com.jnz.teamManager.exception.error.UserNotExistsException; +import com.jnz.teamManager.exception.error.UsernameAlreadyExistsException; +import com.jnz.teamManager.repository.UserRepository; +import com.jnz.teamManager.service.TeamService; +import com.jnz.teamManager.service.UserService; +import com.jnz.teamManager.service.auth.AuthenticationService; +import com.jnz.teamManager.service.auth.JwtService; +import lombok.val; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentMatchers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.crypto.password.PasswordEncoder; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.Arrays; +import java.util.Optional; + +@ExtendWith(MockitoExtension.class) +public class UserServiceTest { + + @Mock + private UserRepository userRepository; + + @Mock + private TeamService teamService; + + @InjectMocks + private UserService userService; + + private User user; + + @BeforeEach + public void setup() { + user = User.builder() + .id(1L) + .email("test@test.com") + .username("test") + .password("test") + .role(Role.USER) + .build(); + } + + @AfterEach + public void tearDown() { + userRepository.deleteById(user.getId()); + } + + @Test + public void shouldGetUserById() { + Mockito.when(userRepository.findById(1L)).thenReturn(Optional.of(user)); + User result = userService.getUserById(1L); + Assertions.assertEquals(user, result); + } + + @Test + public void shouldThrowUserNotExistsException() { + Mockito.when(userRepository.findById(2L)).thenReturn(Optional.empty()); + Assertions.assertThrows(UserNotExistsException.class, () -> userService.getUserById(2L)); + } + + @Test + public void shouldAddUser() { + Mockito.when(userRepository.save(ArgumentMatchers.any(User.class))).thenReturn(user); + User result = userService.addUser(user); + Assertions.assertEquals(user, result); + } + + @Test + public void shouldThrowUsernameAlreadyExistsException() { + Mockito.when(userRepository.findAll()).thenReturn(Arrays.asList(user)); + User newUser = User.builder() + .email("test2@test.com") + .username("test") + .password("test") + .role(Role.USER) + .build(); + Assertions.assertThrows(UsernameAlreadyExistsException.class, () -> userService.addUser(newUser)); + } + + @Test + public void shouldThrowEmailAlreadyExistsException() { + Mockito.when(userRepository.findAll()).thenReturn(Arrays.asList(user)); + User newUser = User.builder() + .email("test@test.com") + .username("test2") + .password("test") + .role(Role.USER) + .build(); + Assertions.assertThrows(EmailAlreadyExistsException.class, () -> userService.addUser(newUser)); + } + + @Test + void shouldDeleteUser() { + // Arrange + User user = User.builder() + .email("user@example.com") + .username("user1") + .password("password") + .role(Role.USER) + .build(); + userRepository.save(user); + + Long userId = user.getId(); + + // Act + userService.deleteUser(userId); + + // Assert + assertThrows(UserNotExistsException.class, () -> userService.getUserById(userId)); + } +} \ No newline at end of file