스프링

스프링 권한에 따라 다른 기능 추가 - 등록, 찾기

근즈리얼 2021. 10. 7. 14:15
728x90

이전까지 만들었던 회원가입과 로그인을 이용해 권한에 따라 다른 기능을 주는 프로젝트를 진행해보겠습니다.

 

1. home.html 파일 수정

2. Register entity 설명

3. RegisterService

4. UtilController

5. register.html

 

우선 데이터베이스에 두 가지 권한을 갖는 member를 만들었습니다.

 

1. home.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
    xmlns:sec="http://thymeleaf.org/extras/spring-security">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>환영합니다</h1>
<a href="members/login" sec:authorize="isAnonymous()">로그인</a>
<a href="members/new" sec:authorize="isAnonymous()">회원가입</a>
<a href="members/logout" sec:authorize="isAuthenticated()">로그아웃</a>
<a href="util/find" sec:authorize = "hasRole('USER')">찾아보기</a>
<a href="util/register" sec:authorize = "hasRole('ADMIN')">등록하기</a>
<!--<p th:text="${name}"></p>-->
</body>
</html>

- USER권한을 갖고 있으면 찾아보기가 보이고 ADMIN 권한을 갖고 있으면 등록하기가 보이도록 설정했습니다.

 

ADMIN 계정일 때 HOME 화면

USER 계정일 때 HOME 화면

이렇게 계정에 따라 다르게 보이는 것을 확인할 수 있습니다.

 

2. register 엔티티, registerDto

Register는

ADMIN 계정을 가진 member가 무언가를 등록할 때 테이블로 쓸 엔티티입니다.

이때 중요한게 member와의 관계입니다.

저는 member한명이 Register에 한번 등록할 수 있게 만들 것이므로 1대1 관계로 잡았습니다.

package com.asdanything.ask.Entity;

import com.asdanything.ask.dto.RegisterDto;
import lombok.*;

import javax.persistence.*;

@Entity
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Getter
@Setter
public class Register {

    @Id @GeneratedValue
    private Long id;

    @OneToOne
    private Member member;

    private String phoneNum;

    private String ability;

    private String address;

    public static Register createRegister(RegisterDto registerDto, Member member){
        Register register = new Register();
        register.setAbility(registerDto.getAbility());
        register.setMember(member);
        register.setPhoneNum(registerDto.getPhoneNum());
        register.setAddress(registerDto.getAddress());

        return register;
    }
}

RegisterDto

package com.asdanything.ask.dto;

import com.asdanything.ask.Entity.Member;
import lombok.Data;

import javax.validation.constraints.NotBlank;

@Data
public class RegisterDto {

    @NotBlank(message = "빈 칸이면 안됩니다.")
    private String phoneNum;
    @NotBlank(message = "빈 칸이면 안됩니다.")
    private String ability;
    @NotBlank(message = "빈 칸이면 안됩니다.")
    private String address;
}

 

3. RegisterService

registerService는 회원가입과 로직이 매우 비슷합니다.

package com.asdanything.ask.service;

import com.asdanything.ask.Entity.Member;
import com.asdanything.ask.Entity.Register;
import com.asdanything.ask.dto.RegisterDto;
import com.asdanything.ask.repository.MemberRepository;
import com.asdanything.ask.repository.RegisterRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class RegisterService {

    private final RegisterRepository registerRepository;
    private final MemberRepository memberRepository;

    public void saveRegister(String memberName, RegisterDto registerDto){
        Member findMember = memberRepository.findByName(memberName);
        Register register = Register.createRegister(registerDto, findMember);
        duplicateCheck(register);
        registerRepository.save(register);
    }

    public void duplicateCheck(Register register){
        //Register findRegister = registerRepository.findByMemberId(register.getMember().getId());
        Register findRegister = registerRepository.findByMember(register.getMember());

        if(findRegister != null){
            throw new IllegalStateException("이미 등록하셨습니다.");
        }
    }
}

- 1대1 매핑이기 때문에 중복성 검사를 해야합니다.

 

4. utilController

utilController

package com.asdanything.ask.controller;


import com.asdanything.ask.Entity.Member;
import com.asdanything.ask.Entity.Register;
import com.asdanything.ask.dto.RegisterDto;
import com.asdanything.ask.repository.MemberRepository;
import com.asdanything.ask.repository.RegisterRepository;
import com.asdanything.ask.service.RegisterService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import javax.validation.Valid;

@Controller
@RequiredArgsConstructor
public class UtilController {

    private final RegisterService registerService;

    private final MemberRepository memberRepository;
    private final RegisterRepository registerRepository;

    @GetMapping("/util/find")
    public String find(){
        return "util/find";
    }

    @GetMapping("/util/register")
    public String registerForm(Model model){
        model.addAttribute("registerDto",new RegisterDto());
        return "util/register";
    }

    @PostMapping("/util/register")
    public String register(@Valid RegisterDto registerDto, BindingResult bindingResult, Authentication auth, Model model){

        if(bindingResult.hasErrors()){
            return "util/register";
        }

        try{
            registerService.saveRegister(auth.getName(),registerDto);
        }catch (IllegalStateException e){
            model.addAttribute("errorMessage",e.getMessage());
            return "util/register";
        }

        return "redirect:/";
    }
}

- error처리를 하는 로직이 있습니다. 회원가입과 같습니다.

 

5. register.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
</head>

<script th:inline="javascript">
    $(document).ready(function (){
        let errorMessage =[[${errorMessage}]];
        if(errorMessage != null){
            alert(errorMessage);
        }
    })
</script>


<style>
    .fieldError{
        color : red;
    }
</style>

<body>
<form action="/util/register" method="post" th:object="${registerDto}">
    <div>
        <label th:for="phoneNum">전화번호</label>
        <input type="text" th:field="*{phoneNum}" placeholder="전화번호를 입력하세요">
        <p th:if="${#fields.hasErrors('phoneNum')}"
           th:errors="*{phoneNum}" class="fieldError">Incorrect data</p>
    </div>
    <div>
        <label th:for="ability">할 수 있는 일</label>
        <input type="text" th:field="*{ability}" placeholder="할 수 있는 일을 입력하세요">
        <p th:if="${#fields.hasErrors('ability')}"
           th:errors="*{ability}" class="fieldError">Incorrect data</p>
    </div>
    <div>
        <label th:for="address">주소</label>
        <input type="text" th:field="*{address}" placeholder="주소를 입력하세요">
        <p th:if="${#fields.hasErrors('address')}"
           th:errors="*{address}" class="fieldError">Incorrect data</p>
    </div>
    <button type="submit">제출하기</button>
</form>

</body>
</html>

 

결과!

 

데이터베이스에 저장된 모습입니다.

 

현재 member_id가 1인 계정으로 다시 한번 등록하려 할때 alert창이 뜨는 것을 확인할 수 있습니다.

 

이제 ADMIN계정이 등록하는 것을 만들었고 다음번에는 USER계정이 ADMIN계정이 등록한 것들을 보는 기능을 만들어 보겠습니다.

728x90