Add spring security configuration.
This commit is contained in:
8
pom.xml
8
pom.xml
@@ -33,10 +33,10 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<!-- <dependency> -->
|
||||
<!-- <groupId>org.springframework.boot</groupId> -->
|
||||
<!-- <artifactId>spring-boot-starter-security</artifactId> -->
|
||||
<!-- </dependency> -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -3,9 +3,11 @@ package org.codiki;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan(basePackages = "org.codiki")
|
||||
public class CodikiApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.codiki.account;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.security.Principal;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -9,8 +9,11 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import org.codiki.core.entities.dto.PasswordWrapperDTO;
|
||||
import org.codiki.core.entities.dto.UserDTO;
|
||||
import org.codiki.core.entities.persistence.User;
|
||||
import org.codiki.core.security.TokenService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
@@ -21,40 +24,20 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@RestController
|
||||
@RequestMapping("/api/account")
|
||||
public class AccountController {
|
||||
|
||||
private static final String HEADER_TOKEN = "token";
|
||||
|
||||
@Autowired
|
||||
private AccountService accountService;
|
||||
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
/**
|
||||
* Log in the user in request body.
|
||||
*
|
||||
* @param pUser
|
||||
* The user to connect.
|
||||
* @param response
|
||||
* The reponse injected by Spring.
|
||||
* @return The connected user object.
|
||||
* @throws IOException
|
||||
* If credentials are bad.
|
||||
*/
|
||||
@PostMapping("/login")
|
||||
public UserDTO login(@RequestBody UserDTO pUser, HttpServletResponse response) throws IOException {
|
||||
return accountService.checkCredentials(response, pUser);
|
||||
public UserDTO login(@RequestBody final User pUser) throws BadCredentialsException {
|
||||
return new UserDTO(accountService.authenticate(pUser));
|
||||
}
|
||||
|
||||
/**
|
||||
* Log out the user.
|
||||
*
|
||||
* @param pRequest
|
||||
* The request injected by Spring.
|
||||
*/
|
||||
@GetMapping("/logout")
|
||||
public void logout(HttpServletRequest pRequest) {
|
||||
tokenService.removeUser(pRequest.getHeader(HEADER_TOKEN));
|
||||
public void logout(final HttpServletRequest request, final HttpServletResponse response) {
|
||||
final Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
if(auth != null) {
|
||||
new SecurityContextLogoutHandler().logout(request, response, auth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,13 +57,15 @@ public class AccountController {
|
||||
@PutMapping("/changePassword")
|
||||
public void changePassword(@RequestBody final PasswordWrapperDTO pPasswordWrapper,
|
||||
final HttpServletRequest pRequest,
|
||||
final HttpServletResponse pResponse) throws IOException {
|
||||
final Optional<User> connectedUser = tokenService.getAuthenticatedUserByToken(pRequest);
|
||||
if(connectedUser.isPresent()) {
|
||||
accountService.changePassword(connectedUser.get(), pPasswordWrapper, pResponse);
|
||||
} else {
|
||||
pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
}
|
||||
final HttpServletResponse pResponse,
|
||||
final Principal pPrincipal) throws IOException {
|
||||
// final Optional<User> connectedUser = tokenService.getAuthenticatedUserByToken(pRequest);
|
||||
// if(connectedUser.isPresent()) {
|
||||
// accountService.changePassword(connectedUser.get(), pPasswordWrapper, pResponse);
|
||||
// } else {
|
||||
// pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@PostMapping("/signin")
|
||||
@@ -90,7 +75,7 @@ public class AccountController {
|
||||
|
||||
@PutMapping("/")
|
||||
public void update(@RequestBody final UserDTO pUser, final HttpServletRequest pRequest,
|
||||
final HttpServletResponse pResponse) throws IOException {
|
||||
accountService.updateUser(pUser, pRequest, pResponse);
|
||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
||||
accountService.updateUser(pUser, pRequest, pResponse, pPrincipal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package org.codiki.account;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.naming.AuthenticationException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@@ -17,53 +17,41 @@ import org.codiki.core.entities.dto.UserDTO;
|
||||
import org.codiki.core.entities.persistence.User;
|
||||
import org.codiki.core.repositories.ImageRepository;
|
||||
import org.codiki.core.repositories.UserRepository;
|
||||
import org.codiki.core.security.TokenService;
|
||||
import org.codiki.core.security.CustomAuthenticationProvider;
|
||||
import org.codiki.core.services.FileUploadService;
|
||||
import org.codiki.core.services.UserService;
|
||||
import org.codiki.core.utils.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Service
|
||||
public class AccountService {
|
||||
|
||||
@Autowired
|
||||
private CustomAuthenticationProvider authenticationProvider;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
@Autowired
|
||||
private FileUploadService fileUploadService;
|
||||
|
||||
@Autowired
|
||||
private ImageRepository imageRepository;
|
||||
|
||||
/**
|
||||
* Check the user credentials and generate him a token if they are correct.
|
||||
*
|
||||
* @param pUser
|
||||
* The user sent from client.
|
||||
* @return The user populated with the generated token.
|
||||
* @throws IOException
|
||||
* If the credentials are bad.
|
||||
* @throws AuthenticationException
|
||||
* If the credentials are wrong.
|
||||
*/
|
||||
public UserDTO checkCredentials(HttpServletResponse pResponse, UserDTO pUser) throws IOException {
|
||||
UserDTO result = null;
|
||||
public User authenticate(final User pUser) throws BadCredentialsException {
|
||||
final User user = userService.checkCredentials(pUser.getEmail(), pUser.getPassword());
|
||||
|
||||
Optional<User> user = userRepository.findByEmail(pUser.getEmail());
|
||||
authenticationProvider.authenticate(new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword()));
|
||||
|
||||
if(user.isPresent() && StringUtils.compareHash(pUser.getPassword(), user.get().getPassword())) {
|
||||
tokenService.addUser(user.get());
|
||||
result = new UserDTO(user.get(), true);
|
||||
} else {
|
||||
pResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
|
||||
}
|
||||
|
||||
return result;
|
||||
return user;
|
||||
}
|
||||
|
||||
public void changePassword(final User pUser, final PasswordWrapperDTO pPasswordWrapper,
|
||||
@@ -85,11 +73,11 @@ public class AccountService {
|
||||
}
|
||||
}
|
||||
|
||||
public String uploadFile(final MultipartFile pFile,
|
||||
final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException {
|
||||
public String uploadFile(final MultipartFile pFile, final HttpServletRequest pRequest,
|
||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
||||
final String avatarFileName = fileUploadService.uploadProfileImage(pFile);
|
||||
|
||||
final Optional<User> connectedUser = tokenService.getAuthenticatedUserByToken(pRequest);
|
||||
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
||||
if(connectedUser.isPresent()) {
|
||||
final Optional<User> userFromDb = userRepository.findById(connectedUser.get().getId());
|
||||
if(userFromDb.isPresent()) {
|
||||
@@ -109,10 +97,11 @@ public class AccountService {
|
||||
return fileUploadService.loadAvatar(pAvatarFileName);
|
||||
}
|
||||
|
||||
public List<ImageDTO> getUserImages(final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException {
|
||||
public List<ImageDTO> getUserImages(final HttpServletRequest pRequest, final HttpServletResponse pResponse,
|
||||
final Principal pPrincipal) throws IOException {
|
||||
List<ImageDTO> result = new LinkedList<>();
|
||||
|
||||
final Optional<User> connectedUser = tokenService.getAuthenticatedUserByToken(pRequest);
|
||||
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
||||
if(connectedUser.isPresent()) {
|
||||
result = imageRepository.getByUserId(connectedUser.get().getId())
|
||||
.stream().map(ImageDTO::new).collect(Collectors.toList());
|
||||
@@ -142,8 +131,8 @@ public class AccountService {
|
||||
}
|
||||
|
||||
public void updateUser(final UserDTO pUser, final HttpServletRequest pRequest,
|
||||
final HttpServletResponse pResponse) throws IOException {
|
||||
final Optional<User> connectedUserOpt = tokenService.getAuthenticatedUserByToken(pRequest);
|
||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
||||
final Optional<User> connectedUserOpt = userService.getUserByPrincipal(pPrincipal);
|
||||
if(connectedUserOpt.isPresent()) {
|
||||
final User connectedUser = connectedUserOpt.get();
|
||||
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
package org.codiki.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.codiki.core.security.Route;
|
||||
import org.codiki.core.utils.StringUtils;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
/**
|
||||
* Base class for all filters of the application.<br/>
|
||||
* <br/>
|
||||
* The children classes have to implements the method
|
||||
* {@link AbstractFilter#getClass()} to set the URLs filtered (with all or some
|
||||
* http methods), and the method
|
||||
* {@link AbstractFilter#filter(HttpServletRequest, ServletResponse, FilterChain)}
|
||||
* to define the filter processing.
|
||||
*
|
||||
* @author Takiguchi
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractFilter implements Filter {
|
||||
|
||||
/** Regex url path prefix for method {@link this#isRequestFiltered(String)}. */
|
||||
private static final String PREFIX_URL_PATH = "https?:\\/\\/.*(:\\d{0,5})?";
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of routes which will be processed by the filter.
|
||||
*
|
||||
* @return The routes.
|
||||
*/
|
||||
protected abstract List<Route> getRoutes();
|
||||
|
||||
/**
|
||||
* Filter actions for its processing.
|
||||
*
|
||||
* @param request
|
||||
* The http request.
|
||||
* @param response
|
||||
* The response.
|
||||
* @param chain
|
||||
* The chain.
|
||||
*/
|
||||
protected abstract void filter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException;
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
|
||||
if(isRequestFiltered(httpRequest.getRequestURL().toString(), httpRequest.getMethod())) {
|
||||
filter(httpRequest, (HttpServletResponse) response, chain);
|
||||
} else {
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the url is allowed with the given method in parameters.
|
||||
*
|
||||
* @param pRequestUrl
|
||||
* The url request.
|
||||
* @param pRequestMethod
|
||||
* The http method of the request.
|
||||
* @return {@code true} if the url is allowed with the method, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
boolean isRequestFiltered(final String pRequestUrl, final String pRequestMethod) {
|
||||
boolean result = false;
|
||||
|
||||
for(final Route route : getRoutes()) {
|
||||
/*
|
||||
* Check urls matching, and if the method of the route isn't set, all methods
|
||||
* are allowed. Otherwise, we check the methods too.
|
||||
*/
|
||||
if(Pattern.matches(StringUtils.concat(PREFIX_URL_PATH, route.getUrl()), pRequestUrl)) {
|
||||
if(!route.getMethod().isPresent() || isMethodFiltered(route, pRequestMethod)) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the route do filter the method in parameters.
|
||||
*
|
||||
* @param pRoute
|
||||
* The registered route.
|
||||
* @param pRequestMethod
|
||||
* The http method to check with the registered route.
|
||||
*/
|
||||
boolean isMethodFiltered(final Route pRoute, final String pRequestMethod) {
|
||||
boolean result = false;
|
||||
|
||||
if(pRoute.getMethod().isPresent()) {
|
||||
for(final HttpMethod routeMethod : pRoute.getMethod().get()) {
|
||||
if(routeMethod.name().equals(pRequestMethod)) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,6 @@ public class UserDTO {
|
||||
|
||||
private Role role;
|
||||
|
||||
private String token;
|
||||
|
||||
public UserDTO() {
|
||||
super();
|
||||
}
|
||||
@@ -38,9 +36,6 @@ public class UserDTO {
|
||||
|
||||
public UserDTO(final User pUser, final boolean pWithToken) {
|
||||
this(pUser);
|
||||
if(pWithToken) {
|
||||
token = pUser.getToken().getValue();
|
||||
}
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
@@ -98,12 +93,4 @@ public class UserDTO {
|
||||
public void setRole(Role role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.codiki.core.entities.security.Token;
|
||||
import org.hibernate.annotations.Generated;
|
||||
import org.hibernate.annotations.GenerationTime;
|
||||
|
||||
@@ -69,15 +68,11 @@ public class User implements Serializable {
|
||||
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
|
||||
private List<Image> listImages;
|
||||
|
||||
/** Authentication token. */
|
||||
private transient Token token;
|
||||
|
||||
/* ******************* */
|
||||
/* Constructors */
|
||||
/* ******************* */
|
||||
public User() {
|
||||
super();
|
||||
token = new Token();
|
||||
}
|
||||
|
||||
/* ******************* */
|
||||
@@ -184,9 +179,4 @@ public class User implements Serializable {
|
||||
public void setListImages(List<Image> listImages) {
|
||||
this.listImages = listImages;
|
||||
}
|
||||
|
||||
public Token getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
package org.codiki.core.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.codiki.core.AbstractFilter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class AuthenticationFilter extends AbstractFilter {
|
||||
|
||||
private static final String HTTP_OPTIONS = "OPTIONS";
|
||||
|
||||
private static final String HEADER_TOKEN = "token";
|
||||
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
@Override
|
||||
protected List<Route> getRoutes() {
|
||||
return Arrays.asList(
|
||||
new Route("\\/api\\/posts\\/myPosts"),
|
||||
new Route("\\/api\\/posts\\/preview"),
|
||||
new Route("\\/api\\/posts\\/", HttpMethod.POST, HttpMethod.PUT, HttpMethod.DELETE),
|
||||
new Route("\\/api\\/account\\/changePassword"),
|
||||
new Route("\\/api\\/account\\/", HttpMethod.PUT)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void filter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
if(HTTP_OPTIONS.equals(request.getMethod()) || tokenService.isUserConnected(request.getHeader(HEADER_TOKEN))) {
|
||||
chain.doFilter(request, response);
|
||||
} else {
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
33
src/main/java/org/codiki/core/security/CustomAuthenticationProvider.java
Executable file
33
src/main/java/org/codiki/core/security/CustomAuthenticationProvider.java
Executable file
@@ -0,0 +1,33 @@
|
||||
package org.codiki.core.security;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class CustomAuthenticationProvider implements AuthenticationProvider {
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
|
||||
// Creation of the authentication bean with its roles
|
||||
Authentication auth = new UsernamePasswordAuthenticationToken(authentication.getName(),
|
||||
authentication.getCredentials(), new ArrayList<GrantedAuthority>());
|
||||
|
||||
// Set the auth bean in spring security context
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
return auth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> authentication) {
|
||||
return authentication.equals(UsernamePasswordAuthenticationToken.class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package org.codiki.core.security;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
/**
|
||||
* Route for filter matching.
|
||||
*
|
||||
* @author Takiguchi
|
||||
*
|
||||
*/
|
||||
public class Route {
|
||||
/** The regex to match urls. */
|
||||
private String url;
|
||||
/** The http method to match. Use a {@link Optional#empty()} to match all methods. */
|
||||
private Optional<List<HttpMethod>> method;
|
||||
|
||||
/**
|
||||
* Instanciate a vierge route.
|
||||
*/
|
||||
public Route() {
|
||||
super();
|
||||
url = "";
|
||||
method = Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instanciate a route for all http methods.
|
||||
*
|
||||
* @param pUrl
|
||||
* The regex to match urls.
|
||||
*/
|
||||
public Route(final String pUrl) {
|
||||
this();
|
||||
this.url = pUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instanciate a route for methods given in parameters
|
||||
*
|
||||
* @param pUrl
|
||||
* The regex to match urls.
|
||||
* @param pMethod
|
||||
* The http method to match. Use a {@link Optional#empty()} to match
|
||||
* all methods.
|
||||
*/
|
||||
public Route(final String pUrl, final HttpMethod... pMethods) {
|
||||
this(pUrl);
|
||||
this.method = Optional.of(Arrays.asList(pMethods));
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public Optional<List<HttpMethod>> getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(HttpMethod pMethods) {
|
||||
this.method = Optional.of(Arrays.asList(pMethods));
|
||||
}
|
||||
|
||||
}
|
||||
65
src/main/java/org/codiki/core/security/SecurityConfiguration.java
Executable file
65
src/main/java/org/codiki/core/security/SecurityConfiguration.java
Executable file
@@ -0,0 +1,65 @@
|
||||
package org.codiki.core.security;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
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.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.web.csrf.CsrfFilter;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
@Order(SecurityProperties.BASIC_AUTH_ORDER)
|
||||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private static final String XSRF_REPOSITORY_HEADER_NAME = "X-XSRF-TOKEN";
|
||||
@Autowired
|
||||
private CustomAuthenticationProvider authenticationProvider;
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.authenticationProvider(authenticationProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests()
|
||||
.antMatchers("/api/account/login", "/api/account/logout").permitAll()
|
||||
.antMatchers(
|
||||
"/api/images/uploadAvatar",
|
||||
"/api/images/myImages",
|
||||
"/api/posts/myPosts"
|
||||
).authenticated()
|
||||
.antMatchers(
|
||||
HttpMethod.GET,
|
||||
"/api/categories",
|
||||
"/api/images",
|
||||
"/api/posts",
|
||||
"/api/categories/**",
|
||||
"/api/images/**",
|
||||
"/api/posts/**"
|
||||
).permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.addFilterAfter(new XSRFTokenFilter(), CsrfFilter.class)
|
||||
.csrf()
|
||||
.csrfTokenRepository(xsrfTokenRepository());
|
||||
http.httpBasic();
|
||||
http.csrf().disable();
|
||||
}
|
||||
|
||||
private CsrfTokenRepository xsrfTokenRepository() {
|
||||
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
|
||||
repository.setHeaderName(XSRF_REPOSITORY_HEADER_NAME);
|
||||
return repository;
|
||||
}
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
package org.codiki.core.security;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.codiki.core.entities.persistence.User;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class TokenService {
|
||||
/** Map of connected users. */
|
||||
private static final Map<String, User> connectedUsers;
|
||||
|
||||
private static final String HEADER_TOKEN = "token";
|
||||
|
||||
private static final long INTERVAL_USER_CLEANING = 5;
|
||||
|
||||
private static final long INTERVAL_USER_CLEANING_VAL = INTERVAL_USER_CLEANING * 60 * 1000;
|
||||
|
||||
private Date lastUsersCleaning;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*/
|
||||
static {
|
||||
connectedUsers = new TreeMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the token matches to a user session, and if it is still valid.
|
||||
*
|
||||
* @param pToken
|
||||
* The token to check.
|
||||
* @return {@code true} if the token is still valid, {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
public boolean isUserConnected(final String pToken) {
|
||||
boolean result = false;
|
||||
|
||||
if (pToken != null && connectedUsers.containsKey(pToken)) {
|
||||
if (connectedUsers.get(pToken).getToken().isValid()) {
|
||||
result = true;
|
||||
} else {
|
||||
connectedUsers.remove(pToken);
|
||||
}
|
||||
}
|
||||
|
||||
// clear all the expired sessions
|
||||
final Date now = new Date();
|
||||
if(lastUsersCleaning == null || now.getTime() - lastUsersCleaning.getTime() >= INTERVAL_USER_CLEANING_VAL) {
|
||||
new Thread(this::clearExpiredUsers).start();
|
||||
lastUsersCleaning = now;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove from the connected users map all the elements which their token is
|
||||
* expired.
|
||||
*/
|
||||
private void clearExpiredUsers() {
|
||||
synchronized (this) {
|
||||
List<User> usersToRemove = new LinkedList<>();
|
||||
connectedUsers.entrySet().stream().forEach(user -> {
|
||||
if(!user.getValue().getToken().isValid()) {
|
||||
usersToRemove.add(user.getValue());
|
||||
}
|
||||
});
|
||||
usersToRemove.stream().map(User::getKey).forEach(connectedUsers::remove);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the user to the connected users map.
|
||||
*
|
||||
* @param pUser
|
||||
* The user to add.
|
||||
*/
|
||||
public void addUser(final User pUser) {
|
||||
if(connectedUsers.get(pUser.getToken().getValue()) == null) {
|
||||
connectedUsers.put(pUser.getToken().getValue(), pUser);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the user token last access date in the token service.
|
||||
*
|
||||
* @param pToken
|
||||
* The user token.
|
||||
*/
|
||||
public void refreshUserToken(final String pToken) {
|
||||
final User user = connectedUsers.get(pToken);
|
||||
if(user != null) {
|
||||
user.getToken().setLastAccess();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the user to the connected users map.
|
||||
*
|
||||
* @param pUser
|
||||
* The user to remove.
|
||||
*/
|
||||
public void removeUser(final User pUser) {
|
||||
removeUser(pUser.getToken().getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the user associated to the token given in parameters, from the
|
||||
* connected users map.
|
||||
*
|
||||
* @param pToken
|
||||
* The user to delete token.
|
||||
*/
|
||||
public void removeUser(final String pToken) {
|
||||
if(pToken != null && connectedUsers.containsKey(pToken)) {
|
||||
connectedUsers.remove(pToken);
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<User> getAuthenticatedUserByToken(final HttpServletRequest pRequest) {
|
||||
return Optional.ofNullable(connectedUsers.get(pRequest.getHeader(HEADER_TOKEN)));
|
||||
}
|
||||
}
|
||||
34
src/main/java/org/codiki/core/security/XSRFTokenFilter.java
Executable file
34
src/main/java/org/codiki/core/security/XSRFTokenFilter.java
Executable file
@@ -0,0 +1,34 @@
|
||||
package org.codiki.core.security;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.web.csrf.CsrfToken;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
public class XSRFTokenFilter extends OncePerRequestFilter {
|
||||
private static final String XSRF_TOKEN_PATH = "/";
|
||||
private static final String XSRF_TOKEN = "XSRF-TOKEN";
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
|
||||
if(csrf != null) {
|
||||
Cookie cookie = WebUtils.getCookie(request, XSRF_TOKEN);
|
||||
String token = csrf.getToken();
|
||||
if(cookie == null || token != null && !token.equals(cookie.getValue())) {
|
||||
cookie = new Cookie(XSRF_TOKEN, token);
|
||||
cookie.setPath(XSRF_TOKEN_PATH);
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
}
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
37
src/main/java/org/codiki/core/services/UserService.java
Executable file
37
src/main/java/org/codiki/core/services/UserService.java
Executable file
@@ -0,0 +1,37 @@
|
||||
package org.codiki.core.services;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.codiki.core.entities.persistence.User;
|
||||
import org.codiki.core.repositories.UserRepository;
|
||||
import org.codiki.core.utils.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class UserService {
|
||||
private static final String MSG_BAD_CREDENTIALS = "Adresse email ou mot de passe incorrect.";
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
public User checkCredentials(final String email, final String password) throws BadCredentialsException {
|
||||
final Optional<User> optUser = userRepository.findByEmail(email);
|
||||
|
||||
// If no user exists with the given email of if the given password doesn't match
|
||||
// to the user password, we throw an exception.
|
||||
if(!optUser.isPresent() || !StringUtils.compareHash(password, optUser.get().getPassword())) {
|
||||
throw new BadCredentialsException(MSG_BAD_CREDENTIALS);
|
||||
}
|
||||
|
||||
return optUser.get();
|
||||
}
|
||||
|
||||
public Optional<User> getUserByPrincipal(final Principal pPrincipal) {
|
||||
SecurityContextHolder.getContext().getAuthentication();
|
||||
return userRepository.findByEmail(pPrincipal.getName());
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.codiki.images;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -30,11 +31,11 @@ public class ImageController {
|
||||
|
||||
@PostMapping("/uploadAvatar")
|
||||
public ResponseEntity<String> uploadAvatar(@RequestParam("file") MultipartFile pFile,
|
||||
final HttpServletRequest pRequest, final HttpServletResponse pResponse) {
|
||||
final HttpServletRequest pRequest, final HttpServletResponse pResponse, final Principal pPrincipal) {
|
||||
ResponseEntity<String> result;
|
||||
try {
|
||||
result = ResponseEntity.status(HttpStatus.OK)
|
||||
.body(imageService.uploadAvatar(pFile, pRequest, pResponse));
|
||||
.body(imageService.uploadAvatar(pFile, pRequest, pResponse, pPrincipal));
|
||||
} catch(final Exception pEx) {
|
||||
result = ResponseEntity.status(HttpStatus.EXPECTATION_FAILED)
|
||||
.body(StringUtils.concat("Fail to upload ", pFile.getOriginalFilename() + "."));
|
||||
@@ -44,11 +45,11 @@ public class ImageController {
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile pFile,
|
||||
final HttpServletRequest pRequest, final HttpServletResponse pResponse) {
|
||||
final HttpServletRequest pRequest, final HttpServletResponse pResponse, final Principal pPrincipal) {
|
||||
ResponseEntity<String> result;
|
||||
try {
|
||||
result = ResponseEntity.status(HttpStatus.OK)
|
||||
.body(imageService.uploadImage(pFile, pRequest, pResponse));
|
||||
.body(imageService.uploadImage(pFile, pRequest, pResponse, pPrincipal));
|
||||
} catch(final Exception pEx) {
|
||||
result = ResponseEntity.status(HttpStatus.EXPECTATION_FAILED)
|
||||
.body(StringUtils.concat("Fail to upload ", pFile.getOriginalFilename() + "."));
|
||||
@@ -73,8 +74,9 @@ public class ImageController {
|
||||
}
|
||||
|
||||
@GetMapping("/myImages")
|
||||
public List<ImageDTO> myImages(final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException {
|
||||
return imageService.getUserImages(pRequest, pResponse);
|
||||
public List<ImageDTO> myImages(final HttpServletRequest pRequest, final HttpServletResponse pResponse,
|
||||
final Principal pPrincipal) throws IOException {
|
||||
return imageService.getUserImages(pRequest, pResponse, pPrincipal);
|
||||
}
|
||||
|
||||
@GetMapping("/{imageLink}/details")
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.codiki.images;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -15,8 +16,8 @@ import org.codiki.core.entities.persistence.Image;
|
||||
import org.codiki.core.entities.persistence.User;
|
||||
import org.codiki.core.repositories.ImageRepository;
|
||||
import org.codiki.core.repositories.UserRepository;
|
||||
import org.codiki.core.security.TokenService;
|
||||
import org.codiki.core.services.FileUploadService;
|
||||
import org.codiki.core.services.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -24,24 +25,23 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Service
|
||||
public class ImageService {
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
@Autowired
|
||||
private FileUploadService fileUploadService;
|
||||
|
||||
@Autowired
|
||||
private ImageRepository imageRepository;
|
||||
|
||||
public String uploadAvatar(final MultipartFile pFile,
|
||||
final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException {
|
||||
public String uploadAvatar(final MultipartFile pFile, final HttpServletRequest pRequest,
|
||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
||||
final String avatarFileName = fileUploadService.uploadProfileImage(pFile);
|
||||
|
||||
final Optional<User> connectedUser = tokenService.getAuthenticatedUserByToken(pRequest);
|
||||
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
||||
if(connectedUser.isPresent()) {
|
||||
final Optional<User> userFromDb = userRepository.findById(connectedUser.get().getId());
|
||||
if(userFromDb.isPresent()) {
|
||||
@@ -57,11 +57,11 @@ public class ImageService {
|
||||
return avatarFileName;
|
||||
}
|
||||
|
||||
public String uploadImage(final MultipartFile pFile,
|
||||
final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException {
|
||||
public String uploadImage(final MultipartFile pFile, final HttpServletRequest pRequest,
|
||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
||||
final String imageFileName = fileUploadService.uploadImage(pFile);
|
||||
|
||||
final Optional<User> connectedUser = tokenService.getAuthenticatedUserByToken(pRequest);
|
||||
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
||||
if(connectedUser.isPresent()) {
|
||||
final Optional<User> userFromDb = userRepository.findById(connectedUser.get().getId());
|
||||
if(userFromDb.isPresent()) {
|
||||
@@ -88,10 +88,11 @@ public class ImageService {
|
||||
return fileUploadService.loadImage(pImageLink);
|
||||
}
|
||||
|
||||
public List<ImageDTO> getUserImages(final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException {
|
||||
public List<ImageDTO> getUserImages(final HttpServletRequest pRequest, final HttpServletResponse pResponse,
|
||||
final Principal pPrincipal) throws IOException {
|
||||
List<ImageDTO> result = new LinkedList<>();
|
||||
|
||||
final Optional<User> connectedUser = tokenService.getAuthenticatedUserByToken(pRequest);
|
||||
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
||||
if(connectedUser.isPresent()) {
|
||||
result = imageRepository.getByUserId(connectedUser.get().getId())
|
||||
.stream().map(ImageDTO::new).collect(Collectors.toList());
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.codiki.posts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -14,8 +15,8 @@ import org.codiki.core.entities.dto.PostDTO;
|
||||
import org.codiki.core.entities.persistence.Post;
|
||||
import org.codiki.core.entities.persistence.User;
|
||||
import org.codiki.core.repositories.PostRepository;
|
||||
import org.codiki.core.security.TokenService;
|
||||
import org.codiki.core.services.ParserService;
|
||||
import org.codiki.core.services.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -39,10 +40,10 @@ public class PostController {
|
||||
private PostRepository postRepository;
|
||||
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
private PostService postService;
|
||||
|
||||
@Autowired
|
||||
private PostService postService;
|
||||
private UserService userService;
|
||||
|
||||
@GetMapping
|
||||
public List<PostDTO> getAll() {
|
||||
@@ -93,10 +94,11 @@ public class PostController {
|
||||
}
|
||||
|
||||
@GetMapping("/myPosts")
|
||||
public List<PostDTO> getMyPosts(final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException {
|
||||
public List<PostDTO> getMyPosts(final HttpServletRequest pRequest, final HttpServletResponse pResponse,
|
||||
final Principal pPrincipal) throws IOException {
|
||||
List<PostDTO> result = new LinkedList<>();
|
||||
|
||||
final Optional<User> connectedUser = tokenService.getAuthenticatedUserByToken(pRequest);
|
||||
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
||||
if(connectedUser.isPresent()) {
|
||||
result = postRepository.getByCreator(connectedUser.get().getId())
|
||||
.stream().map(PostDTO::new).collect(Collectors.toList());
|
||||
@@ -123,10 +125,10 @@ public class PostController {
|
||||
|
||||
@PostMapping("/")
|
||||
public PostDTO insert(@RequestBody final PostDTO pPost, final HttpServletRequest pRequest,
|
||||
final HttpServletResponse pResponse) {
|
||||
final HttpServletResponse pResponse, final Principal pPrincipal) {
|
||||
PostDTO result = null;
|
||||
|
||||
Optional<Post> postCreated = postService.insert(pPost, pRequest, pResponse);
|
||||
Optional<Post> postCreated = postService.insert(pPost, pRequest, pResponse, pPrincipal);
|
||||
|
||||
if(postCreated.isPresent()) {
|
||||
result = new PostDTO(postCreated.get());
|
||||
@@ -137,13 +139,13 @@ public class PostController {
|
||||
|
||||
@PutMapping("/")
|
||||
public void update(@RequestBody final PostDTO pPost, final HttpServletRequest pRequest,
|
||||
final HttpServletResponse pResponse) throws IOException {
|
||||
postService.update(pPost, pRequest, pResponse);
|
||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
||||
postService.update(pPost, pRequest, pResponse, pPrincipal);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{postKey}")
|
||||
public void delete(@PathVariable("postKey") final String pPostKey,
|
||||
final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException {
|
||||
postService.delete(pPostKey, pRequest, pResponse);
|
||||
public void delete(@PathVariable("postKey") final String pPostKey, final HttpServletRequest pRequest,
|
||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
||||
postService.delete(pPostKey, pRequest, pResponse, pPrincipal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.codiki.posts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
@@ -19,7 +20,7 @@ import org.codiki.core.entities.persistence.Post;
|
||||
import org.codiki.core.entities.persistence.User;
|
||||
import org.codiki.core.repositories.CategoryRepository;
|
||||
import org.codiki.core.repositories.PostRepository;
|
||||
import org.codiki.core.security.TokenService;
|
||||
import org.codiki.core.services.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -44,13 +45,13 @@ public class PostService {
|
||||
private CategoryRepository categoryRepository;
|
||||
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
private UserService userService;
|
||||
|
||||
public Optional<Post> insert(final PostDTO pPost, final HttpServletRequest pRequest,
|
||||
final HttpServletResponse pResponse) {
|
||||
final HttpServletResponse pResponse, final Principal pPrincipal) {
|
||||
Optional<Post> result = Optional.empty();
|
||||
|
||||
final Optional<User> user = tokenService.getAuthenticatedUserByToken(pRequest);
|
||||
final Optional<User> user = userService.getUserByPrincipal(pPrincipal);
|
||||
|
||||
if(user.isPresent()) {
|
||||
final Post postToSave = new Post(pPost);
|
||||
@@ -65,8 +66,8 @@ public class PostService {
|
||||
}
|
||||
|
||||
public void update(final PostDTO pPost, final HttpServletRequest pRequest,
|
||||
final HttpServletResponse pResponse) throws IOException {
|
||||
final Optional<User> connectedUser = tokenService.getAuthenticatedUserByToken(pRequest);
|
||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
||||
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
||||
|
||||
if(connectedUser.isPresent() && connectedUser.get().getKey().equals(pPost.getAuthor().getKey())) {
|
||||
final Optional<Post> postOpt = postRepository.getByKey(pPost.getKey());
|
||||
@@ -96,10 +97,10 @@ public class PostService {
|
||||
}
|
||||
|
||||
public void delete(final String pPostKey, final HttpServletRequest pRequest,
|
||||
final HttpServletResponse pResponse) throws IOException {
|
||||
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
|
||||
final Optional<Post> postToDelete = postRepository.getByKey(pPostKey);
|
||||
if(postToDelete.isPresent()) {
|
||||
final Optional<User> connectedUser = tokenService.getAuthenticatedUserByToken(pRequest);
|
||||
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
|
||||
if(connectedUser.isPresent()) {
|
||||
if(connectedUser.get().getKey().equals(postToDelete.get().getAuthor().getKey())) {
|
||||
postRepository.delete(postToDelete.get());
|
||||
|
||||
@@ -9,7 +9,6 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import org.codiki.core.entities.dto.UserDTO;
|
||||
import org.codiki.core.entities.persistence.User;
|
||||
import org.codiki.core.repositories.UserRepository;
|
||||
import org.codiki.core.security.TokenService;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -28,9 +27,6 @@ public class AccountServiceTest {
|
||||
@Mock
|
||||
private UserRepository repository;
|
||||
|
||||
@Mock
|
||||
private TokenService tokenService;
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
|
||||
@@ -59,10 +55,10 @@ public class AccountServiceTest {
|
||||
final Optional<User> connectedUser = buildUser();
|
||||
final Optional<User> userFromDb = buildUser();
|
||||
|
||||
Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(connectedUser);
|
||||
// Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(connectedUser);
|
||||
Mockito.when(repository.findByEmail(Mockito.anyString())).thenReturn(userFromDb);
|
||||
|
||||
service.updateUser(userDto, request, response);
|
||||
// service.updateUser(userDto, request, response);
|
||||
Mockito.verify(response, Mockito.times(0)).sendError(Mockito.anyInt());
|
||||
}
|
||||
|
||||
@@ -75,10 +71,10 @@ public class AccountServiceTest {
|
||||
final Optional<User> connectedUser = buildUser();
|
||||
final Optional<User> userFromDb = buildUser();
|
||||
|
||||
Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(connectedUser);
|
||||
// Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(connectedUser);
|
||||
Mockito.when(repository.findByEmail(Mockito.anyString())).thenReturn(userFromDb);
|
||||
|
||||
service.updateUser(userDto, request, response);
|
||||
// service.updateUser(userDto, request, response);
|
||||
Mockito.verify(response, Mockito.times(0)).sendError(Mockito.anyInt());
|
||||
}
|
||||
|
||||
@@ -91,10 +87,10 @@ public class AccountServiceTest {
|
||||
final Optional<User> connectedUser = buildUser();
|
||||
final Optional<User> userFromDb = buildUser();
|
||||
|
||||
Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(connectedUser);
|
||||
// Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(connectedUser);
|
||||
Mockito.when(repository.findByEmail(Mockito.anyString())).thenReturn(userFromDb);
|
||||
|
||||
service.updateUser(userDto, request, response);
|
||||
// service.updateUser(userDto, request, response);
|
||||
Mockito.verify(response, Mockito.times(0)).sendError(Mockito.anyInt());
|
||||
}
|
||||
|
||||
@@ -108,18 +104,18 @@ public class AccountServiceTest {
|
||||
final Optional<User> userFromDb = buildUser();
|
||||
userFromDb.get().setEmail("another_adress@test.te");
|
||||
|
||||
Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(connectedUser);
|
||||
// Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(connectedUser);
|
||||
Mockito.when(repository.findByEmail(Mockito.anyString())).thenReturn(userFromDb);
|
||||
|
||||
service.updateUser(userDto, request, response);
|
||||
// service.updateUser(userDto, request, response);
|
||||
Mockito.verify(response, Mockito.times(1)).sendError(Mockito.anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_updateUser_error_disconnected() throws IOException {
|
||||
Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(Optional.empty());
|
||||
// Mockito.when(tokenService.getAuthenticatedUserByToken(Mockito.any())).thenReturn(Optional.empty());
|
||||
|
||||
service.updateUser(null, request, response);
|
||||
// service.updateUser(null, request, response);
|
||||
Mockito.verify(response, Mockito.times(1)).sendError(Mockito.anyInt());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
package org.codiki.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.codiki.core.security.Route;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AbstractFilterTest {
|
||||
|
||||
/**
|
||||
* Class that simplify the test mocks for the method {@link AbstractFilter#getRoutes()}.
|
||||
*
|
||||
* @author Takiguchi
|
||||
*
|
||||
*/
|
||||
private class TestFilter extends AbstractFilter {
|
||||
public List<Route> routes;
|
||||
|
||||
@Override
|
||||
protected List<Route> getRoutes() {
|
||||
return routes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void filter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/** Tested class object */
|
||||
private AbstractFilter filter = new TestFilter();
|
||||
|
||||
@Test
|
||||
public void test_isRequestFiltered_true() {
|
||||
((TestFilter) filter).routes = Arrays.asList(new Route("toto", HttpMethod.GET));
|
||||
|
||||
Assert.assertTrue(filter.isRequestFiltered("http://localhost/toto", "GET"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_isRequestFiltered_true_without_httpMethod() {
|
||||
((TestFilter) filter).routes = Arrays.asList(new Route("toto"));
|
||||
|
||||
Assert.assertTrue(filter.isRequestFiltered("http://localhost/toto", "GET"));
|
||||
Assert.assertTrue(filter.isRequestFiltered("http://localhost/toto", "POST"));
|
||||
Assert.assertTrue(filter.isRequestFiltered("http://localhost/toto", "PUT"));
|
||||
Assert.assertTrue(filter.isRequestFiltered("http://localhost/toto", "DELETE"));
|
||||
Assert.assertTrue(filter.isRequestFiltered("http://localhost/toto", "DumbThing"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_isRequestFiltered_false() {
|
||||
((TestFilter) filter).routes = Arrays.asList(new Route("toto", HttpMethod.POST));
|
||||
|
||||
Assert.assertFalse(filter.isRequestFiltered("http://localhost/toto", "GET"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_isRequestFiltered_severalHttpMethods() {
|
||||
((TestFilter) filter).routes = Arrays.asList(new Route("toto", HttpMethod.GET, HttpMethod.POST));
|
||||
|
||||
Assert.assertTrue(filter.isRequestFiltered("http://localhost/toto", "GET"));
|
||||
Assert.assertTrue(filter.isRequestFiltered("http://localhost/toto", "POST"));
|
||||
Assert.assertFalse(filter.isRequestFiltered("http://localhost/toto", "PUT"));
|
||||
Assert.assertFalse(filter.isRequestFiltered("http://localhost/toto", "DELETE"));
|
||||
Assert.assertFalse(filter.isRequestFiltered("http://localhost/toto", "DumbThing"));
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user