Skip to content
Open
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
14 changes: 10 additions & 4 deletions cheshire/week4/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@ repositories {

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-webmvc'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa-test'
testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testCompileOnly 'org.projectlombok:lombok'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testAnnotationProcessor 'org.projectlombok:lombok'
Expand All @@ -34,11 +33,18 @@ dependencies {
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:3.0.1'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-api:3.0.1'


// 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'

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

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
package com.example.umc10th.domain.member.controller;


import com.example.umc10th.domain.member.dto.MemberReqDTO;
import com.example.umc10th.domain.member.exception.code.MemberSuccessCode;
import com.example.umc10th.domain.member.service.MemberService;
import com.example.umc10th.global.apiPayload.ApiResponse;
import com.example.umc10th.global.apiPayload.code.BaseSuccessCode;
import com.sun.net.httpserver.Authenticator;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@Tag(name = "인증", description = "회원가입 및 로그인 관련 API")
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/auth")
public class MemberController {
private final MemberService memberService;



@Operation(summary = "회원가입", description = "이메일과 비밀번호로 일반 회원가입을 합니다.")
@PostMapping("/signup")
public ApiResponse<?> signUp(@RequestBody MemberReqDTO.SignUp request){
public ApiResponse<?> signUp(@RequestBody MemberReqDTO.SignUp request) {
BaseSuccessCode code = MemberSuccessCode.SIGN_UP_CREATED;
return ApiResponse.onSuccess(code, memberService.signUp(request));
}

}
@Operation(summary = "로그인", description = "이메일과 비밀번호로 로그인 후 JWT 토큰을 반환합니다.")
@PostMapping("/login")
public ApiResponse<?> login(@RequestBody MemberReqDTO.Login request) {
BaseSuccessCode code = MemberSuccessCode.SIGN_IN_OK;
return ApiResponse.onSuccess(code, memberService.login(request));
}
}
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
package com.example.umc10th.domain.member.controller;

import com.example.umc10th.domain.member.dto.MemberResDTO;
import com.example.umc10th.domain.member.entity.Member;
import com.example.umc10th.domain.member.exception.code.MemberSuccessCode;
import com.example.umc10th.domain.member.service.MemberService;
import com.example.umc10th.global.apiPayload.ApiResponse;
import com.example.umc10th.global.apiPayload.code.BaseSuccessCode;
import com.example.umc10th.global.security.entity.AuthMember;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "마이페이지", description = "회원 정보 관련 API")
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/members")
public class MyPageController {
private final MemberService memberService;

@Operation(summary = "내 프로필 조회", description = "로그인한 회원의 프로필 정보를 반환합니다.")
@GetMapping("/me")
public ApiResponse<?> getProfile(@RequestHeader("memberId") Long memberId) {
Member member = memberService.getMember(memberId);

MemberResDTO.ProfileRes response = new MemberResDTO.ProfileRes(
member.getName(),
member.getEmail(),
member.getPhoneNumber(),
member.getTotalPoint()
);
return ApiResponse.onSuccess(MemberSuccessCode.MY_PAGE_OK, response);
public ApiResponse<MemberResDTO.ProfileRes> profileRes(
@AuthenticationPrincipal AuthMember member
) {
BaseSuccessCode code = MemberSuccessCode.MY_PAGE_OK;
return ApiResponse.onSuccess(code, memberService.getInfo(member));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.example.umc10th.domain.member.entity.mapping.MemberFood;
import com.example.umc10th.domain.member.entity.mapping.MemberTerm;
import com.example.umc10th.domain.member.enums.Agreement;
import com.example.umc10th.global.security.dto.OAuthDTO;

import java.util.List;

Expand Down Expand Up @@ -44,6 +45,19 @@ public static List<MemberTerm> toMemberTermList(Member member, List<Term> terms)
.toList();
}

public static Member toMember(OAuthDTO dto) {
return Member.builder()
.socialUid(dto.getSocialUid())
.socialType(dto.getSocialType())
.email(dto.getSocialEmail())
.name(dto.getName())
.build();
}

public static MemberResDTO.Login toLogin(String accessToken) {
return new MemberResDTO.Login(accessToken);
}

public static MemberResDTO.ProfileRes toProfileRes(Member member) {
return new MemberResDTO.ProfileRes(
member.getName(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import com.example.umc10th.domain.member.enums.Gender;
import com.example.umc10th.domain.store.enums.Address;
import lombok.Getter;

import java.time.LocalDate;
Expand All @@ -22,6 +23,11 @@ public record SignUp(
List<Long> terms
){}

public record Login(
String email,
String password
){}



}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public record ProfileRes(
String email,
Long phoneNumber,
Integer totalPoint){}

public record Login(String accessToken) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ public class Member extends BaseEntity {
@Column(name="birth", nullable = false)
private LocalDate birth;

@Column(name = "address")
@Enumerated(EnumType.STRING)
private Address address;

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ public enum MemberErrorCode implements BaseErrorCode {
MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND,
"MEMBER404_1",
"해당 사용자를 찾을 수 없습니다."),

NOT_SUPPORT_SOCIAL_PROVIDER(HttpStatus.BAD_REQUEST,
"MEMBER400_1",
"지원하지 않는 소셜 로그인입니다."),
INVALID_MEMBER_PASSWORD(HttpStatus.BAD_REQUEST,
"MEMBER400_2",
"잘못된 비빌번호입니다."
),

;

private final HttpStatus status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ public enum MemberSuccessCode implements BaseSuccessCode {
MY_PAGE_OK(HttpStatus.OK,
"MISSION200_5",
"마이페이지 호출을 성공적으로 처리했습니다."),

OK(HttpStatus.OK,
"MEMBER200_1",
"성공적으로 처리되었습니다."),
;
private final HttpStatus status;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

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

@Repository
public interface FoodRepository extends JpaRepository<Food, Long>{
Optional<Food> findById(Long foodId);
List<Food> findAllById(Iterable<Long> ids);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import com.example.umc10th.domain.member.entity.Member;
import com.example.umc10th.domain.member.enums.SocialType;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

Expand All @@ -10,4 +11,7 @@
@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
Optional<Member> findByEmail(String email);
Optional<Member> findBySocialTypeAndSocialUid(SocialType socialType, String username);

String email(String email);
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
package com.example.umc10th.domain.member.service;

import com.example.umc10th.domain.member.converter.MemberConverter;
import com.example.umc10th.domain.member.dto.MemberReqDTO;
import com.example.umc10th.domain.member.dto.MemberResDTO;
import com.example.umc10th.domain.member.entity.Food;
import com.example.umc10th.domain.member.entity.Member;
import com.example.umc10th.domain.member.entity.Term;
import com.example.umc10th.domain.member.entity.mapping.MemberFood;
import com.example.umc10th.domain.member.entity.mapping.MemberTerm;
import com.example.umc10th.domain.member.enums.Agreement;
import com.example.umc10th.domain.member.exception.MemberException;
import com.example.umc10th.domain.member.exception.code.MemberErrorCode;
import com.example.umc10th.domain.member.repository.*;
import com.example.umc10th.global.security.entity.AuthMember;
import com.example.umc10th.global.security.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
@Transactional
Expand All @@ -23,58 +31,53 @@ public class MemberService {
private final TermRepository termRepository;
private final MemberFoodRepository memberFoodRepository;
private final MemberTermRepository memberTermRepository;

public Member getMember(Long memberId) {
return memberRepository.findById(memberId)
.orElseThrow(() -> new RuntimeException("멤버를 찾을 수 없습니다."));
}
private final JwtUtil jwtUtil;

@Transactional
public Member signUp(MemberReqDTO.SignUp request) {

// 1. 비밀번호 암호화
String encodedPassword = passwordEncoder.encode(request.password());



// 2. Member 엔티티 생성
Member member = Member.builder()
.name(request.name())
.email(request.email())
.password(encodedPassword)
.gender(request.gender())
.birth(request.birthDate())
.detailAddress(request.detailAddress())
.build();
Member member = MemberConverter.toMember(request,encodedPassword);

// 3. 저장
memberRepository.save(member);

// 4. 선호 음식 매핑 처리
for(Long foodId:request.preferredFoods()){
Food food = foodRepository.findById(foodId)
.orElseThrow(()-> new RuntimeException("음식을 찾을 수 없습니다."));

MemberFood memberFood = MemberFood.builder()
.member(member)
.food(food)
.build();
memberFoodRepository.save(memberFood);
}
List<Food> foods = foodRepository.findAllById(request.preferredFoods());
List<MemberFood> memberFood = MemberConverter.toMemberFoodList(member, foods);
memberFoodRepository.saveAll(memberFood);

// 5. 약관 매핑 처리
for(Long termId: request.terms()){
Term term = termRepository.findById(termId)
.orElseThrow(()->new RuntimeException("이용 약관을 찾을 수 없습니다."));

MemberTerm memberTerm = MemberTerm.builder()
.member(member)
.term(term)
.agreement(Agreement.AGREED)
.build();
memberTermRepository.save(memberTerm);
}
List<Term> terms = termRepository.findAllById(request.terms());
List<MemberTerm> memberTerm = MemberConverter.toMemberTermList(member, terms);
memberTermRepository.saveAll(memberTerm);

return member;
}

@Transactional
public String login(MemberReqDTO.Login request) {
Member member = memberRepository.findByEmail(request.email())
.orElseThrow(()->new MemberException(MemberErrorCode.MEMBER_NOT_FOUND));
if(!passwordEncoder.matches(request.password(), member.getPassword())){
throw new MemberException(MemberErrorCode.INVALID_MEMBER_PASSWORD);
}

return jwtUtil.createAccessToken(new AuthMember(member));

}

public MemberResDTO.ProfileRes getInfo(
AuthMember member
){
return MemberConverter.toProfileRes(member.getMember());
}



}
Loading