Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Refactor] 로그인 에러 페이지 반환 #151

Merged
merged 10 commits into from
Feb 2, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class DeliveryMeeting extends Meeting {
private String accountNumber;

@Column(nullable = false)
@Enumerated(EnumType.STRING)
private BankName bankName;

public void updateDeliveryMeeting(
Expand All @@ -47,13 +48,14 @@ public void updateDeliveryMeeting(
String storeName,
String pickupLocation,
String accountNumber,
BankName bankName,
Image backgroundImage
) {
super.updateMeeting(meetingName, description, backgroundImage);

this.foodCategory = foodCategory;
this.storeName = storeName;
this.pickupLocation = pickupLocation;
this.accountNumber = accountNumber;
this.bankName = bankName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,8 @@ private ConstructorExpression<MeetingListResponseDto> createDeliveryMeetingProje
meeting.participantLimit.maxParticipants,
deliveryMeeting.storeName.as("location"),
meeting.createdAt,
deliveryMeeting.orderDeadline.as("dueDateTime")
deliveryMeeting.orderDeadline.as("dueDateTime"),
meeting.chatRoom.lastChatAt
);
}

Expand All @@ -326,7 +327,8 @@ private ConstructorExpression<MeetingListResponseDto> createOfflineMeetingProjec
meeting.participantLimit.maxParticipants,
offlineMeeting.meetingPlace.as("location"),
meeting.createdAt,
offlineMeeting.meetingDate.as("dueDateTime")
offlineMeeting.meetingDate.as("dueDateTime"),
meeting.chatRoom.lastChatAt
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ public class MeetingDetailResponseDto {
private LocalDateTime dueDateTime;
private String backgroundImage;
private Boolean isOwner;
private Boolean isCurrentUser;
private List<ParticipantDto> participants;

@Builder
private MeetingDetailResponseDto(String meetingType, String meetingName, String meetingDescription,
GenderRestriction genderRestriction, String location, LocalDateTime dueDateTime,
String backgroundImage, Boolean isOwner, List<ParticipantDto> participants) {
String backgroundImage, Boolean isOwner, Boolean isCurrentUser, List<ParticipantDto> participants) {
this.meetingType = meetingType;
this.meetingName = meetingName;
this.meetingDescription = meetingDescription;
Expand All @@ -32,29 +33,35 @@ private MeetingDetailResponseDto(String meetingType, String meetingName, String
this.dueDateTime = dueDateTime;
this.backgroundImage = backgroundImage;
this.isOwner = isOwner;
this.isCurrentUser = isCurrentUser;
this.participants = participants;
}

@Getter
public static class ParticipantDto {
private Long userId;
private String name;
private String userProfileImage;
private Boolean isOwner;
private Boolean isCurrentUser;

@Builder
private ParticipantDto(Long userId, String name, Boolean isOwner, Boolean isCurrentUser) {
private ParticipantDto(Long userId, String name, Boolean isOwner, Boolean isCurrentUser,
String userProfileImage) {
this.userId = userId;
this.name = name;
this.userProfileImage = userProfileImage;
this.isOwner = isOwner;
this.isCurrentUser = isCurrentUser;
}

public static ParticipantDto createParticipantDto(Long userId, String name, Boolean isOwner,
public static ParticipantDto createParticipantDto(Long userId, String name, String userProfileImage,
Boolean isOwner,
Boolean isCurrentUser) {
return ParticipantDto.builder()
.userId(userId)
.name(name)
.userProfileImage(userProfileImage)
.isOwner(isOwner)
.isCurrentUser(isCurrentUser)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ public class MeetingListResponseDto {
private String location;
private LocalDateTime createdAt;
private LocalDateTime dueDateTime;
private LocalDateTime lastChatAt;

public MeetingListResponseDto(Long meetingId, String meetingName, String meetingDescription,
Long currentParticipantCount, Long maxParticipants, String location, LocalDateTime createdAt,
LocalDateTime dueDateTime) {
LocalDateTime dueDateTime, LocalDateTime lastChatAt) {
this.meetingId = meetingId;
this.meetingName = meetingName;
this.meetingDescription = meetingDescription;
Expand All @@ -26,6 +27,7 @@ public MeetingListResponseDto(Long meetingId, String meetingName, String meeting
this.location = location;
this.createdAt = createdAt;
this.dueDateTime = dueDateTime;
this.lastChatAt = lastChatAt;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import org.springframework.web.multipart.MultipartFile;

import com.example.eatmate.app.domain.meeting.domain.BankName;
import com.example.eatmate.app.domain.meeting.domain.FoodCategory;

import jakarta.validation.constraints.Future;
Expand Down Expand Up @@ -34,5 +35,7 @@ public class UpdateDeliveryMeetingRequestDto {
@Pattern(regexp = "^[0-9-]*$", message = "올바른 계좌번호 형식이 아닙니다")
private String accountNumber;

private BankName bankName;

private MultipartFile backgroundImage;
}
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,9 @@ public MeetingDetailResponseDto getMeetingDetail(Long meetingId, UserDetails use
Meeting meeting = meetingRepository.findById(meetingId)
.orElseThrow(() -> new CommonException(ErrorCode.MEETING_NOT_FOUND));

Long currentUserId = securityUtils.getMember(userDetails).getMemberId();
Member member = securityUtils.getMember(userDetails);

List<MeetingDetailResponseDto.ParticipantDto> participants = getParticipants(meeting, currentUserId);
List<MeetingDetailResponseDto.ParticipantDto> participants = getParticipants(meeting, member.getMemberId());

return MeetingDetailResponseDto.builder()
.meetingType(meeting.getType())
Expand All @@ -284,7 +284,8 @@ public MeetingDetailResponseDto getMeetingDetail(Long meetingId, UserDetails use
.location(getLocation(meeting))
.dueDateTime(getDueDateTime(meeting))
.backgroundImage(Optional.ofNullable(meeting.getBackgroundImage()).map(Image::getImageUrl).orElse(null))
.isOwner(isOwner(meeting, currentUserId))
.isOwner(isOwner(meeting, member.getMemberId()))
.isCurrentUser(isCurrentUser(meeting, member))
.participants(participants)
.build();
}
Expand Down Expand Up @@ -313,6 +314,10 @@ private Boolean isOwner(Meeting meeting, Long currentUserId) {
.orElse(false);
}

private Boolean isCurrentUser(Meeting meeting, Member member) {
return meetingParticipantRepository.existsByMeetingAndMember(meeting, member);
}

private List<MeetingDetailResponseDto.ParticipantDto> getParticipants(Meeting meeting, Long currentUserId) {
return meetingParticipantRepository.findByMeeting(meeting).stream()
.sorted((p1, p2) -> {
Expand All @@ -327,6 +332,9 @@ private List<MeetingDetailResponseDto.ParticipantDto> getParticipants(Meeting me
.map(participant -> MeetingDetailResponseDto.ParticipantDto.createParticipantDto(
participant.getMember().getMemberId(),
participant.getMember().getNickname(),
Optional.ofNullable(participant.getMember().getProfileImage())
.map(Image::getImageUrl)
.orElse(null),
participant.getRole() == ParticipantRole.HOST,
participant.getMember().getMemberId().equals(currentUserId)
))
Expand Down Expand Up @@ -534,6 +542,7 @@ public void updateDeliveryMeeting(Long meetingId, UpdateDeliveryMeetingRequestDt
updateDeliveryMeetingRequestDto.getStoreName(),
updateDeliveryMeetingRequestDto.getPickupLocation(),
updateDeliveryMeetingRequestDto.getAccountNumber(),
updateDeliveryMeetingRequestDto.getBankName(),
backgroundImage
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public ResponseEntity<GlobalResponseDto<UserInfoResponseDto>> getProfileInfo(
@PatchMapping("/myinfo")
@Operation(summary = "프로필 수정", description = "사용자의 닉네임, 전화번호, MBTI, 생년월일을 일부 수정합니다.")
public ResponseEntity<GlobalResponseDto<MyInfoResponseDto>> updateMyProfile(
@RequestPart(value = "data") @Valid MyInfoUpdateRequestDto updateRequestDto,
@RequestPart(value = "data", required = false) @Valid MyInfoUpdateRequestDto updateRequestDto,
@RequestPart(value = "profileImage", required = false) MultipartFile profileImage,
@AuthenticationPrincipal UserDetails userDetails
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,8 @@ public class MemberSignUpRequestDto {
@Pattern(regexp = "^[가-힣a-zA-Z0-9]{2,12}$", message = "닉네임은 한글, 영문, 숫자로 이루어진 2~12자여야 하며 공백이 없어야 합니다.")
private String nickname;

public void setMbti(String mbti) {
this.mbti = mbti != null ? Mbti.valueOf(mbti.toUpperCase()) : null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@ public class MyInfoUpdateRequestDto {

private Mbti mbti;

public void setMbti(String mbti) {
this.mbti = mbti != null ? Mbti.valueOf(mbti.toUpperCase()) : null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -107,20 +107,22 @@ public MyInfoResponseDto updateMyInfo(UserDetails userDetails, MyInfoUpdateReque
Member member = memberRepository.findByEmailWithProfileImage(email)
.orElseThrow(() -> new CommonException(ErrorCode.USER_NOT_FOUND));

// 닉네임 중복 확인
if (myInfoUpdateRequestDto.getNickname() != null &&
memberRepository.existsByNickname(myInfoUpdateRequestDto.getNickname())) {
throw new CommonException(ErrorCode.DUPLICATE_NICKNAME);
}

// 닉네임 업데이트
if (myInfoUpdateRequestDto.getNickname() != null) {
member.updateNickname(myInfoUpdateRequestDto.getNickname());
}

// MBTI 업데이트
if (myInfoUpdateRequestDto.getMbti() != null) {
member.updateMbti(myInfoUpdateRequestDto.getMbti());
if (myInfoUpdateRequestDto != null) {
// 닉네임 중복 확인
if (myInfoUpdateRequestDto.getNickname() != null &&
memberRepository.existsByNickname(myInfoUpdateRequestDto.getNickname())) {
throw new CommonException(ErrorCode.DUPLICATE_NICKNAME);
}

// 닉네임 업데이트
if (myInfoUpdateRequestDto.getNickname() != null) {
member.updateNickname(myInfoUpdateRequestDto.getNickname());
}

// MBTI 업데이트
if (myInfoUpdateRequestDto.getMbti() != null) {
member.updateMbti(myInfoUpdateRequestDto.getMbti());
}
}

// 프로필 이미지 업로드 처리
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;


import com.example.eatmate.app.domain.member.domain.Gender;
import com.example.eatmate.app.domain.member.domain.Member;
import com.example.eatmate.app.domain.member.domain.Role;
import com.example.eatmate.app.domain.member.domain.repository.MemberRepository;
import com.example.eatmate.global.config.error.ErrorCode;
import com.example.eatmate.global.config.error.exception.CommonException;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

//Spring Security가 OAuth 인증 후 사용자 정보를 가져와 처리하는 커스텀 서비스.

@Slf4j
@Service
@RequiredArgsConstructor
Expand All @@ -33,45 +33,50 @@ public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequ
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
log.info("CustomOAuth2UserService.loadUser() 실행 - OAuth2 로그인 요청 진입");

// 사용자 정보 로드
OAuth2UserService<OAuth2UserRequest, OAuth2User> delegate = new DefaultOAuth2UserService();
OAuth2User oAuth2User = delegate.loadUser(userRequest);

// 사용자 정보 추출
String userNameAttributeName = userRequest.getClientRegistration()
.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();
Map<String, Object> attributes = oAuth2User.getAttributes();

// 사용자 정보를 매핑하여 추출
OAuthAttributes extractAttributes = OAuthAttributes.of(userNameAttributeName, attributes);

// 이메일 도메인 필터링
validateEmailDomain(extractAttributes.getEmail());

// 사용자 정보 조회 또는 저장
Member member = getMember(extractAttributes);


Gender gender = member.getGender();


// 사용자 정보를 CustomOAuth2User로 반환
return new CustomOAuth2User(
Collections.singleton(new SimpleGrantedAuthority(member.getRole() != null
? member.getRole().getRoleType() : Role.GUEST.getRoleType())), // 권한 설정
attributes, // 사용자 속성
extractAttributes.getNameAttributeKey(), // 기본 식별자 키

member.getRole() != null ? member.getRole() : Role.GUEST, // Role 전달
gender
);

try {
// 사용자 정보 로드
OAuth2UserService<OAuth2UserRequest, OAuth2User> delegate = new DefaultOAuth2UserService();
OAuth2User oAuth2User = delegate.loadUser(userRequest);

// 사용자 정보 추출
String userNameAttributeName = userRequest.getClientRegistration()
.getProviderDetails().getUserInfoEndpoint().getUserNameAttributeName();
Map<String, Object> attributes = oAuth2User.getAttributes();

// 사용자 정보를 매핑하여 추출
OAuthAttributes extractAttributes = OAuthAttributes.of(userNameAttributeName, attributes);

// 이메일 도메인 필터링
validateEmailDomain(extractAttributes.getEmail());

// 사용자 정보 조회 또는 저장
Member member = getMember(extractAttributes);

Gender gender = member.getGender();

// 사용자 정보를 CustomOAuth2User로 반환
return new CustomOAuth2User(
Collections.singleton(new SimpleGrantedAuthority(member.getRole() != null
? member.getRole().getRoleType() : Role.GUEST.getRoleType())),
attributes,
extractAttributes.getNameAttributeKey(),
member.getRole() != null ? member.getRole() : Role.GUEST,
gender
);

} catch (CommonException ex) {
throw new OAuth2AuthenticationException(
new OAuth2Error(ex.getErrorCode().getCode()),
ex.getErrorCode().getMessage(),
ex
);
}
}

// 가천 도메인 필터링
private void validateEmailDomain(String email) {
if (!email.endsWith("@gachon.ac.kr")) {
throw new IllegalArgumentException("가천대학교 학생만 이용가능합니다.");
if (email == null || !email.endsWith("@gachon.ac.kr")) {
throw new CommonException(ErrorCode.INVALID_EMAIL_DOMAIN);
}
}

Expand Down
Loading