diff --git a/src/main/java/com/wedit/weditapp/domain/bankAccounts/domain/BankAccount.java b/src/main/java/com/wedit/weditapp/domain/bankAccount/domain/BankAccount.java similarity index 97% rename from src/main/java/com/wedit/weditapp/domain/bankAccounts/domain/BankAccount.java rename to src/main/java/com/wedit/weditapp/domain/bankAccount/domain/BankAccount.java index d8ffa12..bf9903b 100644 --- a/src/main/java/com/wedit/weditapp/domain/bankAccounts/domain/BankAccount.java +++ b/src/main/java/com/wedit/weditapp/domain/bankAccount/domain/BankAccount.java @@ -1,4 +1,4 @@ -package com.wedit.weditapp.domain.bankAccounts.domain; +package com.wedit.weditapp.domain.bankAccount.domain; import com.wedit.weditapp.domain.invitation.domain.Invitation; import com.wedit.weditapp.domain.shared.AccountSide; diff --git a/src/main/java/com/wedit/weditapp/domain/bankAccounts/domain/repository/BankAccountRepository.java b/src/main/java/com/wedit/weditapp/domain/bankAccount/domain/repository/BankAccountRepository.java similarity index 76% rename from src/main/java/com/wedit/weditapp/domain/bankAccounts/domain/repository/BankAccountRepository.java rename to src/main/java/com/wedit/weditapp/domain/bankAccount/domain/repository/BankAccountRepository.java index 32694f7..a2bb6dd 100644 --- a/src/main/java/com/wedit/weditapp/domain/bankAccounts/domain/repository/BankAccountRepository.java +++ b/src/main/java/com/wedit/weditapp/domain/bankAccount/domain/repository/BankAccountRepository.java @@ -1,9 +1,9 @@ -package com.wedit.weditapp.domain.bankAccounts.domain.repository; +package com.wedit.weditapp.domain.bankAccount.domain.repository; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; -import com.wedit.weditapp.domain.bankAccounts.domain.BankAccount; +import com.wedit.weditapp.domain.bankAccount.domain.BankAccount; import com.wedit.weditapp.domain.invitation.domain.Invitation; import com.wedit.weditapp.domain.shared.AccountSide; diff --git a/src/main/java/com/wedit/weditapp/domain/bankAccounts/dto/BankAccountDto.java b/src/main/java/com/wedit/weditapp/domain/bankAccount/dto/BankAccountDto.java similarity index 90% rename from src/main/java/com/wedit/weditapp/domain/bankAccounts/dto/BankAccountDto.java rename to src/main/java/com/wedit/weditapp/domain/bankAccount/dto/BankAccountDto.java index b8cd7c8..1a54a41 100644 --- a/src/main/java/com/wedit/weditapp/domain/bankAccounts/dto/BankAccountDto.java +++ b/src/main/java/com/wedit/weditapp/domain/bankAccount/dto/BankAccountDto.java @@ -1,6 +1,6 @@ -package com.wedit.weditapp.domain.bankAccounts.dto; +package com.wedit.weditapp.domain.bankAccount.dto; -import com.wedit.weditapp.domain.bankAccounts.domain.BankAccount; +import com.wedit.weditapp.domain.bankAccount.domain.BankAccount; import com.wedit.weditapp.domain.shared.AccountSide; import jakarta.validation.constraints.NotBlank; @@ -11,6 +11,7 @@ @Getter @NoArgsConstructor public class BankAccountDto { + @NotBlank(message = "side cannot be blank") private AccountSide side; // 신랑/신부 구분 diff --git a/src/main/java/com/wedit/weditapp/domain/bankAccounts/service/BankAccountService.java b/src/main/java/com/wedit/weditapp/domain/bankAccount/service/BankAccountService.java similarity index 91% rename from src/main/java/com/wedit/weditapp/domain/bankAccounts/service/BankAccountService.java rename to src/main/java/com/wedit/weditapp/domain/bankAccount/service/BankAccountService.java index c67a800..cc3ffcf 100644 --- a/src/main/java/com/wedit/weditapp/domain/bankAccounts/service/BankAccountService.java +++ b/src/main/java/com/wedit/weditapp/domain/bankAccount/service/BankAccountService.java @@ -1,13 +1,13 @@ -package com.wedit.weditapp.domain.bankAccounts.service; +package com.wedit.weditapp.domain.bankAccount.service; import java.util.List; import java.util.stream.Collectors; import org.springframework.stereotype.Service; -import com.wedit.weditapp.domain.bankAccounts.domain.BankAccount; -import com.wedit.weditapp.domain.bankAccounts.domain.repository.BankAccountRepository; -import com.wedit.weditapp.domain.bankAccounts.dto.BankAccountDto; +import com.wedit.weditapp.domain.bankAccount.domain.BankAccount; +import com.wedit.weditapp.domain.bankAccount.domain.repository.BankAccountRepository; +import com.wedit.weditapp.domain.bankAccount.dto.BankAccountDto; import com.wedit.weditapp.domain.invitation.domain.Invitation; import com.wedit.weditapp.global.error.ErrorCode; import com.wedit.weditapp.global.error.exception.CommonException; diff --git a/src/main/java/com/wedit/weditapp/domain/comment/controller/CommentController.java b/src/main/java/com/wedit/weditapp/domain/comment/controller/CommentController.java index 69294ef..5d03e61 100644 --- a/src/main/java/com/wedit/weditapp/domain/comment/controller/CommentController.java +++ b/src/main/java/com/wedit/weditapp/domain/comment/controller/CommentController.java @@ -34,6 +34,7 @@ public ResponseEntity> findAllComment @RequestParam(defaultValue = "1") int page){ PagedCommentResponseDto response = commentService.findAllCommentsByInvitationId(invitationId, page); + return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success(response)); } diff --git a/src/main/java/com/wedit/weditapp/domain/comment/domain/Comment.java b/src/main/java/com/wedit/weditapp/domain/comment/domain/Comment.java index 239dd2c..b9e4265 100644 --- a/src/main/java/com/wedit/weditapp/domain/comment/domain/Comment.java +++ b/src/main/java/com/wedit/weditapp/domain/comment/domain/Comment.java @@ -42,5 +42,4 @@ public static Comment createComment(String name, String content, Invitation invi .invitation(invitation) .build(); } - } diff --git a/src/main/java/com/wedit/weditapp/domain/comment/domain/repository/CommentRepository.java b/src/main/java/com/wedit/weditapp/domain/comment/domain/repository/CommentRepository.java index d40583b..08c5030 100644 --- a/src/main/java/com/wedit/weditapp/domain/comment/domain/repository/CommentRepository.java +++ b/src/main/java/com/wedit/weditapp/domain/comment/domain/repository/CommentRepository.java @@ -3,7 +3,6 @@ import java.util.List; import com.wedit.weditapp.domain.comment.domain.Comment; -import com.wedit.weditapp.domain.image.domain.Image; import com.wedit.weditapp.domain.invitation.domain.Invitation; import org.springframework.data.domain.Page; diff --git a/src/main/java/com/wedit/weditapp/domain/comment/service/CommentService.java b/src/main/java/com/wedit/weditapp/domain/comment/service/CommentService.java index 4115167..2893b4b 100644 --- a/src/main/java/com/wedit/weditapp/domain/comment/service/CommentService.java +++ b/src/main/java/com/wedit/weditapp/domain/comment/service/CommentService.java @@ -61,8 +61,6 @@ public PagedCommentResponseDto findAllCommentsByInvitationId(Long invitationId, // 필요한 정보만으로 DTO 생성 return PagedCommentResponseDto.of(commentDTOPage, commentPage.isLast(), page); - - } // 방명록 등록 diff --git a/src/main/java/com/wedit/weditapp/domain/decision/domain/repository/DecisionRepository.java b/src/main/java/com/wedit/weditapp/domain/decision/domain/repository/DecisionRepository.java index ff087eb..dfb1a67 100644 --- a/src/main/java/com/wedit/weditapp/domain/decision/domain/repository/DecisionRepository.java +++ b/src/main/java/com/wedit/weditapp/domain/decision/domain/repository/DecisionRepository.java @@ -6,7 +6,6 @@ import com.wedit.weditapp.domain.invitation.domain.Invitation; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/src/main/java/com/wedit/weditapp/domain/decision/service/DecisionService.java b/src/main/java/com/wedit/weditapp/domain/decision/service/DecisionService.java index 4892844..4aa3893 100644 --- a/src/main/java/com/wedit/weditapp/domain/decision/service/DecisionService.java +++ b/src/main/java/com/wedit/weditapp/domain/decision/service/DecisionService.java @@ -20,7 +20,6 @@ public class DecisionService { private final DecisionRepository decisionRepository; - private final InvitationRepository invitationRepository; // 특정 청첩장의 참석의사 누계 조회 diff --git a/src/main/java/com/wedit/weditapp/domain/image/domain/Image.java b/src/main/java/com/wedit/weditapp/domain/image/domain/Image.java index 8ee1204..9a64131 100644 --- a/src/main/java/com/wedit/weditapp/domain/image/domain/Image.java +++ b/src/main/java/com/wedit/weditapp/domain/image/domain/Image.java @@ -22,6 +22,7 @@ @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Image extends BaseTimeEntity { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; diff --git a/src/main/java/com/wedit/weditapp/domain/image/dto/response/ImageResponseDto.java b/src/main/java/com/wedit/weditapp/domain/image/dto/response/ImageResponseDto.java index 159e8f7..abc26ea 100644 --- a/src/main/java/com/wedit/weditapp/domain/image/dto/response/ImageResponseDto.java +++ b/src/main/java/com/wedit/weditapp/domain/image/dto/response/ImageResponseDto.java @@ -10,7 +10,6 @@ @NoArgsConstructor public class ImageResponseDto { private String url; - private int location; @Builder diff --git a/src/main/java/com/wedit/weditapp/domain/image/service/ImageService.java b/src/main/java/com/wedit/weditapp/domain/image/service/ImageService.java index 3f1821e..6005f4f 100644 --- a/src/main/java/com/wedit/weditapp/domain/image/service/ImageService.java +++ b/src/main/java/com/wedit/weditapp/domain/image/service/ImageService.java @@ -75,6 +75,7 @@ public void updateImages(List newImages, Invitation invitation) { } catch (Exception e) { throw new CommonException(ErrorCode.IMAGE_UPLOAD_FAILED); } + imageRepository.delete(image); // DB에서 이미지 삭제 }); diff --git a/src/main/java/com/wedit/weditapp/domain/invitation/controller/InvitationController.java b/src/main/java/com/wedit/weditapp/domain/invitation/controller/InvitationController.java index 9845f77..16e19ae 100644 --- a/src/main/java/com/wedit/weditapp/domain/invitation/controller/InvitationController.java +++ b/src/main/java/com/wedit/weditapp/domain/invitation/controller/InvitationController.java @@ -13,7 +13,6 @@ 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.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; @@ -51,6 +50,7 @@ public ResponseEntity> createInvitation( public ResponseEntity> getInvitation( @PathVariable Long invitationId, @AuthenticationPrincipal UserDetails userDetail){ + return ResponseEntity.status(HttpStatus.OK) .body(GlobalResponseDto.success(invitationService.getInvitation(userDetail, invitationId))); } @@ -62,7 +62,9 @@ public ResponseEntity> updateInvitation( @RequestPart("images") List newImages, @Valid @RequestPart("content") InvitationUpdateRequestDto updateRequest, @AuthenticationPrincipal UserDetails userDetail) { + invitationService.updateInvitation(userDetail, invitationId, updateRequest, newImages); + return ResponseEntity.status(HttpStatus.OK) .body(GlobalResponseDto.success()); } @@ -72,7 +74,9 @@ public ResponseEntity> updateInvitation( public ResponseEntity> generateInvitationUrl( @PathVariable Long invitationId, @AuthenticationPrincipal UserDetails userDetail) { + String url = invitationService.generateAndSaveInvitationUrl(userDetail, invitationId); + return ResponseEntity.status(HttpStatus.OK) .body(GlobalResponseDto.success(url)); } @@ -82,7 +86,9 @@ public ResponseEntity> generateInvitationUrl( public ResponseEntity> deleteInvitation( @PathVariable Long invitationId, @AuthenticationPrincipal UserDetails userDetail) { + invitationService.deleteInvitation(userDetail, invitationId); // 서비스 호출 + return ResponseEntity.status(HttpStatus.OK) // HTTP 204 No Content .body(GlobalResponseDto.success()); } @@ -91,7 +97,9 @@ public ResponseEntity> deleteInvitation( @Operation(summary = "비회원 청첩장 조회", description = "UUID 기반으로 청첩장 조회") public ResponseEntity> getInvitationForGuest( @PathVariable String uniqueId) { + InvitationResponseDto response = invitationService.getInvitationForGuest(uniqueId); + return ResponseEntity.status(HttpStatus.OK) .body(GlobalResponseDto.success(response)); } diff --git a/src/main/java/com/wedit/weditapp/domain/invitation/domain/Invitation.java b/src/main/java/com/wedit/weditapp/domain/invitation/domain/Invitation.java index 15ca210..594d9cf 100644 --- a/src/main/java/com/wedit/weditapp/domain/invitation/domain/Invitation.java +++ b/src/main/java/com/wedit/weditapp/domain/invitation/domain/Invitation.java @@ -18,6 +18,7 @@ @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Invitation extends BaseTimeEntity { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; diff --git a/src/main/java/com/wedit/weditapp/domain/invitation/dto/request/InvitationCreateRequestDto.java b/src/main/java/com/wedit/weditapp/domain/invitation/dto/request/InvitationCreateRequestDto.java index 9daa4f3..576b72e 100644 --- a/src/main/java/com/wedit/weditapp/domain/invitation/dto/request/InvitationCreateRequestDto.java +++ b/src/main/java/com/wedit/weditapp/domain/invitation/dto/request/InvitationCreateRequestDto.java @@ -8,12 +8,13 @@ import java.time.LocalTime; import java.util.List; -import com.wedit.weditapp.domain.bankAccounts.dto.BankAccountDto; +import com.wedit.weditapp.domain.bankAccount.dto.BankAccountDto; import com.wedit.weditapp.domain.shared.Theme; @Getter @NoArgsConstructor public class InvitationCreateRequestDto { + @NotBlank(message = "groom cannot be blank") private String groom; // 신랑 이름 @@ -21,28 +22,22 @@ public class InvitationCreateRequestDto { private String bride; // 신부 이름 private String groomF; // 신랑 아버지 이름 - private String groomM; // 신랑 어머니 이름 private String brideF; // 신부 아버지 이름 - private String brideM; // 신부 어머니 이름 @NotBlank(message = "address cannot be blank") private String address; // 주소 - private String extraAddress; // 상세 주소 private LocalDate date; // 결혼식 날짜 - private LocalTime time; private Theme theme; // 테마 private boolean guestBookOption; // 방명록 옵션 - private boolean decisionOption; // 참석 의사 수집 옵션 - private boolean accountOption; // 계좌 공개 옵션 private List bankAccounts; // 계좌 정보 리스트 diff --git a/src/main/java/com/wedit/weditapp/domain/invitation/dto/request/InvitationUpdateRequestDto.java b/src/main/java/com/wedit/weditapp/domain/invitation/dto/request/InvitationUpdateRequestDto.java index 3a822f9..6661d31 100644 --- a/src/main/java/com/wedit/weditapp/domain/invitation/dto/request/InvitationUpdateRequestDto.java +++ b/src/main/java/com/wedit/weditapp/domain/invitation/dto/request/InvitationUpdateRequestDto.java @@ -1,7 +1,6 @@ package com.wedit.weditapp.domain.invitation.dto.request; import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.NoArgsConstructor; @@ -9,12 +8,13 @@ import java.time.LocalTime; import java.util.List; -import com.wedit.weditapp.domain.bankAccounts.dto.BankAccountDto; +import com.wedit.weditapp.domain.bankAccount.dto.BankAccountDto; import com.wedit.weditapp.domain.shared.Theme; @Getter @NoArgsConstructor public class InvitationUpdateRequestDto { + @NotBlank(message = "groom cannot be blank") private String groom; // 신랑 이름 @@ -22,28 +22,22 @@ public class InvitationUpdateRequestDto { private String bride; // 신부 이름 private String groomF; // 신랑 아버지 이름 - private String groomM; // 신랑 어머니 이름 private String brideF; // 신부 아버지 이름 - private String brideM; // 신부 어머니 이름 @NotBlank(message = "address cannot be blank") private String address; // 주소 - private String extraAddress; // 상세 주소 private LocalDate date; // 결혼식 날짜 - private LocalTime time; // 결혼식 날짜 private Theme theme; // 테마 private boolean guestBookOption; // 방명록 옵션 - private boolean decisionOption; // 참석 의사 수집 옵션 - private boolean accountOption; // 계좌 공개 옵션 private List bankAccounts; // 계좌 정보 리스트 diff --git a/src/main/java/com/wedit/weditapp/domain/invitation/dto/response/InvitationResponseDto.java b/src/main/java/com/wedit/weditapp/domain/invitation/dto/response/InvitationResponseDto.java index afbf687..804f41d 100644 --- a/src/main/java/com/wedit/weditapp/domain/invitation/dto/response/InvitationResponseDto.java +++ b/src/main/java/com/wedit/weditapp/domain/invitation/dto/response/InvitationResponseDto.java @@ -1,6 +1,6 @@ package com.wedit.weditapp.domain.invitation.dto.response; -import com.wedit.weditapp.domain.bankAccounts.dto.BankAccountDto; +import com.wedit.weditapp.domain.bankAccount.dto.BankAccountDto; import com.wedit.weditapp.domain.comment.dto.response.CommentResponseDto; import com.wedit.weditapp.domain.image.dto.response.ImageResponseDto; import com.wedit.weditapp.domain.invitation.domain.Invitation; @@ -21,39 +21,27 @@ public class InvitationResponseDto { private Long id; private String groom; // 신랑 이름 - private String bride; // 신부 이름 - private String groomF; // 신랑 아버지 이름 - private String groomM; // 신랑 어머니 이름 - private String brideF; // 신부 아버지 이름 - private String brideM; // 신부 어머니 이름 private String address; // 주소 - private String extraAddress; // 상세 주소 private LocalDate date; // 결혼식 날짜 - private LocalTime time; private Theme theme; // 테마 - private String distribution; // 청첩장 URL private boolean guestBookOption; // 방명록 옵션 - private boolean decisionOption; // 참석 여부 옵션 - private boolean accountOption; // 계좌 공개 옵션 private List bankAccounts; // 계좌 정보 리스트 - private List image; - private List comment; // 방명록 리스트 @Builder diff --git a/src/main/java/com/wedit/weditapp/domain/invitation/service/InvitationService.java b/src/main/java/com/wedit/weditapp/domain/invitation/service/InvitationService.java index f021eb0..354a50e 100644 --- a/src/main/java/com/wedit/weditapp/domain/invitation/service/InvitationService.java +++ b/src/main/java/com/wedit/weditapp/domain/invitation/service/InvitationService.java @@ -1,15 +1,14 @@ package com.wedit.weditapp.domain.invitation.service; import java.util.List; -import java.util.UUID; import java.util.stream.Collectors; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; -import com.wedit.weditapp.domain.bankAccounts.dto.BankAccountDto; -import com.wedit.weditapp.domain.bankAccounts.service.BankAccountService; +import com.wedit.weditapp.domain.bankAccount.dto.BankAccountDto; +import com.wedit.weditapp.domain.bankAccount.service.BankAccountService; import com.wedit.weditapp.domain.comment.domain.Comment; import com.wedit.weditapp.domain.comment.domain.repository.CommentRepository; import com.wedit.weditapp.domain.comment.dto.response.CommentResponseDto; @@ -30,11 +29,14 @@ import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +@Slf4j @Service @Transactional @RequiredArgsConstructor public class InvitationService { + private final InvitationRepository invitationRepository; private final ImageService imageService; private final MemberRepository memberRepository; @@ -42,6 +44,7 @@ public class InvitationService { private final CommentService commentService; private final DecisionService decisionService; private final CommentRepository commentRepository; + private static final int MAX_INVITATIONS = 10; @@ -111,6 +114,7 @@ public InvitationResponseDto getInvitation(UserDetails userDetails, Long invitat // 청첩장 목록 조회 (생성일 기준 오름차순) public List getMemberInvitations(UserDetails userDetails) { Member member = getMember(userDetails); + List invitations = invitationRepository.findByMemberIdOrderByCreatedAtAsc(member.getId()); return invitations.stream() @@ -158,7 +162,7 @@ public void updateInvitation(UserDetails userDetails, Long invitationId, Invitat // 계좌 정보 업데이트 / isAccountOption이 false로 변경될 경우 계좌 정보 삭제 if (updateRequest.isAccountOption() && updateRequest.getBankAccounts() != null) { bankAccountService.updateBankAccount(updateRequest.getBankAccounts(), invitation); - }else if (!updateRequest.isAccountOption()) { + } else if (!updateRequest.isAccountOption()) { bankAccountService.deleteBankAccount(invitation); } @@ -195,7 +199,8 @@ public String generateAndSaveInvitationUrl(UserDetails userDetails, Long invitat // URL 저장 invitation.updateUrl(generatedUrl); - System.out.println("생성된 url = " + invitation.getDistribution()); + log.info("생성된 url : {}", generatedUrl); + invitationRepository.save(invitation); } @@ -205,6 +210,7 @@ public String generateAndSaveInvitationUrl(UserDetails userDetails, Long invitat // 청첩장 삭제 public void deleteInvitation(UserDetails userDetails, Long invitationId) { Member member = getMember(userDetails); + // 청첩장 조회 Invitation invitation = invitationRepository.findByIdAndMember(invitationId, member) .orElseThrow(() -> new CommonException(ErrorCode.INVITATION_NOT_FOUND)); @@ -231,8 +237,10 @@ public void cleanUpExcessInvitations(UserDetails userDetails) { Long memberId = member.getId(); List invitations = invitationRepository.findByMemberIdOrderByCreatedAtAsc(memberId); + if (invitations.size() > MAX_INVITATIONS) { int excessCount = invitations.size() - MAX_INVITATIONS; + List excessInvitations = invitations.subList(0, excessCount); List excessInvitationIds = excessInvitations.stream() .map(Invitation::getId) @@ -270,12 +278,11 @@ private Member getMember(UserDetails userDetails) { } public StatisticsDto getInvitationStatistics(UserDetails userDetails, Long invitationId) { - Member member = getMember(userDetails); + //Member member = getMember(userDetails); Invitation invitation = invitationRepository.findById(invitationId) .orElseThrow(() -> new CommonException(ErrorCode.INVITATION_NOT_FOUND)); return StatisticsDto.of(invitation, decisionService.getDecisionCounts(invitationId)); } - } diff --git a/src/main/java/com/wedit/weditapp/domain/member/controller/MemberController.java b/src/main/java/com/wedit/weditapp/domain/member/controller/MemberController.java index 368f1d8..ce2d91b 100644 --- a/src/main/java/com/wedit/weditapp/domain/member/controller/MemberController.java +++ b/src/main/java/com/wedit/weditapp/domain/member/controller/MemberController.java @@ -3,8 +3,6 @@ import com.wedit.weditapp.domain.invitation.dto.response.InvitationResponseDto; import com.wedit.weditapp.domain.invitation.dto.response.StatisticsDto; import com.wedit.weditapp.domain.invitation.service.InvitationService; -import com.wedit.weditapp.global.error.ErrorCode; -import com.wedit.weditapp.global.error.exception.CommonException; import com.wedit.weditapp.global.response.GlobalResponseDto; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -36,6 +34,7 @@ public class MemberController { public ResponseEntity>> getMemberInvitations( @AuthenticationPrincipal UserDetails userDetails) { List invitations = invitationService.getMemberInvitations(userDetails); + return ResponseEntity.status(HttpStatus.OK).body(GlobalResponseDto.success(invitations)); } diff --git a/src/main/java/com/wedit/weditapp/domain/shared/S3Service.java b/src/main/java/com/wedit/weditapp/domain/shared/S3Service.java index c8f89dc..d31d88f 100644 --- a/src/main/java/com/wedit/weditapp/domain/shared/S3Service.java +++ b/src/main/java/com/wedit/weditapp/domain/shared/S3Service.java @@ -53,23 +53,27 @@ private String putS3(MultipartFile multipartFile, String fileName, ObjectMetadat } catch (IOException e) { throw new RuntimeException("파일 업로드 중 오류 발생", e); } + return amazonS3Client.getUrl(bucket, fileName).toString(); } //이미지 가져오기(url) => 사실상 DB에 저장된 Url을 사용하기에 문제 없음 public String getImageFileUrl(String fileName) { String filePath = imageFolder + fileName; + return amazonS3Client.getUrl(bucket, filePath).toString(); } //파일 이름 중복 방지 코드 private String generateUniqueFileName(String originalFilename) { String extension = originalFilename.substring(originalFilename.lastIndexOf(".")); + return UUID.randomUUID() + extension; // 고유 파일 이름 생성 } //검증로직 필요하면 사용 가능 private void validateFileFormat(MultipartFile multipartFile) { String contentType = multipartFile.getContentType(); + if (contentType == null || !contentType.startsWith("image/")) { throw new IllegalArgumentException("지원하지 않는 파일 형식입니다."); } diff --git a/src/main/java/com/wedit/weditapp/global/auth/jwt/JwtAuthenticationFilter.java b/src/main/java/com/wedit/weditapp/global/auth/jwt/JwtAuthenticationFilter.java index 072fb6d..bf63643 100644 --- a/src/main/java/com/wedit/weditapp/global/auth/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/com/wedit/weditapp/global/auth/jwt/JwtAuthenticationFilter.java @@ -30,7 +30,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { private final JwtProvider jwtProvider; private final MemberRepository memberRepository; private final RefreshTokenService refreshTokenService; - private final GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper(); @Override @@ -80,6 +79,7 @@ private Optional extractCookie(HttpServletRequest request, String cookie if (request.getCookies() == null) { return Optional.empty(); } + return Arrays.stream(request.getCookies()) .filter(cookie -> cookieName.equals(cookie.getName())) .map(Cookie::getValue) diff --git a/src/main/java/com/wedit/weditapp/global/auth/jwt/JwtProvider.java b/src/main/java/com/wedit/weditapp/global/auth/jwt/JwtProvider.java index c934b70..a044e37 100644 --- a/src/main/java/com/wedit/weditapp/global/auth/jwt/JwtProvider.java +++ b/src/main/java/com/wedit/weditapp/global/auth/jwt/JwtProvider.java @@ -32,11 +32,11 @@ public class JwtProvider { @Value("${jwt.refresh.expiration}") private long refreshTokenExpiry; // 만료 시간 : 1209600000 (2주) - private Key key; // 실제 사용할 HMAC용 key 객체 - /*@Value("${cookie-domain}") private String cookieDomain;*/ + private Key key; // 실제 사용할 HMAC용 key 객체 + private static final String EMAIL_CLAIM = "email"; private static final String ACCESS_COOKIE_NAME = "accessToken"; private static final String REFRESH_COOKIE_NAME = "refreshToken"; @@ -79,6 +79,7 @@ private String buildToken(String email, String subject, long expiryTime) { // Access Token : HttpOnly, Secure 쿠키로 설정 public void setAccessTokenCookie(HttpServletResponse response, String accessToken) { Cookie accessCookie = new Cookie(ACCESS_COOKIE_NAME, accessToken); + accessCookie.setHttpOnly(true); // JavaScript에서 접근 불가능 accessCookie.setSecure(true); // HTTPS 상황에서만 전송 accessCookie.setPath("/"); @@ -94,6 +95,7 @@ public void setAccessTokenCookie(HttpServletResponse response, String accessToke // Refresh Token : HttpOnly, Secure 쿠키로 설정 public void setRefreshTokenCookie(HttpServletResponse response, String refreshToken) { Cookie refreshCookie = new Cookie(REFRESH_COOKIE_NAME, refreshToken); + refreshCookie.setHttpOnly(true); // JavaScript에서 접근 불가능 refreshCookie.setSecure(true); // HTTPS 환경에서만 전송 refreshCookie.setPath("/"); @@ -111,6 +113,7 @@ public Optional extractAccessCookie(HttpServletRequest request) { if (request.getCookies() == null) { return Optional.empty(); } + return Arrays.stream(request.getCookies()) .filter(cookie -> ACCESS_COOKIE_NAME.equals(cookie.getName())) .map(Cookie::getValue) @@ -122,6 +125,7 @@ public Optional extractRefreshCookie(HttpServletRequest request) { if (request.getCookies() == null) { return Optional.empty(); } + return Arrays.stream(request.getCookies()) .filter(cookie -> REFRESH_COOKIE_NAME.equals(cookie.getName())) .map(Cookie::getValue) @@ -140,6 +144,7 @@ public Optional extractEmail(String token) { return Optional.ofNullable(claims.get(EMAIL_CLAIM, String.class)); } catch (JwtException e) { log.error("토큰에서 email 클레임 추출 실패: {}", e.getMessage()); + return Optional.empty(); } } @@ -152,7 +157,9 @@ public boolean validateToken(String token) { .verifyWith((SecretKey) key) .build() .parseSignedClaims(token); + return true; + } catch (SecurityException | MalformedJwtException e) { log.error("잘못된 JWT 서명 : {}", e.getMessage()); throw new CommonException(ErrorCode.INVALID_JWT_SIGNATURE); diff --git a/src/main/java/com/wedit/weditapp/global/auth/login/domain/CustomOAuth2User.java b/src/main/java/com/wedit/weditapp/global/auth/login/domain/CustomOAuth2User.java index 77b8ff3..54ec322 100644 --- a/src/main/java/com/wedit/weditapp/global/auth/login/domain/CustomOAuth2User.java +++ b/src/main/java/com/wedit/weditapp/global/auth/login/domain/CustomOAuth2User.java @@ -14,6 +14,7 @@ public class CustomOAuth2User extends DefaultOAuth2User { private String email; private MemberRole role; private MemberStatus status; + public CustomOAuth2User(Collection authorities, Map attributes, String nameAttributeKey, String email, MemberRole role, MemberStatus status) { diff --git a/src/main/java/com/wedit/weditapp/global/config/swagger/SwaggerConfig.java b/src/main/java/com/wedit/weditapp/global/config/swagger/SwaggerConfig.java index 088b745..2caa764 100644 --- a/src/main/java/com/wedit/weditapp/global/config/swagger/SwaggerConfig.java +++ b/src/main/java/com/wedit/weditapp/global/config/swagger/SwaggerConfig.java @@ -19,6 +19,7 @@ version = "v1.0.0")) @Configuration public class SwaggerConfig { + @Bean public OpenAPI openAPI() { SecurityScheme securityScheme = getSecurityScheme(); diff --git a/src/main/java/com/wedit/weditapp/global/error/exception/GlobalExceptionHandler.java b/src/main/java/com/wedit/weditapp/global/error/exception/GlobalExceptionHandler.java index 8da3a4e..35c81ca 100644 --- a/src/main/java/com/wedit/weditapp/global/error/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/wedit/weditapp/global/error/exception/GlobalExceptionHandler.java @@ -65,5 +65,4 @@ public ResponseEntity> handleValidationExceptions( return ResponseEntity.status(HttpStatus.valueOf(errorCode.getStatus())) .body(GlobalResponseDto.fail(errorCode, errorMessage)); } - }