Skip to content

Commit fbd6299

Browse files
authored
Feat/72 (#93)
* fix:softdelete * refactor:클래스이름,경로리팩토링 * feat:관리자 전용 API * test:관리자 테스트
1 parent da830af commit fbd6299

File tree

14 files changed

+926
-303
lines changed

14 files changed

+926
-303
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package com.back.domain.member.member.controller;
2+
3+
import com.back.domain.member.member.dto.MemberSearchResponse;
4+
import com.back.domain.member.member.dto.MentorUpdateRequest;
5+
import com.back.domain.member.member.dto.MenteeUpdateRequest;
6+
import com.back.domain.member.member.service.MemberService;
7+
import com.back.global.rq.Rq;
8+
import com.back.global.rsData.RsData;
9+
import io.swagger.v3.oas.annotations.Operation;
10+
import io.swagger.v3.oas.annotations.tags.Tag;
11+
import lombok.RequiredArgsConstructor;
12+
import org.springframework.security.access.prepost.PreAuthorize;
13+
import org.springframework.web.bind.annotation.*;
14+
15+
@RestController
16+
@RequestMapping("/members")
17+
@RequiredArgsConstructor
18+
@Tag(name = "AdmMemberController", description = "관리자 회원 관리 컨트롤러")
19+
public class AdmMemberController {
20+
private final MemberService memberService;
21+
private final Rq rq;
22+
23+
24+
@GetMapping("/{memberId}")
25+
@Operation(summary = "회원 상세 조회 (관리자)")
26+
@PreAuthorize("hasRole('ADMIN')")
27+
public RsData<MemberSearchResponse> getMember(@PathVariable Long memberId) {
28+
MemberSearchResponse member = memberService.getMemberForAdmin(memberId);
29+
return new RsData<>("200-14", "회원 상세 조회 성공", member);
30+
}
31+
32+
@PostMapping("/{memberId}/delete")
33+
@Operation(summary = "회원 삭제 (관리자) - 소프트 삭제")
34+
@PreAuthorize("hasRole('ADMIN')")
35+
public RsData<Void> deleteMember(@PathVariable Long memberId) {
36+
memberService.deleteMemberByAdmin(memberId);
37+
return new RsData<>("200-15", "회원 삭제 성공");
38+
}
39+
40+
@PutMapping("/{memberId}/mentor")
41+
@Operation(summary = "멘토 정보 수정 (관리자)")
42+
@PreAuthorize("hasRole('ADMIN')")
43+
public RsData<Void> updateMentor(@PathVariable Long memberId, @RequestBody MentorUpdateRequest request) {
44+
memberService.updateMemberByAdmin(memberId, null, request.nickname(), null,
45+
request.career(), request.careerYears(), null);
46+
return new RsData<>("200-16", "멘토 정보 수정 성공");
47+
}
48+
49+
@PutMapping("/{memberId}/mentee")
50+
@Operation(summary = "멘티 정보 수정 (관리자)")
51+
@PreAuthorize("hasRole('ADMIN')")
52+
public RsData<Void> updateMentee(@PathVariable Long memberId, @RequestBody MenteeUpdateRequest request) {
53+
memberService.updateMemberByAdmin(memberId, null, request.nickname(), null,
54+
null, null, request.interestedField());
55+
return new RsData<>("200-17", "멘티 정보 수정 성공");
56+
}
57+
}

back/src/main/java/com/back/domain/member/member/controller/MemberController.java renamed to back/src/main/java/com/back/domain/member/member/controller/MemberAuthController.java

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package com.back.domain.member.member.controller;
22

3-
import com.back.domain.member.member.dto.*;
3+
import com.back.domain.member.member.dto.MenteeSignupRequest;
4+
import com.back.domain.member.member.dto.MentorSignupVerifyRequest;
5+
import com.back.domain.member.member.dto.MentorVerificationRequest;
6+
import com.back.domain.member.member.dto.LoginRequest;
47
import com.back.domain.member.member.entity.Member;
58
import com.back.domain.member.member.service.MemberService;
69
import com.back.global.rq.Rq;
@@ -15,8 +18,8 @@
1518
@RestController
1619
@RequestMapping("/auth")
1720
@RequiredArgsConstructor
18-
@Tag(name = "MemberController", description = "회원 컨트롤러")
19-
public class MemberController {
21+
@Tag(name = "MemberAuthController", description = "회원 인증 컨트롤러")
22+
public class MemberAuthController {
2023
private final MemberService memberService;
2124
private final Rq rq;
2225
private final EmailVerificationService emailVerificationService;
@@ -102,9 +105,9 @@ public RsData<Void> refresh() {
102105
return new RsData<>("200-6", "토큰 갱신 성공");
103106
}
104107

105-
@DeleteMapping("/me")
108+
@PostMapping("/me/withdraw")
106109
@Operation(summary = "회원 탈퇴")
107-
public RsData<Void> deleteMember() {
110+
public RsData<Void> withdrawMember() {
108111
Member currentUser = rq.getActor();
109112
memberService.deleteMember(currentUser);
110113

@@ -115,35 +118,4 @@ public RsData<Void> deleteMember() {
115118
return new RsData<>("200-7", "회원 탈퇴가 완료되었습니다.");
116119
}
117120

118-
@GetMapping("/me/mentee")
119-
@Operation(summary = "멘티 마이페이지 조회")
120-
public RsData<MenteeMyPageResponse> getMenteeMyPage() {
121-
Member currentUser = rq.getActor();
122-
MenteeMyPageResponse response = memberService.getMenteeMyPage(currentUser);
123-
return new RsData<>("200-9", "멘티 정보 조회 성공", response);
124-
}
125-
126-
@PutMapping("/me/mentee")
127-
@Operation(summary = "멘티 정보 수정")
128-
public RsData<Void> updateMentee(@RequestBody MenteeUpdateRequest request) {
129-
Member currentUser = rq.getActor();
130-
memberService.updateMentee(currentUser, request);
131-
return new RsData<>("200-10", "멘티 정보 수정 성공");
132-
}
133-
134-
@GetMapping("/me/mentor")
135-
@Operation(summary = "멘토 마이페이지 조회")
136-
public RsData<MentorMyPageResponse> getMentorMyPage() {
137-
Member currentUser = rq.getActor();
138-
MentorMyPageResponse response = memberService.getMentorMyPage(currentUser);
139-
return new RsData<>("200-11", "멘토 정보 조회 성공", response);
140-
}
141-
142-
@PutMapping("/me/mentor")
143-
@Operation(summary = "멘토 정보 수정")
144-
public RsData<Void> updateMentor(@RequestBody MentorUpdateRequest request) {
145-
Member currentUser = rq.getActor();
146-
memberService.updateMentor(currentUser, request);
147-
return new RsData<>("200-12", "멘토 정보 수정 성공");
148-
}
149121
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.back.domain.member.member.controller;
2+
3+
import com.back.domain.member.member.dto.MenteeMyPageResponse;
4+
import com.back.domain.member.member.dto.MenteeUpdateRequest;
5+
import com.back.domain.member.member.dto.MentorMyPageResponse;
6+
import com.back.domain.member.member.dto.MentorUpdateRequest;
7+
import com.back.domain.member.member.entity.Member;
8+
import com.back.domain.member.member.service.MemberService;
9+
import com.back.global.rq.Rq;
10+
import com.back.global.rsData.RsData;
11+
import io.swagger.v3.oas.annotations.Operation;
12+
import io.swagger.v3.oas.annotations.tags.Tag;
13+
import lombok.RequiredArgsConstructor;
14+
import org.springframework.web.bind.annotation.*;
15+
16+
@RestController
17+
@RequestMapping("/members")
18+
@RequiredArgsConstructor
19+
@Tag(name = "MemberMyPageController", description = "회원 마이페이지 컨트롤러")
20+
public class MemberMyPageController {
21+
private final MemberService memberService;
22+
private final Rq rq;
23+
24+
@GetMapping("/me/mentee")
25+
@Operation(summary = "멘티 마이페이지 조회")
26+
public RsData<MenteeMyPageResponse> getMenteeMyPage() {
27+
Member currentUser = rq.getActor();
28+
MenteeMyPageResponse response = memberService.getMenteeMyPage(currentUser);
29+
return new RsData<>("200-9", "멘티 정보 조회 성공", response);
30+
}
31+
32+
@PutMapping("/me/mentee")
33+
@Operation(summary = "멘티 정보 수정")
34+
public RsData<Void> updateMentee(@RequestBody MenteeUpdateRequest request) {
35+
Member currentUser = rq.getActor();
36+
memberService.updateMentee(currentUser, request);
37+
return new RsData<>("200-10", "멘티 정보 수정 성공");
38+
}
39+
40+
@GetMapping("/me/mentor")
41+
@Operation(summary = "멘토 마이페이지 조회")
42+
public RsData<MentorMyPageResponse> getMentorMyPage() {
43+
Member currentUser = rq.getActor();
44+
MentorMyPageResponse response = memberService.getMentorMyPage(currentUser);
45+
return new RsData<>("200-11", "멘토 정보 조회 성공", response);
46+
}
47+
48+
@PutMapping("/me/mentor")
49+
@Operation(summary = "멘토 정보 수정")
50+
public RsData<Void> updateMentor(@RequestBody MentorUpdateRequest request) {
51+
Member currentUser = rq.getActor();
52+
memberService.updateMentor(currentUser, request);
53+
return new RsData<>("200-12", "멘토 정보 수정 성공");
54+
}
55+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.back.domain.member.member.dto;
2+
3+
import com.back.domain.member.member.entity.Member;
4+
import com.back.domain.member.mentee.entity.Mentee;
5+
import com.back.domain.member.mentor.entity.Mentor;
6+
7+
import java.time.LocalDateTime;
8+
9+
public record MemberSearchResponse(
10+
Long id,
11+
String email,
12+
String name,
13+
String nickname,
14+
Member.Role role,
15+
Boolean isDeleted,
16+
LocalDateTime createdAt,
17+
LocalDateTime modifiedAt,
18+
String career, // 멘토인 경우에만 값이 있음 (TODO: Job 연결 후 수정 예정)
19+
Integer careerYears, // 멘토인 경우에만 값이 있음
20+
String interestedField // 멘티인 경우에만 값이 있음 (TODO: Job 연결 후 수정 예정)
21+
) {
22+
public static MemberSearchResponse from(Member member, Mentor mentor, Mentee mentee) {
23+
return new MemberSearchResponse(
24+
member.getId(),
25+
member.getEmail(),
26+
member.getName(),
27+
member.getNickname(),
28+
member.getRole(),
29+
member.getIsDeleted(),
30+
member.getCreateDate(),
31+
member.getModifyDate(),
32+
mentor != null ? "TODO: Job 연결 필요" : null, // TODO: Job 연결 후 수정
33+
mentor != null ? mentor.getCareerYears() : null,
34+
mentee != null ? "TODO: Job 연결 필요" : null // TODO: Job 연결 후 수정
35+
);
36+
}
37+
}

back/src/main/java/com/back/domain/member/member/entity/Member.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ public class Member extends BaseEntity {
1414
@Column(unique = true, nullable = false, length = 36)
1515
private String publicId;
1616

17-
@Column(unique = true, nullable = false)
17+
@Column(nullable = false)
1818
private String email;
1919

2020
@Column(nullable = false)
2121
private String name;
2222

23-
@Column(unique = true, nullable = false)
23+
@Column(nullable = false)
2424
private String nickname;
2525

2626
@Column(nullable = false)
@@ -30,6 +30,9 @@ public class Member extends BaseEntity {
3030
@Column(nullable = false)
3131
private Role role;
3232

33+
@Column(nullable = false)
34+
private Boolean isDeleted = false;
35+
3336
public enum Role {
3437
MENTOR, MENTEE, ADMIN
3538
}
@@ -38,12 +41,21 @@ public void updateNickname(String nickname) {
3841
this.nickname = nickname;
3942
}
4043

44+
public void updateName(String name) {
45+
this.name = name;
46+
}
47+
48+
public void updateEmail(String email) {
49+
this.email = email;
50+
}
51+
4152
public Member(String email, String password, String name, String nickname, Role role) {
4253
this.email = email;
4354
this.password = password;
4455
this.name = name;
4556
this.nickname = nickname;
4657
this.role = role;
58+
this.isDeleted = false;
4759
}
4860

4961
public Member(Long id, String email, String name, String nickname, Role role) {
@@ -52,6 +64,11 @@ public Member(Long id, String email, String name, String nickname, Role role) {
5264
this.name = name;
5365
this.nickname = nickname;
5466
this.role = role;
67+
this.isDeleted = false;
68+
}
69+
70+
public void delete() {
71+
this.isDeleted = true;
5572
}
5673

5774
@PrePersist

back/src/main/java/com/back/domain/member/member/repository/MemberRepository.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,29 @@
22

33
import com.back.domain.member.member.entity.Member;
44
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.data.jpa.repository.Query;
6+
import org.springframework.data.repository.query.Param;
57

68
import java.util.Optional;
79

810
public interface MemberRepository extends JpaRepository<Member, Long> {
9-
Optional<Member> findByEmail(String email);
10-
Optional<Member> findByNickname(String nickname);
11+
// 활성 사용자만 조회 (소프트 삭제된 사용자 제외)
12+
@Query("SELECT m FROM Member m WHERE m.email = :email AND m.isDeleted = false")
13+
Optional<Member> findByEmail(@Param("email") String email);
14+
15+
@Query("SELECT m FROM Member m WHERE m.nickname = :nickname AND m.isDeleted = false")
16+
Optional<Member> findByNickname(@Param("nickname") String nickname);
17+
18+
@Query("SELECT m FROM Member m WHERE m.id = :id AND m.isDeleted = false")
19+
Optional<Member> findById(@Param("id") Long id);
20+
21+
// 관리자용
22+
@Query("SELECT m FROM Member m WHERE m.email = :email")
23+
Optional<Member> findByEmailIncludingDeleted(@Param("email") String email);
24+
25+
@Query("SELECT m FROM Member m WHERE m.nickname = :nickname")
26+
Optional<Member> findByNicknameIncludingDeleted(@Param("nickname") String nickname);
27+
28+
@Query("SELECT m FROM Member m WHERE m.id = :id")
29+
Optional<Member> findByIdIncludingDeleted(@Param("id") Long id);
1130
}

0 commit comments

Comments
 (0)