From 5e44001d6cc9515713f7eb01fbe3c15ac788dd0f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 26 Nov 2024 07:26:05 +0000 Subject: [PATCH 1/4] Create PR for #425 From 1e477b307d553aff1dde9acbc594cb016389e9cc Mon Sep 17 00:00:00 2001 From: tackyu <tack970913@gmail.com> Date: Wed, 27 Nov 2024 21:15:26 +0900 Subject: [PATCH 2/4] :sparkles: use oracle object storage --- backend/build.gradle | 103 +++++++++--------- .../authentication/service/LoginService.java | 6 +- .../pengcook/image/config/ImageConfig.java | 58 ++++++++++ .../net/pengcook/image/config/S3Config.java | 34 ------ ...S3Controller.java => ImageController.java} | 12 +- .../image/dto/PresignedUrlResponse.java | 4 - .../pengcook/image/dto/UploadUrlResponse.java | 4 + .../image/service/ImageClientService.java | 11 ++ .../service/ObjectStorageClientService.java | 62 +++++++++++ .../image/service/S3ClientService.java | 69 ------------ .../recipe/service/RecipeService.java | 8 +- .../recipe/service/RecipeStepService.java | 6 +- .../pengcook/user/service/UserService.java | 6 +- .../src/main/resources/application-dev.yaml | 19 ++-- .../src/main/resources/application-local.yaml | 19 ++-- .../src/main/resources/application-prod.yaml | 19 ++-- .../src/main/resources/application-test.yaml | 19 ++-- ...llerTest.java => ImageControllerTest.java} | 34 +++--- .../image/service/ImageClientServiceTest.java | 63 +++++++++++ .../image/service/S3ClientServiceTest.java | 64 ----------- .../user/controller/UserControllerTest.java | 6 +- .../user/service/UserServiceTest.java | 6 +- 22 files changed, 333 insertions(+), 299 deletions(-) create mode 100644 backend/src/main/java/net/pengcook/image/config/ImageConfig.java delete mode 100644 backend/src/main/java/net/pengcook/image/config/S3Config.java rename backend/src/main/java/net/pengcook/image/controller/{S3Controller.java => ImageController.java} (56%) delete mode 100644 backend/src/main/java/net/pengcook/image/dto/PresignedUrlResponse.java create mode 100644 backend/src/main/java/net/pengcook/image/dto/UploadUrlResponse.java create mode 100644 backend/src/main/java/net/pengcook/image/service/ImageClientService.java create mode 100644 backend/src/main/java/net/pengcook/image/service/ObjectStorageClientService.java delete mode 100644 backend/src/main/java/net/pengcook/image/service/S3ClientService.java rename backend/src/test/java/net/pengcook/image/controller/{S3ControllerTest.java => ImageControllerTest.java} (57%) create mode 100644 backend/src/test/java/net/pengcook/image/service/ImageClientServiceTest.java delete mode 100644 backend/src/test/java/net/pengcook/image/service/S3ClientServiceTest.java diff --git a/backend/build.gradle b/backend/build.gradle index cfc6ec15..06fc8bf9 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -1,87 +1,88 @@ plugins { - id 'java' - id 'org.springframework.boot' version '3.2.7' - id 'io.spring.dependency-management' version '1.1.5' - id 'jacoco' - id 'com.epages.restdocs-api-spec' version '0.18.2' + id 'java' + id 'org.springframework.boot' version '3.2.7' + id 'io.spring.dependency-management' version '1.1.5' + id 'jacoco' + id 'com.epages.restdocs-api-spec' version '0.18.2' } group = 'net.pengcook' version = '0.0.1-SNAPSHOT' java { - toolchain { - languageVersion = JavaLanguageVersion.of(21) - } + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } } configurations { - compileOnly { - extendsFrom annotationProcessor - } + compileOnly { + extendsFrom annotationProcessor + } } repositories { - mavenCentral() + mavenCentral() } dependencies { - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-actuator' - implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.5' - implementation 'com.google.firebase:firebase-admin:9.3.0' - implementation 'com.auth0:java-jwt:4.4.0' - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0' - implementation 'com.github.loki4j:loki-logback-appender:1.5.1' - implementation 'io.micrometer:micrometer-registry-prometheus' - implementation 'org.zalando:logbook-spring-boot-starter:3.9.0' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-actuator' + implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.5' + implementation 'com.google.firebase:firebase-admin:9.3.0' + implementation 'com.auth0:java-jwt:4.4.0' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0' + implementation 'com.github.loki4j:loki-logback-appender:1.5.1' + implementation 'io.micrometer:micrometer-registry-prometheus' + implementation 'org.zalando:logbook-spring-boot-starter:3.9.0' - runtimeOnly 'mysql:mysql-connector-java:8.0.33' - runtimeOnly 'com.h2database:h2' - compileOnly 'org.projectlombok:lombok' - annotationProcessor 'org.projectlombok:lombok' + runtimeOnly 'mysql:mysql-connector-java:8.0.33' + runtimeOnly 'com.h2database:h2' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'org.springframework.restdocs:spring-restdocs-restassured' - testImplementation 'com.epages:restdocs-api-spec-restassured:0.18.2' - testImplementation 'com.epages:restdocs-api-spec-mockmvc:0.18.2' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.restdocs:spring-restdocs-restassured' + testImplementation 'com.epages:restdocs-api-spec-restassured:0.18.2' + testImplementation 'com.epages:restdocs-api-spec-mockmvc:0.18.2' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - implementation platform('software.amazon.awssdk:bom:2.17.89') - implementation 'software.amazon.awssdk:s3' + implementation platform('com.oracle.oci.sdk:oci-java-sdk-bom:3.54.0') + implementation 'com.oracle.oci.sdk:oci-java-sdk-objectstorage' + implementation 'com.oracle.oci.sdk:oci-java-sdk-common-httpclient-jersey3' } test { - useJUnitPlatform() - systemProperty 'spring.profiles.active', 'test' + useJUnitPlatform() + systemProperty 'spring.profiles.active', 'test' } openapi3 { - servers = [{ url = "https://dev.pengcook.net" }, { url = "http://localhost:8080" }] - title = 'Pengcook API' - description = 'Pengcook API description' - version = '0.1.0' - format = 'yaml' + servers = [{ url = "https://dev.pengcook.net" }, { url = "http://localhost:8080" }] + title = 'Pengcook API' + description = 'Pengcook API description' + version = '0.1.0' + format = 'yaml' } tasks.register("copyOasToSwagger", Copy) { - dependsOn("openapi3") + dependsOn("openapi3") - from layout.buildDirectory.file("api-spec/openapi3.yaml").get() - into "src/main/resources/static" + from layout.buildDirectory.file("api-spec/openapi3.yaml").get() + into "src/main/resources/static" } tasks.named("jar") { - enabled = false + enabled = false } jacocoTestReport { - dependsOn("test") - reports { - xml.required = true - csv.required = false - html.required = false - } + dependsOn("test") + reports { + xml.required = true + csv.required = false + html.required = false + } } diff --git a/backend/src/main/java/net/pengcook/authentication/service/LoginService.java b/backend/src/main/java/net/pengcook/authentication/service/LoginService.java index a6f0b238..fe626e8d 100644 --- a/backend/src/main/java/net/pengcook/authentication/service/LoginService.java +++ b/backend/src/main/java/net/pengcook/authentication/service/LoginService.java @@ -15,7 +15,7 @@ import net.pengcook.authentication.exception.DuplicationException; import net.pengcook.authentication.exception.FirebaseTokenException; import net.pengcook.authentication.exception.NoSuchUserException; -import net.pengcook.image.service.S3ClientService; +import net.pengcook.image.service.ImageClientService; import net.pengcook.user.domain.User; import net.pengcook.user.repository.UserRepository; import org.springframework.stereotype.Service; @@ -28,7 +28,7 @@ public class LoginService { private final FirebaseAuth firebaseAuth; private final UserRepository userRepository; private final JwtTokenManager jwtTokenManager; - private final S3ClientService s3ClientService; + private final ImageClientService imageClientService; @Transactional(readOnly = true) public GoogleLoginResponse loginWithGoogle(GoogleLoginRequest googleLoginRequest) { @@ -90,7 +90,7 @@ private User createUser(GoogleSignUpRequest googleSignUpRequest) { userImage = decodedToken.getPicture(); } if (!userImage.startsWith("http")) { - userImage = s3ClientService.getImageUrl(userImage).url(); + userImage = imageClientService.getImageUrl(userImage).url(); } return new User( diff --git a/backend/src/main/java/net/pengcook/image/config/ImageConfig.java b/backend/src/main/java/net/pengcook/image/config/ImageConfig.java new file mode 100644 index 00000000..aa1f3cc5 --- /dev/null +++ b/backend/src/main/java/net/pengcook/image/config/ImageConfig.java @@ -0,0 +1,58 @@ +package net.pengcook.image.config; + +import com.oracle.bmc.Region; +import com.oracle.bmc.auth.AuthenticationDetailsProvider; +import com.oracle.bmc.auth.SimpleAuthenticationDetailsProvider; +import com.oracle.bmc.objectstorage.ObjectStorage; +import com.oracle.bmc.objectstorage.ObjectStorageClient; +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import net.pengcook.image.service.ImageClientService; +import net.pengcook.image.service.ObjectStorageClientService; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ImageConfig { + + @Value("${oracle.cloud.user-id}") + private String userId; + + @Value("${oracle.cloud.tenancy-id}") + private String tenancyId; + + @Value("${oracle.cloud.fingerprint}") + private String fingerprint; + + @Value("${oracle.cloud.private-key}") + private String privateKey; + + @Value("${oracle.cloud.region}") + private String region; + + @Bean + public ObjectStorage objectStorage() { + AuthenticationDetailsProvider provider = SimpleAuthenticationDetailsProvider.builder() + .userId(userId) + .tenantId(tenancyId) + .fingerprint(fingerprint) + .privateKeySupplier(() -> { + try { + return new ByteArrayInputStream(privateKey.getBytes(StandardCharsets.UTF_8)); + } catch (Exception e) { + throw new RuntimeException("Failed to load private key", e); + } + }) + .region(Region.fromRegionId(region)) + .build(); + + return ObjectStorageClient.builder() + .build(provider); + } + + @Bean + public ImageClientService imageClientService() { + return new ObjectStorageClientService(objectStorage()); + } +} diff --git a/backend/src/main/java/net/pengcook/image/config/S3Config.java b/backend/src/main/java/net/pengcook/image/config/S3Config.java deleted file mode 100644 index 7317321b..00000000 --- a/backend/src/main/java/net/pengcook/image/config/S3Config.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.pengcook.image.config; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.presigner.S3Presigner; - -@Configuration -public class S3Config { - - @Value("${cloud.aws.region.static}") - private String regionValue; - - @Bean - public S3Presigner s3Presigner() { - Region region = Region.of(regionValue); - - return S3Presigner.builder() - .region(region) - .credentialsProvider(DefaultCredentialsProvider.create()) - .build(); - } - - @Bean - public S3Client s3Client() { - return S3Client.builder() - .region(Region.of(regionValue)) - .credentialsProvider(DefaultCredentialsProvider.create()) - .build(); - } -} diff --git a/backend/src/main/java/net/pengcook/image/controller/S3Controller.java b/backend/src/main/java/net/pengcook/image/controller/ImageController.java similarity index 56% rename from backend/src/main/java/net/pengcook/image/controller/S3Controller.java rename to backend/src/main/java/net/pengcook/image/controller/ImageController.java index 1a25da4c..f4ca47e7 100644 --- a/backend/src/main/java/net/pengcook/image/controller/S3Controller.java +++ b/backend/src/main/java/net/pengcook/image/controller/ImageController.java @@ -1,8 +1,8 @@ package net.pengcook.image.controller; import lombok.RequiredArgsConstructor; -import net.pengcook.image.dto.PresignedUrlResponse; -import net.pengcook.image.service.S3ClientService; +import net.pengcook.image.dto.UploadUrlResponse; +import net.pengcook.image.service.ImageClientService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -11,12 +11,12 @@ @RestController @RequestMapping("/image") @RequiredArgsConstructor -public class S3Controller { +public class ImageController { - private final S3ClientService s3ClientService; + private final ImageClientService imageClientService; @GetMapping - public PresignedUrlResponse getPresignedURL(@RequestParam String fileName) { - return s3ClientService.generatePresignedPutUrl(fileName); + public UploadUrlResponse getUploadURL(@RequestParam String fileName) { + return imageClientService.generateUploadUrl(fileName); } } diff --git a/backend/src/main/java/net/pengcook/image/dto/PresignedUrlResponse.java b/backend/src/main/java/net/pengcook/image/dto/PresignedUrlResponse.java deleted file mode 100644 index 9dd4cebf..00000000 --- a/backend/src/main/java/net/pengcook/image/dto/PresignedUrlResponse.java +++ /dev/null @@ -1,4 +0,0 @@ -package net.pengcook.image.dto; - -public record PresignedUrlResponse(String url) { -} diff --git a/backend/src/main/java/net/pengcook/image/dto/UploadUrlResponse.java b/backend/src/main/java/net/pengcook/image/dto/UploadUrlResponse.java new file mode 100644 index 00000000..ab47d5bd --- /dev/null +++ b/backend/src/main/java/net/pengcook/image/dto/UploadUrlResponse.java @@ -0,0 +1,4 @@ +package net.pengcook.image.dto; + +public record UploadUrlResponse(String url) { +} diff --git a/backend/src/main/java/net/pengcook/image/service/ImageClientService.java b/backend/src/main/java/net/pengcook/image/service/ImageClientService.java new file mode 100644 index 00000000..09150a12 --- /dev/null +++ b/backend/src/main/java/net/pengcook/image/service/ImageClientService.java @@ -0,0 +1,11 @@ +package net.pengcook.image.service; + +import net.pengcook.image.dto.ImageUrlResponse; +import net.pengcook.image.dto.UploadUrlResponse; + +public interface ImageClientService { + + UploadUrlResponse generateUploadUrl(String fileName); + + ImageUrlResponse getImageUrl(String fileName); +} diff --git a/backend/src/main/java/net/pengcook/image/service/ObjectStorageClientService.java b/backend/src/main/java/net/pengcook/image/service/ObjectStorageClientService.java new file mode 100644 index 00000000..8421c93b --- /dev/null +++ b/backend/src/main/java/net/pengcook/image/service/ObjectStorageClientService.java @@ -0,0 +1,62 @@ +package net.pengcook.image.service; + +import com.oracle.bmc.objectstorage.ObjectStorage; +import com.oracle.bmc.objectstorage.model.CreatePreauthenticatedRequestDetails; +import com.oracle.bmc.objectstorage.model.CreatePreauthenticatedRequestDetails.AccessType; +import com.oracle.bmc.objectstorage.requests.CreatePreauthenticatedRequestRequest; +import java.time.Instant; +import java.util.Date; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.pengcook.image.dto.ImageUrlResponse; +import net.pengcook.image.dto.UploadUrlResponse; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +@Slf4j +public class ObjectStorageClientService implements ImageClientService { + + private final ObjectStorage client; + + @Value("${oracle.cloud.bucket-name}") + private String bucketName; + + @Value("${oracle.cloud.namespace}") + private String namespace; + + @Value("${oracle.cloud.url-prefix}") + private String urlPrefix; + + private static final int DURATION_SECONDS = 600; + + public UploadUrlResponse generateUploadUrl(String fileName) { + CreatePreauthenticatedRequestDetails details = CreatePreauthenticatedRequestDetails.builder() + .accessType(AccessType.ObjectWrite) + .name("upload-" + fileName) + .timeExpires(Date.from(Instant.now().plusSeconds(DURATION_SECONDS))) + .objectName(fileName) + .build(); + + CreatePreauthenticatedRequestRequest request = CreatePreauthenticatedRequestRequest.builder() + .namespaceName(namespace) + .bucketName(bucketName) + .createPreauthenticatedRequestDetails(details) + .build(); + + String uploadUri = client.createPreauthenticatedRequest(request) + .getPreauthenticatedRequest() + .getAccessUri(); + + return new UploadUrlResponse(urlPrefix + uploadUri); + } + + public ImageUrlResponse getImageUrl(String fileName) { + return new ImageUrlResponse(String.format("%s/n/%s/b/%s/o/%s", + client.getEndpoint(), + namespace, + bucketName, + fileName)); + } +} diff --git a/backend/src/main/java/net/pengcook/image/service/S3ClientService.java b/backend/src/main/java/net/pengcook/image/service/S3ClientService.java deleted file mode 100644 index b28d86b3..00000000 --- a/backend/src/main/java/net/pengcook/image/service/S3ClientService.java +++ /dev/null @@ -1,69 +0,0 @@ -package net.pengcook.image.service; - -import java.time.Duration; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import net.pengcook.image.dto.ImageUrlResponse; -import net.pengcook.image.dto.PresignedUrlResponse; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.GetUrlRequest; -import software.amazon.awssdk.services.s3.model.PutObjectRequest; -import software.amazon.awssdk.services.s3.presigner.S3Presigner; -import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest; - -@Service -@RequiredArgsConstructor -@Slf4j -public class S3ClientService { - - private static final int DURATION_MINUTES = 10; - - private final S3Presigner s3Presigner; - - private final S3Client s3Client; - - @Value("${cloud.aws.S3.bucket}") - private String bucketName; - - @Value("${cloud.aws.S3.path}") - private String imagePath; - - @Value("${cloud.aws.S3.s3-url}") - private String s3Url; - - @Value("${cloud.aws.S3.cloudfront-cname}") - private String cloudFrontCname; - - public PresignedUrlResponse generatePresignedPutUrl(String fileName) { - - PutObjectRequest putObjectRequest = PutObjectRequest.builder() - .bucket(bucketName) - .key(imagePath + fileName) - .build(); - - PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder() - .signatureDuration(Duration.ofMinutes(DURATION_MINUTES)) - .putObjectRequest(putObjectRequest) - .build(); - - String url = s3Presigner.presignPutObject(presignRequest).url().toString(); - - return new PresignedUrlResponse(url); - } - - public ImageUrlResponse getImageUrl(String fileName) { - GetUrlRequest request = GetUrlRequest.builder() - .bucket(bucketName) - .key(imagePath + fileName) - .build(); - - String savedUrl = s3Client.utilities() - .getUrl(request) - .toString() - .replace(s3Url, cloudFrontCname); - - return new ImageUrlResponse(savedUrl); - } -} diff --git a/backend/src/main/java/net/pengcook/recipe/service/RecipeService.java b/backend/src/main/java/net/pengcook/recipe/service/RecipeService.java index 59151437..08b65ac0 100644 --- a/backend/src/main/java/net/pengcook/recipe/service/RecipeService.java +++ b/backend/src/main/java/net/pengcook/recipe/service/RecipeService.java @@ -10,7 +10,7 @@ import net.pengcook.authentication.domain.UserInfo; import net.pengcook.category.service.CategoryService; import net.pengcook.comment.service.CommentService; -import net.pengcook.image.service.S3ClientService; +import net.pengcook.image.service.ImageClientService; import net.pengcook.ingredient.service.IngredientRecipeService; import net.pengcook.ingredient.service.IngredientService; import net.pengcook.like.repository.RecipeLikeRepository; @@ -51,7 +51,7 @@ public class RecipeService { private final CategoryService categoryService; private final IngredientService ingredientService; - private final S3ClientService s3ClientService; + private final ImageClientService imageClientService; private final RecipeStepService recipeStepService; private final IngredientRecipeService ingredientRecipeService; private final CommentService commentService; @@ -151,7 +151,7 @@ public List<RecipeHomeWithMineResponseV1> readLikeRecipesV1(UserInfo userInfo) { @Transactional public RecipeResponse createRecipe(UserInfo userInfo, RecipeRequest recipeRequest) { User author = userRepository.findById(userInfo.getId()).orElseThrow(); - String thumbnailUrl = s3ClientService.getImageUrl(recipeRequest.thumbnail()).url(); + String thumbnailUrl = imageClientService.getImageUrl(recipeRequest.thumbnail()).url(); Recipe recipe = new Recipe( recipeRequest.title(), author, @@ -177,7 +177,7 @@ public void updateRecipe(UserInfo userInfo, Long recipeId, RecipeUpdateRequest r Recipe updatedRecipe = recipe.updateRecipe( recipeUpdateRequest.title(), LocalTime.parse(recipeUpdateRequest.cookingTime()), - s3ClientService.getImageUrl(recipeUpdateRequest.thumbnail()).url(), + imageClientService.getImageUrl(recipeUpdateRequest.thumbnail()).url(), recipeUpdateRequest.difficulty(), recipeUpdateRequest.description() ); diff --git a/backend/src/main/java/net/pengcook/recipe/service/RecipeStepService.java b/backend/src/main/java/net/pengcook/recipe/service/RecipeStepService.java index 6eb51a71..0e838bd9 100644 --- a/backend/src/main/java/net/pengcook/recipe/service/RecipeStepService.java +++ b/backend/src/main/java/net/pengcook/recipe/service/RecipeStepService.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.Optional; import lombok.RequiredArgsConstructor; -import net.pengcook.image.service.S3ClientService; +import net.pengcook.image.service.ImageClientService; import net.pengcook.recipe.domain.Recipe; import net.pengcook.recipe.domain.RecipeStep; import net.pengcook.recipe.dto.RecipeStepRequest; @@ -23,7 +23,7 @@ public class RecipeStepService { private final RecipeStepRepository recipeStepRepository; private final RecipeRepository recipeRepository; - private final S3ClientService s3ClientService; + private final ImageClientService imageClientService; @Transactional(readOnly = true) public List<RecipeStepResponse> readRecipeSteps(long recipeId) { @@ -71,7 +71,7 @@ private String getValidatedImageUrl(String image) { if (image.isBlank()) { throw new InvalidParameterException("적절하지 않은 이미지 이름입니다."); } - return s3ClientService.getImageUrl(image).url(); + return imageClientService.getImageUrl(image).url(); } private LocalTime getValidatedCookingTime(String cookingTime) { diff --git a/backend/src/main/java/net/pengcook/user/service/UserService.java b/backend/src/main/java/net/pengcook/user/service/UserService.java index 9a063b03..c61a0c3d 100644 --- a/backend/src/main/java/net/pengcook/user/service/UserService.java +++ b/backend/src/main/java/net/pengcook/user/service/UserService.java @@ -5,7 +5,7 @@ import lombok.AllArgsConstructor; import net.pengcook.authentication.domain.UserInfo; import net.pengcook.comment.repository.CommentRepository; -import net.pengcook.image.service.S3ClientService; +import net.pengcook.image.service.ImageClientService; import net.pengcook.like.repository.RecipeLikeRepository; import net.pengcook.recipe.repository.RecipeRepository; import net.pengcook.recipe.service.RecipeService; @@ -41,7 +41,7 @@ public class UserService { private final RecipeLikeRepository recipeLikeRepository; private final UserBlockRepository userBlockRepository; private final UserReportRepository userReportRepository; - private final S3ClientService s3ClientService; + private final ImageClientService imageClientService; @Transactional(readOnly = true) public ProfileResponse getUserById(long userId) { @@ -64,7 +64,7 @@ public UpdateProfileResponse updateProfile(long userId, UpdateProfileRequest upd String userImage = updateProfileRequest.image(); if (!userImage.startsWith("http")) { - userImage = s3ClientService.getImageUrl(userImage).url(); + userImage = imageClientService.getImageUrl(userImage).url(); } user.update( diff --git a/backend/src/main/resources/application-dev.yaml b/backend/src/main/resources/application-dev.yaml index e9bcd389..1cafbf2f 100644 --- a/backend/src/main/resources/application-dev.yaml +++ b/backend/src/main/resources/application-dev.yaml @@ -17,15 +17,16 @@ firebase: service-account: ENC(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) project-name: ENC(xdfH+UHlUvqfsfYLJqN1ZiBPPLh/xZflhx6sWYuZVy59c6MjjwryKy+6yRkNRoNr) -cloud: - aws: - S3: - bucket: ENC(vHtLR4hquZmrp7cqlrr6vXrazA0rLJApEalSU6QPYX4O1GHrbQd9dquGAWtCy1vZcOVfFUZ5aDqqSMSrycfhlw==) - path: ENC(enM1r+Mv5m9E/UFDfKiPN5mdu/JJ3BOvWgSW05+vDE4SaI4iHlnEN4vqZVa3pGxL) - s3-url: ENC(vXFQrV7EqIN++so+O8z8ZrhzS9tqn0n2cxy1HeNfSYBqV6zNZm3BwKeRt+OlctQVHbBMUfXdCYdEcoxsgKtJnu8veV21IEe04+yEfQSe/u/44Gij3ekxVKRx6FZT+A4c) - cloudfront-cname: ENC(74un+Yr6O9u4VwCyLGWBTLMU862azaovIEJP8+3ouJ2jxk+zTNDD6OFQLjzeBqK/vINfMT8DDt5AbOb18wAiAg==) - region: - static: ENC(a7sCLLXDx5Fn76E+NLdyxLoL3MEp6x1J/OcoFyg0ejxLrGAQ/O+82ZoDr6LXcRAt) +oracle: + cloud: + user-id: ENC(VzKc+Bt84Cc2E7n1A3BlJoDTj55NdKVueyDPACY249KlAcIz/t/aMwx/O8DxVUaxOQtj/kcMN0xj/aQyg66Tu9kIsh77pPdy82Wc4N7L2060rYwMSMknFO9NbOEfoP9CUFC13CUxzrKSFU2Fc8Usqg==) + tenancy-id: ENC(nYeYRuOFsHhqvbP72iaN5RdNAHbIg8rFAEy5fD1iGdN0j3iIVtpDYFamQ6alT4DUHfha7JuilXP0t+ELNpJhAB4q/YNh30oWAVITAOCDhepl6bnd71NIOrkf8HvdNwMNd254J1dcwAzXpnMgGO/Q5w==) + fingerprint: ENC(MT5LUKbu/lX+MW9UbokNJrNccgptDRnTOdyWfFnvTVhEK9U4oJdrO/kGK8gHikxkPOFN0ImeXJKcgB/7k9DVezBkYfFWHt6EciUA49Wwpuk=) + private-key: ENC(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) + region: ENC(ccHajBInFHARtYI4jVvpl7qlldf22upRjUg7T2hxavDg6ADypFmVAHYd/hPhRGLV) + bucket-name: ENC(7AyUEbDIf9u78oT0rRRw1i6tMB2GgeA2TbqdrXNibewynpOLyY7JT3SIE9zqgiHG) + namespace: ENC(6Il9NSYH1SYAcKaLxi6VlFs9XvqwkSB9VhMnKGoko3ul4hQcGoS5gZcxEa0sNWP5) + url-prefix: ENC(KH5PC5/BySZUQQhEG+OZv7tyC+ia5F7nP/Y4jsch9I1xMAbdKNZn8396+BSRkP3CvyWLZZ6eI/WMgbynISAn6jYZ5GfP4bV9bKO2Vp97sZ/zJz0BNKOG8XHZSozoPqgI) logging: level: diff --git a/backend/src/main/resources/application-local.yaml b/backend/src/main/resources/application-local.yaml index 6af7853b..fb01375b 100644 --- a/backend/src/main/resources/application-local.yaml +++ b/backend/src/main/resources/application-local.yaml @@ -20,15 +20,16 @@ firebase: service-account: ENC(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) project-name: ENC(OOSGdLyJrH+9WtM2tVpC/LviYbnQQegK9313jNRbKOS5XB6FmHPZCLCyFoBMxECi) -cloud: - aws: - S3: - bucket: ENC(EFtkn1OzzzzNZYiN9Qi31sBaGOk426fl93NKNepOmljtIXILd7X4HF3RErsJifK2uySAv1AbbIeavYgClMaMfw==) - path: ENC(aPfB8+KIk5WMfXFhMkxxGTfo9+lyjq+ir4i05EBFIe8MOAOubWQkA0OScFN+4hut) - s3-url: ENC(ZiMq9hhiEZJrDcyFUkH5OSphgAZYcVnoaq+07UYSrEXtn0q/67e5XqrK1ED9LgmD0Grq05KjEtIfJ3LikMBYXXYthbxlkL/zH3PRgbkOmIKL8XEns8aXNsKZ5Opnn1qA) - cloudfront-cname: ENC(3hfGWnS8F+CY67V0fc9kjS9inVeoFpNbnrjVE0xivh+P+BgBrbZOi19ZwdIRBL9tNO5L8+y9gJHSH1TKtaV+lA==) - region: - static: ENC(+TXuroM2fUTZ5CpylDnJfO672+ZFCdA+AVKRDLKoCWKJm+0gQ8/GH+QtS7jLG2v9) +oracle: + cloud: + user-id: ENC(WJ6PcyoyWPbwR0b7ieuAE4/3+tIxfvaFXAa9GBdoXd7X8GzfdgIRufd1ohOuFqhJYqXuX91JcXebIW1NUj6mH9b4H71OyH/GsJ3mU3S2MHUY/QELxRsnPW5m83w+OKv0KLkDHZOZ1huPBgAeUxSibw==) + tenancy-id: ENC(oVq4+9+25UdisjTk4lrxmU2qkc+O0CnSl0hsy0uGKLQnU6Lc6qkrc183XwKkHooRuv96b3ev9EbYGjuSh3gCbnXRnC8r8aGpJy5nQWGK+n+PfYYkYGJFE1QCbepYWcmA1sktMTbyqL968jSDN6eAYA==) + fingerprint: ENC(DizUyqlGqn7iPUCOPwgQ0ir89Ar7/u6+/wquX0wpLouJZBrvlUcEP9ZFB5o+oRb++Gyaw0mC0vwhznw3r7POQue/oA0U3PnN/8XprcLt4vs=) + private-key: ENC(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) + region: ENC(CFsFxZiEddGhD37YV84vVlnd6OXipizN7WvdC0ALaqJEIZRYCvHWYJl4kV0Tig2/) + bucket-name: ENC(UOUpk4WqCJ2uCJC9TLuimSbIleeXUjq10oHOf9R/4ogHfU3pMqywNYA6dHFcqyGz) + namespace: ENC(qOxV5BZjZLS9Ems+CFZNMFeKYselnH70DLLAfwgZzpTIXd4bHxWevLALm6CHli6h) + url-prefix: ENC(2GeAcJRUdCxHYOKBlKjbBJqZBlw6PNIB4pYOa6X82dFa+n1H+uu4QvIFxtbbS/yLoafQ+1It4S3BvUBttFdsBuRCyAEIayN27YBi2fpQZqoX4YrBOQY3r1RRMb/ybHlv) server: tomcat: diff --git a/backend/src/main/resources/application-prod.yaml b/backend/src/main/resources/application-prod.yaml index f879c5a5..2718a1da 100644 --- a/backend/src/main/resources/application-prod.yaml +++ b/backend/src/main/resources/application-prod.yaml @@ -22,15 +22,16 @@ firebase: service-account: ENC(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) project-name: ENC(Bx4psOQ3Jx2o13s96GCxyiQxzpFFFZwacbt6blpeja8ff/Vzru0jQTIs4EcZNEd+) -cloud: - aws: - S3: - bucket: ENC(rKxRm4yCCuPIbYo59E7ImxNwsSHbrIubVtNyEe6EPbPFM+Bu16dnqPorXLPD18S57aSsrajMY8tYc3XKw7Gwug==) - path: ENC(ZMKZRrEXXpiAXq6C/RkvuRX29u8h58J7ZAuA/Xb+NkQ+Ae/Ix1NpErVRcYaYv0cz) - s3-url: ENC(O/OI16EMUuXwRIbCifs4WXz4fZFTskquGw4Xg5iKa6/pxz0GbmSrnlqYceinry1y15TEU78j8pmwfJYBZXZlpTTnp1bMpmIqe5fsVjfpX2bZljGTwElJLYY6XEvhnaJe) - cloudfront-cname: ENC(eG3jV3fA2iMks/OfVdEoOC1yuP00D/sTquppxx27pJl6YdMcNfFcX1PUwingvuNsNzoUdGO3Oie+upv/OFGcCA==) - region: - static: ENC(QHjkS/cQk6BtfKT6UkdHZrnxZKGCvSsc15GvFz/KKBf25F5XBWhLAjEtHjk+up3V) +oracle: + cloud: + user-id: ENC(6MS5UEI0ACEgff1793D87WGwSb5TEM6V09oZoqiSSCz+Dh4taIfDuRyB6y2zAgc/+051nStvXzLXyaEiphMqyFoTRfBfsHA5Adn0TDJD5dVcxclBmuEGGR5E/HkJaWqDXWGFyu/hCUJJYaJGmrdW3w==) + tenancy-id: ENC(Vv/YsKwbiaH1+UZy1gshyIYh6R1NSOh+X0GXTO/BRIySdDYc70ag9uZkqyFjbEVVgUzQCgH2vW955dXXZZ5TYy07DeLFWBH9VB4QWaUWmLAIh1iLmq/FJUCp7KOY54pCGN59ZVoq4zvyJzn4NeBXXQ==) + fingerprint: ENC(5lmXFoSvqHYT41H7GZR0R9Qy46kZjvasTIQTOgSoIfd/Lm2CX9EZp9upfHMlZ4F1LZOltywdZNfE9tNDUYF5Gh2+6caRRkoMKoCvNo2ic9I=) + private-key: ENC(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) + region: ENC(JyyYnpuxK8I9NQQH0ufFtYsmnwWWou5z3k/i2N0Ly8y3jLc7QSvJJOD7KZbg5tnD) + bucket-name: ENC(FlPAx/iHK75QmJTdlOguLyEvPoi1d+ZxF1pNQBo5UZk4oxSD2xPGjmgC/LHBKvWe) + namespace: ENC(8zdD/nolmplXP9Lz7TVBWxOuJyKA07GEauQZ1Jkn4Jiddc2LA9tDVMQfCc2f5tKZ) + url-prefix: ENC(e0dxHgl3UDKMLyjgxDkN1sOi+UcPbqs0WpLvlmUxt/O9/nA9W2jlzROQv8A3tgpi2CGKnFiksz9N7xMVo1xJZ0kbqGerY7fzI5XQI4BLCqFwcaSGYq1T/p5xCVNuhXel) springdoc: swagger-ui: diff --git a/backend/src/main/resources/application-test.yaml b/backend/src/main/resources/application-test.yaml index 49a454a9..8437af9e 100644 --- a/backend/src/main/resources/application-test.yaml +++ b/backend/src/main/resources/application-test.yaml @@ -21,12 +21,13 @@ firebase: service-account: ENC(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) project-name: ENC(xO8NtLkIqyzQq4KSSsb4EymTKGrYB9TmQqD7dc15tsTs2/NMy3RY3kJ8JiHIvG2i) -cloud: - aws: - S3: - bucket: ENC(cPm11Vv1sXSp4ss+V1ZbfnlQdNHECuMmJpuyGKajSS54R4x4jgyGtJV/D47vPfTBv0ncj/lCFVEZ58EnG88LEQ==) - path: ENC(d5dnR+n9VrdxNBpqNVnrTIbi7KKP5LOVtoLL1gKxg1vUEgxTHSdY+KGfH4WFmYY2) - s3-url: ENC(U5ZP89bDyZV+Bd3TsKSqat9aNGNSzlniFHg1WILe0u87KpByE1Ujca3WWiBHrxraX7+61H5SzViK0rOkfo3k4LLJm3u/iQIybHEBjEIsIaY3POuKY3GKSRMvnQ5d/QAf) - cloudfront-cname: ENC(QYuQV8q2Tfspf63e+LXExMVKO9TDpIBn+l0447hi8ZQyO01oim3oLGyBaEocpuv2GDaLfJOZJIeHj+VB7Z3uCw==) - region: - static: ENC(ucd7wzvhDVyi6NQfORb/onMVHFgCMW0+Z0a/ocjoVp3hG93nVRoaE9+KuQzImjK/) +oracle: + cloud: + user-id: ENC(pOD2wcdF0DcH1o4z59kY0Je4uJlGtpPBNkFqreJXpw6u+E0WKfEU3mgV3YpEN+VvbiVOJ4OgQHo/9wVx9oaQR45gcpj9cN2BA3bnJ3+QYZS4jDayN9PhgY1p1Cr7sFjTCSj1C+XFC4aqO1vQYU4+7A==) + tenancy-id: ENC(SSqTivLAMywV4VHJxey/T3iQAEIjSWfS3Nhe10DiTYyqX5Cz6GsGeyrvtbjfXNOqooAtVwkTtEymiiWSsyjLMQdbcVKOdBOzLgdJPIbeZysvM0LY7vCO78XNkRBwjXWtE8NOPAqTf3hbR5E+pr3QOg==) + fingerprint: ENC(VLfxICJLQM4PPlB4nEGje/L/WWKO0MBtsS0kVALoC6VPjlYqeffBZif6YbaQ+uca4dbunHR+Xv1YsCTgASHLG7yxwfZI3MG4bFEdcOApZ0A=) + private-key: ENC(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) + region: ENC(V6cAvA+x6zAE+h/GPr1z2XVAWCPOexpKZzQRQB8rQHD9UpDUGsiHu/IWI7gXTdFK) + bucket-name: ENC(wlsU2SkF+HxI3fx9dmUGU0sbQx8/ZJ85BeD7eteIaJV5zMvIOCSkieSjzlFHQkNZ) + namespace: ENC(1ruYxdhedknwAfB+MnaLkSAMxibH2HsaqmjWyocyyF5Aj8fKo40DUPArfvQ+pegP) + url-prefix: ENC(8EPwqoGID2d6nlODzV8b3LHulBcvp4tAL06KpuX5quG+QyDHBSlx4Gp6AufGGxz8t+TsXFDBjRBJK9bHOEQuzWY87EnGQEf+E6Qpf/WOesL0WeqOtTIFU80VV1sF4/ZS) diff --git a/backend/src/test/java/net/pengcook/image/controller/S3ControllerTest.java b/backend/src/test/java/net/pengcook/image/controller/ImageControllerTest.java similarity index 57% rename from backend/src/test/java/net/pengcook/image/controller/S3ControllerTest.java rename to backend/src/test/java/net/pengcook/image/controller/ImageControllerTest.java index 94bfdadb..a459bcdf 100644 --- a/backend/src/test/java/net/pengcook/image/controller/S3ControllerTest.java +++ b/backend/src/test/java/net/pengcook/image/controller/ImageControllerTest.java @@ -11,41 +11,43 @@ import io.restassured.RestAssured; import net.pengcook.RestDocsSetting; -import net.pengcook.image.dto.PresignedUrlResponse; -import net.pengcook.image.service.S3ClientService; +import net.pengcook.image.dto.UploadUrlResponse; +import net.pengcook.image.service.ImageClientService; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.mock.mockito.MockBean; -class S3ControllerTest extends RestDocsSetting { +class ImageControllerTest extends RestDocsSetting { @MockBean - private S3ClientService s3ClientService; + @Qualifier("imageClientService") + private ImageClientService imageClientService; @Test - @DisplayName("presigned url을 반환한다.") - void getPresignedUrl() { - String presignedUrl = - "https://bucketName.s3.region.amazonaws.com/serviceName/image/fileName?X-Amz-Security-Token=REDACTED&X-Amz-Algorithm=REDACTED&X-Amz-Date=REDACTED&X-Amz-SignedHeaders=REDACTED&X-Amz-Expires=REDACTED&X-Amz-Credential=REDACTED&X-Amz-Signature=REDACTED"; + @DisplayName("upload url을 반환한다.") + void getUploadUrl() { + String fileName = "guiny.jpg"; + String uploadUrl = "https://objectstorage.region.oraclecloud.com/p/REDACTED_TOKEN/n/namespace/b/bucketName/o/" + + fileName; - when(s3ClientService.generatePresignedPutUrl(any())) - .thenReturn(new PresignedUrlResponse(presignedUrl)); + when(imageClientService.generateUploadUrl(any())).thenReturn(new UploadUrlResponse(uploadUrl)); RestAssured.given(spec).log().all() .filter(document(DEFAULT_RESTDOCS_PATH, - "이미지 업로드를 위한 presigned url을 요청합니다.", - "presigned url 요청 API", + "이미지 업로드를 위한 Upload URL을 요청합니다.", + "Upload URL 요청 API", queryParameters( - parameterWithName("fileName").description("이미지 파일 이름") + parameterWithName("fileName").description("저장할 이미지 파일 이름") ), responseFields( - fieldWithPath("url").description("presigned url") + fieldWithPath("url").description("Upload URL") ))) .when() - .queryParam("fileName", "testImage.jpg") + .queryParam("fileName", fileName) .get("/image") .then().log().all() .statusCode(200) - .body("url", equalTo(presignedUrl)); + .body("url", equalTo(uploadUrl)); } } diff --git a/backend/src/test/java/net/pengcook/image/service/ImageClientServiceTest.java b/backend/src/test/java/net/pengcook/image/service/ImageClientServiceTest.java new file mode 100644 index 00000000..4475efb8 --- /dev/null +++ b/backend/src/test/java/net/pengcook/image/service/ImageClientServiceTest.java @@ -0,0 +1,63 @@ +package net.pengcook.image.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +import net.pengcook.image.dto.ImageUrlResponse; +import net.pengcook.image.dto.UploadUrlResponse; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.mock.mockito.MockBean; + +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +class ImageClientServiceTest { + + private static final String OBJECT_NAME = "testImage.jpg"; + + @Value("${oracle.cloud.region}") + private String region; + + @Value("${oracle.cloud.bucket-name}") + private String bucketName; + + @Value("${oracle.cloud.namespace}") + private String namespace; + + @MockBean + @Qualifier("imageClientService") + private ImageClientService imageClientService; + + @Test + @DisplayName("upload url을 반환한다.") + void generateUploadUrl() { + String uploadUrl = String.format("https://objectstorage.%s.oraclecloud.com/p/REDACTED_TOKEN/n/%s/b/%s/o/%s", + region, namespace, bucketName, OBJECT_NAME); + + when(imageClientService.generateUploadUrl(OBJECT_NAME)) + .thenReturn(new UploadUrlResponse(uploadUrl)); + + UploadUrlResponse uploadUrlResponse = imageClientService.generateUploadUrl(OBJECT_NAME); + + assertThat(uploadUrlResponse.url()) + .isEqualTo(uploadUrl); + } + + @Test + @DisplayName("이미지 조회 url을 반환한다.") + void getImageUrl() { + String publicUrl = String.format("https://objectstorage.%s.oraclecloud.com/n/%s/b/%s/o/%s", + region, namespace, bucketName, OBJECT_NAME); + + when(imageClientService.getImageUrl(OBJECT_NAME)) + .thenReturn(new ImageUrlResponse(publicUrl)); + + ImageUrlResponse imageUrlResponse = imageClientService.getImageUrl(OBJECT_NAME); + + assertThat(imageUrlResponse.url()) + .isEqualTo(publicUrl); + } +} diff --git a/backend/src/test/java/net/pengcook/image/service/S3ClientServiceTest.java b/backend/src/test/java/net/pengcook/image/service/S3ClientServiceTest.java deleted file mode 100644 index c0650239..00000000 --- a/backend/src/test/java/net/pengcook/image/service/S3ClientServiceTest.java +++ /dev/null @@ -1,64 +0,0 @@ -package net.pengcook.image.service; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.net.MalformedURLException; -import java.net.URL; -import net.pengcook.image.dto.ImageUrlResponse; -import net.pengcook.image.dto.PresignedUrlResponse; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.mock.mockito.MockBean; -import software.amazon.awssdk.services.s3.presigner.S3Presigner; -import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest; -import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest; - -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) -class S3ClientServiceTest { - - private static final String FILE_NAME = "testImage.jpg"; - - @Autowired - private S3ClientService s3ClientService; - - @MockBean - private S3Presigner s3Presigner; - - @Value("${cloud.aws.S3.cloudfront-cname}") - private String cloudfrontCname; - - @Test - @DisplayName("presigned url을 반환한다.") - void generatePresignedUrl() throws MalformedURLException { - String expectedPresignedUrl = - "https://bucketName.s3.region.amazonaws.com/serviceName/image/fileName?X-Amz-Security-Token=REDACTED&X-Amz-Algorithm=REDACTED&X-Amz-Date=REDACTED&X-Amz-SignedHeaders=REDACTED&X-Amz-Expires=REDACTED&X-Amz-Credential=REDACTED&X-Amz-Signature=REDACTED"; - URL presignedUrl = new URL(expectedPresignedUrl); - PresignedPutObjectRequest presignedPutObjectRequest = mock(PresignedPutObjectRequest.class); - - when(presignedPutObjectRequest.url()) - .thenReturn(presignedUrl); - when(s3Presigner.presignPutObject(any(PutObjectPresignRequest.class))) - .thenReturn(presignedPutObjectRequest); - PresignedUrlResponse presignedUrlResponse = s3ClientService.generatePresignedPutUrl(FILE_NAME); - - assertThat(presignedUrlResponse.url()) - .isEqualTo(expectedPresignedUrl); - } - - @Test - @DisplayName("이미지 조회 url을 반환한다.") - void getImageUrl() { - String expectedImageUrl = cloudfrontCname + "/pengcook/image/" + FILE_NAME; - ImageUrlResponse imageUrlResponse = new ImageUrlResponse(expectedImageUrl); - - assertThat(s3ClientService.getImageUrl(FILE_NAME)) - .isEqualTo(imageUrlResponse); - } -} diff --git a/backend/src/test/java/net/pengcook/user/controller/UserControllerTest.java b/backend/src/test/java/net/pengcook/user/controller/UserControllerTest.java index 6b84229a..43daaced 100644 --- a/backend/src/test/java/net/pengcook/user/controller/UserControllerTest.java +++ b/backend/src/test/java/net/pengcook/user/controller/UserControllerTest.java @@ -16,7 +16,7 @@ import net.pengcook.RestDocsSetting; import net.pengcook.authentication.annotation.WithLoginUser; import net.pengcook.authentication.annotation.WithLoginUserTest; -import net.pengcook.image.service.S3ClientService; +import net.pengcook.image.service.ImageClientService; import net.pengcook.user.domain.Reason; import net.pengcook.user.domain.Type; import net.pengcook.user.dto.ProfileResponse; @@ -38,7 +38,7 @@ class UserControllerTest extends RestDocsSetting { UserRepository userRepository; @Autowired - S3ClientService s3ClientService; + ImageClientService imageClientService; @Test @WithLoginUser(email = "loki@pengcook.net") @@ -144,7 +144,7 @@ void updateUserProfile() { "loki@pengcook.net", "loki_changed", "로키_changed", - s3ClientService.getImageUrl("loki_changed.jpg").url(), + imageClientService.getImageUrl("loki_changed.jpg").url(), "KOREA", "hello world" ); diff --git a/backend/src/test/java/net/pengcook/user/service/UserServiceTest.java b/backend/src/test/java/net/pengcook/user/service/UserServiceTest.java index e1e588e2..5c7a6c38 100644 --- a/backend/src/test/java/net/pengcook/user/service/UserServiceTest.java +++ b/backend/src/test/java/net/pengcook/user/service/UserServiceTest.java @@ -6,7 +6,7 @@ import net.pengcook.authentication.domain.UserInfo; import net.pengcook.comment.repository.CommentRepository; -import net.pengcook.image.service.S3ClientService; +import net.pengcook.image.service.ImageClientService; import net.pengcook.like.repository.RecipeLikeRepository; import net.pengcook.recipe.repository.RecipeRepository; import net.pengcook.user.domain.BlockedUserGroup; @@ -49,7 +49,7 @@ class UserServiceTest { @Autowired UserService userService; @Autowired - S3ClientService s3ClientService; + ImageClientService imageClientService; @Test @DisplayName("id를 통해 사용자의 정보를 불러온다.") @@ -100,7 +100,7 @@ void updateProfile() { "loki@pengcook.net", "loki_changed", "로키_changed", - s3ClientService.getImageUrl("loki_changed.jpg").url(), + imageClientService.getImageUrl("loki_changed.jpg").url(), "KOREA", "hello world" ); From ec46ce2c80241a5c9180463cc829b2ff8f175bb9 Mon Sep 17 00:00:00 2001 From: hyxrxn <gpfls981220@gmail.com> Date: Sat, 30 Nov 2024 23:38:44 +0900 Subject: [PATCH 3/4] :recycle: clarify exception message --- .../src/main/java/net/pengcook/image/config/ImageConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/net/pengcook/image/config/ImageConfig.java b/backend/src/main/java/net/pengcook/image/config/ImageConfig.java index aa1f3cc5..348cff02 100644 --- a/backend/src/main/java/net/pengcook/image/config/ImageConfig.java +++ b/backend/src/main/java/net/pengcook/image/config/ImageConfig.java @@ -41,7 +41,7 @@ public ObjectStorage objectStorage() { try { return new ByteArrayInputStream(privateKey.getBytes(StandardCharsets.UTF_8)); } catch (Exception e) { - throw new RuntimeException("Failed to load private key", e); + throw new RuntimeException("object storage의 private key를 로드하는 데 실패했습니다.", e); } }) .region(Region.fromRegionId(region)) From 0ff0e006c40fcfa706c3341265fcb14065d0917b Mon Sep 17 00:00:00 2001 From: hyxrxn <gpfls981220@gmail.com> Date: Tue, 3 Dec 2024 13:37:06 +0900 Subject: [PATCH 4/4] :recycle: move duration seconds setting to yaml --- .../pengcook/image/service/ObjectStorageClientService.java | 5 +++-- backend/src/main/resources/application-dev.yaml | 1 + backend/src/main/resources/application-local.yaml | 1 + backend/src/main/resources/application-prod.yaml | 1 + backend/src/main/resources/application-test.yaml | 1 + 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/net/pengcook/image/service/ObjectStorageClientService.java b/backend/src/main/java/net/pengcook/image/service/ObjectStorageClientService.java index 8421c93b..8d984b24 100644 --- a/backend/src/main/java/net/pengcook/image/service/ObjectStorageClientService.java +++ b/backend/src/main/java/net/pengcook/image/service/ObjectStorageClientService.java @@ -29,13 +29,14 @@ public class ObjectStorageClientService implements ImageClientService { @Value("${oracle.cloud.url-prefix}") private String urlPrefix; - private static final int DURATION_SECONDS = 600; + @Value("${oracle.cloud.duration-seconds}") + private int durationSeconds; public UploadUrlResponse generateUploadUrl(String fileName) { CreatePreauthenticatedRequestDetails details = CreatePreauthenticatedRequestDetails.builder() .accessType(AccessType.ObjectWrite) .name("upload-" + fileName) - .timeExpires(Date.from(Instant.now().plusSeconds(DURATION_SECONDS))) + .timeExpires(Date.from(Instant.now().plusSeconds(durationSeconds))) .objectName(fileName) .build(); diff --git a/backend/src/main/resources/application-dev.yaml b/backend/src/main/resources/application-dev.yaml index 1cafbf2f..dcc9284e 100644 --- a/backend/src/main/resources/application-dev.yaml +++ b/backend/src/main/resources/application-dev.yaml @@ -27,6 +27,7 @@ oracle: bucket-name: ENC(7AyUEbDIf9u78oT0rRRw1i6tMB2GgeA2TbqdrXNibewynpOLyY7JT3SIE9zqgiHG) namespace: ENC(6Il9NSYH1SYAcKaLxi6VlFs9XvqwkSB9VhMnKGoko3ul4hQcGoS5gZcxEa0sNWP5) url-prefix: ENC(KH5PC5/BySZUQQhEG+OZv7tyC+ia5F7nP/Y4jsch9I1xMAbdKNZn8396+BSRkP3CvyWLZZ6eI/WMgbynISAn6jYZ5GfP4bV9bKO2Vp97sZ/zJz0BNKOG8XHZSozoPqgI) + duration-seconds: 600 logging: level: diff --git a/backend/src/main/resources/application-local.yaml b/backend/src/main/resources/application-local.yaml index fb01375b..b254a0c7 100644 --- a/backend/src/main/resources/application-local.yaml +++ b/backend/src/main/resources/application-local.yaml @@ -30,6 +30,7 @@ oracle: bucket-name: ENC(UOUpk4WqCJ2uCJC9TLuimSbIleeXUjq10oHOf9R/4ogHfU3pMqywNYA6dHFcqyGz) namespace: ENC(qOxV5BZjZLS9Ems+CFZNMFeKYselnH70DLLAfwgZzpTIXd4bHxWevLALm6CHli6h) url-prefix: ENC(2GeAcJRUdCxHYOKBlKjbBJqZBlw6PNIB4pYOa6X82dFa+n1H+uu4QvIFxtbbS/yLoafQ+1It4S3BvUBttFdsBuRCyAEIayN27YBi2fpQZqoX4YrBOQY3r1RRMb/ybHlv) + duration-seconds: 600 server: tomcat: diff --git a/backend/src/main/resources/application-prod.yaml b/backend/src/main/resources/application-prod.yaml index 2718a1da..8cf62026 100644 --- a/backend/src/main/resources/application-prod.yaml +++ b/backend/src/main/resources/application-prod.yaml @@ -32,6 +32,7 @@ oracle: bucket-name: ENC(FlPAx/iHK75QmJTdlOguLyEvPoi1d+ZxF1pNQBo5UZk4oxSD2xPGjmgC/LHBKvWe) namespace: ENC(8zdD/nolmplXP9Lz7TVBWxOuJyKA07GEauQZ1Jkn4Jiddc2LA9tDVMQfCc2f5tKZ) url-prefix: ENC(e0dxHgl3UDKMLyjgxDkN1sOi+UcPbqs0WpLvlmUxt/O9/nA9W2jlzROQv8A3tgpi2CGKnFiksz9N7xMVo1xJZ0kbqGerY7fzI5XQI4BLCqFwcaSGYq1T/p5xCVNuhXel) + duration-seconds: 600 springdoc: swagger-ui: diff --git a/backend/src/main/resources/application-test.yaml b/backend/src/main/resources/application-test.yaml index 8437af9e..1ec5c411 100644 --- a/backend/src/main/resources/application-test.yaml +++ b/backend/src/main/resources/application-test.yaml @@ -31,3 +31,4 @@ oracle: bucket-name: ENC(wlsU2SkF+HxI3fx9dmUGU0sbQx8/ZJ85BeD7eteIaJV5zMvIOCSkieSjzlFHQkNZ) namespace: ENC(1ruYxdhedknwAfB+MnaLkSAMxibH2HsaqmjWyocyyF5Aj8fKo40DUPArfvQ+pegP) url-prefix: ENC(8EPwqoGID2d6nlODzV8b3LHulBcvp4tAL06KpuX5quG+QyDHBSlx4Gp6AufGGxz8t+TsXFDBjRBJK9bHOEQuzWY87EnGQEf+E6Qpf/WOesL0WeqOtTIFU80VV1sF4/ZS) + duration-seconds: 600