안녕하세요
댓글 기능구현(2): 수정, 삭제 권한 분기(유저/게스트/관리자) 본문
전체 기능 설계
목차
댓글 기능 구현(1): https://sakuraop.tistory.com/601
1. 전체 기능 설계
2. 유저/게스트에 따라 Form 다르게 하기
3. 댓글 작성기능 구현
4. 댓글 리스트 구현
댓글 기능 구현(2)
5. 댓글 수정/삭제 구현 (유저/게스트/관리자에 따라 수정/삭제 권한 다르게 하기)
5. 댓글 수정/삭제 구현 (유저/게스트에 따라 수정 권한 다르게 하기)
구현 방법 간단 요약
- 관리자는 모든 버튼 가능
- 유저는 자신 댓글 버튼, 게스트 댓글 버튼 가능
- 게스트는 게스트 댓글만 가능
분기는 게스트, 유저, 관리자 세가지 입니다.
수정/삭제 버튼 visible 여부
게스트: 유저 댓글에 대해서 수정/삭제 버튼 hide
유저: 자신의 댓글에 대해서만 수정/삭제 버튼 visible
관리자: 모든 댓글에 대해서 수정/삭제 버튼 visible
수정/삭제 권한 여부
게스트: ID와 Password 입력으로 댓글을 작성/삭제는 할 수 있으나 댓글 수정은 불가능합니다.
유저: 로그인 한 유저는 "자신의 글" 작성/수정/삭제와 "Password 입력으로 게스트 댓글" 삭제가 가능합니다.
관리자: 모든 작업이 Password 입력 없이 가능합니다.
조건별로 의미를 알기 쉽도록 변수명을 작명합니다.
// 댓글 수정 및 삭제 권한이 있는지 여부에 따라 삭제 버튼이 나타나도록 합니다.
const isSameCommenter: boolean = isLoggedIn && userEmail === author; // 동일한 댓글 작성자
const isBlogAdmin: boolean = checkBlogAdmin(userEmail); // 블로그 관리자
const canEdit: boolean = isSameCommenter || !isLoggedIn || isBlogAdmin; // 수정 권한
const isVisibleConfirmDeletePassword =
deletingCommentId === commentId && checkingGuestPassword && !isLoggedIn; // 게스트 댓글 삭제버튼 visible 여부
로그인 유저는 자신의 댓글에 수정 버튼이 보여야 한다 -> isSameCommenter
관리자는 모든 권한이 있어야 한다 -> isBlogAdmin
수정권한은 자신의 댓글(isSameCommenter) 또는 관리자 (isBlogAdmin) 또는 게스트 댓글에 나타나야 한다 -> canEdit
현재 선택한 댓글 삭제 비밀번호 입력창은 관리자에게는 나타나지 않아야 한다 -> isVisibleConfirmDeletePassword
프로필 이미지 여부
로그인 유저라면 유저의 고유 thumbnail을 나타나도록 하고,
게스트라면 게스트 전용 thummbnail 을 나타나도록 한다.
<div className={styles.thumbnail}>{isLoggedIn ? "✅" : "😀"}</div>
수정/삭제 버튼 여부
수정권한이 있다면 ( isSameCommenter || !isLoggedIn || isBlogAdmin ) 나타나도록 한다.
게스트 댓글은 수정 버튼이 나타나지 않도록 한다. ( `${!isLoggedIn && "hide"}` )
{canEdit && (
<div>
<buttonclassName={`${styles.editButton} ${!isLoggedIn && "hide"}`}>수정</button>
<buttonclassName={styles.deleteButton}>삭제</button>
</div>
)}
게스트 댓글은 비밀번호 확인을 거쳐야 합니다.
따라서 삭제 요청 api도 달라야 합니다.
{canEdit && (
<div>
<buttonclassName={`${styles.editButton} ${!isLoggedIn && "hide"}`}>수정</button>
<button
className={styles.deleteButton}
onClick={
isSameCommenter || isBlogAdmin
? () => handleClickDeleteButton(commentId)
: () => handleClickGuestDeleteButton(commentId)
}
>
삭제
</button>
<divclassName={`${styles.guestConfirm} ${isVisibleConfirmDeletePassword && "visible"}`}>비밀번호 확인</div>
</div>
)}
자신의 댓글 또는 관리자라면( isSameCommenter || isBlogAdmin )
비밀번호 확인을 거치지 않고 삭제하는 api 를 요청합니다.
자신의 댓글이 아니거나 관리자가 아닌 요청의 경우엔 삭제할 수 없도록 합니다.
if ( !isBlogAdmin && !isSameAuthor ) {
return NextResponse.json({ message: "댓글 삭제: 수정 권한이 없습니다." }, { status: 400 });
}
// 삭제 버튼 클릭 이벤트
const handleClickDeleteButton = async (_id: string) => {
try {
// DELETE 요청을 보냅니다.
const res = await deleteCommentApi(postId, _id);
// 삭제한 댓글을 제외한 결과를 state에 저장합니다.
const afterDeleteComments: Comment[] = commentList.filter((comment: Comment) => String(comment._id) !== _id);
setCommentList(afterDeleteComments);
} catch (err) {
console.error(err);
}
};
// 로그인 댓글 삭제 API
export const DELETE = async (req: NextRequest) => {
// 로그인 유저일 경우 블로그 관리자가 아니거나, 동일한 작성자가 아닐 경우 400 응답
if (token) {
const isBlogAdmin = checkBlogAdmin(token.email as string);
const isSameAuthor = token.email === foundResult.author;
if (!isBlogAdmin && !isSameAuthor) {
return NextResponse.json({ message: "댓글 삭제: 수정 권한이 없습니다." }, { status: 400 });
}
}
};
게스트 댓글이라면
비밀번호 확인을 거치고 삭제하는 api 를 요청합니다.
비밀번호가 다른 경우에는 삭제할 수 없도록 합니다.
const isValidPassword = await compare(password, foundComment.password); // 댓글 비밀번호 검사
// 입력한 비밀번호가 다른 경우 삭제할 수 없도록
if (isValidPassword) {
return NextResponse.json({ message: "게스트 댓글 삭제: 비밀번호가 다릅니다." }, { status: 400 });
}
// 게스트 비밀번호 입력 후 삭제확인 버튼 클릭 이벤트
const handleClickConfirmGuestPassword = async (_id: string) => {
try {
// POST로 비밀번호 확인삭제 요청을 보냅니다.
const res = await postGuestCommentDeletionApi(postId, _id, deletePassword);
// 댓글 삭제 비밀번호가 다른 경우
if (!res) {
window.alert("비밀번호가 다릅니다.");
return;
}
// 삭제된 댓글 리스트 렌더링
const deletedCommentList = [...commentList].filter((comment: Comment) => String(comment._id) != _id);
setCommentList(deletedCommentList);
} catch (err) {
console.error(err);
}
};
// 게스트 댓글 삭제 API
export const POST = async (req: NextRequest) => {
const isValidPassword = await compare(password, foundComment.password); // 댓글 비밀번호 검사
// 입력한 비밀번호가 다른 경우
if (isValidPassword) {
return NextResponse.json({ message: "게스트 댓글 삭제: 비밀번호가 다릅니다." }, { status: 400 });
}
//...
};
'Next13 블로그 프로젝트' 카테고리의 다른 글
카테고리(2) - 카테고리로 포스트 검색 기능 구현 방법 (0) | 2023.10.01 |
---|---|
Next13 동적 라우트 params, body, 응답, nextauth (기존 vs Next13 비교) (0) | 2023.09.26 |
댓글 기능구현(1): 댓글 작성, 수정, 삭제, 리스트 조회 (0) | 2023.09.23 |
XSS 방어 DOMpurify - JavaScript HTML 삽입 방지 방법 (0) | 2023.09.20 |
router.refresh(): redirect한 게시물이 새로고침 되지 않는 문제 해결 (0) | 2023.09.19 |