Refactor some code in Java8 and transform properties file to yaml file.

This commit is contained in:
2019-07-29 22:10:45 +02:00
parent 54e15ffa59
commit 126126b28e
15 changed files with 304 additions and 202 deletions

25
pom.xml
View File

@@ -14,7 +14,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version> <version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository --> <relativePath/> <!-- lookup parent from repository -->
</parent> </parent>
@@ -25,35 +25,40 @@
</properties> </properties>
<dependencies> <dependencies>
<!-- ************* -->
<!-- Spring boot -->
<!-- ************* -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-security</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<!-- Runtime -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId> <artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<!-- Test -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId> <!-- <dependency>-->
</dependency> <!-- <groupId>com.fasterxml.jackson.core</groupId>-->
<!-- https://mvnrepository.com/artifact/org.mindrot/jbcrypt --> <!-- <artifactId>jackson-annotations</artifactId>-->
<!-- </dependency>-->
<dependency> <dependency>
<groupId>org.mindrot</groupId> <groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId> <artifactId>jbcrypt</artifactId>

View File

@@ -7,7 +7,6 @@ import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication @SpringBootApplication
@EnableAutoConfiguration @EnableAutoConfiguration
@ComponentScan(basePackages = "org.codiki")
public class CodikiApplication { public class CodikiApplication {
public static void main(String[] args) { public static void main(String[] args) {

View File

@@ -29,11 +29,21 @@ import com.fasterxml.jackson.annotation.JsonView;
@RestController @RestController
@RequestMapping("/api/account") @RequestMapping("/api/account")
public class AccountController { public class AccountController {
@Autowired /** Account service. */
private AccountService accountService; private AccountService accountService;
@Autowired /** User service. */
private UserService userService; private UserService userService;
/**
* Constructor.
* @param accountService Account service.
* @param userService User service.
*/
public AccountController(AccountService accountService, UserService userService) {
this.accountService = accountService;
this.userService = userService;
}
@JsonView(View.UserDTO.class) @JsonView(View.UserDTO.class)
@PostMapping("/login") @PostMapping("/login")
public User login(@RequestBody final User pUser) throws BadCredentialsException { public User login(@RequestBody final User pUser) throws BadCredentialsException {
@@ -54,8 +64,6 @@ public class AccountController {
* @param pPasswordWrapper * @param pPasswordWrapper
* The object which contains the old password for verification and * The object which contains the old password for verification and
* the new password to set to the user. * the new password to set to the user.
* @param pRequest
* The request injected by Spring.
* @param pResponse * @param pResponse
* The reponse injected by Spring. * The reponse injected by Spring.
* @throws IOException * @throws IOException
@@ -64,15 +72,19 @@ public class AccountController {
*/ */
@PutMapping("/changePassword") @PutMapping("/changePassword")
public void changePassword(@RequestBody final PasswordWrapperDTO pPasswordWrapper, public void changePassword(@RequestBody final PasswordWrapperDTO pPasswordWrapper,
final HttpServletRequest pRequest,
final HttpServletResponse pResponse, final HttpServletResponse pResponse,
final Principal pPrincipal) throws IOException { final Principal pPrincipal) {
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal); int httpResponseCode = userService.getUserByPrincipal(pPrincipal)
if(connectedUser.isPresent()) { .map(user -> {
accountService.changePassword(connectedUser.get(), pPasswordWrapper, pResponse); try {
} else { return accountService.changePassword(user, pPasswordWrapper);
pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); } catch (IllegalArgumentException e) {
} return HttpServletResponse.SC_BAD_REQUEST;
}
})
.orElse(HttpServletResponse.SC_UNAUTHORIZED);
pResponse.setStatus(httpResponseCode);
} }
@PostMapping("/signin") @PostMapping("/signin")

View File

@@ -1,6 +1,7 @@
package org.codiki.account; package org.codiki.account;
import java.io.IOException; import java.io.IOException;
import java.nio.file.NoSuchFileException;
import java.security.Principal; import java.security.Principal;
import java.util.Date; import java.util.Date;
import java.util.LinkedList; import java.util.LinkedList;
@@ -21,6 +22,8 @@ import org.codiki.core.security.CustomAuthenticationProvider;
import org.codiki.core.services.FileUploadService; import org.codiki.core.services.FileUploadService;
import org.codiki.core.services.UserService; import org.codiki.core.services.UserService;
import org.codiki.core.utils.StringUtils; import org.codiki.core.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
@@ -30,22 +33,39 @@ import org.springframework.web.multipart.MultipartFile;
@Service @Service
public class AccountService { public class AccountService {
/** Logger. */
private static final Logger LOG = LoggerFactory.getLogger(FileUploadService.class);
@Autowired
private CustomAuthenticationProvider authenticationProvider; private CustomAuthenticationProvider authenticationProvider;
@Autowired
private UserService userService; private UserService userService;
@Autowired
private UserRepository userRepository; private UserRepository userRepository;
@Autowired
private FileUploadService fileUploadService; private FileUploadService fileUploadService;
@Autowired
private ImageRepository imageRepository; private ImageRepository imageRepository;
/**
* Constructor.
* @param authenticationProvider
* @param userService
* @param userRepository
* @param fileUploadService
* @param imageRepository
*/
public AccountService(CustomAuthenticationProvider authenticationProvider,
UserService userService,
UserRepository userRepository,
FileUploadService fileUploadService,
ImageRepository imageRepository) {
this.authenticationProvider = authenticationProvider;
this.userService = userService;
this.userRepository = userRepository;
this.fileUploadService = fileUploadService;
this.imageRepository = imageRepository;
}
public User authenticate(final User pUser) throws BadCredentialsException { public User authenticate(final User pUser) throws BadCredentialsException {
final User user = userService.checkCredentials(pUser.getEmail(), pUser.getPassword()); final User user = userService.checkCredentials(pUser.getEmail(), pUser.getPassword());
@@ -54,23 +74,23 @@ public class AccountService {
return user; return user;
} }
public void changePassword(final User pUser, final PasswordWrapperDTO pPasswordWrapper, public int changePassword(final User pUser, final PasswordWrapperDTO pPasswordWrapper) throws IllegalArgumentException {
final HttpServletResponse pResponse) throws IOException { int resultCode = HttpServletResponse.SC_NO_CONTENT;
if(pPasswordWrapper.getNewPassword().equals(pPasswordWrapper.getConfirmPassword())) { if(pPasswordWrapper.getNewPassword().equals(pPasswordWrapper.getConfirmPassword())) {
// We fetch the connected user from database to get his hashed password // We fetch the connected user from database to get his hashed password
final Optional<User> userFromDb = userRepository.findById(pUser.getId()); User user = userRepository.findById(pUser.getId())
if(userFromDb.isPresent() && StringUtils.compareHash(pPasswordWrapper.getOldPassword(), .filter(u -> StringUtils.compareHash(pPasswordWrapper.getOldPassword(),
userFromDb.get().getPassword())) { u.getPassword()))
userFromDb.get().setPassword(StringUtils.hashPassword(pPasswordWrapper.getNewPassword())); .orElseThrow(IllegalArgumentException::new);
userRepository.save(userFromDb.get());
} else { user.setPassword(StringUtils.hashPassword(pPasswordWrapper.getNewPassword()));
pResponse.sendError(HttpServletResponse.SC_FORBIDDEN, userRepository.save(user);
"Le mot de passe saisi ne correspond pas au votre.");
}
} else { } else {
pResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, resultCode = HttpServletResponse.SC_BAD_REQUEST;
"Le mot de passe saisi ne correspond pas au votre.");
} }
return resultCode;
} }
public String uploadFile(final MultipartFile pFile, final HttpServletRequest pRequest, public String uploadFile(final MultipartFile pFile, final HttpServletRequest pRequest,
@@ -93,7 +113,7 @@ public class AccountService {
return avatarFileName; return avatarFileName;
} }
public Resource loadAvatar(final String pAvatarFileName) { public Optional<Resource> loadAvatar(final String pAvatarFileName) {
return fileUploadService.loadAvatar(pAvatarFileName); return fileUploadService.loadAvatar(pAvatarFileName);
} }

View File

@@ -12,25 +12,25 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration @Configuration
@EntityScan("org.codiki") @EntityScan("org.codiki.core.entities.persistence")
@EnableTransactionManagement @EnableTransactionManagement
@EnableJpaRepositories("org.codiki") @EnableJpaRepositories("org.codiki.core.repositories")
@PropertySource("classpath:application.properties") @PropertySource("classpath:application.yml")
public class JpaConfiguration { public class JpaConfiguration {
@Value("${spring.datasource.driverClassName}") @Value("${spring.jpa.datasource.driverClassName}")
private String driverClassName; private String driverClassName;
@Value("${spring.datasource.url}") @Value("${spring.jpa.datasource.url}")
private String url; private String url;
@Value("${spring.datasource.username}") @Value("${spring.jpa.datasource.username}")
private String username; private String username;
@Value("${spring.datasource.password}") @Value("${spring.jpa.datasource.password}")
private String password; private String password;
@Bean(name="dataSource") @Bean(name = "dataSource")
public DataSource getDataSource() { public DataSource getDataSource() {
return DataSourceBuilder.create() return DataSourceBuilder.create()
.username(username) .username(username)

View File

@@ -1,7 +1,5 @@
package org.codiki.core.config; package org.codiki.core.config;
import java.io.IOException;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
@@ -9,6 +7,8 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.resource.PathResourceResolver; import org.springframework.web.servlet.resource.PathResourceResolver;
import java.io.IOException;
/** /**
* This configuration class serves Angular app if the url isn't available in sprint REST module. * This configuration class serves Angular app if the url isn't available in sprint REST module.
* *

View File

@@ -22,7 +22,7 @@ import org.springframework.stereotype.Component;
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override @Override
public void commence(HttpServletRequest request, HttpServletResponse response, public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException { AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
} }
} }

View File

@@ -23,13 +23,22 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final String XSRF_REPOSITORY_HEADER_NAME = "X-XSRF-TOKEN"; private static final String XSRF_REPOSITORY_HEADER_NAME = "X-XSRF-TOKEN";
@Autowired
private CustomAuthenticationProvider authenticationProvider; private CustomAuthenticationProvider authenticationProvider;
@Autowired
private RestAuthenticationEntryPoint authenticationEntryPoint; private RestAuthenticationEntryPoint authenticationEntryPoint;
/**
* Constructor.
* @param authenticationProvider
* @param authenticationEntryPoint
*/
public SecurityConfiguration(CustomAuthenticationProvider authenticationProvider,
RestAuthenticationEntryPoint authenticationEntryPoint) {
this.authenticationProvider = authenticationProvider;
this.authenticationEntryPoint = authenticationEntryPoint;
}
@Override @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception { protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(authenticationProvider); auth.authenticationProvider(authenticationProvider);
} }
@@ -44,7 +53,9 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
.antMatchers( .antMatchers(
"/api/images/uploadAvatar", "/api/images/uploadAvatar",
"/api/images/myImages", "/api/images/myImages",
"/api/posts/myPosts" "/api/posts/myPosts",
"/api/account/changePassword",
"/api/account/"
).authenticated() ).authenticated()
.antMatchers( .antMatchers(
HttpMethod.GET, HttpMethod.GET,

View File

@@ -1,11 +1,15 @@
package org.codiki.core.services; package org.codiki.core.services;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Optional;
import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.RandomStringUtils;
import org.codiki.core.utils.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@@ -61,27 +65,41 @@ public class FileUploadService {
} }
} }
public Resource loadAvatar(final String pAvatarFileName) { public Optional<Resource> loadAvatar(final String pAvatarFileName) {
return loadImage(pAvatarFileName, folderProfileImages); Optional<Resource> result = Optional.empty();
}
public Resource loadImage(final String pImageLink) {
return loadImage(pImageLink, folderImages);
}
private Resource loadImage(final String pImageLink, final String pFilePath) {
try { try {
Path imageFile = Paths.get(pFilePath).resolve(pImageLink); result = loadImage(pAvatarFileName, folderImages);
Resource imageResource = new UrlResource(imageFile.toUri()); } catch(final IOException ex) {
if(imageResource.exists() || imageResource.isReadable()) { LOG.error("Unable to load avatar file {}", pAvatarFileName, ex);
return imageResource;
} else {
// TODO : Refactor exception
throw new RuntimeException();
}
} catch(final MalformedURLException pEx) {
// TODO : Refactor exception
throw new RuntimeException();
} }
return result;
}
public Optional<Resource> loadImage(final String pImageLink) {
Optional<Resource> result = Optional.empty();
try {
result = loadImage(pImageLink, folderImages);
} catch(final IOException ex) {
LOG.error("Unable to load image file {}", pImageLink, ex);
}
return result;
}
private Optional<Resource> loadImage(final String pImageLink, final String pFilePath) throws IOException {
Optional<Resource> result = Optional.empty();
Path imageFile = Paths.get(pFilePath).resolve(pImageLink);
Resource imageResource = new UrlResource(imageFile.toUri());
if(imageResource.exists() || imageResource.isReadable()) {
result = Optional.of(imageResource);
} else {
LOG.warn("Unknown file {}", imageFile);
}
return result;
} }
} }

View File

@@ -11,6 +11,8 @@ import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.swing.text.html.Option;
@Service @Service
public class UserService { public class UserService {
private static final String MSG_BAD_CREDENTIALS = "Adresse email ou mot de passe incorrect."; private static final String MSG_BAD_CREDENTIALS = "Adresse email ou mot de passe incorrect.";
@@ -31,7 +33,13 @@ public class UserService {
} }
public Optional<User> getUserByPrincipal(final Principal pPrincipal) { public Optional<User> getUserByPrincipal(final Principal pPrincipal) {
SecurityContextHolder.getContext().getAuthentication(); Optional<User> result = Optional.empty();
return userRepository.findByEmail(pPrincipal.getName());
if(pPrincipal != null) {
SecurityContextHolder.getContext().getAuthentication();
result = userRepository.findByEmail(pPrincipal.getName());
}
return result;
} }
} }

View File

@@ -1,45 +1,48 @@
package org.codiki.images; package org.codiki.images;
import java.io.IOException;
import java.security.Principal;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.codiki.core.entities.dto.ImageDTO; import org.codiki.core.entities.dto.ImageDTO;
import org.codiki.core.utils.StringUtils; import org.codiki.core.utils.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Principal;
import java.util.Collections;
import java.util.List;
import java.util.NoSuchElementException;
@RestController @RestController
@RequestMapping("/api/images") @RequestMapping("/api/images")
public class ImageController { public class ImageController {
private static final Logger LOG = LoggerFactory.getLogger(ImageController.class); private static final Logger LOG = LoggerFactory.getLogger(ImageController.class);
/** Image service. */
@Autowired
private ImageService imageService; private ImageService imageService;
@PostMapping("/uploadAvatar") /**
* Constructor.
* @param imageService Image service.
*/
public ImageController(ImageService imageService) {
this.imageService = imageService;
}
@PostMapping("/uploadAvatar")
public ResponseEntity<String> uploadAvatar(@RequestParam("file") MultipartFile pFile, public ResponseEntity<String> uploadAvatar(@RequestParam("file") MultipartFile pFile,
final HttpServletRequest pRequest, final HttpServletResponse pResponse, final Principal pPrincipal) { final HttpServletRequest pRequest,
final HttpServletResponse pResponse,
final Principal pPrincipal) {
LOG.debug("Upload avatar."); LOG.debug("Upload avatar.");
ResponseEntity<String> result; ResponseEntity<String> result;
try { try {
result = ResponseEntity.status(HttpStatus.OK) result = ResponseEntity.ok(imageService.uploadAvatar(pFile, pResponse, pPrincipal));
.body(imageService.uploadAvatar(pFile, pRequest, pResponse, pPrincipal));
} catch(final Exception pEx) { } catch(final Exception pEx) {
LOG.error("Error during avatar upload.", pEx); LOG.error("Error during avatar upload.", pEx);
result = ResponseEntity.status(HttpStatus.EXPECTATION_FAILED) result = ResponseEntity.status(HttpStatus.EXPECTATION_FAILED)
@@ -50,11 +53,14 @@ public class ImageController {
@PostMapping @PostMapping
public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile pFile, public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile pFile,
final HttpServletRequest pRequest, final HttpServletResponse pResponse, final Principal pPrincipal) { final HttpServletResponse pResponse,
ResponseEntity<String> result; final Principal pPrincipal) throws IOException {
ResponseEntity<String> result = null;
try { try {
result = ResponseEntity.status(HttpStatus.OK) result = ResponseEntity.status(HttpStatus.OK)
.body(imageService.uploadImage(pFile, pRequest, pResponse, pPrincipal)); .body(imageService.uploadImage(pFile, pPrincipal));
} catch(NoSuchElementException pEx) {
pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
} catch(final Exception pEx) { } catch(final Exception pEx) {
result = ResponseEntity.status(HttpStatus.EXPECTATION_FAILED) result = ResponseEntity.status(HttpStatus.EXPECTATION_FAILED)
.body(StringUtils.concat("Fail to upload ", pFile.getOriginalFilename() + ".")); .body(StringUtils.concat("Fail to upload ", pFile.getOriginalFilename() + "."));
@@ -64,12 +70,16 @@ public class ImageController {
@GetMapping("/loadAvatar/{avatarFileName}") @GetMapping("/loadAvatar/{avatarFileName}")
public ResponseEntity<Resource> loadAvatar(@PathVariable("avatarFileName") final String pAvatarFileName) { public ResponseEntity<Resource> loadAvatar(@PathVariable("avatarFileName") final String pAvatarFileName) {
return buildLoadImageResponse(imageService.loadAvatar(pAvatarFileName)); return imageService.loadAvatar(pAvatarFileName)
.map(this::buildLoadImageResponse)
.orElse(ResponseEntity.notFound().build());
} }
@GetMapping("/{imageLink}") @GetMapping("/{imageLink}")
public ResponseEntity<Resource> loadImage(@PathVariable("imageLink") final String pImageLink) { public ResponseEntity<Resource> loadImage(@PathVariable("imageLink") final String pImageLink) {
return buildLoadImageResponse(imageService.loadImage(pImageLink)); return imageService.loadImage(pImageLink)
.map(this::buildLoadImageResponse)
.orElse(ResponseEntity.notFound().build());
} }
private ResponseEntity<Resource> buildLoadImageResponse(final Resource pImageFile) { private ResponseEntity<Resource> buildLoadImageResponse(final Resource pImageFile) {
@@ -79,13 +89,18 @@ public class ImageController {
} }
@GetMapping("/myImages") @GetMapping("/myImages")
public List<ImageDTO> myImages(final HttpServletRequest pRequest, final HttpServletResponse pResponse, public List<ImageDTO> myImages(final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
final Principal pPrincipal) throws IOException { List<ImageDTO> result = Collections.emptyList();
return imageService.getUserImages(pRequest, pResponse, pPrincipal); try {
result = imageService.getUserImages(pPrincipal);
} catch (NoSuchElementException ex) {
pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
return result;
} }
@GetMapping("/{imageLink}/details") @GetMapping("/{imageLink}/details")
public ImageDTO getImageDetails(@PathVariable("imageLink") final String pImageLink, final HttpServletResponse pResponse) throws IOException { public ResponseEntity<ImageDTO> getImageDetails(@PathVariable("imageLink") final String pImageLink) {
return imageService.getImageDetails(pImageLink, pResponse); return ResponseEntity.of(imageService.getImageDetails(pImageLink));
} }
} }

View File

@@ -1,16 +1,5 @@
package org.codiki.images; package org.codiki.images;
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.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.codiki.core.entities.dto.ImageDTO; import org.codiki.core.entities.dto.ImageDTO;
import org.codiki.core.entities.persistence.Image; import org.codiki.core.entities.persistence.Image;
import org.codiki.core.entities.persistence.User; import org.codiki.core.entities.persistence.User;
@@ -18,27 +7,50 @@ import org.codiki.core.repositories.ImageRepository;
import org.codiki.core.repositories.UserRepository; import org.codiki.core.repositories.UserRepository;
import org.codiki.core.services.FileUploadService; import org.codiki.core.services.FileUploadService;
import org.codiki.core.services.UserService; import org.codiki.core.services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Principal;
import java.util.Date;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.stream.Collectors;
@Service @Service
public class ImageService { public class ImageService {
@Autowired /** User service. */
private UserService userService; private UserService userService;
/** User repository. */
@Autowired
private UserRepository userRepository; private UserRepository userRepository;
/** File upload service. */
@Autowired
private FileUploadService fileUploadService; private FileUploadService fileUploadService;
/** Image repository. */
@Autowired
private ImageRepository imageRepository; private ImageRepository imageRepository;
public String uploadAvatar(final MultipartFile pFile, final HttpServletRequest pRequest, /**
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException { * Constructor.
* @param userService User service.
* @param userRepository User repository.
* @param fileUploadService File upload service.
* @param imageRepository Image repository.
*/
public ImageService(UserService userService,
UserRepository userRepository,
FileUploadService fileUploadService,
ImageRepository imageRepository) {
this.userService = userService;
this.userRepository = userRepository;
this.fileUploadService = fileUploadService;
this.imageRepository = imageRepository;
}
public String uploadAvatar(final MultipartFile pFile,
final HttpServletResponse pResponse,
final Principal pPrincipal) throws IOException {
final String avatarFileName = fileUploadService.uploadProfileImage(pFile); final String avatarFileName = fileUploadService.uploadProfileImage(pFile);
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal); final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal);
@@ -57,62 +69,44 @@ public class ImageService {
return avatarFileName; return avatarFileName;
} }
public String uploadImage(final MultipartFile pFile, final HttpServletRequest pRequest, public String uploadImage(final MultipartFile pFile, final Principal pPrincipal) {
final HttpServletResponse pResponse, final Principal pPrincipal) throws IOException {
final String imageFileName = fileUploadService.uploadImage(pFile); final String imageFileName = fileUploadService.uploadImage(pFile);
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal); userService.getUserByPrincipal(pPrincipal)
if(connectedUser.isPresent()) { .map(User::getId)
final Optional<User> userFromDb = userRepository.findById(connectedUser.get().getId()); .map(userRepository::findById)
if(userFromDb.isPresent()) { .orElseThrow(NoSuchElementException::new)
final Image image = new Image(); .ifPresent(user -> {
image.setLink(imageFileName); final Image image = new Image();
image.setDate(new Date()); image.setLink(imageFileName);
image.setUser(userFromDb.get()); image.setDate(new Date());
imageRepository.save(image); image.setUser(user);
} else { imageRepository.save(image);
pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); });
}
} else {
pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
return imageFileName; return imageFileName;
} }
public Resource loadAvatar(final String pAvatarFileName) { public Optional<Resource> loadAvatar(final String pAvatarFileName) {
return fileUploadService.loadAvatar(pAvatarFileName); return fileUploadService.loadAvatar(pAvatarFileName);
} }
public Resource loadImage(final String pImageLink) { public Optional<Resource> loadImage(final String pImageLink) {
return fileUploadService.loadImage(pImageLink); return fileUploadService.loadImage(pImageLink);
} }
public List<ImageDTO> getUserImages(final HttpServletRequest pRequest, final HttpServletResponse pResponse, public List<ImageDTO> getUserImages(final Principal pPrincipal) {
final Principal pPrincipal) throws IOException { return userService.getUserByPrincipal(pPrincipal)
List<ImageDTO> result = new LinkedList<>(); .map(User::getId)
.map(imageRepository::getByUserId)
final Optional<User> connectedUser = userService.getUserByPrincipal(pPrincipal); .orElseThrow(NoSuchElementException::new)
if(connectedUser.isPresent()) { .stream()
result = imageRepository.getByUserId(connectedUser.get().getId()) .map(ImageDTO::new)
.stream().map(ImageDTO::new).collect(Collectors.toList()); .collect(Collectors.toList());
} else {
pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
return result;
} }
public ImageDTO getImageDetails(final String pImageLink, final HttpServletResponse pResponse) throws IOException { public Optional<ImageDTO> getImageDetails(final String pImageLink) {
ImageDTO result = null; return imageRepository.findByLink(pImageLink)
.map(ImageDTO::new);
final Optional<Image> imageFromDb = imageRepository.findByLink(pImageLink);
if(imageFromDb.isPresent()) {
result = new ImageDTO(imageFromDb.get());
} else {
pResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
}
return result;
} }
} }

View File

@@ -1,23 +0,0 @@
#server.error.whitelabel.enabled=false
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/codiki
spring.datasource.username=codiki
spring.datasource.password=P@ssword
# Disable feature detection by this undocumented parameter. Check the org.hibernate.engine.jdbc.internal.JdbcServiceImpl.configure method for more details.
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
# Because detection is disabled you have to set correct dialect by hand.
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect
#logging.level.org.hibernate=DEBUG
spring.servlet.multipart.max-file-size=104857600
codiki.files.upload=/opt/codiki/pictures/tmp
codiki.files.profile-images=/opt/codiki/pictures/profiles
codiki.files.images=/opt/codiki/pictures/posts
logging.level.org.codiki=DEBUG
logging.path=/opt/codiki/logs
logging.file=codiki
cors.enabled=false

View File

@@ -0,0 +1,43 @@
app:
name: Codiki
description: A wiki application.
codiki:
files:
upload: /opt/codiki/pictures/tmp
profile-images: /opt/codiki/pictures/profiles
images: /opt/codiki/pictures/posts
cors.enabled=false:
logging:
file: codiki
level:
org.codiki: DEBUG
# org.hibernate: DEBUG
path: /opt/codiki/logs
server:
# use-forward-headers=true
port: 8080
# ssl:
# key-store: /home/takiguchi/Developpement/Java/codiki/keystore.p12
# key-store-password: aaSrTBqpyRbwLhLi7iVwat2QWHCFQr3e4B9UkBpBPoUxH5UGdJpwenWAKZNTXwgww227CtBYUHogXivRdKpeyHPu2UafsPkGNuKgnDyzZfceFN5r3CxT2eTt
# keyStoreType: PKCS12
# keyAlias: tomcat
# whitelabel:
# enabled: false
spring:
jpa:
datasource:
driverClassName: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/codiki
username: codiki
password: P@ssword
# Because detection is disabled you have to set correct dialect by hand.
database-platform: org.hibernate.dialect.PostgreSQL9Dialect
# Disable feature detection by this undocumented parameter.
# Check the org.hibernate.engine.jdbc.internal.JdbcServiceImpl.configure method for more details.
properties.hibernate.temp.use_jdbc_metadata_defaults: false
servlet.multipart.max-file-size: 104857600

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration> <configuration>
<property resource="application.properties" /> <property resource="application.yml" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target> <target>System.out</target>