diff --git a/src/main/java/demo/api/auth/AuthController.java b/src/main/java/demo/api/auth/AuthController.java new file mode 100644 index 0000000..6e4faaa --- /dev/null +++ b/src/main/java/demo/api/auth/AuthController.java @@ -0,0 +1,49 @@ +package demo.api.auth; + +import demo.api.jwt.dtos.TokenDto; +import demo.api.user.domain.User; +import demo.api.user.dtos.UserSignInRequest; +import demo.api.user.dtos.UserSignUpRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@Controller +@RequestMapping("/auth") +@RequiredArgsConstructor +public class AuthController { + private final AuthService authService; + + @GetMapping("/signUp") + public String signUp() { + return "user/signUp"; + } + + @PostMapping("/signUp") + public String signUp(@Validated UserSignUpRequest signUpReq) throws Exception { + User user = authService.signUp(signUpReq); + + if(user.getEmail() != "") { + return "redirect:/user/signIn"; + } + + return "redirect:/user/signUp"; + } + + @GetMapping("/signIn") + public String signIn(@RequestParam(value = "fail", required = false) String flag, Model model) { + model.addAttribute("failed", flag != null); + + return "user/signIn"; + } + + @PostMapping + public TokenDto signIn(@Validated UserSignInRequest signInReq) { + return authService.signIn(signInReq); + } +} diff --git a/src/main/java/demo/api/auth/AuthService.java b/src/main/java/demo/api/auth/AuthService.java new file mode 100644 index 0000000..ab6382d --- /dev/null +++ b/src/main/java/demo/api/auth/AuthService.java @@ -0,0 +1,22 @@ +package demo.api.auth; + +import demo.api.jwt.dtos.TokenDto; +import demo.api.user.domain.User; +import demo.api.user.dtos.UserSignInRequest; +import demo.api.user.dtos.UserSignUpRequest; + +public interface AuthService { + /** + * 유저의 정보로 회원가입 + * @param signUpReq 가입할 유저의 정보 Dto + * @return 가입된 유저 정보 + */ + User signUp(UserSignUpRequest signUpReq) throws Exception; + + /** + * 유저 정보로 로그인 + * @param signInReq 유저의 이메일과 비밀번호 + * @return json web token + */ + TokenDto signIn(UserSignInRequest signInReq); +} diff --git a/src/main/java/demo/api/auth/AuthServiceImpl.java b/src/main/java/demo/api/auth/AuthServiceImpl.java new file mode 100644 index 0000000..5b8e592 --- /dev/null +++ b/src/main/java/demo/api/auth/AuthServiceImpl.java @@ -0,0 +1,67 @@ +package demo.api.auth; + +import demo.api.exception.CustomException; +import demo.api.jwt.JwtTokenProvider; +import demo.api.jwt.dtos.TokenDto; +import demo.api.user.domain.User; +import demo.api.user.dtos.UserSignInRequest; +import demo.api.user.dtos.UserSignUpRequest; +import demo.api.user.repository.UserRepository; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class AuthServiceImpl implements AuthService { + private final UserRepository userRepository; + private final PasswordEncoder bCryptPasswordEncoder; + private final JwtTokenProvider jwtTokenProvider; + private final AuthenticationManager authenticationManager; + + @Override + @Transactional + public User signUp(UserSignUpRequest signUpReq) throws Exception { + System.out.println("signUpReq = " + signUpReq.toString()); + if(this.isEmailExist(signUpReq.getEmail())) { + throw new Exception("Your Mail already Exist."); + } + User newUser = signUpReq.toUserEntity(); + newUser.hashPassword(bCryptPasswordEncoder); + return userRepository.save(newUser); + } + + @Override + public TokenDto signIn(UserSignInRequest signInReq) { + try { + Authentication authentication = authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken( + signInReq.getEmail(), + signInReq.getPassword() + ) + ); + + return new TokenDto(jwtTokenProvider.generateToken(authentication)); + } catch (AuthenticationException e) { + throw new CustomException("Invalid credentials supplied", HttpStatus.UNPROCESSABLE_ENTITY); + } + } + + /** + * 이메일 중복 여부를 확인 + * + * @param email + * @return true | false + */ + private boolean isEmailExist(String email) { + Optional byEmail = userRepository.findByEmail(email); + return !byEmail.isEmpty(); + } +} diff --git a/src/main/java/demo/api/config/SecurityConfig.java b/src/main/java/demo/api/config/SecurityConfig.java index 5b01272..3300ad0 100644 --- a/src/main/java/demo/api/config/SecurityConfig.java +++ b/src/main/java/demo/api/config/SecurityConfig.java @@ -21,11 +21,7 @@ public class SecurityConfig { private final JwtTokenProvider jwtTokenProvider; private final JwtAccessDeniedHandler jwtAccessDeniedHandler; private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; - -// @Bean -// public UserDetailsService userDetailsService() { -// return new UserDetailsServiceImpl(); -// } + @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); @@ -48,9 +44,9 @@ public class SecurityConfig { .authorizeRequests() .antMatchers( "/", - "/user/signUp", + "/auth/signUp", "/user/userList", - "/user/signIn*", + "/auth/signIn*", "/favicon.ico" ).permitAll() .anyRequest().authenticated(); diff --git a/src/main/java/demo/api/config/UserDetailsServiceImpl.java b/src/main/java/demo/api/config/UserDetailsServiceImpl.java index 8ff2c30..f072735 100644 --- a/src/main/java/demo/api/config/UserDetailsServiceImpl.java +++ b/src/main/java/demo/api/config/UserDetailsServiceImpl.java @@ -15,7 +15,7 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; -@Component +@Service public class UserDetailsServiceImpl implements UserDetailsService { @Autowired private UserRepository userRepository; diff --git a/src/main/java/demo/api/jwt/dtos/TokenDto.java b/src/main/java/demo/api/jwt/dtos/TokenDto.java new file mode 100644 index 0000000..0bfdd77 --- /dev/null +++ b/src/main/java/demo/api/jwt/dtos/TokenDto.java @@ -0,0 +1,8 @@ +package demo.api.jwt.dtos; + +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public class TokenDto { + private String access_token; +} diff --git a/src/main/java/demo/api/user/UserController.java b/src/main/java/demo/api/user/UserController.java index 2037218..9eebc98 100644 --- a/src/main/java/demo/api/user/UserController.java +++ b/src/main/java/demo/api/user/UserController.java @@ -24,25 +24,6 @@ import org.springframework.web.bind.annotation.RequestParam; public class UserController { private final UserService userService; - @GetMapping("/signUp") - public String signUp() { - return "user/signUp"; - } - - @PostMapping("/signUp") - public String signUp(@Validated UserSignUpRequest signUpReq) throws Exception { - User user = userService.signUp(signUpReq); - - return "redirect:/user/signIn"; - } - - @GetMapping("/signIn") - public String signIn(@RequestParam(value = "fail", required = false) String flag, Model model) { - model.addAttribute("failed", flag != null); - - return "user/signIn"; - } - @GetMapping("/profile") public String profile(Model model, @AuthenticationPrincipal UserDetails userDetails) { if (userDetails != null) { diff --git a/src/main/java/demo/api/user/UserService.java b/src/main/java/demo/api/user/UserService.java index dfeee6d..1e42a4b 100644 --- a/src/main/java/demo/api/user/UserService.java +++ b/src/main/java/demo/api/user/UserService.java @@ -6,13 +6,6 @@ import java.util.List; import java.util.Optional; public interface UserService { - /** - * 유저의 정보로 회원가입 - * @param signUpReq 가입할 유저의 정보 Dto - * @return 가입된 유저 정보 - */ - User signUp(UserSignUpRequest signUpReq) throws Exception; - /** * 모든 유저 리스트를 반환 * @return 유저 리스트 diff --git a/src/main/java/demo/api/user/UserServiceImpl.java b/src/main/java/demo/api/user/UserServiceImpl.java index acb5ade..5998c7c 100644 --- a/src/main/java/demo/api/user/UserServiceImpl.java +++ b/src/main/java/demo/api/user/UserServiceImpl.java @@ -1,32 +1,16 @@ package demo.api.user; import demo.api.user.domain.User; -import demo.api.user.dtos.UserSignUpRequest; import demo.api.user.repository.UserRepository; import java.util.List; import java.util.Optional; import lombok.RequiredArgsConstructor; -import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor -@Transactional public class UserServiceImpl implements UserService { private final UserRepository userRepository; - private final PasswordEncoder bCryptPasswordEncoder; - - @Override - public User signUp(UserSignUpRequest signUpReq) throws Exception { - System.out.println("signUpReq = " + signUpReq.toString()); - if(this.isEmailExist(signUpReq.getEmail())) { - throw new Exception("Your Mail already Exist."); - } - User newUser = signUpReq.toUserEntity(); - newUser.hashPassword(bCryptPasswordEncoder); - return userRepository.save(newUser); - } @Override public List findAll() { @@ -42,15 +26,4 @@ public class UserServiceImpl implements UserService { public User updateUser(User user, String newInfo) { return null; } - - /** - * 이메일 중복 여부를 확인 - * - * @param email - * @return true | false - */ - private boolean isEmailExist(String email) { - Optional byEmail = userRepository.findByEmail(email); - return !byEmail.isEmpty(); - } } diff --git a/src/main/java/demo/api/user/dtos/UserSignInRequest.java b/src/main/java/demo/api/user/dtos/UserSignInRequest.java new file mode 100644 index 0000000..c6cab39 --- /dev/null +++ b/src/main/java/demo/api/user/dtos/UserSignInRequest.java @@ -0,0 +1,26 @@ +package demo.api.user.dtos; + +import demo.api.user.domain.User; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@ToString +public class UserSignInRequest { + @NotEmpty(message = "Please enter your Email") + @Email + private String email; + @NotEmpty(message = "Please enter your Password") + private String password; + + @Builder + public UserSignInRequest(String email, String password) { + this.email = email; + this.password = password; + } +} + diff --git a/src/main/java/demo/api/user/repository/UserRepository.java b/src/main/java/demo/api/user/repository/UserRepository.java index 394d793..1c192a2 100644 --- a/src/main/java/demo/api/user/repository/UserRepository.java +++ b/src/main/java/demo/api/user/repository/UserRepository.java @@ -5,7 +5,7 @@ import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -// @Repository +@Repository public interface UserRepository extends JpaRepository { Optional findByEmail(String email); diff --git a/src/main/resources/templates/user/signIn.html b/src/main/resources/templates/user/signIn.html index 1c6d9f9..844cda2 100644 --- a/src/main/resources/templates/user/signIn.html +++ b/src/main/resources/templates/user/signIn.html @@ -10,7 +10,7 @@

로그인

Fail to login

-
+
diff --git a/src/main/resources/templates/user/signUp.html b/src/main/resources/templates/user/signUp.html index e24d719..9429d33 100644 --- a/src/main/resources/templates/user/signUp.html +++ b/src/main/resources/templates/user/signUp.html @@ -5,7 +5,7 @@

회원가입

- +
diff --git a/src/test/java/demo/api/user/service/UserServiceTest.java b/src/test/java/demo/api/user/service/UserServiceTest.java index da05f1c..92fae17 100644 --- a/src/test/java/demo/api/user/service/UserServiceTest.java +++ b/src/test/java/demo/api/user/service/UserServiceTest.java @@ -3,24 +3,17 @@ package demo.api.user.service; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; -import demo.api.AppConfig; +import demo.api.auth.AuthService; import demo.api.user.UserService; -import demo.api.user.UserServiceImpl; import demo.api.user.domain.User; import demo.api.user.dtos.UserSignUpRequest; import demo.api.user.repository.UserRepository; import java.util.List; import java.util.Optional; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.transaction.annotation.Transactional; @@ -31,17 +24,13 @@ class UserServiceTest { private static final String EMAIL = "test@email.com"; private static final String PASSWORD = "12345"; private static final String NAME = "김정호"; - private UserService userService; - @Autowired - private UserRepository userRepository; + @Autowired private PasswordEncoder bCryptPasswordEncoder; - - @BeforeEach - public void beforeEach() { - AppConfig appConfig = new AppConfig(userRepository, bCryptPasswordEncoder); - userService = appConfig.userService(); - } + @Autowired + private UserService userService; + @Autowired + private AuthService authService; @Test @DisplayName("유저 회원가입") @@ -51,7 +40,7 @@ class UserServiceTest { System.out.println("user = " + user.toString()); // when - User newUser = userService.signUp(user); + User newUser = authService.signUp(user); // then System.out.println("newUser = " + newUser.toString()); @@ -65,7 +54,7 @@ class UserServiceTest { UserSignUpRequest user = createSignUpRequest(); // when - User newUser = userService.signUp(user); + User newUser = authService.signUp(user); // then System.out.println("newUser pw = " + newUser.getPassword()); @@ -78,10 +67,10 @@ class UserServiceTest { // given UserSignUpRequest user = createSignUpRequest(); System.out.println("user = " + user.toString()); - User newUser = userService.signUp(user); + User newUser = authService.signUp(user); // when - Boolean flag = newUser.checkPassword(PASSWORD, bCryptPasswordEncoder); + boolean flag = newUser.checkPassword(PASSWORD, bCryptPasswordEncoder); System.out.println("flag = " + flag); // then @@ -94,7 +83,7 @@ class UserServiceTest { List prevUserList = userService.findAll(); int prevLen = prevUserList.size(); UserSignUpRequest user1 = createSignUpRequest(); - userService.signUp(user1); + authService.signUp(user1); // when List userList = userService.findAll(); @@ -108,7 +97,7 @@ class UserServiceTest { void findByEmail() throws Exception { // given UserSignUpRequest user1 = createSignUpRequest(); - userService.signUp(user1); + authService.signUp(user1); // when Optional byEmail = userService.findByEmail(EMAIL);