From 9e93d1fd64162c05d1a2b9219c89d5d5323597ba Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Date: Fri, 18 Aug 2023 03:28:13 -0300 Subject: [PATCH] Implements Micro-service Integration for Storage Handling --- pom.xml | 7 +- .../security/{ => config}/SecurityConfig.java | 2 +- .../base/security/service/AuthService.java | 2 + .../security/service/AuthServiceImpl.java | 6 + .../base/user/api/UserController.java | 51 ++++-- .../config/StorageServiceConfig.java | 13 ++ .../storageService/enums/FileTypeEnum.java | 17 ++ .../model/StorageServiceDownloadResponse.java | 18 ++ .../model/StorageServiceUploadResponse.java | 18 ++ .../service/StorageService.java | 166 ++++++++++++++++++ .../util/guard/UserResourceGuardEnum.java | 6 +- src/main/resources/application.yml | 3 + 12 files changed, 291 insertions(+), 18 deletions(-) rename src/main/java/com/hideyoshi/backendportfolio/base/security/{ => config}/SecurityConfig.java (98%) create mode 100644 src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/config/StorageServiceConfig.java create mode 100644 src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/enums/FileTypeEnum.java create mode 100644 src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/model/StorageServiceDownloadResponse.java create mode 100644 src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/model/StorageServiceUploadResponse.java create mode 100644 src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/service/StorageService.java diff --git a/pom.xml b/pom.xml index af74d5a..36ff7da 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,12 @@ junit test - + + org.apache.httpcomponents + httpclient + 4.5.13 + + diff --git a/src/main/java/com/hideyoshi/backendportfolio/base/security/SecurityConfig.java b/src/main/java/com/hideyoshi/backendportfolio/base/security/config/SecurityConfig.java similarity index 98% rename from src/main/java/com/hideyoshi/backendportfolio/base/security/SecurityConfig.java rename to src/main/java/com/hideyoshi/backendportfolio/base/security/config/SecurityConfig.java index 1e7196e..655d51f 100644 --- a/src/main/java/com/hideyoshi/backendportfolio/base/security/SecurityConfig.java +++ b/src/main/java/com/hideyoshi/backendportfolio/base/security/config/SecurityConfig.java @@ -1,4 +1,4 @@ -package com.hideyoshi.backendportfolio.base.security; +package com.hideyoshi.backendportfolio.base.security.config; import com.hideyoshi.backendportfolio.base.config.RestAuthenticationEntryPointConfig; import com.hideyoshi.backendportfolio.base.security.filter.CustomAuthenticationFilter; diff --git a/src/main/java/com/hideyoshi/backendportfolio/base/security/service/AuthService.java b/src/main/java/com/hideyoshi/backendportfolio/base/security/service/AuthService.java index 5a8561c..7e0afd8 100644 --- a/src/main/java/com/hideyoshi/backendportfolio/base/security/service/AuthService.java +++ b/src/main/java/com/hideyoshi/backendportfolio/base/security/service/AuthService.java @@ -34,4 +34,6 @@ public interface AuthService { void loginOAuthUser(HttpServletRequest request, HttpServletResponse response, OAuth2User user) throws IOException; + UserDTO getLoggedUser(); + } diff --git a/src/main/java/com/hideyoshi/backendportfolio/base/security/service/AuthServiceImpl.java b/src/main/java/com/hideyoshi/backendportfolio/base/security/service/AuthServiceImpl.java index 1d0bcd6..0219981 100644 --- a/src/main/java/com/hideyoshi/backendportfolio/base/security/service/AuthServiceImpl.java +++ b/src/main/java/com/hideyoshi/backendportfolio/base/security/service/AuthServiceImpl.java @@ -21,6 +21,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Service; import org.springframework.web.servlet.HandlerExceptionResolver; @@ -258,4 +259,9 @@ public class AuthServiceImpl implements AuthService { } + public UserDTO getLoggedUser() { + String username = (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + return userService.getUser(username); + } + } diff --git a/src/main/java/com/hideyoshi/backendportfolio/base/user/api/UserController.java b/src/main/java/com/hideyoshi/backendportfolio/base/user/api/UserController.java index ef5f90c..a36b64a 100644 --- a/src/main/java/com/hideyoshi/backendportfolio/base/user/api/UserController.java +++ b/src/main/java/com/hideyoshi/backendportfolio/base/user/api/UserController.java @@ -4,25 +4,24 @@ import com.hideyoshi.backendportfolio.base.security.service.AuthService; import com.hideyoshi.backendportfolio.base.user.model.TokenDTO; import com.hideyoshi.backendportfolio.base.user.model.UserDTO; import com.hideyoshi.backendportfolio.base.user.service.UserService; +import com.hideyoshi.backendportfolio.microservice.storageService.enums.FileTypeEnum; +import com.hideyoshi.backendportfolio.microservice.storageService.model.StorageServiceDownloadResponse; +import com.hideyoshi.backendportfolio.microservice.storageService.model.StorageServiceUploadResponse; +import com.hideyoshi.backendportfolio.microservice.storageService.service.StorageService; import com.hideyoshi.backendportfolio.util.guard.UserResourceGuard; import com.hideyoshi.backendportfolio.util.guard.UserResourceGuardEnum; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; -import java.io.IOException; import java.net.URI; -import java.security.Provider; import java.util.List; @Log4j2 @@ -36,6 +35,8 @@ public class UserController { private final AuthService authService; + private final StorageService storageService; + @GetMapping @UserResourceGuard(accessType = UserResourceGuardEnum.ADMIN_USER) public ResponseEntity> getUsers() { @@ -62,13 +63,6 @@ public class UserController { return ResponseEntity.ok(this.authService.refreshAccessToken(refreshToken.getToken(), request, response)); } - @GetMapping("/login/callback") - @UserResourceGuard(accessType = UserResourceGuardEnum.OPEN) - public void oauthCallback(HttpServletResponse response) throws IOException { - log.info("Teste"); - response.sendRedirect("http://localhost:4200"); - } - @DeleteMapping("/delete/{id}") @UserResourceGuard(accessType = UserResourceGuardEnum.SAME_USER) public ResponseEntity deleteUser(@PathVariable("id") Long id) { @@ -76,4 +70,37 @@ public class UserController { return new ResponseEntity<>(HttpStatus.NO_CONTENT); } + @PostMapping("/profile-picture") + @UserResourceGuard(accessType = UserResourceGuardEnum.USER) + public StorageServiceUploadResponse addProfilePicture() { + UserDTO user = this.authService.getLoggedUser(); + return this.storageService.getNewFileUrl( + user.getUsername(), + "profile", + FileTypeEnum.PNG + ); + } + + @GetMapping("/profile-picture") + @UserResourceGuard(accessType = UserResourceGuardEnum.USER) + public StorageServiceDownloadResponse getProfilePicture() { + UserDTO user = this.authService.getLoggedUser(); + return this.storageService.getFileUrl( + user.getUsername(), + "profile" + ); + } + + @PostMapping("/profile-picture/proccess") + @UserResourceGuard(accessType = UserResourceGuardEnum.USER) + public void processProfilePicture() { + UserDTO user = this.authService.getLoggedUser(); + this.storageService.processFile( + user.getUsername(), + "profile" + ); + } + + + } diff --git a/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/config/StorageServiceConfig.java b/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/config/StorageServiceConfig.java new file mode 100644 index 0000000..4e5a9ca --- /dev/null +++ b/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/config/StorageServiceConfig.java @@ -0,0 +1,13 @@ +package com.hideyoshi.backendportfolio.microservice.storageService.config; + +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + + +@Getter +@Configuration +public class StorageServiceConfig { + @Value("${com.hideyoshi.microservice.storageServicePath}") + private String fileServicePath; +} diff --git a/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/enums/FileTypeEnum.java b/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/enums/FileTypeEnum.java new file mode 100644 index 0000000..31bde63 --- /dev/null +++ b/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/enums/FileTypeEnum.java @@ -0,0 +1,17 @@ +package com.hideyoshi.backendportfolio.microservice.storageService.enums; + +public enum FileTypeEnum { + PNG("png"), + JPEG("jpeg"); + + + private String fileExtension; + + private FileTypeEnum(String fileExtension) { + this.fileExtension = fileExtension; + } + + public String getFileExtension() { + return this.fileExtension; + } +} diff --git a/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/model/StorageServiceDownloadResponse.java b/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/model/StorageServiceDownloadResponse.java new file mode 100644 index 0000000..a5a4f86 --- /dev/null +++ b/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/model/StorageServiceDownloadResponse.java @@ -0,0 +1,18 @@ +package com.hideyoshi.backendportfolio.microservice.storageService.model; + + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.NonNull; + + +@NoArgsConstructor +@AllArgsConstructor +public class StorageServiceDownloadResponse { + + @JsonProperty("presigned_url") + private String presignedUrl; + +} diff --git a/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/model/StorageServiceUploadResponse.java b/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/model/StorageServiceUploadResponse.java new file mode 100644 index 0000000..7a099cf --- /dev/null +++ b/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/model/StorageServiceUploadResponse.java @@ -0,0 +1,18 @@ +package com.hideyoshi.backendportfolio.microservice.storageService.model; + + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NonNull; + +@AllArgsConstructor +public class StorageServiceUploadResponse { + + @JsonProperty("presigned_url") + private String presignedUrl; + + @JsonProperty("file_key") + private String fileKey; + +} diff --git a/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/service/StorageService.java b/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/service/StorageService.java new file mode 100644 index 0000000..075d27e --- /dev/null +++ b/src/main/java/com/hideyoshi/backendportfolio/microservice/storageService/service/StorageService.java @@ -0,0 +1,166 @@ +package com.hideyoshi.backendportfolio.microservice.storageService.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.hideyoshi.backendportfolio.microservice.storageService.config.StorageServiceConfig; +import com.hideyoshi.backendportfolio.microservice.storageService.enums.FileTypeEnum; +import com.hideyoshi.backendportfolio.microservice.storageService.model.StorageServiceDownloadResponse; +import com.hideyoshi.backendportfolio.microservice.storageService.model.StorageServiceUploadResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.log4j.Log4j2; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpHead; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.DefaultRedirectStrategy; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.LaxRedirectStrategy; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +@Log4j2 +@Service +@RequiredArgsConstructor +public class StorageService { + + private final ObjectMapper objectMapper; + + private final StorageServiceConfig storageServiceConfig; + + private final String PARAMETER_USERNAME = "username"; + + private final String PARAMETER_FILE_POSTFIX = "file_postfix"; + + private final String PARAMETER_FILE_TYPE = "file_type"; + + private final String PARAMETER_KEY_STRING = "string_url"; + + public StorageServiceUploadResponse getNewFileUrl(String username, String filePostfix, FileTypeEnum fileTypeEnum) { + HashMap values = new HashMap<>() {{ + put(PARAMETER_USERNAME, username); + put(PARAMETER_FILE_POSTFIX, filePostfix); + put(PARAMETER_FILE_TYPE, fileTypeEnum.getFileExtension()); + }}; + + String requestBody = null; + try { + requestBody = objectMapper + .writeValueAsString(values); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + + HttpPost request = new HttpPost(URI.create(storageServiceConfig.getFileServicePath() + "/new_file_url")); + request.setHeader("Content-Type", "application/json"); + + try { + request.setEntity(new ByteArrayEntity(requestBody.getBytes("UTF-8"))); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + + CloseableHttpClient httpClient = HttpClientBuilder.create() + .setRedirectStrategy(new LaxRedirectStrategy()).build(); + + try { + return httpClient.execute( + request, + response -> { + String responseString = EntityUtils.toString(response.getEntity(), "UTF-8"); + return objectMapper.readValue(responseString, StorageServiceUploadResponse.class); + } + ); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public StorageServiceDownloadResponse getFileUrl(String username, String filePostfix) { + URI uri = null; + try { + uri = new URIBuilder(storageServiceConfig.getFileServicePath() + "/file_url") + .addParameter(PARAMETER_USERNAME, username) + .addParameter(PARAMETER_FILE_POSTFIX, filePostfix) + .build(); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + + HttpGet request = new HttpGet(uri); + request.setHeader("Content-Type", "application/json"); + + CloseableHttpClient httpClient = HttpClientBuilder.create() + .setRedirectStrategy(new LaxRedirectStrategy()).build(); + + try { + return httpClient.execute( + request, + response -> { + String responseString = EntityUtils.toString(response.getEntity(), "UTF-8"); + return objectMapper.readValue(responseString, StorageServiceDownloadResponse.class); + } + ); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void processFile(String username, String filePostfix) { + HashMap values = new HashMap<>() {{ + put(PARAMETER_USERNAME, username); + put(PARAMETER_FILE_POSTFIX, filePostfix); + }}; + + ObjectMapper objectMapper = new ObjectMapper(); + + String requestBody = null; + try { + requestBody = objectMapper + .writeValueAsString(values); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + + HttpPost request = new HttpPost(URI.create(storageServiceConfig.getFileServicePath() + "/process_file")); + request.setHeader("Content-Type", "application/json"); + + try { + request.setEntity(new ByteArrayEntity(requestBody.getBytes("UTF-8"))); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + + CloseableHttpClient httpClient = HttpClientBuilder.create() + .setRedirectStrategy(new LaxRedirectStrategy()).build(); + + try { + httpClient.execute( + request, + response -> { + String responseString = EntityUtils.toString(response.getEntity(), "UTF-8"); + return objectMapper.readValue(responseString, StorageServiceUploadResponse.class); + } + ); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/com/hideyoshi/backendportfolio/util/guard/UserResourceGuardEnum.java b/src/main/java/com/hideyoshi/backendportfolio/util/guard/UserResourceGuardEnum.java index 1cc77e1..ce08014 100644 --- a/src/main/java/com/hideyoshi/backendportfolio/util/guard/UserResourceGuardEnum.java +++ b/src/main/java/com/hideyoshi/backendportfolio/util/guard/UserResourceGuardEnum.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.hideyoshi.backendportfolio.base.user.entity.Role; import com.hideyoshi.backendportfolio.base.user.model.UserDTO; import com.hideyoshi.backendportfolio.base.user.service.UserService; +import lombok.Getter; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.servlet.HandlerMapping; @@ -11,6 +12,7 @@ import org.springframework.web.servlet.HandlerMapping; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; +@Getter public enum UserResourceGuardEnum { USER("user") { @@ -64,10 +66,6 @@ public enum UserResourceGuardEnum { ObjectMapper objectMapper, HttpServletRequest request); - public String getAccessType() { - return this.accessType; - } - public static UserResourceGuardEnum byValue(String accessType) { for (UserResourceGuardEnum o : values()) { if (o.getAccessType().equals(accessType)) { diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index ffe8e02..2df6c08 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -10,6 +10,9 @@ com: username: ${DEFAULT_USER_USERNAME} password: ${DEFAULT_USER_PASSWORD} + microservice: + storageServicePath: ${STORAGE_SERVICE_PATH} + server: servlet: