Skip to content

Commit

Permalink
Merge branch 'week11' into prod
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/main/java/poomasi/domain/auth/config/SecurityConfig.java
  • Loading branch information
stopmin committed Nov 14, 2024
2 parents f8d7e4c + aac5c17 commit c29286d
Show file tree
Hide file tree
Showing 55 changed files with 804 additions and 55 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/deploy-ecs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ jobs:
IMP_SECRET_KEY=${{ secrets.IMP_SECRET_KEY }}
KAKAO_CLIENT_ID=${{ secrets.KAKAO_CLIENT_ID }}
KAKAO_CLIENT_SECRET=${{ secrets.KAKAO_CLIENT_SECRET }}
NAVER_OCR_SECRET=${{ secrets.NAVER_OCR_SECRET }}
NAVER_OCR_INVOKE=${{ secrets.NAVER_OCR_INVOKE }}
NAVER_OCR_TEMPLATE=${{ secrets.NAVER_OCR_TEMPLATE }}
cache-from: type=gha
cache-to: type=gha,mode=min,ignore-error=true

Expand Down
10 changes: 10 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ ARG IMP_API_KEY
ARG IMP_SECRET_KEY
ARG KAKAO_CLIENT_ID
ARG KAKAO_CLIENT_SECRET
ARG NAVER_OCR_SECRET
ARG NAVER_OCR_INVOKE
ARG NAVER_OCR_TEMPLATE

# 환경 변수 설정
ENV SPRING_DATASOURCE_URL=$SPRING_DATASOURCE_URL
Expand All @@ -35,6 +38,10 @@ ENV IMP_API_KEY=$IMP_API_KEY
ENV IMP_SECRET_KEY=$IMP_SECRET_KEY
ENV KAKAO_CLIENT_ID=$KAKAO_CLIENT_ID
ENV KAKAO_CLIENT_SECRET=$KAKAO_CLIENT_SECRET
ENV NAVER_OCR_SECRET=$NAVER_OCR_SECRET
ENV NAVER_OCR_INVOKE=$NAVER_OCR_INVOKE
ENV NAVER_OCR_TEMPLATE=$NAVER_OCR_TEMPLATE


COPY build/libs/*.jar app.jar

Expand All @@ -55,4 +62,7 @@ ENTRYPOINT ["java", "-Duser.timezone=Asia/Seoul", \
"-Dimp.api.secretKey=${IMP_SECRET_KEY}", \
"-Dkakao.client.id=${KAKAO_CLIENT_ID}", \
"-Dkakao.client.secret=${KAKAO_CLIENT_SECRET}", \
"-Dnaver.ocr.secret=${NAVER_OCR_SECRET}", \
"-Dnaver.ocr.invoke=${NAVER_OCR_INVOKE}", \
"-Dnaver.ocr.template=${NAVER_OCR_TEMPLATE}", \
"-jar", "/app.jar"]
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.requestMatchers(HttpMethod.GET, "/api/review/**").permitAll()
.requestMatchers(HttpMethod.GET, "/health").permitAll()
.requestMatchers(HttpMethod.GET, "/api/image/**").permitAll()
.requestMatchers("/api/farm/**", "/api/member/sign-up", "/api/login", "api/reissue", "api/payment/**", "api/order/**", "api/reservation/**", "/api/v1/farmer/reservations").permitAll()
.requestMatchers("/api/farm/**", "/api/member/sign-up", "/api/login", "api/reissue", "api/payment/**", "api/order/**", "api/reservation/**", "/api/v1/farmer/reservations", "/api/v1/biz/farmer/**").permitAll()
.requestMatchers("/api/need-auth/**").authenticated()
.anyRequest().
authenticated()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package poomasi.domain.auth.token.reissue.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
Expand All @@ -19,7 +20,7 @@ public class ReissueTokenController {

@PostMapping("/api/reissue")
public ResponseEntity<ReissueResponse> reissue(@RequestHeader(HttpHeaders.AUTHORIZATION) String authorizationHeader,
@RequestBody ReissueRequest reissueRequest){
@Valid @RequestBody ReissueRequest reissueRequest){

String accessToken = authorizationHeader.replace("Bearer ", "");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
package poomasi.domain.auth.token.reissue.dto;

public record ReissueRequest(String refreshToken) {
import jakarta.validation.constraints.NotBlank;

public record ReissueRequest(
@NotBlank(message = "리프레시 토큰을 입력해야 합니다.")
String refreshToken) {
}
18 changes: 12 additions & 6 deletions src/main/java/poomasi/domain/image/controller/ImageController.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package poomasi.domain.image.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
Expand All @@ -23,7 +24,8 @@ public class ImageController {
// 이미지 정보 저장
@PostMapping
@Secured({"ROLE_CUSTOMER", "ROLE_FARMER", "ROLE_ADMIN"})
public ResponseEntity<?> saveImageInfo(@AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody ImageRequest imageRequest) {
public ResponseEntity<?> saveImageInfo(@AuthenticationPrincipal UserDetailsImpl userDetails,
@Valid @RequestBody ImageRequest imageRequest) {
Member member = userDetails.getMember();
Image savedImage = imageService.saveImage(member.getId(), imageRequest);
return ResponseEntity.ok(savedImage);
Expand All @@ -32,7 +34,8 @@ public ResponseEntity<?> saveImageInfo(@AuthenticationPrincipal UserDetailsImpl
// 여러 이미지 정보 저장
@PostMapping("/multiple")
@Secured({"ROLE_CUSTOMER", "ROLE_FARMER", "ROLE_ADMIN"})
public ResponseEntity<List<Image>> saveMultipleImages(@AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody List<ImageRequest> imageRequests) {
public ResponseEntity<List<Image>> saveMultipleImages(@AuthenticationPrincipal UserDetailsImpl userDetails,
@Valid @RequestBody List<ImageRequest> imageRequests) {
Member member = userDetails.getMember();
List<Image> savedImages = imageService.saveMultipleImages(member.getId(), imageRequests);
return ResponseEntity.ok(savedImages);
Expand All @@ -41,7 +44,8 @@ public ResponseEntity<List<Image>> saveMultipleImages(@AuthenticationPrincipal U
// 특정 이미지 삭제
@DeleteMapping("/delete/{id}")
@Secured({"ROLE_CUSTOMER", "ROLE_FARMER", "ROLE_ADMIN"})
public ResponseEntity<Void> deleteImage(@AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable Long id) {
public ResponseEntity<Void> deleteImage(@AuthenticationPrincipal UserDetailsImpl userDetails,
@PathVariable Long id) {
Member member = userDetails.getMember();
imageService.deleteImage(member.getId(), id);
return ResponseEntity.noContent().build();
Expand All @@ -55,7 +59,8 @@ public ResponseEntity<Image> getImage(@PathVariable Long id) {

// 모든 이미지 조회 (특정 referenceId에 따라)
@GetMapping("/reference/{type}/{referenceId}")
public ResponseEntity<List<Image>> getImagesByTypeAndReference(@PathVariable ImageType type, @PathVariable Long referenceId) {
public ResponseEntity<List<Image>> getImagesByTypeAndReference(@PathVariable ImageType type,
@PathVariable Long referenceId) {
List<Image> images = imageService.getImagesByTypeAndReferenceId(type, referenceId);
return ResponseEntity.ok(images);
}
Expand All @@ -65,15 +70,16 @@ public ResponseEntity<List<Image>> getImagesByTypeAndReference(@PathVariable Ima
@Secured({"ROLE_CUSTOMER", "ROLE_FARMER", "ROLE_ADMIN"})
public ResponseEntity<?> updateImageInfo(@AuthenticationPrincipal UserDetailsImpl userDetails,
@PathVariable Long id,
@RequestBody ImageRequest imageRequest) {
@Valid @RequestBody ImageRequest imageRequest) {
Member member = userDetails.getMember();
Image updatedImage = imageService.updateImage(member.getId(), id, imageRequest);
return ResponseEntity.ok(updatedImage);
}

@PutMapping("/recover/{id}")
@Secured({"ROLE_CUSTOMER", "ROLE_FARMER", "ROLE_ADMIN"})
public ResponseEntity<Void> recoverImage(@AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable Long id) {
public ResponseEntity<Void> recoverImage(@AuthenticationPrincipal UserDetailsImpl userDetails,
@PathVariable Long id) {
Member member = userDetails.getMember();
imageService.recoverImage(member.getId(), id);
return ResponseEntity.noContent().build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,21 @@
import org.springframework.stereotype.Component;
import poomasi.domain.image.entity.ImageType;

import java.util.HashMap;
import java.util.Map;
import java.util.List;

@Component
public class ImageDeleteFactory {

private final Map<ImageType, ImageDeleteLinker> handlerMap;
private final List<ImageDeleteLinker> deleteLinkers;

public ImageDeleteFactory(
ProductDeleteLinker productDeleteLinker,
MemberProfileDeleteLinker memberProfileDeleteLinker) {
this.handlerMap = new HashMap<>();
handlerMap.put(ImageType.PRODUCT, productDeleteLinker);
handlerMap.put(ImageType.MEMBER_PROFILE, memberProfileDeleteLinker);
public ImageDeleteFactory(List<ImageDeleteLinker> deleteLinkers) {
this.deleteLinkers = deleteLinkers;
}

public ImageDeleteLinker getDeleteLinker(ImageType type) {
return handlerMap.get(type);
return deleteLinkers.stream()
.filter(linker -> linker.supports(type))
.findFirst()
.orElse(null);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package poomasi.domain.image.deleteLinker;

import poomasi.domain.image.entity.Image;
import poomasi.domain.image.entity.ImageType;

public interface ImageDeleteLinker {
boolean supports(ImageType type);
void handleImageDeletion(Image image);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.springframework.stereotype.Component;
import poomasi.domain.image.entity.Image;
import poomasi.domain.image.entity.ImageType;
import poomasi.domain.member._profile.entity.MemberProfile;
import poomasi.domain.member._profile.service.MemberProfileService;

Expand All @@ -14,6 +15,11 @@ public MemberProfileDeleteLinker(MemberProfileService memberProfileService) {
this.memberProfileService = memberProfileService;
}

@Override
public boolean supports(ImageType type) {
return type == ImageType.MEMBER_PROFILE;
}

@Override
public void handleImageDeletion(Image image) {
MemberProfile memberProfile = memberProfileService.getMemberProfileById(image.getReferenceId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.springframework.stereotype.Component;
import poomasi.domain.image.entity.Image;
import poomasi.domain.image.entity.ImageType;
import poomasi.domain.product.entity.Product;
import poomasi.domain.product.service.ProductService;

Expand All @@ -14,6 +15,11 @@ public ProductDeleteLinker(ProductService productService) {
this.productService = productService;
}

@Override
public boolean supports(ImageType type) {
return type == ImageType.PRODUCT;
}

@Override
public void handleImageDeletion(Image image) {
Product product = productService.findProductById(image.getReferenceId());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package poomasi.domain.image.deleteLinker;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import poomasi.domain.image.entity.Image;
import poomasi.domain.image.entity.ImageType;
import poomasi.domain.product._intro.entity.ProductIntro;
import poomasi.domain.product._intro.service.ProductIntroService;

import java.util.Arrays;
import java.util.List;

@Component
public class ProductIntroDeleteLinker implements ImageDeleteLinker {

private final ProductIntroService productIntroService;

public ProductIntroDeleteLinker(ProductIntroService productIntroService) {
this.productIntroService = productIntroService;
}

@Override
public boolean supports(ImageType type) {
return type == ImageType.PRODUCT_INTRO;
}

@Transactional
@Override
public void handleImageDeletion(Image image) {
ProductIntro productIntro = productIntroService.getIntroByIntroId(image.getReferenceId());

List<Image> images = Arrays.asList(productIntro.getMainImage(), productIntro.getSubImage1(), productIntro.getSubImage2(), productIntro.getSubImage3());
for (int i = 0; i < images.size(); i++) {
if (images.get(i) == image) {
switch (i) {
case 0 -> productIntro.setMainImage(null);
case 1 -> productIntro.setSubImage1(null);
case 2 -> productIntro.setSubImage2(null);
case 3 -> productIntro.setSubImage3(null);
}
}
}
productIntroService.saveExistedProductIntro(productIntro);
}
}
18 changes: 17 additions & 1 deletion src/main/java/poomasi/domain/image/dto/ImageRequest.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
package poomasi.domain.image.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import poomasi.domain.image.entity.Image;
import poomasi.domain.image.entity.ImageType;

public record ImageRequest(String objectKey, String imageUrl, ImageType type, Long referenceId) {
public record ImageRequest(
@NotBlank(message = "Object key이 blank입니다.")
String objectKey,

@NotBlank(message = "Image URL이 blank입니다.")
String imageUrl,

@NotNull(message = "Image type이 null입니다.")
ImageType type,

@NotNull(message = "Reference ID가 null입니다.")
@Positive(message = "Reference ID는 양의 정수이어야 합니다.")
Long referenceId
) {
public Image toEntity(ImageRequest imageRequest){
return new Image(
imageRequest.objectKey,
Expand Down
4 changes: 1 addition & 3 deletions src/main/java/poomasi/domain/image/entity/Image.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
import java.time.LocalDateTime;

@Entity
@Table(name = "image")/*, )uniqueConstraints = {
@UniqueConstraint(columnNames = {"type", "reference_id"})
})*/
@Table(name = "image")
@Getter
@Setter
@NoArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package poomasi.domain.image.linker;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import poomasi.domain.image.entity.Image;
import poomasi.domain.image.entity.ImageType;
import poomasi.domain.product._intro.entity.ProductIntro;
import poomasi.domain.product._intro.service.ProductIntroService;
import poomasi.global.error.BusinessException;

