11.1 회원 상세 목록 구현
Ex) 아이디 눌렀을 때 상세 화면으로 이동 - 모자이크 부분은 이메일
Note) 실행 결과
Ex) 상세 페이지 만들기
- detail
<hide/>
<!doctype html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>관리자 화면</title>
<style>
</style>
</head>
<body>
<h1>관리자 회원 관리 - 회원 상세 정보</h1>
<!-- <div th:replace="/fragments/layout.html :: fragment-body-menu" ></div>-->
<div>
<a href="/admin/main.do">관리자 메인</a>
|
<a href="/admin/member/list.do">회원 관리</a>
|
<a href="#">카테고리 관리</a>
|
<a href="#">강의 관리</a>
|
<a href="/member/logout">로그 아웃</a>
<br>
<hr/>
</div>
<div class="detail">
</div>
</body>
</html>
- param 에 추가
String userId;
- detail 수정 - 모자이크는 이메일
- adminMemberCont 메서드
<hide/>
@GetMapping("/admin/member/detail.do")
public String detail(Model model, MemberParam parameter){
parameter.init(); // 유효한 값이 되도록 만든다.
return "admin/member/detail";
}
Note) 실행 결과
- 회원관리 탭 누르면?
Ex)
- detail()
MemberDto detail(String userId);
- 목록을 가져올 때 마이바티스 쿼리 매퍼를 이용해서 가져왔다. '페이징'이 복잡, 쿼리가 복잡하면 마이바티스 사용
- detail 파일은 JPA가 빠르고 편하다. 심플한 쿼리 => JPA
- Dto에 메서드 of() 추가
<hide/>
public static MemberDto of(Member member){
MemberDto memberDto = MemberDto.builder()
.userId(member.getUserId())
.userName(member.getUserName())
.phone(member.getPhone())
.regDt(member.getRegDt())
.emailAuthYn(member.isEmailAuthYn())
.emailAuthDt(member.getEmailAuthDt())
.emailAuthKey(member.getEmailAuthKey())
.resetPasswordKey(member.getResetPasswordKey())
.resetPasswordLimitDt(member.getResetPasswordLimitDt())
.adminYn(member.isAdminYn())
.build();
return memberDto;
}
- 임플 -detail (멤버의 상세 정보를 가져오는 메서드)
<hide/>
@Override
public MemberDto detail(String userId) {
Optional<Member> optionalMember = memberRepository.findById(userId);
if(!optionalMember.isPresent()){
return null;
}
// optional 멤버 존재할 때만
Member member = optionalMember.get();
return MemberDto.of(member);
}
- 컨트롤러
<hide/>
@GetMapping("/admin/member/detail.do")
public String detail(Model model, MemberParam parameter){
parameter.init(); // 유효한 값이 되도록 만든다.
MemberDto member = memberService.detail(parameter.getUserId());
model.addAttribute("member", member);
return "admin/member/detail";
}
=================오류 =======================
================= 오류 ==================
- 오류: SQL문을 건드리지 않았는데 다음과 같은 오류가 났다.
- 원인: DTO 클래스를 빌드 하기 위해서 @NoArgs, @AllArgs 를 붙여야 한다.
Note) 실행 결과
- 이제 이 데이터를 표로 만들자
Ex) 테이블로 만들기
<hide/>
<!doctype html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>관리자 화면</title>
<style>
</style>
</head>
<body>
<h1>관리자 회원 관리 - 회원 상세 정보</h1>
<!-- <div th:replace="/fragments/layout.html :: fragment-body-menu" ></div>-->
<div>
<a href="/admin/main.do">관리자 메인</a>
|
<a href="/admin/member/list.do">회원 관리</a>
|
<a href="#">카테고리 관리</a>
|
<a href="#">강의 관리</a>
|
<a href="/member/logout">로그 아웃</a>
<br>
<hr/>
</div>
<div class="detail">
<table>
<tbody>
<tr>
<th>아이디</th>
<td>
<p th:text="${member.userId}"></p>
</td>
</tr>
<tr>
<th>이름</th>
<td>
<p th:text="${member.userName}"></p>
</td>
</tr>
<tr>
<th>연락처</th>
<td>
<p th:text="${member.phone}"></p>
</td>
</tr>
<tr>
<th>가입일</th>
<td>
<p th:text="${member.regDt}"></p>
</td>
</tr>
<tr>
<th>이메일 인증</th>
<td>
<p th:text="${member.isEmailAuthYn()}"></p>
</td>
</tr>
<tr>
<th>관리자 여부</th>
<td>
<p th:text="${member.isAdminYn()}"></p>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Note) 실행 결과
Ex) CSS - 표 테두리
<hide/>
<style>
.detail table{
width: 100%;
border-collapse: collapse;
}
.detail table th, .detail table td{
border: solid 1px #000;
}
</style>
Note) 실행 결과
11.2 회원 상태 및 비밀번호 초기화 구현
Ex) 회원이 로그인 가능한지 아닌지 파악
- 엔티티
private String userStatus;
- 멤버코드 인터페이스
<hide?>
package com.zerobase.fastlms.member.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.time.LocalDateTime;
public interface MemberCode {
String MEMBER_STATUS_ING = "ING";
String MEMBER_STATUS_STOP = "STOP";
}
- 방금 생성한 변수가 테이블에 나오게 하려면?
- 임플 - register()에 추가한다. - 회원 가입 중일 때는 멤버 코드가 요청 중이다.
-> emailAuth() 에서 이메일 인증을 한 다음에 회원이 되도록 구현
<hide/>
Member member = Member.builder()
.userId(parameter.getUserId())
.userName(parameter.getUserName())
.phone(parameter.getPhone())
.password(encPassword)
.regDt(LocalDateTime.now())
.emailAuthYn(false)
.emailAuthKey(uuid)
.userStatus(Member.MEMBER_STATUS_REQ)
.build();
- emailAuth() => ING를 넣어줘야 이용 가능한 회원이 된다.
<hide/>
@Override
public boolean emailAuth(String uuid) { // 이메일 인증
Optional<Member> optionalMember = memberRepository.findByEmailAuthKey(uuid); // 있으면 Optional<Member> 가 리턴된다.
if(!optionalMember.isPresent()){
return false;
}
Member member = optionalMember.get(); // 존재하는 경우 멤버
// 이미 활성화됐기 때문에 또 활성화할 필요없다.
if(member.isEmailAuthYn()){
return false;
}
member.setUserStatus(MemberCode.MEMBER_STATUS_ING);
member.setEmailAuthYn(true);
member.setEmailAuthDt(LocalDateTime.now());
memberRepository.save(member);
return true;
}
- 임플 클래스 loadUserBuUsername
<hide/>
if(Member.MEMBER_STATUS_REQ.equals(member.getUserStatus())){
throw new MemberNotEmailAuthException("");
}
if(Member.MEMBER_STATUS_STOP.equals(member.getUserStatus())){
throw new MemberStopUserException("정지된 회원입니다.");
}
- 새로운 예외 클래스
<hide/>
package com.zerobase.fastlms.member.exception;
public class MemberStopUserException extends RuntimeException{
public MemberStopUserException(String error) {
super(error);
}
}
Ex) Status 테스트
- 회원가입 후, db
- 이메일 활성화하지 않고 로그인 하면?
- 활성화 하고 나면 상태가 ING로 바뀐다.
Ex) 회원 정지
- DTO 클래스에도 추가해야 detail페이지에서 userStatus를 사용 가능하다.
String userStatus;
- of()
<hide/>
public static MemberDto of(Member member){
MemberDto memberDto = MemberDto.builder()
.userId(member.getUserId())
.userName(member.getUserName())
.phone(member.getPhone())
.regDt(member.getRegDt())
.emailAuthYn(member.isEmailAuthYn())
.emailAuthDt(member.getEmailAuthDt())
.emailAuthKey(member.getEmailAuthKey())
.resetPasswordKey(member.getResetPasswordKey())
.resetPasswordLimitDt(member.getResetPasswordLimitDt())
.adminYn(member.isAdminYn())
.userStatus(member.getUserStatus())
.build();
return memberDto;
}
Note) 방금 가입하면 회원 상태 정보에 데이터가 들어가서 볼 수 있다.
Ex) 회원 상태 변경하기
- detail
<hide/>
<tr>
<th>회원 상태</th>
<td>
<p>
현재 상태: <span th:text="${member.userStatus}"></span>
</p>
<select name="userStatus">
<option value="REQ">가입 승인 중</option>
<option value="ING">정상 이용 중</option>
<option value="STOP">정지 중</option>
</select>
<p th:text="${member.userStatus}"></p>
</td>
</tr>
- 관리자가 옵션을 선택해서 변경 가능하도록 구현한다.
- 상태 변경 버튼을 누르면 서버로 전송되게끔 <form> 으로 감싼다.
-> 상태만 전송하면 안되니까 <input> 으로 아이디도 함께 보낸다.
<hide/>
<form method="post" action="/admin/member/status.do">
<input type="hidden" th:value="${member.userId}"/>
<select name="userStatus">
<option value="REQ">가입 승인 중</option>
<option value="ING">정상 이용 중</option>
<option value="STOP">정지 중</option>
</select>
<button type="submit">상태 변경</button>
</form>
- 컨트롤러에서 주소를 만든다.
- MemberStatusInput'
<hide/>
package com.zerobase.fastlms.member.model;
import lombok.Data;
import lombok.ToString;
@Data
public class MemberStatusInput {
String userId;
String userStatus;
}
- 컨트롤러
-> redirect 로 주소를 직접 이동시킨다. 페이지 직접 이동
<hide/>
@PostMapping("/admin/member/status.do")
public String status(Model model, MemberStatusInput parameter){
boolean result = memberService.updateStatus(parameter.getUserId(), parameter.getUserStatus());
return "redirect:/admin/member/detail.do?userId?=" + parameter.getUserId();
}
- 멤버서비스: updateStatus()
/**
* 회원 상태 변경
*/
boolean updateStatus(String userId, String userStatus);
- 임플 클래스에 위 메서드 구현
- 기존 화면
- 정지 중 선택
- 상태 변경 클릭
========================오류 ========================
- 오류: 상태변경을 클릭하면 로그인 페이지로 이동한다.
- 원인: impl클래스에서 updateStatus()의 반환값을 false로 뒀다 틀림, .. 말고도 다른 원인이 있다.
-> detail 파일의 <input>태그를 잘못 작성했다. 아래처럼 수정하면 된다.
<input th:value="${member.userId}" type="hidden" name="userId"/>
Ex) 비밀번호 초기화
- 사용자 아이디를 가지고 비밀번호를 초기화 하도록한다.
<hide/>
<tr>
<th>비밀번호 초기화</th>
<td>
<div>
<form method="post" action="/admin/member/password.do">
<input th:value="${member.userId}" type="hidden" name="userId"/>
<input type="text" name="password"/>
<button type="submit">비밀번호 초기화</button>
</form>
</div>
</td>
</tr>
- 멤버 컨트롤러
<hide/>
@PostMapping("/admin/member/password.do")
public String password(Model model, MemberStatusInput parameter){
boolean result = memberService.updatePassword(parameter.getUserId(), parameter.getUserStatus());
return "redirect:/admin/member/detail.do?userId=" + parameter.getUserId();
}
- admin에 모델 패키지를 하나 만든다. (멤버에도 이름이 같은 패키지가 있다.)
<hide/>
package com.zerobase.fastlms.admin.model;
import lombok.Data;
@Data
public class MemberInput {
String userId;
String userStatus;
String password;
}
- 컨트롤러
<hide/>
@PostMapping("/admin/member/password.do")
public String password(Model model, MemberInput parameter){
boolean result = memberService.updatePassword(parameter.getUserId(), parameter.getPassword());
return "redirect:/admin/member/detail.do?userId=" + parameter.getUserId();
}
- updatePassword()
<hide/>
@Override
public boolean updatePassword(String userId, String password) {
Optional<Member> optionalMember = memberRepository.findById(userId);
if(!optionalMember.isPresent()){
throw new UsernameNotFoundException("회원 정보가 존재하지 않습니다.");
}
Member member = optionalMember.get();
String encPassword = BCrypt.hashpw(password, BCrypt.gensalt());
member.setPassword(encPassword);
memberRepository.save(member);
return true;
}
- 비번 초기화
Note) 실행 결과 - 정상
'Spring Projcect > 학습 관리 시스템 & 백오피스 구축' 카테고리의 다른 글
Chapter 13. 강좌 목록 (0) | 2022.08.23 |
---|---|
Chapter 12. 카테고리 화면 (0) | 2022.08.22 |
Chapter 10. 회원 목록 (0) | 2022.08.20 |
Chapter 09. 관리자 로그인 구현 (0) | 2022.08.20 |
Chapter 08. 스프링 부트 프로젝트 - 비밀번호 찾기(초기화) (0) | 2022.08.18 |