Skip to content

Commit 5c90c04

Browse files
authored
feat: �내 정보 수정 (#116)
* fix: member 기본키 값 변경 * feat: 내 정보 조회 * feat: 회원 정보 수정 및 삭제 * fix: 로그인 로직 에러 수정 (#118) * feat: 회원 정보 수정 및 삭제 * fix: 테스트 코드 추가 * feat: 회원 정보 수정 및 탈퇴 테스트코드 추가 * fix: 코드 리뷰 반영 * fix: 오류 수정
1 parent 3106476 commit 5c90c04

21 files changed

+538
-152
lines changed

src/main/java/org/myteam/server/member/controller/AdminController.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.myteam.server.member.dto.MemberGetRequest;
99
import org.myteam.server.member.controller.response.MemberResponse;
1010
import org.myteam.server.member.entity.Member;
11+
import org.myteam.server.member.service.MemberReadService;
1112
import org.myteam.server.member.service.MemberService;
1213
import org.springframework.http.HttpStatus;
1314
import org.springframework.http.ResponseEntity;
@@ -25,36 +26,42 @@
2526
@RequiredArgsConstructor
2627
@PreAuthorize("hasAuthority(T(org.myteam.server.member.domain.MemberRole).ADMIN.name())")
2728
public class AdminController {
29+
30+
private final MemberReadService memberReadService;
2831
private final MemberService memberService;
2932

3033
@GetMapping("/email")
3134
public ResponseEntity<?> getByEmail(@Valid MemberGetRequest memberGetRequest, BindingResult bindingResult) {
3235
log.info("MemberController getByEmail 메서드 실행 : {}", memberGetRequest);
33-
MemberResponse response = memberService.getByEmail(memberGetRequest.getEmail());
36+
MemberResponse response = memberReadService.getByEmail(memberGetRequest.getEmail());
3437
return new ResponseEntity<>(new ResponseDto<>(SUCCESS.name(), "회원 정보 조회 성공", response), HttpStatus.OK);
3538
}
3639

3740
@GetMapping("/nickname")
3841
public ResponseEntity<?> getByNickname(@Valid MemberGetRequest memberGetRequest, BindingResult bindingResult) {
3942
log.info("MemberController getByNickname 메서드 실행 : {}", memberGetRequest);
40-
MemberResponse response = memberService.getByNickname(memberGetRequest.getNickname());
43+
MemberResponse response = memberReadService.getByNickname(memberGetRequest.getNickname());
4144
return new ResponseEntity<>(new ResponseDto<>(SUCCESS.name(), "회원 정보 조회 성공", response), HttpStatus.OK);
4245
}
4346

4447
@GetMapping
4548
public ResponseEntity<?> list() {
4649
log.info("getAllMembers : 회원 정보 목록 조회 메서드 실행");
47-
List<Member> allMembers = memberService.list();
50+
List<Member> allMembers = memberReadService.list();
4851
List<MemberResponse> response = allMembers.stream().map(MemberResponse::new).toList();
4952
return new ResponseEntity<>(new ResponseDto<>(SUCCESS.name(), "회원 정보 목록 조회 성공", response), HttpStatus.OK);
5053
}
5154

5255
@Deprecated
5356
@DeleteMapping("/delete")
54-
public ResponseEntity<?> delete(@RequestBody MemberDeleteRequest memberDeleteRequest, BindingResult bindingResult) {
57+
public ResponseEntity<ResponseDto<String>> delete(@RequestBody MemberDeleteRequest memberDeleteRequest, BindingResult bindingResult) {
5558
log.info("MemberController delete 메서드 실행 : {}", memberDeleteRequest);
5659
String email = memberDeleteRequest.getEmail();
5760
memberService.delete(email);
58-
return new ResponseEntity<>(new ResponseDto<>(SUCCESS.name(), "회원 삭제 성공", null), HttpStatus.OK);
61+
return ResponseEntity.ok(new ResponseDto<>(
62+
SUCCESS.name(),
63+
"회원 삭제 성공",
64+
null
65+
));
5966
}
6067
}

src/main/java/org/myteam/server/member/controller/MemberController.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.myteam.server.member.dto.ExistMemberNicknameRequest;
1313
import org.myteam.server.member.dto.MemberRoleUpdateRequest;
1414
import org.myteam.server.member.dto.MemberStatusUpdateRequest;
15+
import org.myteam.server.member.service.MemberReadService;
1516
import org.myteam.server.member.service.MemberService;
1617
import org.springframework.http.HttpStatus;
1718
import org.springframework.http.ResponseEntity;
@@ -28,6 +29,7 @@
2829
@RequestMapping("/api/members")
2930
@RequiredArgsConstructor
3031
public class MemberController {
32+
private final MemberReadService memberReadService;
3133
private final MemberService memberService;
3234
private final JwtProvider jwtProvider;
3335

@@ -48,7 +50,7 @@ public ResponseEntity<?> existsByEmail(@Valid ExistMemberNicknameRequest existMe
4850
@GetMapping("/exists/nickname")
4951
public ResponseEntity<?> existsByNickname(@Valid ExistMemberNicknameRequest existMemberNicknameRequest, BindingResult bindingResult) {
5052
log.info("MemberController existsByNickname 메서드 실행 : {}", existMemberNicknameRequest.getNickname());
51-
boolean exists = memberService.existsByNickname(existMemberNicknameRequest.getNickname());
53+
boolean exists = memberReadService.existsByNickname(existMemberNicknameRequest.getNickname());
5254
return ResponseEntity.ok(new ResponseDto<>(SUCCESS.name(), "닉네임 존재 여부 확인", exists));
5355
}
5456

@@ -61,7 +63,7 @@ public ResponseEntity<?> existsByNickname(@Valid ExistMemberNicknameRequest exis
6163
@GetMapping("/{email}/type")
6264
public ResponseEntity<?> getMemberType(@PathVariable String email) {
6365
log.info("MemberController getMemberType 메서드 실행: {}", email);
64-
MemberType memberType = memberService.getMemberTypeByEmail(email);
66+
MemberType memberType = memberReadService.getMemberTypeByEmail(email);
6567
return ResponseEntity.ok(new ResponseDto<>(SUCCESS.name(), "회원 타입 조회 성공", memberType));
6668
}
6769

@@ -74,7 +76,7 @@ public ResponseEntity<?> updateStatus(@RequestBody @Valid MemberStatusUpdateRequ
7476
String authorizationHeader = httpServletRequest.getHeader(HEADER_AUTHORIZATION);
7577

7678
// accessToken 으로 부터 유저 정보 반환
77-
MemberResponse response = memberService.getAuthenticatedMember(authorizationHeader);
79+
MemberResponse response = memberReadService.getAuthenticatedMember(authorizationHeader);
7880

7981
log.info("email : {}", response.getEmail());
8082

@@ -97,7 +99,7 @@ public ResponseEntity<?> updateRole(@RequestBody @Valid MemberRoleUpdateRequest
9799
@GetMapping("/get-token/user/{email}/second/{second}")
98100
public ResponseEntity<?> getToken(@PathVariable String email, @PathVariable Integer second) {
99101
log.info("getToken 메서드가 실행되었습니다.");
100-
MemberResponse response = memberService.getByEmail(email);
102+
MemberResponse response = memberReadService.getByEmail(email);
101103
String encode = TOKEN_PREFIX + jwtProvider.generateToken(TOKEN_CATEGORY_ACCESS, Duration.ofSeconds(second), response.getPublicId(), response.getRole().name(), response.getStatus().name());
102104
return new ResponseEntity<>(new ResponseDto<>(SUCCESS.name(), "토큰 조회 성공", encode), HttpStatus.OK);
103105
}

src/main/java/org/myteam/server/member/controller/MyInfoController.java

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99
import org.myteam.server.global.security.jwt.JwtProvider;
1010
import org.myteam.server.global.web.response.ResponseDto;
1111
import org.myteam.server.member.controller.response.MemberResponse;
12-
import org.myteam.server.member.dto.MemberDeleteRequest;
1312
import org.myteam.server.member.dto.MemberSaveRequest;
14-
import org.myteam.server.member.dto.MemberUpdateRequest;
1513
import org.myteam.server.member.dto.PasswordChangeRequest;
14+
import org.myteam.server.member.service.MemberReadService;
1615
import org.myteam.server.member.service.MemberService;
1716
import org.springframework.http.HttpStatus;
1817
import org.springframework.http.ResponseEntity;
@@ -31,6 +30,8 @@
3130
@RequestMapping("/api/me")
3231
@RequiredArgsConstructor
3332
public class MyInfoController {
33+
34+
private final MemberReadService memberReadService;
3435
private final MemberService memberService;
3536
private final JwtProvider jwtProvider;
3637
private final ReIssueService reIssueService;
@@ -57,39 +58,17 @@ public ResponseEntity<?> get(@AuthenticationPrincipal CustomUserDetails userDeta
5758
log.info("publicId : {}", userDetails.getPublicId());
5859

5960
UUID publicId = userDetails.getPublicId();
60-
MemberResponse response = memberService.getByPublicId(publicId);
61+
MemberResponse response = memberReadService.getByPublicId(publicId);
6162
return new ResponseEntity<>(new ResponseDto<>(SUCCESS.name(), "로그인 회원 정보 조회 성공", response), HttpStatus.OK);
6263
}
6364

64-
@PutMapping("/update")
65-
public ResponseEntity<?> update(@RequestBody @Valid MemberUpdateRequest memberUpdateRequest,
66-
BindingResult bindingResult,
67-
@AuthenticationPrincipal CustomUserDetails userDetails) {
68-
log.info("MyInfoController update 메서드 실행 : {}", memberUpdateRequest.toString());
69-
String loginUserEmail = memberService.getCurrentLoginUserEmail(userDetails.getPublicId()); // 현재 로그인한 사용자 이메일
70-
MemberResponse response = memberService.update(loginUserEmail, memberUpdateRequest);
71-
return new ResponseEntity<>(new ResponseDto<>(SUCCESS.name(), "회원정보 수정 성공", response), HttpStatus.OK);
72-
}
73-
7465
@PutMapping("/change-password")
7566
public ResponseEntity<?> changePassword(@RequestBody @Valid PasswordChangeRequest passwordChangeRequest,
7667
BindingResult bindingResult,
7768
@AuthenticationPrincipal CustomUserDetails userDetails) {
7869
log.info("MyInfoController changePassword 메서드 실행 : {}", passwordChangeRequest.toString());
79-
String email = memberService.getCurrentLoginUserEmail(userDetails.getPublicId()); // 현재 로그인한 사용자 이메일
70+
String email = memberReadService.getCurrentLoginUserEmail(userDetails.getPublicId()); // 현재 로그인한 사용자 이메일
8071
memberService.changePassword(email, passwordChangeRequest);
8172
return new ResponseEntity<>(new ResponseDto<>(SUCCESS.name(), "비밀번호 변경 성공", null), HttpStatus.OK);
8273
}
83-
84-
@DeleteMapping("/delete")
85-
public ResponseEntity<?> delete(@RequestBody @Valid MemberDeleteRequest memberDeleteRequest,
86-
BindingResult bindingResult,
87-
@AuthenticationPrincipal CustomUserDetails userDetails) {
88-
log.info("MyInfoController delete 메서드 실행");
89-
String loginUserEmail = memberService.getCurrentLoginUserEmail(userDetails.getPublicId()); // 현재 로그인한 사용자 이메일
90-
91-
memberService.delete(memberDeleteRequest.getEmail(), loginUserEmail, memberDeleteRequest.getPassword());
92-
93-
return new ResponseEntity<>(new ResponseDto<>(SUCCESS.name(), "회원 삭제 성공", null), HttpStatus.OK);
94-
}
9574
}

src/main/java/org/myteam/server/member/dto/MemberUpdateRequest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package org.myteam.server.member.dto;
22

33
import jakarta.validation.constraints.NotBlank;
4+
import jakarta.validation.constraints.NotNull;
45
import jakarta.validation.constraints.Pattern;
6+
import jakarta.validation.constraints.Size;
57
import lombok.Builder;
68
import lombok.Getter;
79

@@ -11,6 +13,14 @@ public class MemberUpdateRequest {
1113
@Pattern(regexp = "^[0-9a-zA-Z]+@[0-9a-zA-Z]+(\\.[a-zA-Z]{2,3}){1,2}$", message = "이메일 형식으로 작성해주세요")
1214
private String email; // 계정
1315

16+
@NotNull(message = "영문 + 숫자 조합 4 ~ 10자 이내로 작성해주세요")
17+
@Size(min = 4, max = 10, message = "비밀번호는 4~10자 이내로 입력해주세요.")
18+
@Pattern(
19+
regexp = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{4,10}$",
20+
message = "비밀번호는 영문 + 숫자 조합 4 ~ 10자 이내로 작성해주세요."
21+
)
22+
private String password;
23+
1424
@NotBlank
1525
@Pattern(regexp = "^010[0-9]{7,8}$", message = "연락처는 '010'으로 시작하고 뒤에 7 또는 8 자리 숫자로 작성해주세요.")
1626
private String tel; // 전화번호

src/main/java/org/myteam/server/member/entity/Member.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
import org.myteam.server.member.domain.MemberStatus;
1414
import org.myteam.server.member.domain.MemberType;
1515
import org.myteam.server.member.dto.MemberSaveRequest;
16-
import org.myteam.server.member.dto.MemberUpdateRequest;
1716
import org.myteam.server.member.dto.PasswordChangeRequest;
17+
import org.myteam.server.profile.dto.request.ProfileRequestDto.MemberUpdateRequest;
1818
import org.springframework.security.crypto.password.PasswordEncoder;
1919

2020
import java.util.Objects;
@@ -87,7 +87,7 @@ public Member(MemberSaveRequest memberSaveRequest, PasswordEncoder passwordEncod
8787
// 전체 업데이트 메서드
8888
public void update(MemberUpdateRequest memberUpdateRequest, PasswordEncoder passwordEncoder) {
8989
// this.email = memberUpdateRequest.getEmail();
90-
// this.password = passwordEncoder.encode(memberUpdateRequest.getPassword()); // 비밀번호 변경 시 암호화 필요
90+
this.password = passwordEncoder.encode(memberUpdateRequest.getPassword()); // 비밀번호 변경 시 암호화 필요
9191
this.tel = memberUpdateRequest.getTel();
9292
this.nickname = memberUpdateRequest.getNickname();
9393
}
@@ -130,4 +130,8 @@ public void confirmMemberEquals(Member member) {
130130
throw new PlayHiveException(ErrorCode.MEMBER_NOT_EQUALS);
131131
}
132132
}
133+
134+
public void updateMemberActivity(MemberActivity memberActivity) {
135+
this.memberActivity = memberActivity;
136+
}
133137
}

src/main/java/org/myteam/server/member/entity/MemberActivity.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@ public void increaseInviteCount() {
3434

3535
public MemberActivity(Member member) {
3636
this.member = member;
37+
member.updateMemberActivity(this);
3738
}
3839
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,103 @@
11
package org.myteam.server.member.service;
22

3+
import java.util.Collections;
4+
import java.util.List;
5+
import java.util.Optional;
36
import java.util.UUID;
47
import lombok.RequiredArgsConstructor;
58
import org.myteam.server.global.exception.ErrorCode;
69
import org.myteam.server.global.exception.PlayHiveException;
10+
import org.myteam.server.global.security.jwt.JwtProvider;
11+
import org.myteam.server.member.controller.response.MemberResponse;
12+
import org.myteam.server.member.domain.MemberType;
713
import org.myteam.server.member.entity.Member;
14+
import org.myteam.server.member.repository.MemberJpaRepository;
815
import org.myteam.server.member.repository.MemberRepository;
16+
import org.myteam.server.profile.dto.response.ProfileResponseDto.ProfileResponse;
17+
import org.springframework.security.crypto.password.PasswordEncoder;
918
import org.springframework.stereotype.Service;
1019
import org.springframework.transaction.annotation.Transactional;
1120

21+
import static org.myteam.server.global.exception.ErrorCode.NO_PERMISSION;
22+
import static org.myteam.server.global.exception.ErrorCode.RESOURCE_NOT_FOUND;
23+
import static org.myteam.server.global.security.jwt.JwtProvider.TOKEN_PREFIX;
24+
1225
@Service
1326
@RequiredArgsConstructor
1427
@Transactional(readOnly = true)
1528
public class MemberReadService {
1629

1730
private final MemberRepository memberRepository;
31+
private final MemberJpaRepository memberJpaRepository;
32+
private final SecurityReadService securityReadService;
33+
private final PasswordEncoder passwordEncoder;
34+
private final JwtProvider jwtProvider;
1835

1936
public Member findById(UUID publicId) {
2037
return memberRepository.findByPublicId(publicId)
2138
.orElseThrow(() -> new PlayHiveException(ErrorCode.USER_NOT_FOUND));
2239
}
40+
41+
public ProfileResponse getProfile() {
42+
Member member = securityReadService.getMember();
43+
44+
return ProfileResponse.createProfileResponse(member);
45+
}
46+
47+
public MemberResponse getByPublicId(UUID publicId) {
48+
return new MemberResponse(memberRepository.getByPublicId(publicId));
49+
}
50+
51+
public MemberResponse getByEmail(String email) {
52+
return memberRepository.findByEmail(email)
53+
.map(MemberResponse::new)
54+
.orElseThrow(() -> new PlayHiveException(RESOURCE_NOT_FOUND, email + " 는 존재하지 않는 이메일 입니다"));
55+
}
56+
57+
public MemberResponse getByNickname(String nickname) {
58+
return memberRepository.findByNickname(nickname)
59+
.map(MemberResponse::new)
60+
.orElseThrow(() -> new PlayHiveException(RESOURCE_NOT_FOUND, nickname + " 는 존재하지 않는 닉네임 입니다"));
61+
}
62+
63+
public List<Member> list() {
64+
return Optional.of(memberJpaRepository.findAll()).orElse(Collections.emptyList());
65+
}
66+
67+
public boolean existsByNickname(String nickname) {
68+
return memberJpaRepository.existsByNickname(nickname);
69+
}
70+
71+
/**
72+
* publicId 를 통한 사용자 아이디 조회
73+
*
74+
* @param publicId token 에 저장할 고유 번호
75+
* @return
76+
*/
77+
public String getCurrentLoginUserEmail(UUID publicId) {
78+
MemberResponse response = getByPublicId(publicId);
79+
return response != null ? response.getEmail() : null;
80+
}
81+
82+
/**
83+
* jwt 토큰에서 publicId 를 추출한다.
84+
*
85+
* @param authorizationHeader JWT 토큰
86+
* @return
87+
*/
88+
public MemberResponse getAuthenticatedMember(String authorizationHeader) {
89+
if (authorizationHeader == null || !authorizationHeader.startsWith(TOKEN_PREFIX)) {
90+
throw new PlayHiveException(NO_PERMISSION);
91+
}
92+
93+
String accessToken = jwtProvider.getAccessToken(authorizationHeader);
94+
UUID publicId = jwtProvider.getPublicId(accessToken);
95+
return getByPublicId(publicId);
96+
}
97+
98+
public MemberType getMemberTypeByEmail(String email) {
99+
return memberRepository.findByEmail(email)
100+
.map(Member::getType)
101+
.orElse(null);
102+
}
23103
}

0 commit comments

Comments
 (0)