본문 바로가기
개발일지_development diary/YSit

YSit [14] - 관리자 페이지 구현 & 권한 구현하기

by YES_developNewbie 2022. 12. 31.

관리자 권한 처리에 대해 한 가지 고민이 있었다. 3가지 선택지가 있었는데, 첫번째로 한 페이지에서 관리자인지 유저인지 판단하도록 코드를 짜는 것이었고, 두번째는 똑같은 페이지를 두 개로 만들어서 각각 유저, 어드민 페이지를 만드는 것이었다. 세번째는 따로 관리자 프로그램을 만드는 것이었다. 처음 기획하고 설계할 땐 1안을 할 생각으로 설계를 했었는데, 이게 지금 와서 조금 생각을 해보니 웹에서도 관리자인지 유저인지 판단해야하고, 컨트롤러쪽에서도 판단을 해야하는데 이게 좀 구현에 어려움이 있었다. 오히려 코드 중복이 많아지는 2안보다 코드가 더 번잡해질 것 같아서 포기했다. 그래서 2안과 3안 중에서 조금 고민을 했었는데, 3안은 프로그램을 다운 받아서 관리를 해야하는데, 만약 학생에게 파일이 들어갈 수도 있고, 급한 상황에 파일이 없어질 경우도 존재하기 때문에 코드 중복을 감수하고 2안으로 만들기로 했다. 코드 중복은 참 맘에 안들긴해요 

 

[ 어드민 페이지 만들기 ]

 

진짜 2안을 고민했던 게 사실 유저와 어드민페이지의 차이가 별로 없다. 그래서 유저를 어드민으로 바꾸는 수준밖에 안됐다. 로그인할 때 유저 아이디 세션을 만들지 않고 어드민 아이디 세션을 생성하고, 경로 또한 어드민 페이지로 다 변경해주었다. 

 

[ . . . ]

 

권한 처리가 지금까지 만들었던 것들 중에서는 관리자는 유저와 달리 다른 유저의 댓글을 삭제할 수 있어야 하고, 모든 유저 목록에서 수정 및 삭제가 가능해야 한다. 또한 유저가 비밀글로 작성한다면 얼마든지 확인할 수 있고, 게시물 삭제 또한 가능해야 한다. 

그리고 유저 중에서는 선생님 계정도 있기 때문에 학생이 비공개 글을 쓴다면 학생은 보지 못하지만 선생님은 볼 수 있도록 해야한다.

학생 계정은 공지 게시물을 쓰지 못하게 막아야 한다.

 

[ 비공개 기능 구현 ]

 

일단 학생이 비공개 게시물을 작성자 본인 제외하고는 들어가지 못하게 막아야 한다. 그래서 게시물 페이지를 들어가는 단계인 ArticleController에서 Get방식으로 게시물 페이지와 http통신을 하는 articlePageForm에서 조건을 달아주기로 했다.

if (article.getStatus() == ArticleStatus.PRIVATE) {
    if (user.getSchoolCategory() == SchoolCategory.STUDENT) {
        if (user.getLoginId() != article.getWriteUser() && !Objects.isNull(article.getUser())) {
            return "redirect:/article/articleList";
        }
    }
}

첫번째로 글이 비공개인지 확인하고, 확인하는 유저가 학생인지 선생님인지 판단하고, 작성자의 아이디가 게시물을 보려는 유저와 같은지 판단하고, 아니라면 다시 들어가지 못하게 게시물 목록으로 돌아간다.

관리자는 비공개더라도 마음대로 볼 수 있으므로 검증 단계 자체를 넣지 않으면 된다.

 

[ 관리자 게시물 삭제 ]

 

게시물을 삭제하기 위해서 Repository와 Service에 삭제 메서드를 만들어준다. 

public void deleteById(Long Id) {
    Article art = em.find(Article.class, Id);
    em.remove(art);
}

그 후 테스트를 진행한다.

@Test
public void deleteTest() {
    String title = "게시물1";
    String body = "내용1";
    Board category = Board.자유;
    ArticleStatus status = ArticleStatus.PUBLIC;
    User user = User.builder()
            .name("TEST")
            .loginId("TEST")
            .loginPw("TEST")
            .build();
    userService.register(user);
    Article article = Article.builder()
            .title(title)
            .body(body)
            .category(category)
            .user(user)
            .status(status)
            .build();
    articleService.save(article);

    articleService.deleteById(article.getId());
    Article art = articleService.findOne(article.getId());
    if (!Objects.isNull(art)){
        fail("실패");
    }
}

테스트가 성공했다면 컨트롤러에 가서 메서드를 만들어준다.

@GetMapping("/admin/articleDelete/{articleId}")
public String articleDelete(@PathVariable("articleId") Long articleId) {
    articleService.deleteById(articleId);

    return "redirect:/admin/article/articleList";
}

잘 작동한다면 성공

 

[ 학생은 공지사항을 쓰지 못합니다 ]

 

ArticleController에서 Post방식으로 통신하는 write 메서드에서 다음 코드를 추가해주었다.

if (form.getCategory() == null) {
    result.rejectValue("category", "required");
} else if (form.getCategory() == Board.공지 && user.getSchoolCategory() == SchoolCategory.STUDENT) {
    result.rejectValue("category", "studentCantSetNotice");
}

그 후 errors.properties에서 에러코드를 추가해줬다

studentCantSetNotice=학생은 공지사항을 작성할 수 없습니다

 

[ 관리자의 댓글 삭제 ]

 

유저가 본인 댓글만 삭제할 수 있는 기능은 이미 댓글 기능 구현할 때 구현했으므로 관리자만 구현하면 된다.

먼저 Repository와 Serivce에서 삭제 메서드를 구현한다. 게시물 삭제와 달리 일부러 댓글은 삭제됐다는 것으로 내용을 바꾸게 했다. 

@Transactional(readOnly = false)
public void delCommentByAdmin(Comment delCom) {
    Comment comment = commentRepository.findOne(delCom.getId());
    String deleteMention = "관리자에 의해 삭제되었습니다";
    comment.changeBody(deleteMention);
}

그 후 컨트롤러에서 메서드를 사용해 삭제 문구로 바꿔준다.

@PostMapping("/admin/comment/delComment")
public String delete(@ModelAttribute CommentForm form,
                     Model model, HttpServletRequest request) {
    HttpSession session = request.getSession();
    Long adminId = (Long) session.getAttribute("adminId");
    
    Comment comment = commentService.findOne(form.getId());
    commentService.delCommentByAdmin(comment);

    Comment check = commentService.findOne(form.getId());
    log.info("\nCommentBody = {}", check.getBody());

    return returnPage(adminId, form.getArticleId(), model);
}