Merge pull request 'refresh-token' (#35) from refresh-token into master
Accepted Reviewed-on: http://git.plannaplan.pl/filipizydorczyk/backend/pulls/35
This commit is contained in:
		@@ -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();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,9 @@ public interface UserRepository extends JpaRepository<User, Long> {
 | 
			
		||||
    @Query("FROM User WHERE email = ?1")
 | 
			
		||||
    Optional<User> getByAuthority(@Param("authority") String authority);
 | 
			
		||||
 | 
			
		||||
    @Query("FROM User WHERE refreshToken = ?1")
 | 
			
		||||
    Optional<User> getByRefreshToken(@Param("refreshToken") String refreshToken);
 | 
			
		||||
 | 
			
		||||
    @Query("FROM User WHERE token = ?1")
 | 
			
		||||
    Optional<User> getByToken(@Param("token") String token);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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.");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -81,4 +81,8 @@ public class UserService {
 | 
			
		||||
        return this.repo.getAllByRole(UserRoles.STUDENT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Optional<User> getUserByRefreshToken(String refreshToken) {
 | 
			
		||||
        return this.repo.getByRefreshToken(refreshToken);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -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<TokenResponse> getRefreshToken(
 | 
			
		||||
            @RequestParam("refreshToken") @ApiParam(value = "Refresh token obtained in /token request") final String refreshToken)
 | 
			
		||||
            throws NullPointerException {
 | 
			
		||||
        Optional<User> 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);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user