spring Security 6. - 삭제 기능

알파로그·2023년 3월 22일
0

Spring Boot

목록 보기
28/57
post-custom-banner

✏️ 삭제 기능 구현

  • 권한이 있는 클라이언트에 한해 삭제 기능 정상 작동

📍 Web 삭제 버튼 추가 - V1.

  • 삭제는 수정과 달리 href 속성값을 javascript:void(0)로 설정했다.
    • javascprit 를 호출하는 코드이다.
    • 삭제 버튼을 눌렀을 경우 “정말로 삭제하시겠습니까?” 와같은 확인 절차를 넣으려고 설정되었다.
  • th:data-uri
    • 삭제를 실행할 URL 을 얻기 위한 로직
    • javascript 코드가 시작되고 얻어낸 URL 을 매개변수로 사용하기위해 추가되었다.
  • delete
    • 삭제 버튼이 눌리는 이벤트를 확인할 수 있도록 class 속성에 추가
  • javascript
    • 최 하단에 javascript 영역을 만들어 확인로직을 구현했다.
    • 사용자가 확인을 누르면 data-uri 값으로 url 을 호출해 삭제가 완료된다.
    • 취소를 누르면 아무일도 발생하지 않는다.
<a href="javascript:void(0);"
   th:data-uri="@{|/question/delete/${question.id}|}"
   class="delete btn btn-sm btn-outline-secondary"
   sec:authorize="isAuthenticated()"
   th:if="${question.author != null
          and #authentication.getPrincipal().getUsername() == question.author.username}"
   th:text="삭제"></a>

<!--javascript 영역-->
<script layout:fragment="script"
        type="text/javascript">
    const delete_elements = document.getElementsByClassName("delete");
    Array.from(delete_elements).forEach(function (element) {
        element.addEventListener('clic', function () {
            if (confirm("정말로 삭제하시겠습니까?")) {
                location.href = this.dataset.url;
            };
        });
    });
</script>
</html>

📍 Web 삭제 버튼 추가 - V2.

  • 자바스크립트 로직을 별도로 만들지 않고 onclick 만으로 동일한 효과를 만들어낼 수 있다.
  • onclick="return confirm(...)
    • 버튼을 클릭할경우 괄호 안의 메시지가 팝업된다.
    • 팝업 메시지에서 확인을 누를경우 로직이 실행되고,
      취소를 누르면 실행되지 않는다.
<a onclick="return confirm('정말로 삭제하시겠습니까?');"
   th:href="@{|/question/delete/${question.id}|}"
   class="btn btn-sm btn-outline-secondary"
   sec:authorize="isAuthenticated()"
   th:if="${question.author != null
   and #authentication.getPrincipal().getUsername() == question.author.username}"
   th:text="삭제"></a>

📍 layout 계층 - javascript 레이아웃으로 추가

  • body 의 최 하단부에 javascript 를 포함시킨다.
    • 화면 랜더링이 완료되지 않은 상태로 javascript 가 실행되면 오류 또는 로딩 지연이 발생할 수 있다.
<!doctype html>
<html lang="ko" xmlns:layout="">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" type="text/css" th:href="@{/bootstrap.min.css}">
    <!-- sbb CSS -->
    <link rel="stylesheet" type="text/css" th:href="@{/style.css}">
    <title>Hello, sbb!</title>
</head>
<body>
<!-- 네비게이션 바 -->
<nav th:replace="~{navbar :: navbarFragment}"></nav>

<!-- 기본 템플릿 안에 삽입될 내용 Start -->
<th:block layout:fragment="content"></th:block>
<!-- 기본 템플릿 안에 삽입될 내용 End -->
<!-- Bootstrap JS 시작 -->
<script th:src="@{/bootstrap.min.js}"></script>
<!-- Bootstrap JS 종료 -->
<!-- 자바스크립트 시작 -->
<th:block layout:fragment="script"></th:block>
<!-- 자바스크립트 종료 -->
</body>
</html>

📍 Service 계층 - 객체 삭제 기능 추가

@Service
@RequiredArgsConstructor
public class QuestionService {

    private final QuestionRepository questionRepository;

    //-- question 삭제 --//
    public void delete(Question question) {
        questionRepository.delete(question);
    }

}

📍 Controller 계층

@Controller
@RequestMapping("/question")
@RequiredArgsConstructor
public class QuestionController {

    private final QuestionService questionService;
    private final UserService userService;

    //-- question 삭제 --//
    @GetMapping("/delete/{id}")
    @PreAuthorize("isAuthenticated()")
    public String questionDelete(
            @PathVariable Integer id,
            Principal principal
    ) {
        Question question = questionService.getQuestion(id);

        if (!question.getAuthor().getUsername().equals(principal.getName()))
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "삭제 권한이 없습니다.");

        questionService.delete(question);
        return "redirect:/";
    }
}
profile
잘못된 내용 PR 환영
post-custom-banner

0개의 댓글