Skip to content

Commit

Permalink
Merge pull request #130 from kakao-tech-campus-2nd-step3/fix/ISSUE-129
Browse files Browse the repository at this point in the history
MemberService <-> SecurityBeanGenerator 순환 참조 문제 해결
  • Loading branch information
jjt4515 authored Nov 11, 2024
2 parents f92ef30 + e7e62ec commit 4e8322e
Show file tree
Hide file tree
Showing 33 changed files with 312 additions and 166 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@
@Configuration
public class SecurityBeanGenerator {

private final TokenStorageService tokenStorageService;
private final MemberService memberService;
private final TokenBlacklistService tokenBlacklistService;

@Bean
@Description("AuthenticationProvider를 위한 Spring bean")
Expand All @@ -37,11 +34,5 @@ MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) {
return new MvcRequestMatcher.Builder(introspector);
}

@Bean
JwtUtil jwtUtil(){
return new JwtUtil(tokenBlacklistService,
tokenStorageService,
memberService);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2Authentic


//일단 없으면 가입시키는 쪽으로 구현ㄴ
Member member = memberRepository.findByEmail(email).orElse(null);
Member member = memberRepository.findByEmailAndDeletedAtIsNull(email).orElse(null);
if(member == null) {
member = Member.builder()
.email(email)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public UserDetailsServiceImpl(MemberRepository memberRepository) {

@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Member member = memberRepository.findByEmail(email)
Member member = memberRepository.findByEmailAndDeletedAtIsNull(email)
.orElseThrow(() -> new BusinessException(BusinessError.MEMBER_NOT_FOUND));
return new UserDetailsImpl(member);
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package poomasi.domain.auth.token.refreshtoken.service;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
package poomasi.domain.auth.token.reissue.controller;


import org.springframework.beans.factory.annotation.Autowired;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import poomasi.domain.auth.security.userdetail.UserDetailsImpl;
import poomasi.domain.auth.token.reissue.dto.ReissueRequest;
import poomasi.domain.auth.token.reissue.dto.ReissueResponse;
import poomasi.domain.auth.token.reissue.service.ReissueTokenService;
import poomasi.domain.member.entity.Member;

@RestController
@RequiredArgsConstructor
public class ReissueTokenController {

@Autowired
private ReissueTokenService reissueTokenService;
private final ReissueTokenService reissueTokenService;

@Secured({"ROLE_FARMER", "ROLE_CUSTOMER"})
@PostMapping("/api/reissue")
public ResponseEntity<ReissueResponse> reissue(@AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody ReissueRequest reissueRequest){
Member member = userDetails.getMember();
return ResponseEntity.ok(reissueTokenService.reissueToken(member.getId(), reissueRequest));
public ResponseEntity<ReissueResponse> reissue(@RequestHeader(HttpHeaders.AUTHORIZATION) String authorizationHeader,
@RequestBody ReissueRequest reissueRequest){

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

return ResponseEntity.ok(reissueTokenService.reissueToken(accessToken, reissueRequest));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ public class ReissueTokenService {
private final RefreshTokenService refreshTokenService;

// 토큰 재발급
public ReissueResponse reissueToken(Long memberId, ReissueRequest reissueRequest) {
public ReissueResponse reissueToken(String accessToken, ReissueRequest reissueRequest) {
Long memberId = jwtUtil.getIdFromToken(accessToken);

String refreshToken = reissueRequest.refreshToken();
Long requestMemberId = jwtUtil.getIdFromToken(refreshToken);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class ImageController {

// 이미지 정보 저장
@PostMapping
@Secured({"ROLE_MEMBER", "ROLE_FARMER", "ROLE_ADMIN"})
@Secured({"ROLE_CUSTOMER", "ROLE_FARMER", "ROLE_ADMIN"})
public ResponseEntity<?> saveImageInfo(@AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody ImageRequest imageRequest) {
Member member = userDetails.getMember();
Image savedImage = imageService.saveImage(member.getId(), imageRequest);
Expand All @@ -31,7 +31,7 @@ public ResponseEntity<?> saveImageInfo(@AuthenticationPrincipal UserDetailsImpl

// 여러 이미지 정보 저장
@PostMapping("/multiple")
@Secured({"ROLE_MEMBER", "ROLE_FARMER", "ROLE_ADMIN"})
@Secured({"ROLE_CUSTOMER", "ROLE_FARMER", "ROLE_ADMIN"})
public ResponseEntity<List<Image>> saveMultipleImages(@AuthenticationPrincipal UserDetailsImpl userDetails, @RequestBody List<ImageRequest> imageRequests) {
Member member = userDetails.getMember();
List<Image> savedImages = imageService.saveMultipleImages(member.getId(), imageRequests);
Expand All @@ -40,7 +40,7 @@ public ResponseEntity<List<Image>> saveMultipleImages(@AuthenticationPrincipal U

// 특정 이미지 삭제
@DeleteMapping("/delete/{id}")
@Secured({"ROLE_MEMBER", "ROLE_FARMER", "ROLE_ADMIN"})
@Secured({"ROLE_CUSTOMER", "ROLE_FARMER", "ROLE_ADMIN"})
public ResponseEntity<Void> deleteImage(@AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable Long id) {
Member member = userDetails.getMember();
imageService.deleteImage(member.getId(), id);
Expand All @@ -62,7 +62,7 @@ public ResponseEntity<List<Image>> getImagesByTypeAndReference(@PathVariable Ima

// 이미지 정보 수정
@PutMapping("update/{id}")
@Secured({"ROLE_MEMBER", "ROLE_FARMER", "ROLE_ADMIN"})
@Secured({"ROLE_CUSTOMER", "ROLE_FARMER", "ROLE_ADMIN"})
public ResponseEntity<?> updateImageInfo(@AuthenticationPrincipal UserDetailsImpl userDetails,
@PathVariable Long id,
@RequestBody ImageRequest imageRequest) {
Expand All @@ -72,7 +72,7 @@ public ResponseEntity<?> updateImageInfo(@AuthenticationPrincipal UserDetailsImp
}

@PutMapping("/recover/{id}")
@Secured({"ROLE_MEMBER", "ROLE_FARMER", "ROLE_ADMIN"})
@Secured({"ROLE_CUSTOMER", "ROLE_FARMER", "ROLE_ADMIN"})
public ResponseEntity<Void> recoverImage(@AuthenticationPrincipal UserDetailsImpl userDetails, @PathVariable Long id) {
Member member = userDetails.getMember();
imageService.recoverImage(member.getId(), id);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package poomasi.domain.image.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import poomasi.domain.image.entity.Image;
import poomasi.domain.image.entity.ImageType;

import java.util.List;
import java.util.Optional;

@Repository
public interface ImageRepository extends JpaRepository<Image, Long> {
long countByTypeAndReferenceIdAndDeletedAtIsNull(ImageType type, Long referenceId);
List<Image> findByTypeAndReferenceIdAndDeletedAtIsNull(ImageType type, Long referenceId);
Expand Down
19 changes: 12 additions & 7 deletions src/main/java/poomasi/domain/image/service/ImageService.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import poomasi.domain.image.validation.ImageOwnerValidator;
import poomasi.domain.image.validation.ImageOwnerValidatorFactory;
import poomasi.domain.member._profile.entity.MemberProfile;
import poomasi.domain.member._profile.repository.MemberProfileRepository;
import poomasi.domain.member._profile.service.MemberProfileService;
import poomasi.domain.member.entity.Member;
import poomasi.domain.member.repository.MemberRepository;
import poomasi.global.error.BusinessException;
Expand All @@ -26,10 +26,14 @@
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ImageService {

private static final int DEFAULT_IMAGE_LIMIT = 5;
private static final int MEMBER_PROFILE_IMAGE_LIMIT = 1;

private final ImageRepository imageRepository;
private final ImageOwnerValidatorFactory validatorFactory;
private final MemberRepository memberRepository;
private final MemberProfileRepository memberProfileRepository;
private final MemberProfileService memberProfileService;


@Transactional
Expand Down Expand Up @@ -83,19 +87,20 @@ private Image recoverImageOrThrow(Image existingImage, ImageRequest imageRequest
}

private void validateImageLimit(ImageRequest imageRequest) {
int imageLimit = 5;
if (imageRequest.type() == ImageType.MEMBER_PROFILE) imageLimit = 1; // 멤버 프로필 이미지는 한 장으로 제한
int imageLimit = DEFAULT_IMAGE_LIMIT;
if (imageRequest.type() == ImageType.MEMBER_PROFILE) {
imageLimit = MEMBER_PROFILE_IMAGE_LIMIT; // 멤버 프로필 이미지는 한 장으로 제한
}

if (imageRepository.countByTypeAndReferenceIdAndDeletedAtIsNull(imageRequest.type(), imageRequest.referenceId()) >= imageLimit) {
throw new BusinessException(IMAGE_LIMIT_EXCEED);
}
}

private void linkImageToMemberProfile(Long referenceId, Image savedImage) {
MemberProfile memberProfile = memberProfileRepository.findById(referenceId)
.orElseThrow(() -> new BusinessException(MEMBER_PROFILE_NOT_FOUND));
MemberProfile memberProfile = memberProfileService.getMemberProfileById(referenceId);
memberProfile.setProfileImage(savedImage);
memberProfileRepository.save(memberProfile);
memberProfileService.saveMemberProfile(memberProfile);
}

// 여러 이미지 저장
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package poomasi.domain.member._profile.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import poomasi.domain.member._profile.service.MemberProfileService;

@RestController
@RequiredArgsConstructor
@RequestMapping("api/member/profile")
public class MemberProfileController {

private final MemberProfileService memberProfileService;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package poomasi.domain.member._profile.dto.request;


public record MemberProfileRequest() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package poomasi.domain.member._profile.dto.response;

import lombok.AllArgsConstructor;
import poomasi.domain.image.entity.Image;
import poomasi.domain.member._profile.entity.MemberProfile;

import java.time.LocalDateTime;

@AllArgsConstructor
public class CommonProfileResponse implements MemberProfileResponse {
String phoneNumber;
boolean isBanned;
LocalDateTime createdAt;
Image profileImage;

public static CommonProfileResponse fromEntity(MemberProfile profile) {
return new CommonProfileResponse(
profile.getPhoneNumber(),
profile.isBanned(),
profile.getCreatedAt(),
profile.getProfileImage()
);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package poomasi.domain.member._profile.dto.response;

import lombok.AllArgsConstructor;
import poomasi.domain.image.entity.Image;
import poomasi.domain.member._profile.entity.CustomerProfile;

import java.time.LocalDateTime;

@AllArgsConstructor
public class CustomerProfileResponse implements MemberProfileResponse{
String phoneNumber;
String address;
String addressDetail;
boolean isBanned;
LocalDateTime createdAt;
Image profileImage;

public static CustomerProfileResponse fromEntity(CustomerProfile profile) {
return new CustomerProfileResponse(
profile.getPhoneNumber(),
profile.getAddress(),
profile.getAddressDetail(),
profile.isBanned(),
profile.getCreatedAt(),
profile.getProfileImage()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package poomasi.domain.member._profile.dto.response;

import lombok.AllArgsConstructor;
import poomasi.domain.image.entity.Image;
import poomasi.domain.member._profile.entity.FarmerProfile;

import java.time.LocalDateTime;
import java.util.List;

@AllArgsConstructor
public class FarmerProfileResponse implements MemberProfileResponse {
String phoneNumber;
boolean isBanned;
LocalDateTime createdAt;
Image profileImage;
String storeName;
String farmName;
List<String> businessRegistrationNumbers;
String storeAddress;
String storeAddressDetail;
String farmAddress;
String farmAddressDetail;

public static FarmerProfileResponse fromEntity(FarmerProfile profile) {
return new FarmerProfileResponse(
profile.getPhoneNumber(),
profile.isBanned(),
profile.getCreatedAt(),
profile.getProfileImage(),
profile.getStoreName(),
profile.getFarmName(),
profile.getBusinessRegistrationNumbers(),
profile.getStoreAddress(),
profile.getStoreAddressDetail(),
profile.getFarmAddress(),
profile.getFarmAddressDetail()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package poomasi.domain.member._profile.dto.response;

import poomasi.domain.member._profile.entity.CustomerProfile;
import poomasi.domain.member._profile.entity.FarmerProfile;
import poomasi.domain.member._profile.entity.MemberProfile;

public interface MemberProfileResponse {

static MemberProfileResponse fromEntity(MemberProfile profile) {
if (profile instanceof FarmerProfile farmerProfile) {
return FarmerProfileResponse.fromEntity(farmerProfile);
} else if (profile instanceof CustomerProfile customerProfile) {
return CustomerProfileResponse.fromEntity(customerProfile);
} else {
return CommonProfileResponse.fromEntity(profile);
}
}
}
Loading

0 comments on commit 4e8322e

Please sign in to comment.