본문 바로가기
스프링

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

by 근즈리얼 2021. 10. 7.
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

댓글