diff --git a/buisnesslogic/src/main/java/com/plannaplan/entities/User.java b/buisnesslogic/src/main/java/com/plannaplan/entities/User.java index 0633dcc..6f01759 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/entities/User.java +++ b/buisnesslogic/src/main/java/com/plannaplan/entities/User.java @@ -1,6 +1,7 @@ package com.plannaplan.entities; import java.sql.Timestamp; +import java.util.UUID; import java.util.concurrent.TimeUnit; import javax.persistence.Entity; @@ -28,6 +29,7 @@ public class User { private String usosId; private UserRoles role; private String token; + private String refreshToken; private Timestamp tokenUsageDate; public User() { @@ -105,6 +107,13 @@ public class User { return token; } + /** + * @return token needed to call refresh token after it expired + */ + public String getRefreshToken() { + return refreshToken; + } + /** * token seter. Sets token and automaticly set time when was set * @@ -113,6 +122,7 @@ public class User { public void setToken(String token) { this.tokenUsageDate = new Timestamp(System.currentTimeMillis()); this.token = token; + this.refreshToken = UUID.randomUUID().toString(); } /** diff --git a/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java b/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java index c7af201..debf7ab 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java +++ b/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java @@ -38,6 +38,9 @@ public interface UserRepository extends JpaRepository { @Query("FROM User WHERE email = ?1") Optional getByAuthority(@Param("authority") String authority); + @Query("FROM User WHERE refreshToken = ?1") + Optional getByRefreshToken(@Param("refreshToken") String refreshToken); + @Query("FROM User WHERE token = ?1") Optional getByToken(@Param("token") String token); diff --git a/buisnesslogic/src/main/java/com/plannaplan/services/EventService.java b/buisnesslogic/src/main/java/com/plannaplan/services/EventService.java index f58a4d0..7569bd0 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/services/EventService.java +++ b/buisnesslogic/src/main/java/com/plannaplan/services/EventService.java @@ -1,22 +1,17 @@ package com.plannaplan.services; -import org.springframework.beans.factory.annotation.Autowired; +// import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @Service public class EventService { - @Autowired - private EmailService emailService; + // @Autowired + // private EmailService emailService; @Scheduled(cron = "0 2 17 * * *") public void collectGroupLosses() { System.out.println("Checking for groups"); } - - @Scheduled(cron = "0 5 18 * * *") - public void testMail() { - this.emailService.sendMail("kaczor982@gmail.com", "Cześć. Jestem Tomek."); - } } diff --git a/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java b/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java index d4d2130..9192490 100755 --- a/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java +++ b/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java @@ -81,4 +81,8 @@ public class UserService { return this.repo.getAllByRole(UserRoles.STUDENT); } + public Optional getUserByRefreshToken(String refreshToken) { + return this.repo.getByRefreshToken(refreshToken); + } + } \ No newline at end of file diff --git a/restservice/src/main/java/com/plannaplan/controllers/TokenController.java b/restservice/src/main/java/com/plannaplan/controllers/TokenController.java index e4615d7..d771768 100755 --- a/restservice/src/main/java/com/plannaplan/controllers/TokenController.java +++ b/restservice/src/main/java/com/plannaplan/controllers/TokenController.java @@ -1,5 +1,8 @@ package com.plannaplan.controllers; +import java.util.Optional; +import java.util.UUID; + import com.plannaplan.entities.User; import com.plannaplan.exceptions.UserNotFoundException; import com.plannaplan.responses.models.TokenResponse; @@ -61,4 +64,20 @@ public class TokenController { } } + + @GetMapping("/token/refresh") + @ApiOperation(value = "Endpoint to access new token based on refresh token. It's needed when request with provided token fail with code 403") + public ResponseEntity getRefreshToken( + @RequestParam("refreshToken") @ApiParam(value = "Refresh token obtained in /token request") final String refreshToken) + throws NullPointerException { + Optional userResult = this.userService.getUserByRefreshToken(refreshToken); + if (userResult.isEmpty()) { + return new ResponseEntity<>(null, HttpStatus.NOT_FOUND); + } + User user = userResult.get(); + user.setToken(UUID.randomUUID().toString()); + user = this.userService.save(user); + return new ResponseEntity<>(new TokenResponse(user), HttpStatus.OK); + + } } diff --git a/restservice/src/main/java/com/plannaplan/responses/models/TokenResponse.java b/restservice/src/main/java/com/plannaplan/responses/models/TokenResponse.java index 33f6f6e..583619f 100755 --- a/restservice/src/main/java/com/plannaplan/responses/models/TokenResponse.java +++ b/restservice/src/main/java/com/plannaplan/responses/models/TokenResponse.java @@ -9,6 +9,8 @@ import io.swagger.annotations.ApiModelProperty; public class TokenResponse { @ApiModelProperty(value = "user token used to verify requests") private String token; + @ApiModelProperty(value = "user token needed to refresh") + private String refreshToken; @ApiModelProperty(value = "user id in database") private Long id; @ApiModelProperty(value = "user app role") @@ -21,6 +23,7 @@ public class TokenResponse { this.authorityRole = user.getRole().toString(); this.email = user.getEmail(); this.token = user.getToken(); + this.refreshToken = user.getRefreshToken(); } public String getEmail() { @@ -39,4 +42,8 @@ public class TokenResponse { return token; } + public String getRefreshToken() { + return this.refreshToken; + } + } diff --git a/restservice/src/main/java/com/plannaplan/security/WebSecurityConfig.java b/restservice/src/main/java/com/plannaplan/security/WebSecurityConfig.java index d41b9f6..cbeff0d 100755 --- a/restservice/src/main/java/com/plannaplan/security/WebSecurityConfig.java +++ b/restservice/src/main/java/com/plannaplan/security/WebSecurityConfig.java @@ -37,9 +37,10 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override public void configure(final WebSecurity webSecurity) { - webSecurity.ignoring().antMatchers("/token**").antMatchers("/api/v1/courses/all") - .antMatchers("/api/v1/groups/course/{id}").antMatchers("/v2/api-docs", "/configuration/ui", - "/swagger-resources/**", "/configuration/security", "/swagger-ui.html", "/webjars/**"); + webSecurity.ignoring().antMatchers("/token**").antMatchers("/token/refresh**") + .antMatchers("/api/v1/courses/all").antMatchers("/api/v1/groups/course/{id}") + .antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources/**", "/configuration/security", + "/swagger-ui.html", "/webjars/**"); } @Override diff --git a/restservice/src/test/java/com/plannaplan/controllers/TokenControllerTest.java b/restservice/src/test/java/com/plannaplan/controllers/TokenControllerTest.java index 9716a68..b177a8a 100755 --- a/restservice/src/test/java/com/plannaplan/controllers/TokenControllerTest.java +++ b/restservice/src/test/java/com/plannaplan/controllers/TokenControllerTest.java @@ -3,6 +3,7 @@ package com.plannaplan.controllers; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; @@ -12,11 +13,22 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.lang.reflect.Field; +import java.sql.Timestamp; + +import com.plannaplan.entities.User; +import com.plannaplan.services.UserService; +import com.plannaplan.types.UserRoles; + @RunWith(SpringRunner.class) @SpringBootTest @ContextConfiguration public class TokenControllerTest extends AbstractControllerTest { private final String TOKEN_ENDPOINT = "/token"; + private final String REFRESH_TOKEN_ENDPOINT = "/token/refresh"; + + @Autowired + private UserService service; @Test public void shouldFailWithNoParameter() throws Exception { @@ -39,4 +51,39 @@ public class TokenControllerTest extends AbstractControllerTest { MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); mockMvc.perform(get(TOKEN_ENDPOINT).param("ticket", ticket)).andExpect(status().isOk()); } + + @Test + public void shouldFailWithWrongRefreshToken() throws Exception { + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); + mockMvc.perform(get(REFRESH_TOKEN_ENDPOINT).param("refreshToken", "totaly-wrong-refresh-token")) + .andExpect(status().is4xxClientError()); + } + + @Test + public void shouldRetrunTokenBeforeExpirationOfOldOne() throws Exception { + User user = new User("Eren", "Yager", "shouldRetrunTokenBeforeExpirationOfOldOne@TokenController.test", + UserRoles.TEST_USER); + user.setToken("Totalnie-bezpieczny-token"); + this.service.save(user); + + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); + mockMvc.perform(get(REFRESH_TOKEN_ENDPOINT).param("refreshToken", user.getRefreshToken())) + .andExpect(status().isOk()); + } + + @Test + public void shouldRetrunTokenAfterExpirationOfOldOne() throws Exception { + final Field reader = User.class.getDeclaredField("tokenUsageDate"); + reader.setAccessible(true); + + User user = new User("Mikasa", "Ackerman", "shouldRetrunTokenAfterExpirationOfOldOne@TokenController.test", + UserRoles.TEST_USER); + user.setToken("Totalnie-bezpieczny-token"); + reader.set(user, new Timestamp(System.currentTimeMillis() - 86400000)); + this.service.save(user); + + MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); + mockMvc.perform(get(REFRESH_TOKEN_ENDPOINT).param("refreshToken", user.getRefreshToken())) + .andExpect(status().isOk()); + } }