diff --git a/src/main/java/org/codiki/account/AccountController.java b/src/main/java/org/codiki/account/AccountController.java index 9ec47cb..efa79a6 100755 --- a/src/main/java/org/codiki/account/AccountController.java +++ b/src/main/java/org/codiki/account/AccountController.java @@ -1,7 +1,6 @@ package org.codiki.account; import java.io.IOException; -import java.util.List; import java.util.Optional; import javax.servlet.http.HttpServletRequest; @@ -11,21 +10,13 @@ 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.codiki.core.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.io.Resource; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; 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; @RestController @RequestMapping("/api/account") @@ -91,30 +82,4 @@ public class AccountController { pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); } } - - @PostMapping("/uploadAvatar") - public ResponseEntity uploadAvatar(@RequestParam("file") MultipartFile pFile, - final HttpServletRequest pRequest, final HttpServletResponse pResponse) { - String result; - try { - result = accountService.uploadFile(pFile, pRequest, pResponse); - return ResponseEntity.status(HttpStatus.OK).body(result); - } catch(final Exception pEx) { - result = StringUtils.concat("Fail to upload ", pFile.getOriginalFilename() + "."); - return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(result); - } - } - - @GetMapping("/loadAvatar/{avatarFileName}") - public ResponseEntity loadAvatar(@PathVariable("avatarFileName") final String pAvatarFileName) { - final Resource avatarFile = accountService.loadAvatar(pAvatarFileName); - return ResponseEntity.ok() - .header(HttpHeaders.CONTENT_DISPOSITION, StringUtils.concat("attachment; filename=\"", avatarFile.getFilename(), "\"")) - .body(avatarFile); - } - - @GetMapping("/myImages") - public List myImages() { - return null; - } } diff --git a/src/main/java/org/codiki/account/AccountService.java b/src/main/java/org/codiki/account/AccountService.java index 471d578..163feda 100755 --- a/src/main/java/org/codiki/account/AccountService.java +++ b/src/main/java/org/codiki/account/AccountService.java @@ -4,14 +4,15 @@ import java.io.IOException; 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; +import org.codiki.core.entities.dto.ImageDTO; import org.codiki.core.entities.dto.PasswordWrapperDTO; import org.codiki.core.entities.dto.UserDTO; -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; @@ -107,13 +108,13 @@ public class AccountService { return fileUploadService.loadAvatar(pAvatarFileName); } - public List getUserImages(final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException { - List result = new LinkedList<>(); + public List getUserImages(final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException { + List result = new LinkedList<>(); final Optional connectedUser = tokenService.getAuthenticatedUserByToken(pRequest); if(connectedUser.isPresent()) { - result = imageRepository.getImagesByUserId(connectedUser.get().getId()); - // TODO : Transform Images into ImageDTOs + result = imageRepository.getByUserId(connectedUser.get().getId()) + .stream().map(ImageDTO::new).collect(Collectors.toList()); } else { pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); } diff --git a/src/main/java/org/codiki/core/entities/dto/ImageDTO.java b/src/main/java/org/codiki/core/entities/dto/ImageDTO.java new file mode 100755 index 0000000..2681fa3 --- /dev/null +++ b/src/main/java/org/codiki/core/entities/dto/ImageDTO.java @@ -0,0 +1,37 @@ +package org.codiki.core.entities.dto; + +import java.io.Serializable; + +import org.codiki.core.entities.persistence.Image; + +public class ImageDTO implements Serializable{ + private static final long serialVersionUID = 1L; + + private Long id; + + private String link; + + public ImageDTO() { + super(); + } + + public ImageDTO(final Image pImage) { + this(); + id = pImage.getId(); + link = pImage.getLink(); + } + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + public String getLink() { + return link; + } + public void setLink(String link) { + this.link = link; + } + +} diff --git a/src/main/java/org/codiki/core/repositories/ImageRepository.java b/src/main/java/org/codiki/core/repositories/ImageRepository.java old mode 100644 new mode 100755 index 7f7b7f2..a247536 --- a/src/main/java/org/codiki/core/repositories/ImageRepository.java +++ b/src/main/java/org/codiki/core/repositories/ImageRepository.java @@ -1,6 +1,7 @@ package org.codiki.core.repositories; import java.util.List; +import java.util.Optional; import org.codiki.core.entities.persistence.Image; import org.springframework.data.jpa.repository.Query; @@ -11,5 +12,8 @@ import org.springframework.stereotype.Repository; @Repository public interface ImageRepository extends CrudRepository { @Query(value = "SELECT * FROM image WHERE user_id = :userId", nativeQuery = true) - List getImagesByUserId(@Param("userId") final Long pUserId); + List getByUserId(@Param("userId") final Long pUserId); + + @Query(value = "SELECT * FROM image WHERE link = :link", nativeQuery = true) + Optional findByLink(@Param("link") final String pLink); } diff --git a/src/main/java/org/codiki/core/services/FileUploadService.java b/src/main/java/org/codiki/core/services/FileUploadService.java index 16f8a8f..4c80966 100755 --- a/src/main/java/org/codiki/core/services/FileUploadService.java +++ b/src/main/java/org/codiki/core/services/FileUploadService.java @@ -31,6 +31,10 @@ public class FileUploadService { return uploadFile(pFile, FileEnum.FOLDER_PROFILE_IMAGES); } + public String uploadImage(final MultipartFile pFile) { + return uploadFile(pFile, FileEnum.FOLDER_IMAGE); + } + private String uploadFile(final MultipartFile pFile, final FileEnum pPath) { String result; try { @@ -44,11 +48,19 @@ public class FileUploadService { } public Resource loadAvatar(final String pAvatarFileName) { + return loadImage(pAvatarFileName, FileEnum.FOLDER_PROFILE_IMAGES); + } + + public Resource loadImage(final String pImageLink) { + return loadImage(pImageLink, FileEnum.FOLDER_IMAGE); + } + + private Resource loadImage(final String pImageLink, final FileEnum pFilePath) { try { - Path avatarFile = Paths.get(FileEnum.FOLDER_PROFILE_IMAGES.val()).resolve(pAvatarFileName); - Resource avatarResource = new UrlResource(avatarFile.toUri()); - if(avatarResource.exists() || avatarResource.isReadable()) { - return avatarResource; + Path imageFile = Paths.get(pFilePath.val()).resolve(pImageLink); + Resource imageResource = new UrlResource(imageFile.toUri()); + if(imageResource.exists() || imageResource.isReadable()) { + return imageResource; } else { // TODO : Refactor exception throw new RuntimeException(); diff --git a/src/main/java/org/codiki/images/ImageController.java b/src/main/java/org/codiki/images/ImageController.java new file mode 100755 index 0000000..86b06e4 --- /dev/null +++ b/src/main/java/org/codiki/images/ImageController.java @@ -0,0 +1,84 @@ +package org.codiki.images; + +import java.io.IOException; +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.utils.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +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; + +@RestController +@RequestMapping("/api/images") +public class ImageController { + + @Autowired + private ImageService imageService; + + @PostMapping("/uploadAvatar") + public ResponseEntity uploadAvatar(@RequestParam("file") MultipartFile pFile, + final HttpServletRequest pRequest, final HttpServletResponse pResponse) { + ResponseEntity result; + try { + result = ResponseEntity.status(HttpStatus.OK) + .body(imageService.uploadAvatar(pFile, pRequest, pResponse)); + } catch(final Exception pEx) { + result = ResponseEntity.status(HttpStatus.EXPECTATION_FAILED) + .body(StringUtils.concat("Fail to upload ", pFile.getOriginalFilename() + ".")); + } + return result; + } + + @PostMapping + public ResponseEntity uploadImage(@RequestParam("file") MultipartFile pFile, + final HttpServletRequest pRequest, final HttpServletResponse pResponse) { + ResponseEntity result; + try { + result = ResponseEntity.status(HttpStatus.OK) + .body(imageService.uploadImage(pFile, pRequest, pResponse)); + } catch(final Exception pEx) { + result = ResponseEntity.status(HttpStatus.EXPECTATION_FAILED) + .body(StringUtils.concat("Fail to upload ", pFile.getOriginalFilename() + ".")); + } + return result; + } + + @GetMapping("/loadAvatar/{avatarFileName}") + public ResponseEntity loadAvatar(@PathVariable("avatarFileName") final String pAvatarFileName) { + return buildLoadImageResponse(imageService.loadAvatar(pAvatarFileName)); + } + + @GetMapping("/{imageLink}") + public ResponseEntity loadImage(@PathVariable("imageLink") final String pImageLink) { + return buildLoadImageResponse(imageService.loadImage(pImageLink)); + } + + private ResponseEntity buildLoadImageResponse(final Resource pImageFile) { + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, StringUtils.concat("attachment; filename=\"", pImageFile.getFilename(), "\"")) + .body(pImageFile); + } + + @GetMapping("/myImages") + public List myImages(final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException { + return imageService.getUserImages(pRequest, pResponse); + } + + @GetMapping("/{imageLink}/details") + public ImageDTO getImageDetails(@PathVariable("imageLink") final String pImageLink, final HttpServletResponse pResponse) throws IOException { + return imageService.getImageDetails(pImageLink, pResponse); + } +} diff --git a/src/main/java/org/codiki/images/ImageService.java b/src/main/java/org/codiki/images/ImageService.java new file mode 100755 index 0000000..df04611 --- /dev/null +++ b/src/main/java/org/codiki/images/ImageService.java @@ -0,0 +1,117 @@ +package org.codiki.images; + +import java.io.IOException; +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.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.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +@Service +public class ImageService { + + @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 { + final String avatarFileName = fileUploadService.uploadProfileImage(pFile); + + final Optional connectedUser = tokenService.getAuthenticatedUserByToken(pRequest); + if(connectedUser.isPresent()) { + final Optional userFromDb = userRepository.findById(connectedUser.get().getId()); + if(userFromDb.isPresent()) { + userFromDb.get().setImage(avatarFileName); + userRepository.save(userFromDb.get()); + } else { + pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); + } + } else { + pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); + } + + return avatarFileName; + } + + public String uploadImage(final MultipartFile pFile, + final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException { + final String imageFileName = fileUploadService.uploadImage(pFile); + + final Optional connectedUser = tokenService.getAuthenticatedUserByToken(pRequest); + if(connectedUser.isPresent()) { + final Optional userFromDb = userRepository.findById(connectedUser.get().getId()); + if(userFromDb.isPresent()) { + final Image image = new Image(); + image.setLink(imageFileName); + image.setDate(new Date()); + image.setUser(userFromDb.get()); + imageRepository.save(image); + } else { + pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); + } + } else { + pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); + } + + return imageFileName; + } + + public Resource loadAvatar(final String pAvatarFileName) { + return fileUploadService.loadAvatar(pAvatarFileName); + } + + public Resource loadImage(final String pImageLink) { + return fileUploadService.loadImage(pImageLink); + } + + public List getUserImages(final HttpServletRequest pRequest, final HttpServletResponse pResponse) throws IOException { + List result = new LinkedList<>(); + + final Optional connectedUser = tokenService.getAuthenticatedUserByToken(pRequest); + if(connectedUser.isPresent()) { + result = imageRepository.getByUserId(connectedUser.get().getId()) + .stream().map(ImageDTO::new).collect(Collectors.toList()); + } else { + pResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); + } + + return result; + } + + public ImageDTO getImageDetails(final String pImageLink, final HttpServletResponse pResponse) throws IOException { + ImageDTO result = null; + + final Optional imageFromDb = imageRepository.findByLink(pImageLink); + if(imageFromDb.isPresent()) { + result = new ImageDTO(imageFromDb.get()); + } else { + pResponse.sendError(HttpServletResponse.SC_NOT_FOUND); + } + + return result; + } +}