import java.util.Arrays;
import java.util.List;

import static poomasi.global.error.BusinessError.IMAGE_LIMIT_EXCEED;

@Service
public class ProductIntroImageLinker implements ImageLinker {

private final ProductIntroService productIntroService;

public ProductIntroImageLinker(ProductIntroService productIntroService) {
this.productIntroService = productIntroService;
}

@Override
public boolean supports(ImageType type) {
return type == ImageType.PRODUCT_INTRO;
}

@Transactional
@Override
public void link(Long referenceId, Image savedImage) {
ProductIntro productIntro = productIntroService.getIntroByIntroId(referenceId);
addImageToProductIntro(productIntro, savedImage);
productIntroService.saveExistedProductIntro(productIntro);
}

private void addImageToProductIntro(ProductIntro productIntro, Image savedImage) {
List<Image> images = Arrays.asList(
productIntro.getMainImage(),
productIntro.getSubImage1(),
productIntro.getSubImage2(),
productIntro.getSubImage3()
);

for (int i = 0; i < images.size(); i++) {
if (images.get(i) == null) {
setImageByIndex(productIntro, i, savedImage);
return;
}
}

throw new BusinessException(IMAGE_LIMIT_EXCEED);
}

private void setImageByIndex(ProductIntro productIntro, int index, Image image) {
switch (index) {
case 0 -> productIntro.setMainImage(image);
case 1 -> productIntro.setSubImage1(image);
case 2 -> productIntro.setSubImage2(image);
case 3 -> productIntro.setSubImage3(image);
}
}
}
Loading

0 comments on commit c29286d

Please sign in to comment.