Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,19 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

// Jwt
implementation 'io.jsonwebtoken:jjwt-api:0.12.3'
implementation 'io.jsonwebtoken:jjwt-impl:0.12.3'
implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3'
implementation 'org.springframework.boot:spring-boot-configuration-processor'

// Security
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'

//OAuth
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'

compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

Expand Down
19 changes: 13 additions & 6 deletions src/main/java/umc/domain/member/controller/MemberController.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import umc.domain.member.converter.MemberConverter;
import umc.domain.member.dto.MemberReqDTO;
Expand All @@ -13,6 +14,7 @@
import umc.domain.member.service.MemberQueryService;
import umc.global.apiPayload.ApiResponse;
import umc.global.apiPayload.code.BaseSuccessCode;
import umc.global.security.entity.AuthMember;

@RestController
@RequiredArgsConstructor
Expand All @@ -22,6 +24,15 @@ public class MemberController {
private final MemberQueryService memberQueryService;
private final MemberCommandService memberCommandService;

@PostMapping("/login")
@Operation(summary = "로그인")
public ApiResponse<MemberResDTO.LoginResultDTO> login(
@RequestBody @Valid MemberReqDTO.LoginReqDTO request
){
MemberResDTO.LoginResultDTO result = memberCommandService.login(request);
BaseSuccessCode code = MemberSuccessCode.OK;
return ApiResponse.onSuccess(code, result);
}

@PostMapping("/sign-up")
@Operation(summary = "회원가입")
Expand All @@ -38,14 +49,10 @@ public ApiResponse<MemberResDTO.JoinResultDTO> join(
@GetMapping("/me")
@Operation(summary = "마이페이지 프로필 조회")
public ApiResponse<MemberResDTO.MyProfileDTO> getMyProfile(
@RequestParam (name = "memberId") Long memberId
@AuthenticationPrincipal AuthMember authMember
){
BaseSuccessCode code = MemberSuccessCode.OK;
//회원 엔티티 조회
Member member = memberQueryService.getMyProfile(memberId);

//컨버터 이용
MemberResDTO.MyProfileDTO result = MemberConverter.toMyProfileDTO(member);
MemberResDTO.MyProfileDTO result = memberQueryService.getMyProfile(authMember);

return ApiResponse.onSuccess(code, result);
}
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/umc/domain/member/converter/MemberConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
import umc.domain.member.entity.Member;
import umc.domain.member.entity.mapping.MemberFood;
import umc.domain.member.entity.mapping.MemberPolicy;
import umc.domain.member.enums.Gender;
import umc.domain.member.enums.SocialType;
import umc.domain.policy.entity.Policy;
import umc.global.security.dto.OAuthDTO;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -25,6 +28,7 @@ public static MemberResDTO.MyProfileDTO toMyProfileDTO(Member member){
);
}

//일반 회원 전용
public static Member toMember(MemberReqDTO.JoinDTO request, String encodedPassword){
return Member.builder()
.name(request.name())
Expand All @@ -42,6 +46,18 @@ public static Member toMember(MemberReqDTO.JoinDTO request, String encodedPasswo
.build();
}

//소셜 로그인 전용
public static Member toMember(OAuthDTO dto) {
return Member.builder()
.name(dto.getName())// 카카오는 닉네임을 주므로 이름/닉네임 동일하게 세팅
.mail(dto.getSocialEmail())
.socialUid(dto.getSocialUid())
.socialType(dto.getSocialType()) // 서비스에서 넘겨준 KAKAO, NAVER 등
// 👇 아래는 DB 필수값(nullable = false)을 통과하기 위한 더미(임시) 데이터들입니다.
.gender(Gender.NONE)
.build();
}

public static MemberFood toMemberFood(Food food){
return MemberFood.builder()
.food(food)
Expand Down Expand Up @@ -88,4 +104,10 @@ public static MemberResDTO.JoinResultDTO toJoinResultDTO(Member member){
.createdAt(member.getCreatedAt())
.build();
}

public static MemberResDTO.LoginResultDTO toLogin(String accessToken) {
return MemberResDTO.LoginResultDTO.builder()
.accessToken(accessToken)
.build();
}
}
5 changes: 5 additions & 0 deletions src/main/java/umc/domain/member/dto/MemberReqDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,9 @@ public record AgreeDTO(
boolean location,
boolean marketing
){}

public record LoginReqDTO(
@NotNull String mail,
@NotNull String password
){}
}
6 changes: 6 additions & 0 deletions src/main/java/umc/domain/member/dto/MemberResDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ public record JoinResultDTO(
Long userId,
LocalDateTime createdAt
){}
//로그인 응답
@Builder
public record LoginResultDTO(
String accessToken
){}

//마이페이지 조회용
public record MyProfileDTO(
String nickname,
Expand Down
21 changes: 13 additions & 8 deletions src/main/java/umc/domain/member/entity/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import umc.domain.member.entity.mapping.MemberFood;
import umc.domain.member.entity.mapping.MemberPolicy;
import umc.domain.member.enums.Gender;
import umc.domain.member.enums.SocialType;
import umc.domain.review.entity.Review;
import umc.global.common.BaseEntity;

Expand All @@ -31,41 +32,45 @@ public class Member extends BaseEntity {
@Column(name = "name", nullable = false)
private String name;

@Column(name = "nickname", nullable = false)
@Column(name = "nickname")
private String nickname;

@Column(name = "gender", nullable = false)
@Enumerated(EnumType.STRING)
@Builder.Default
private Gender gender = Gender.NONE;

@Column(name = "birth", nullable = false)
@Column(name = "birth")
private LocalDate birth;

@Column(name = "address", nullable = false)
@Column(name = "address")
private String address;

@Column(name = "mail", nullable = false)
private String mail;

@Column(name = "password", nullable = false)
@Column(name = "password")
private String password;

@Column(name = "photo", nullable = false)
@Column(name = "photo")
private String photoUrl;

@Column(name = "phoneNumber", nullable = false)
@Column(name = "phoneNumber")
private String phoneNumber;

@Column(name = "userPoint", nullable = false)
@Column(name = "userPoint")
private Integer userPoint;

@Column(name = "social_uid", nullable = false)
private String socialUid;

@Column(name = "social_provider", nullable = false)
@Column(name = "social_provider")
private String socialProvider;

@Enumerated(EnumType.STRING)
@Column(name = "social_type", nullable = false)
private SocialType socialType;

@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<Inquiry> inquiryList = new ArrayList<>();

Expand Down
8 changes: 8 additions & 0 deletions src/main/java/umc/domain/member/enums/SocialType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package umc.domain.member.enums;

public enum SocialType {
KAKAO,
NAVER,
GOOGLE,
APPLE
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ public enum MemberErrorCode implements BaseErrorCode {
"해당 사용자를 찾을 수 없습니다."),
MEMBER_ALREADY_EXIST(HttpStatus.ALREADY_REPORTED,
"MEMBER404_2",
"이미 존재하는 사용자입니다.")
"이미 존재하는 사용자입니다."),
MEMBER_INVALID_PASSWORD(HttpStatus.NOT_FOUND,
"PASSWORD404_1",
"해당 비밀번호를 찾을 수 없습니다."),
NOT_SUPPORT_SOCIAL_PROVIDER(HttpStatus.NOT_FOUND,
"SOCIAL404_1",
"해당 소셜 로그인을 지원하지 않습니다.")
;
private final HttpStatus status;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

import org.springframework.data.jpa.repository.JpaRepository;
import umc.domain.member.entity.Member;
import umc.domain.member.enums.SocialType;

import java.util.Optional;

public interface MemberRepository extends JpaRepository<Member, Long> {
Optional<Member> findByMail(String mail);

boolean existsByMail(String mail);

Optional<Member> findBySocialTypeAndSocialUid(SocialType socialType, String username);
}
19 changes: 19 additions & 0 deletions src/main/java/umc/domain/member/service/MemberCommandService.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package umc.domain.member.service;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
Expand All @@ -16,6 +17,8 @@
import umc.domain.member.repository.MemberRepository;
import umc.domain.policy.entity.Policy;
import umc.domain.policy.repository.PolicyRepository;
import umc.global.security.entity.AuthMember;
import umc.global.security.util.JwtUtil;

import java.util.List;

Expand All @@ -27,6 +30,7 @@ public class MemberCommandService {
private final FoodRepository foodRepository;
private final PolicyRepository policyRepository;
private final PasswordEncoder passwordEncoder;
private final JwtUtil jwtUtil;

@Transactional
public MemberResDTO.JoinResultDTO join(MemberReqDTO.JoinDTO request){
Expand All @@ -50,4 +54,19 @@ public MemberResDTO.JoinResultDTO join(MemberReqDTO.JoinDTO request){
//결과 DTO 전송
return MemberConverter.toJoinResultDTO(savedMember);
}

public MemberResDTO.LoginResultDTO login(MemberReqDTO.LoginReqDTO request) {
Member member = memberRepository.findByMail(request.mail())
.orElseThrow(() -> new MemberException(MemberErrorCode.MEMBER_NOT_FOUND));

if(!passwordEncoder.matches(request.password(), member.getPassword())){
throw new MemberException(MemberErrorCode.MEMBER_INVALID_PASSWORD);
}

//accseeToken 있어야 함.
AuthMember authMember = new AuthMember(member);
String accessToken = jwtUtil.createAccessToken(authMember);

return new MemberResDTO.LoginResultDTO(accessToken);
}
}
13 changes: 11 additions & 2 deletions src/main/java/umc/domain/member/service/MemberQueryService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import umc.domain.member.converter.MemberConverter;
import umc.domain.member.dto.MemberResDTO;
import umc.domain.member.entity.Member;
import umc.domain.member.exception.MemberException;
import umc.domain.member.exception.code.MemberErrorCode;
import umc.domain.member.repository.MemberRepository;
import umc.global.security.entity.AuthMember;

@Service
@RequiredArgsConstructor
Expand All @@ -15,8 +18,14 @@ public class MemberQueryService {

private final MemberRepository memberRepository;

public Member getMyProfile(Long memberId){
return memberRepository.findById(memberId)
public MemberResDTO.MyProfileDTO getMyProfile(
AuthMember authMember
){
String email = authMember.getUsername();

Member member = memberRepository.findByMail(email)
.orElseThrow(() -> new MemberException(MemberErrorCode.MEMBER_NOT_FOUND));

return MemberConverter.toMyProfileDTO(member);
}
}
Loading