From dc6280ca6f555f577c377f864f0e0c177f5a01f0 Mon Sep 17 00:00:00 2001 From: jsy3831 Date: Mon, 27 Sep 2021 11:35:24 +0900 Subject: [PATCH 1/3] =?UTF-8?q?#2=20=EC=BD=94=EB=94=A9=EC=BB=A8=EB=B2=A4?= =?UTF-8?q?=EC=85=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 10 + naver-checkstyle-rules.xml | 433 ++++++++++++++++++ naver-intellij-formatter.xml | 62 +++ .../com/photobook/PhotobookApplication.java | 6 +- .../com/photobook/annotation/LoginCheck.java | 6 +- .../com/photobook/annotation/LoginUser.java | 6 +- .../com/photobook/aop/AuthCheckAspect.java | 29 +- .../com/photobook/config/MyBatisConfig.java | 28 +- .../com/photobook/config/WebMvcConfig.java | 21 +- .../photobook/config/WebSecurityConfig.java | 22 +- .../photobook/controller/UserController.java | 116 ++--- .../LoginUserArgumentResolver.java | 31 -- .../LoginUserArgumentResolver.java | 32 ++ .../controller/response/Response.java | 44 +- src/main/java/com/photobook/dto/UserDto.java | 44 +- .../exception/ExceptionController.java | 141 +++--- .../photobook/exception/ExceptionType.java | 8 +- .../customException/DuplicatedException.java | 8 - .../UnauthorizedException.java | 8 - .../customexception/DuplicatedException.java | 8 + .../UnauthorizedException.java | 8 + .../java/com/photobook/mapper/UserMapper.java | 11 +- .../com/photobook/service/LoginService.java | 8 +- .../com/photobook/service/UserService.java | 10 +- .../service/impl/LoginServiceImpl.java | 41 +- .../service/impl/UserServiceImpl.java | 92 ++-- src/main/resources/ehcache.xml | 3 +- .../photobook/PhotobookApplicationTests.java | 6 +- .../service/impl/UserServiceImplTest.java | 149 +++--- .../photobook/utils/PasswordEncoderTest.java | 41 +- 30 files changed, 982 insertions(+), 450 deletions(-) create mode 100644 naver-checkstyle-rules.xml create mode 100644 naver-intellij-formatter.xml delete mode 100644 src/main/java/com/photobook/controller/argumentResolver/LoginUserArgumentResolver.java create mode 100644 src/main/java/com/photobook/controller/argumentresolver/LoginUserArgumentResolver.java delete mode 100644 src/main/java/com/photobook/exception/customException/DuplicatedException.java delete mode 100644 src/main/java/com/photobook/exception/customException/UnauthorizedException.java create mode 100644 src/main/java/com/photobook/exception/customexception/DuplicatedException.java create mode 100644 src/main/java/com/photobook/exception/customexception/UnauthorizedException.java diff --git a/build.gradle b/build.gradle index 88b4502..463cc61 100644 --- a/build.gradle +++ b/build.gradle @@ -2,12 +2,16 @@ plugins { id 'org.springframework.boot' version '2.5.3' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' + id 'checkstyle' } group = 'com' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' +compileJava.options.encoding = 'UTF-8' // UTF-8 설정 +compileTestJava.options.encoding = 'UTF-8' + configurations { compileOnly { extendsFrom annotationProcessor @@ -39,3 +43,9 @@ dependencies { test { useJUnitPlatform() } + +checkstyle { + maxWarnings = 0 // 규칙이 어긋나는 코드가 하나라도 있을 경우 빌드 fail을 내고 싶다면 이 선언을 추가한다. + configFile = file("${rootDir}/naver-checkstyle-rules.xml") + toolVersion ="9.0" +} diff --git a/naver-checkstyle-rules.xml b/naver-checkstyle-rules.xml new file mode 100644 index 0000000..1439aae --- /dev/null +++ b/naver-checkstyle-rules.xml @@ -0,0 +1,433 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/naver-intellij-formatter.xml b/naver-intellij-formatter.xml new file mode 100644 index 0000000..658fc65 --- /dev/null +++ b/naver-intellij-formatter.xml @@ -0,0 +1,62 @@ + + + diff --git a/src/main/java/com/photobook/PhotobookApplication.java b/src/main/java/com/photobook/PhotobookApplication.java index faa3796..e99a7d4 100644 --- a/src/main/java/com/photobook/PhotobookApplication.java +++ b/src/main/java/com/photobook/PhotobookApplication.java @@ -8,8 +8,8 @@ @EnableCaching public class PhotobookApplication { - public static void main(String[] args) { - SpringApplication.run(PhotobookApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(PhotobookApplication.class, args); + } } diff --git a/src/main/java/com/photobook/annotation/LoginCheck.java b/src/main/java/com/photobook/annotation/LoginCheck.java index 1ff2c1a..530e310 100644 --- a/src/main/java/com/photobook/annotation/LoginCheck.java +++ b/src/main/java/com/photobook/annotation/LoginCheck.java @@ -1,6 +1,10 @@ package com.photobook.annotation; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; @Documented @Target(ElementType.METHOD) diff --git a/src/main/java/com/photobook/annotation/LoginUser.java b/src/main/java/com/photobook/annotation/LoginUser.java index d2673b9..4e3e1d8 100644 --- a/src/main/java/com/photobook/annotation/LoginUser.java +++ b/src/main/java/com/photobook/annotation/LoginUser.java @@ -1,6 +1,10 @@ package com.photobook.annotation; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; @Documented @Target(ElementType.PARAMETER) diff --git a/src/main/java/com/photobook/aop/AuthCheckAspect.java b/src/main/java/com/photobook/aop/AuthCheckAspect.java index 021f177..72301fa 100644 --- a/src/main/java/com/photobook/aop/AuthCheckAspect.java +++ b/src/main/java/com/photobook/aop/AuthCheckAspect.java @@ -1,30 +1,31 @@ package com.photobook.aop; -import com.photobook.dto.UserDto; -import com.photobook.exception.customException.UnauthorizedException; -import com.photobook.service.LoginService; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; +import com.photobook.dto.UserDto; +import com.photobook.exception.customexception.UnauthorizedException; +import com.photobook.service.LoginService; + @Component @Aspect public class AuthCheckAspect { - private final LoginService loginService; + private final LoginService loginService; - public AuthCheckAspect(LoginService loginService) { - this.loginService = loginService; - } + public AuthCheckAspect(LoginService loginService) { + this.loginService = loginService; + } - @Before("@annotation(com.photobook.annotation.LoginCheck)") - public void loginCheck() { + @Before("@annotation(com.photobook.annotation.LoginCheck)") + public void loginCheck() { - UserDto userInfo = loginService.getLoginUserInfo(); + UserDto userInfo = loginService.getLoginUserInfo(); - if(userInfo == null) { - throw new UnauthorizedException("로그인된 사용자 정보가 존재하지 않습니다."); - } - } + if (userInfo == null) { + throw new UnauthorizedException("로그인된 사용자 정보가 존재하지 않습니다."); + } + } } diff --git a/src/main/java/com/photobook/config/MyBatisConfig.java b/src/main/java/com/photobook/config/MyBatisConfig.java index 1d272c4..73a13ee 100644 --- a/src/main/java/com/photobook/config/MyBatisConfig.java +++ b/src/main/java/com/photobook/config/MyBatisConfig.java @@ -1,5 +1,7 @@ package com.photobook.config; +import javax.sql.DataSource; + import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.SqlSessionTemplate; @@ -8,23 +10,21 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import javax.sql.DataSource; - @Configuration @MapperScan(basePackages = "com.photobook.mapper") public class MyBatisConfig { - @Bean - public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception{ - SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); - sqlSessionFactoryBean.setDataSource(dataSource); - PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); - sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mapper/*.xml")); - return sqlSessionFactoryBean.getObject(); - } + @Bean + public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { + SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); + sqlSessionFactoryBean.setDataSource(dataSource); + PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mapper/*.xml")); + return sqlSessionFactoryBean.getObject(); + } - @Bean - public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) throws Exception { - return new SqlSessionTemplate(sqlSessionFactory); - } + @Bean + public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) throws Exception { + return new SqlSessionTemplate(sqlSessionFactory); + } } diff --git a/src/main/java/com/photobook/config/WebMvcConfig.java b/src/main/java/com/photobook/config/WebMvcConfig.java index 1914b8f..a42cf72 100644 --- a/src/main/java/com/photobook/config/WebMvcConfig.java +++ b/src/main/java/com/photobook/config/WebMvcConfig.java @@ -1,25 +1,26 @@ package com.photobook.config; -import com.photobook.controller.argumentResolver.LoginUserArgumentResolver; +import java.util.List; + import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import java.util.List; +import com.photobook.controller.argumentresolver.LoginUserArgumentResolver; @Configuration public class WebMvcConfig implements WebMvcConfigurer { - private final LoginUserArgumentResolver loginUserArgumentResolver; + private final LoginUserArgumentResolver loginUserArgumentResolver; - public WebMvcConfig(LoginUserArgumentResolver loginUserArgumentResolver) { - this.loginUserArgumentResolver = loginUserArgumentResolver; - } + public WebMvcConfig(LoginUserArgumentResolver loginUserArgumentResolver) { + this.loginUserArgumentResolver = loginUserArgumentResolver; + } - @Override - public void addArgumentResolvers(List resolvers) { - resolvers.add(loginUserArgumentResolver); - } + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(loginUserArgumentResolver); + } } diff --git a/src/main/java/com/photobook/config/WebSecurityConfig.java b/src/main/java/com/photobook/config/WebSecurityConfig.java index 33f010c..2bb9722 100644 --- a/src/main/java/com/photobook/config/WebSecurityConfig.java +++ b/src/main/java/com/photobook/config/WebSecurityConfig.java @@ -12,17 +12,17 @@ @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { - @Bean - public PasswordEncoder getPasswordEncoder() { - return new BCryptPasswordEncoder(); - } + @Bean + public PasswordEncoder getPasswordEncoder() { + return new BCryptPasswordEncoder(); + } - @Override - protected void configure(HttpSecurity http) throws Exception { - http.cors().disable() - .csrf().disable() - .formLogin().disable() - .headers().frameOptions().disable(); - } + @Override + protected void configure(HttpSecurity http) throws Exception { + http.cors().disable() + .csrf().disable() + .formLogin().disable() + .headers().frameOptions().disable(); + } } diff --git a/src/main/java/com/photobook/controller/UserController.java b/src/main/java/com/photobook/controller/UserController.java index 7fed4af..57162ed 100644 --- a/src/main/java/com/photobook/controller/UserController.java +++ b/src/main/java/com/photobook/controller/UserController.java @@ -1,93 +1,101 @@ package com.photobook.controller; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; + +import org.springframework.http.HttpStatus; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + import com.photobook.annotation.LoginCheck; import com.photobook.annotation.LoginUser; import com.photobook.controller.response.Response; import com.photobook.dto.UserDto; -import com.photobook.exception.customException.DuplicatedException; +import com.photobook.exception.customexception.DuplicatedException; import com.photobook.service.LoginService; import com.photobook.service.UserService; -import org.springframework.http.HttpStatus; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; -import javax.validation.constraints.NotBlank; @RestController @RequestMapping("/users") @Validated public class UserController { - private final UserService userService; - - private final LoginService loginService; + private final UserService userService; - public UserController(UserService userService, LoginService loginService) { - this.userService = userService; - this.loginService = loginService; - } + private final LoginService loginService; - @PostMapping("/login") - public Response login(@RequestParam @NotBlank String id, @RequestParam @NotBlank String password, - @LoginUser UserDto loginUser) { + public UserController(UserService userService, LoginService loginService) { + this.userService = userService; + this.loginService = loginService; + } - if(loginUser != null) { - throw new DuplicatedException("이미 로그인된 상태입니다."); - } + @PostMapping("/login") + public Response login(@RequestParam @NotBlank String id, @RequestParam @NotBlank String password, + @LoginUser UserDto loginUser) { - UserDto userInfo = userService.validateLogin(id, password); + if (loginUser != null) { + throw new DuplicatedException("이미 로그인된 상태입니다."); + } - loginService.setLoginUserInfo(userInfo); + UserDto userInfo = userService.validateLogin(id, password); - return Response.toResponse(200, "로그인 하였습니다.", userInfo); - } + loginService.setLoginUserInfo(userInfo); - @PostMapping("/logout") - @LoginCheck - public Response logout() { + return Response.toResponse(200, "로그인 하였습니다.", userInfo); + } - loginService.removeLoginUserInfo(); + @PostMapping("/logout") + @LoginCheck + public Response logout() { - return Response.toResponse(200, "로그아웃 하였습니다."); - } + loginService.removeLoginUserInfo(); - @GetMapping("/my-info") - @LoginCheck - public Response getUserInfoById(@LoginUser UserDto loginUser) { + return Response.toResponse(200, "로그아웃 하였습니다."); + } - UserDto userInfo = userService.getUserInfoById(loginUser.getId()); + @GetMapping("/my-info") + @LoginCheck + public Response getUserInfoById(@LoginUser UserDto loginUser) { - return Response.toResponse(200, "회원정보 조회", userInfo); - } + UserDto userInfo = userService.getUserInfoById(loginUser.getId()); - @PostMapping("/signup") - @ResponseStatus(HttpStatus.CREATED) - public Response signup(@RequestBody @Valid UserDto userInfo) { + return Response.toResponse(200, "회원정보 조회", userInfo); + } - userService.createUser(userInfo); + @PostMapping("/signup") + @ResponseStatus(HttpStatus.CREATED) + public Response signup(@RequestBody @Valid UserDto userInfo) { - return Response.toResponse(201, "회원가입 하였습니다."); - } + userService.createUser(userInfo); - @GetMapping("/{id}") - public Response checkUserId(@PathVariable @NotBlank String id) { + return Response.toResponse(201, "회원가입 하였습니다."); + } - userService.validateUserId(id); + @GetMapping("/{id}") + public Response checkUserId(@PathVariable @NotBlank String id) { - return Response.toResponse(200, "사용가능한 아이디입니다."); - } + userService.validateUserId(id); + return Response.toResponse(200, "사용가능한 아이디입니다."); + } - @DeleteMapping("/my-info") - @LoginCheck - public Response deleteUser(@LoginUser UserDto loginUser) { + @DeleteMapping("/my-info") + @LoginCheck + public Response deleteUser(@LoginUser UserDto loginUser) { - userService.deleteUser(loginUser.getId()); + userService.deleteUser(loginUser.getId()); - loginService.removeLoginUserInfo(); + loginService.removeLoginUserInfo(); - return Response.toResponse(200, "회원탈퇴 하였습니다."); - } + return Response.toResponse(200, "회원탈퇴 하였습니다."); + } } \ No newline at end of file diff --git a/src/main/java/com/photobook/controller/argumentResolver/LoginUserArgumentResolver.java b/src/main/java/com/photobook/controller/argumentResolver/LoginUserArgumentResolver.java deleted file mode 100644 index a357bf3..0000000 --- a/src/main/java/com/photobook/controller/argumentResolver/LoginUserArgumentResolver.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.photobook.controller.argumentResolver; - -import com.photobook.annotation.LoginUser; -import com.photobook.service.LoginService; -import org.springframework.core.MethodParameter; -import org.springframework.stereotype.Component; -import org.springframework.web.bind.support.WebDataBinderFactory; -import org.springframework.web.context.request.NativeWebRequest; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; -import org.springframework.web.method.support.ModelAndViewContainer; - -@Component -public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver { - - private final LoginService loginService; - - public LoginUserArgumentResolver(LoginService loginService) { - this.loginService = loginService; - } - - @Override - public boolean supportsParameter(MethodParameter parameter) { - return parameter.hasParameterAnnotation(LoginUser.class); - } - - @Override - public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, - NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { - return loginService.getLoginUserInfo(); - } -} diff --git a/src/main/java/com/photobook/controller/argumentresolver/LoginUserArgumentResolver.java b/src/main/java/com/photobook/controller/argumentresolver/LoginUserArgumentResolver.java new file mode 100644 index 0000000..de42cc2 --- /dev/null +++ b/src/main/java/com/photobook/controller/argumentresolver/LoginUserArgumentResolver.java @@ -0,0 +1,32 @@ +package com.photobook.controller.argumentresolver; + +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +import com.photobook.annotation.LoginUser; +import com.photobook.service.LoginService; + +@Component +public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver { + + private final LoginService loginService; + + public LoginUserArgumentResolver(LoginService loginService) { + this.loginService = loginService; + } + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(LoginUser.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { + return loginService.getLoginUserInfo(); + } +} diff --git a/src/main/java/com/photobook/controller/response/Response.java b/src/main/java/com/photobook/controller/response/Response.java index 8c9a5c0..f907597 100644 --- a/src/main/java/com/photobook/controller/response/Response.java +++ b/src/main/java/com/photobook/controller/response/Response.java @@ -1,37 +1,37 @@ package com.photobook.controller.response; +import java.time.LocalDateTime; + import lombok.Builder; import lombok.Getter; -import java.time.LocalDateTime; - @Getter public class Response { - private final LocalDateTime timestamp = LocalDateTime.now(); + private final LocalDateTime timestamp = LocalDateTime.now(); - private final int code; + private final int code; - private final String message; + private final String message; - private final T body; + private final T body; - @Builder - Response(final int code, final String message, final T body) { - this.code = code; - this.message = message; - this.body = body; - } + @Builder + Response(final int code, final String message, final T body) { + this.code = code; + this.message = message; + this.body = body; + } - public static Response toResponse(int code, String message) { - return toResponse(code, message, null); - } + public static Response toResponse(int code, String message) { + return toResponse(code, message, null); + } - public static Response toResponse(int code, String message, T body) { - return Response.builder() - .code(code) - .message(message) - .body(body) - .build(); - } + public static Response toResponse(int code, String message, T body) { + return Response.builder() + .code(code) + .message(message) + .body(body) + .build(); + } } diff --git a/src/main/java/com/photobook/dto/UserDto.java b/src/main/java/com/photobook/dto/UserDto.java index 4df1296..3e3a5d8 100644 --- a/src/main/java/com/photobook/dto/UserDto.java +++ b/src/main/java/com/photobook/dto/UserDto.java @@ -1,41 +1,45 @@ package com.photobook.dto; +import java.io.Serializable; +import java.time.LocalDate; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Past; + import lombok.Getter; import lombok.Setter; import lombok.ToString; -import javax.validation.constraints.*; -import java.io.Serializable; -import java.time.LocalDate; - @Getter @Setter @ToString public class UserDto implements Serializable { - private int userId; + private int userId; - @NotBlank - private String id; + @NotBlank + private String id; - @NotBlank - private String password; + @NotBlank + private String password; - @NotBlank - private String name; + @NotBlank + private String name; - @NotBlank - @Email - private String email; + @NotBlank + @Email + private String email; - @NotNull - @Past - private LocalDate birth; + @NotNull + @Past + private LocalDate birth; - private String profileImageName; + private String profileImageName; - private String profileImagePath; + private String profileImagePath; - private String profileMessage; + private String profileMessage; } diff --git a/src/main/java/com/photobook/exception/ExceptionController.java b/src/main/java/com/photobook/exception/ExceptionController.java index ae9994d..1838be5 100644 --- a/src/main/java/com/photobook/exception/ExceptionController.java +++ b/src/main/java/com/photobook/exception/ExceptionController.java @@ -1,9 +1,10 @@ package com.photobook.exception; -import com.photobook.controller.response.Response; -import com.photobook.exception.customException.DuplicatedException; -import com.photobook.exception.customException.UnauthorizedException; -import lombok.extern.slf4j.Slf4j; +import java.util.ArrayList; +import java.util.List; + +import javax.validation.ConstraintViolationException; + import org.springframework.http.HttpStatus; import org.springframework.security.core.AuthenticationException; import org.springframework.validation.BindingResult; @@ -13,75 +14,77 @@ import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; -import javax.validation.ConstraintViolationException; -import java.util.ArrayList; -import java.util.List; +import com.photobook.controller.response.Response; +import com.photobook.exception.customexception.DuplicatedException; +import com.photobook.exception.customexception.UnauthorizedException; + +import lombok.extern.slf4j.Slf4j; @Slf4j @RestControllerAdvice public class ExceptionController { - private static ExceptionType exceptionType(Exception e) { - return new ExceptionType(e.getClass().getSimpleName()); - } - - @ExceptionHandler(Exception.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Response handleException(Exception e) { - log.error("handleException throw Exception : {}", e.getMessage()); - return Response.toResponse(400, e.getMessage(), exceptionType(e)); - } - - @ExceptionHandler(ConstraintViolationException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Response handleConstraintViolationException(ConstraintViolationException e) { - log.error("handleConstraintViolationException throw ConstraintViolationException : {}", e.getMessage()); - return Response.toResponse(400, e.getMessage(), exceptionType(e)); - } - - @ExceptionHandler(IllegalArgumentException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Response handleIllegalArgumentException(IllegalArgumentException e) { - log.error("handleIllegalArgumentException throw IllegalArgumentException : {}", e.getMessage()); - return Response.toResponse(400, e.getMessage(), exceptionType(e)); - } - - @ExceptionHandler(UnauthorizedException.class) - @ResponseStatus(HttpStatus.UNAUTHORIZED) - public Response handleUnauthorizedException(UnauthorizedException e) { - return Response.toResponse(401, e.getMessage(), exceptionType(e)); - } - - @ExceptionHandler(DuplicatedException.class) - @ResponseStatus(HttpStatus.CONFLICT) - public Response handleDuplicatedException(DuplicatedException e) { - return Response.toResponse(409, e.getMessage(), exceptionType(e)); - } - - @ExceptionHandler(MethodArgumentNotValidException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Response handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { - - BindingResult bindingResult = e.getBindingResult(); - List message = new ArrayList<>(); - - for(FieldError fieldError : bindingResult.getFieldErrors()) { - StringBuilder builder = new StringBuilder(); - - builder.append(fieldError.getField()); - builder.append(" : "); - builder.append(fieldError.getDefaultMessage()); - - message.add(builder); - } - - return Response.toResponse(400, message.toString(), exceptionType(e)); - } - - @ExceptionHandler(AuthenticationException.class) - @ResponseStatus(HttpStatus.FORBIDDEN) - public Response handleAuthenticationException(AuthenticationException e) { - return Response.toResponse(403, e.getMessage(), exceptionType(e)); - } + private static ExceptionType exceptionType(Exception e) { + return new ExceptionType(e.getClass().getSimpleName()); + } + + @ExceptionHandler(Exception.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public Response handleException(Exception e) { + log.error("handleException throw Exception : {}", e.getMessage()); + return Response.toResponse(400, e.getMessage(), exceptionType(e)); + } + + @ExceptionHandler(ConstraintViolationException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public Response handleConstraintViolationException(ConstraintViolationException e) { + log.error("handleConstraintViolationException throw ConstraintViolationException : {}", e.getMessage()); + return Response.toResponse(400, e.getMessage(), exceptionType(e)); + } + + @ExceptionHandler(IllegalArgumentException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public Response handleIllegalArgumentException(IllegalArgumentException e) { + log.error("handleIllegalArgumentException throw IllegalArgumentException : {}", e.getMessage()); + return Response.toResponse(400, e.getMessage(), exceptionType(e)); + } + + @ExceptionHandler(UnauthorizedException.class) + @ResponseStatus(HttpStatus.UNAUTHORIZED) + public Response handleUnauthorizedException(UnauthorizedException e) { + return Response.toResponse(401, e.getMessage(), exceptionType(e)); + } + + @ExceptionHandler(DuplicatedException.class) + @ResponseStatus(HttpStatus.CONFLICT) + public Response handleDuplicatedException(DuplicatedException e) { + return Response.toResponse(409, e.getMessage(), exceptionType(e)); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public Response handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + + BindingResult bindingResult = e.getBindingResult(); + List message = new ArrayList<>(); + + for (FieldError fieldError : bindingResult.getFieldErrors()) { + StringBuilder builder = new StringBuilder(); + + builder.append(fieldError.getField()); + builder.append(" : "); + builder.append(fieldError.getDefaultMessage()); + + message.add(builder); + } + + return Response.toResponse(400, message.toString(), exceptionType(e)); + } + + @ExceptionHandler(AuthenticationException.class) + @ResponseStatus(HttpStatus.FORBIDDEN) + public Response handleAuthenticationException(AuthenticationException e) { + return Response.toResponse(403, e.getMessage(), exceptionType(e)); + } } diff --git a/src/main/java/com/photobook/exception/ExceptionType.java b/src/main/java/com/photobook/exception/ExceptionType.java index 4d8e3d3..76ea3c7 100644 --- a/src/main/java/com/photobook/exception/ExceptionType.java +++ b/src/main/java/com/photobook/exception/ExceptionType.java @@ -5,10 +5,10 @@ @Getter public class ExceptionType { - private final String type; + private final String type; - ExceptionType(final String type) { - this.type = type; - } + ExceptionType(final String type) { + this.type = type; + } } diff --git a/src/main/java/com/photobook/exception/customException/DuplicatedException.java b/src/main/java/com/photobook/exception/customException/DuplicatedException.java deleted file mode 100644 index 2d07007..0000000 --- a/src/main/java/com/photobook/exception/customException/DuplicatedException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.photobook.exception.customException; - -public class DuplicatedException extends RuntimeException { - - public DuplicatedException(String message) { - super(message); - } -} diff --git a/src/main/java/com/photobook/exception/customException/UnauthorizedException.java b/src/main/java/com/photobook/exception/customException/UnauthorizedException.java deleted file mode 100644 index 30f33b5..0000000 --- a/src/main/java/com/photobook/exception/customException/UnauthorizedException.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.photobook.exception.customException; - -public class UnauthorizedException extends RuntimeException { - - public UnauthorizedException(String message) { - super(message); - } -} diff --git a/src/main/java/com/photobook/exception/customexception/DuplicatedException.java b/src/main/java/com/photobook/exception/customexception/DuplicatedException.java new file mode 100644 index 0000000..38338c6 --- /dev/null +++ b/src/main/java/com/photobook/exception/customexception/DuplicatedException.java @@ -0,0 +1,8 @@ +package com.photobook.exception.customexception; + +public class DuplicatedException extends RuntimeException { + + public DuplicatedException(String message) { + super(message); + } +} diff --git a/src/main/java/com/photobook/exception/customexception/UnauthorizedException.java b/src/main/java/com/photobook/exception/customexception/UnauthorizedException.java new file mode 100644 index 0000000..bf661a3 --- /dev/null +++ b/src/main/java/com/photobook/exception/customexception/UnauthorizedException.java @@ -0,0 +1,8 @@ +package com.photobook.exception.customexception; + +public class UnauthorizedException extends RuntimeException { + + public UnauthorizedException(String message) { + super(message); + } +} diff --git a/src/main/java/com/photobook/mapper/UserMapper.java b/src/main/java/com/photobook/mapper/UserMapper.java index 8e67368..d66afc2 100644 --- a/src/main/java/com/photobook/mapper/UserMapper.java +++ b/src/main/java/com/photobook/mapper/UserMapper.java @@ -1,18 +1,19 @@ package com.photobook.mapper; -import com.photobook.dto.UserDto; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +import com.photobook.dto.UserDto; + @Mapper public interface UserMapper { - UserDto getUserInfoById(@Param("id") String id); + UserDto getUserInfoById(@Param("id") String id); - void createUser(UserDto userDto); + void createUser(UserDto userDto); - boolean checkUserId(@Param("id") String id); + boolean checkUserId(@Param("id") String id); - void deleteUser(String id); + void deleteUser(String id); } diff --git a/src/main/java/com/photobook/service/LoginService.java b/src/main/java/com/photobook/service/LoginService.java index acd9812..b64539c 100644 --- a/src/main/java/com/photobook/service/LoginService.java +++ b/src/main/java/com/photobook/service/LoginService.java @@ -2,14 +2,12 @@ import com.photobook.dto.UserDto; -import javax.servlet.http.HttpSession; - public interface LoginService { - void setLoginUserInfo(UserDto userDto); + void setLoginUserInfo(UserDto userDto); - void removeLoginUserInfo(); + void removeLoginUserInfo(); - UserDto getLoginUserInfo(); + UserDto getLoginUserInfo(); } diff --git a/src/main/java/com/photobook/service/UserService.java b/src/main/java/com/photobook/service/UserService.java index 998f652..761c06a 100644 --- a/src/main/java/com/photobook/service/UserService.java +++ b/src/main/java/com/photobook/service/UserService.java @@ -4,13 +4,13 @@ public interface UserService { - UserDto validateLogin(String id, String password); + UserDto validateLogin(String id, String password); - UserDto getUserInfoById(String id); + UserDto getUserInfoById(String id); - void createUser(UserDto userInfo); + void createUser(UserDto userInfo); - void validateUserId(String id); + void validateUserId(String id); - void deleteUser(String id); + void deleteUser(String id); } diff --git a/src/main/java/com/photobook/service/impl/LoginServiceImpl.java b/src/main/java/com/photobook/service/impl/LoginServiceImpl.java index ff83d9b..c77d005 100644 --- a/src/main/java/com/photobook/service/impl/LoginServiceImpl.java +++ b/src/main/java/com/photobook/service/impl/LoginServiceImpl.java @@ -1,35 +1,36 @@ package com.photobook.service.impl; -import com.photobook.dto.UserDto; -import com.photobook.service.LoginService; +import javax.servlet.http.HttpSession; + import org.springframework.stereotype.Service; -import javax.servlet.http.HttpSession; +import com.photobook.dto.UserDto; +import com.photobook.service.LoginService; @Service public class LoginServiceImpl implements LoginService { - private static final String LOGIN_USER_INFO = "LOGIN_USER_INFO"; + private static final String LOGIN_USER_INFO = "LOGIN_USER_INFO"; - private final HttpSession httpSession; + private final HttpSession httpSession; - public LoginServiceImpl(HttpSession httpSession) { - this.httpSession = httpSession; // Scoped Proxy - } + public LoginServiceImpl(HttpSession httpSession) { + this.httpSession = httpSession; // Scoped Proxy + } - @Override - public void setLoginUserInfo(UserDto userDto) { - httpSession.setAttribute(LOGIN_USER_INFO, userDto); - } + @Override + public void setLoginUserInfo(UserDto userDto) { + httpSession.setAttribute(LOGIN_USER_INFO, userDto); + } - @Override - public void removeLoginUserInfo() { - httpSession.invalidate(); - } + @Override + public void removeLoginUserInfo() { + httpSession.invalidate(); + } - @Override - public UserDto getLoginUserInfo() { - return (UserDto) httpSession.getAttribute(LOGIN_USER_INFO); - } + @Override + public UserDto getLoginUserInfo() { + return (UserDto)httpSession.getAttribute(LOGIN_USER_INFO); + } } diff --git a/src/main/java/com/photobook/service/impl/UserServiceImpl.java b/src/main/java/com/photobook/service/impl/UserServiceImpl.java index f2d73b9..12b911c 100644 --- a/src/main/java/com/photobook/service/impl/UserServiceImpl.java +++ b/src/main/java/com/photobook/service/impl/UserServiceImpl.java @@ -1,70 +1,70 @@ package com.photobook.service.impl; -import com.photobook.exception.customException.DuplicatedException; -import com.photobook.mapper.UserMapper; -import com.photobook.dto.UserDto; -import com.photobook.service.UserService; import org.springframework.cache.annotation.Cacheable; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.InternalAuthenticationServiceException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import com.photobook.dto.UserDto; +import com.photobook.exception.customexception.DuplicatedException; +import com.photobook.mapper.UserMapper; +import com.photobook.service.UserService; + @Service public class UserServiceImpl implements UserService { - private final UserMapper userMapper; - private final PasswordEncoder passwordEncoder; + private final UserMapper userMapper; + private final PasswordEncoder passwordEncoder; - public UserServiceImpl(UserMapper userMapper, PasswordEncoder passwordEncoder) { - this.userMapper = userMapper; - this.passwordEncoder = passwordEncoder; - } + public UserServiceImpl(UserMapper userMapper, PasswordEncoder passwordEncoder) { + this.userMapper = userMapper; + this.passwordEncoder = passwordEncoder; + } - @Override - public UserDto validateLogin(String id, String password) { + @Override + public UserDto validateLogin(String id, String password) { - UserDto userInfo = userMapper.getUserInfoById(id); + UserDto userInfo = userMapper.getUserInfoById(id); - if(userInfo == null) { - throw new InternalAuthenticationServiceException("존재하지않는 아이디입니다."); - } + if (userInfo == null) { + throw new InternalAuthenticationServiceException("존재하지않는 아이디입니다."); + } - boolean isPwdMatch = passwordEncoder.matches(password, userInfo.getPassword()); + boolean isPwdMatch = passwordEncoder.matches(password, userInfo.getPassword()); - if(!isPwdMatch) { - throw new BadCredentialsException("일치하지않는 비밀번호입니다."); - } + if (!isPwdMatch) { + throw new BadCredentialsException("일치하지않는 비밀번호입니다."); + } - return userInfo; - } + return userInfo; + } - @Override - @Cacheable(value="findUserCache", key="#id") - public UserDto getUserInfoById(String id) { - UserDto userInfo = userMapper.getUserInfoById(id); - return userInfo; - } + @Override + @Cacheable(value = "findUserCache", key = "#id") + public UserDto getUserInfoById(String id) { + return userMapper.getUserInfoById(id); + } - @Override - public void createUser(UserDto userInfo) { - validateUserId(userInfo.getId()); + @Override + public void createUser(UserDto userInfo) { + validateUserId(userInfo.getId()); - String encodedPwd = passwordEncoder.encode(userInfo.getPassword()); - userInfo.setPassword(encodedPwd); + String encodedPwd = passwordEncoder.encode(userInfo.getPassword()); + userInfo.setPassword(encodedPwd); - userMapper.createUser(userInfo); - } + userMapper.createUser(userInfo); + } - @Override - public void validateUserId(String id) { - if(userMapper.checkUserId(id)) { - throw new DuplicatedException("중복된 아이디입니다."); - } - } + @Override + public void validateUserId(String id) { + if (userMapper.checkUserId(id)) { + throw new DuplicatedException("중복된 아이디입니다."); + } + } - @Override - public void deleteUser(String id) { - userMapper.deleteUser(id); - } -} + @Override + public void deleteUser(String id) { + userMapper.deleteUser(id); + } +} \ No newline at end of file diff --git a/src/main/resources/ehcache.xml b/src/main/resources/ehcache.xml index bbae485..2616924 100644 --- a/src/main/resources/ehcache.xml +++ b/src/main/resources/ehcache.xml @@ -9,7 +9,8 @@ maxEntriesLocalDisk="1000" eternal="false" diskSpoolBufferSizeMB="20" - timeToIdleSeconds="300" timeToLiveSeconds="600" + timeToIdleSeconds="300" + timeToLiveSeconds="600" memoryStoreEvictionPolicy="LFU" transactionalMode="off"> diff --git a/src/test/java/com/photobook/PhotobookApplicationTests.java b/src/test/java/com/photobook/PhotobookApplicationTests.java index 710a826..c0be904 100644 --- a/src/test/java/com/photobook/PhotobookApplicationTests.java +++ b/src/test/java/com/photobook/PhotobookApplicationTests.java @@ -6,8 +6,8 @@ @SpringBootTest class PhotobookApplicationTests { - @Test - void contextLoads() { - } + @Test + void contextLoads() { + } } diff --git a/src/test/java/com/photobook/service/impl/UserServiceImplTest.java b/src/test/java/com/photobook/service/impl/UserServiceImplTest.java index 4d045f7..c2fe7c7 100644 --- a/src/test/java/com/photobook/service/impl/UserServiceImplTest.java +++ b/src/test/java/com/photobook/service/impl/UserServiceImplTest.java @@ -1,7 +1,11 @@ package com.photobook.service.impl; -import com.photobook.mapper.UserMapper; -import com.photobook.dto.UserDto; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.when; + +import java.time.LocalDate; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -12,81 +16,78 @@ import org.springframework.security.authentication.InternalAuthenticationServiceException; import org.springframework.security.crypto.password.PasswordEncoder; -import java.time.LocalDate; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.when; +import com.photobook.dto.UserDto; +import com.photobook.mapper.UserMapper; @ExtendWith(MockitoExtension.class) class UserServiceImplTest { - @InjectMocks - UserServiceImpl userServiceImpl; - - @Mock - UserMapper userMapper; - - @Mock - PasswordEncoder passwordEncoder; - - public UserDto userInfo() { - UserDto userInfo = new UserDto(); - userInfo.setUserId(1); - userInfo.setId("admin"); - userInfo.setPassword(passwordEncoder.encode("1234")); - userInfo.setName("관리자"); - userInfo.setEmail("admin@gmail.com"); - userInfo.setBirth(LocalDate.of(1993, 10, 28)); - userInfo.setProfileImageName("프로필사진1"); - userInfo.setProfileImagePath("이미지경로"); - userInfo.setProfileMessage("상태메세지"); - - return userInfo; - } - - @Test - @DisplayName("로그인 검증 성공") - public void successValidateLogin() { - //given - UserDto userInfo = userInfo(); - when(userMapper.getUserInfoById("admin")).thenReturn(userInfo); - when(passwordEncoder.matches("1234", userInfo.getPassword())).thenReturn(true); - - //when - UserDto result = userServiceImpl.validateLogin("admin", "1234"); - - //then - assertEquals(result, userInfo); - } - - @Test - @DisplayName("로그인 검증 실패_존재하지 않는 아이디") - public void failureValidateLoginId() { - //given - when(userMapper.getUserInfoById("admin")).thenReturn(null); - - //then - assertThrows(InternalAuthenticationServiceException.class, () -> { - //when - userServiceImpl.validateLogin("admin", "1234"); - }); - - } - - @Test - @DisplayName("로그인 검증 실패_비밀번호 불일치") - public void failureValidateLoginPwd() { - //given - UserDto userInfo = userInfo(); - when(userMapper.getUserInfoById("admin")).thenReturn(userInfo); - when(passwordEncoder.matches("1234", userInfo.getPassword())).thenReturn(false); - - //then - assertThrows(BadCredentialsException.class, () -> { - //when - userServiceImpl.validateLogin("admin", "1234"); - }); - } + @InjectMocks + UserServiceImpl userServiceImpl; + + @Mock + UserMapper userMapper; + + @Mock + PasswordEncoder passwordEncoder; + + public UserDto userInfo() { + UserDto userInfo = new UserDto(); + userInfo.setUserId(1); + userInfo.setId("admin"); + userInfo.setPassword(passwordEncoder.encode("1234")); + userInfo.setName("관리자"); + userInfo.setEmail("admin@gmail.com"); + userInfo.setBirth(LocalDate.of(1993, 10, 28)); + userInfo.setProfileImageName("프로필사진1"); + userInfo.setProfileImagePath("이미지경로"); + userInfo.setProfileMessage("상태메세지"); + + return userInfo; + } + + @Test + @DisplayName("로그인 검증 성공") + public void successValidateLogin() { + //given + UserDto userInfo = userInfo(); + when(userMapper.getUserInfoById("admin")).thenReturn(userInfo); + when(passwordEncoder.matches("1234", userInfo.getPassword())).thenReturn(true); + + //when + UserDto result = userServiceImpl.validateLogin("admin", "1234"); + + //then + assertEquals(result, userInfo); + } + + @Test + @DisplayName("로그인 검증 실패_존재하지 않는 아이디") + public void failureValidateLoginId() { + //given + when(userMapper.getUserInfoById("admin")).thenReturn(null); + + //then + assertThrows(InternalAuthenticationServiceException.class, () -> { + //when + userServiceImpl.validateLogin("admin", "1234"); + }); + + } + + @Test + @DisplayName("로그인 검증 실패_비밀번호 불일치") + public void failureValidateLoginPwd() { + //given + UserDto userInfo = userInfo(); + when(userMapper.getUserInfoById("admin")).thenReturn(userInfo); + when(passwordEncoder.matches("1234", userInfo.getPassword())).thenReturn(false); + + //then + assertThrows(BadCredentialsException.class, () -> { + //when + userServiceImpl.validateLogin("admin", "1234"); + }); + } } \ No newline at end of file diff --git a/src/test/java/com/photobook/utils/PasswordEncoderTest.java b/src/test/java/com/photobook/utils/PasswordEncoderTest.java index 267966d..d54ebcc 100644 --- a/src/test/java/com/photobook/utils/PasswordEncoderTest.java +++ b/src/test/java/com/photobook/utils/PasswordEncoderTest.java @@ -1,34 +1,33 @@ package com.photobook.utils; +import static org.junit.jupiter.api.Assertions.*; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.security.crypto.password.PasswordEncoder; -import static org.junit.jupiter.api.Assertions.*; - @SpringBootTest class PasswordEncoderTest { - @Autowired - private PasswordEncoder passwordEncoder; - - @Test - @DisplayName("패스워드 암호화 테스트") - void passwordEncode() { - //given - String rawPwd = "1234"; - - //when - String encodedPwd = passwordEncoder.encode(rawPwd); - System.out.println(encodedPwd); - - //then - assertAll( - () -> assertNotEquals(rawPwd, encodedPwd), - () -> assertTrue(passwordEncoder.matches(rawPwd, encodedPwd)) - ); - } + @Autowired + private PasswordEncoder passwordEncoder; + + @Test + @DisplayName("패스워드 암호화 테스트") + void passwordEncode() { + //given + String rawPwd = "1234"; + + //when + String encodedPwd = passwordEncoder.encode(rawPwd); + + //then + assertAll( + () -> assertNotEquals(rawPwd, encodedPwd), + () -> assertTrue(passwordEncoder.matches(rawPwd, encodedPwd)) + ); + } } From d4b7e9d2cd0516a5d87cb5463a1a4a0105b0142f Mon Sep 17 00:00:00 2001 From: jsy3831 Date: Mon, 27 Sep 2021 14:39:41 +0900 Subject: [PATCH 2/3] =?UTF-8?q?#2=20=EC=BD=94=EB=93=9C=EB=A6=AC=EB=B7=B0?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../photobook/controller/UserController.java | 12 +++--- .../controller/response/Response.java | 25 +++-------- src/main/java/com/photobook/dto/UserDto.java | 14 +++--- .../exception/ExceptionController.java | 43 +++++++------------ .../photobook/utils/PasswordEncoderTest.java | 33 -------------- 5 files changed, 35 insertions(+), 92 deletions(-) delete mode 100644 src/test/java/com/photobook/utils/PasswordEncoderTest.java diff --git a/src/main/java/com/photobook/controller/UserController.java b/src/main/java/com/photobook/controller/UserController.java index 57162ed..0055a52 100644 --- a/src/main/java/com/photobook/controller/UserController.java +++ b/src/main/java/com/photobook/controller/UserController.java @@ -49,7 +49,7 @@ public Response login(@RequestParam @NotBlank String id, @RequestParam loginService.setLoginUserInfo(userInfo); - return Response.toResponse(200, "로그인 하였습니다.", userInfo); + return new Response("로그인 하였습니다.", userInfo); } @PostMapping("/logout") @@ -58,7 +58,7 @@ public Response logout() { loginService.removeLoginUserInfo(); - return Response.toResponse(200, "로그아웃 하였습니다."); + return new Response("로그아웃 하였습니다."); } @GetMapping("/my-info") @@ -67,7 +67,7 @@ public Response getUserInfoById(@LoginUser UserDto loginUser) { UserDto userInfo = userService.getUserInfoById(loginUser.getId()); - return Response.toResponse(200, "회원정보 조회", userInfo); + return new Response("회원정보 조회", userInfo); } @PostMapping("/signup") @@ -76,7 +76,7 @@ public Response signup(@RequestBody @Valid UserDto userInfo) { userService.createUser(userInfo); - return Response.toResponse(201, "회원가입 하였습니다."); + return new Response("회원가입 하였습니다."); } @GetMapping("/{id}") @@ -84,7 +84,7 @@ public Response checkUserId(@PathVariable @NotBlank String id) { userService.validateUserId(id); - return Response.toResponse(200, "사용가능한 아이디입니다."); + return new Response("사용가능한 아이디입니다."); } @DeleteMapping("/my-info") @@ -95,7 +95,7 @@ public Response deleteUser(@LoginUser UserDto loginUser) { loginService.removeLoginUserInfo(); - return Response.toResponse(200, "회원탈퇴 하였습니다."); + return new Response("회원탈퇴 하였습니다."); } } \ No newline at end of file diff --git a/src/main/java/com/photobook/controller/response/Response.java b/src/main/java/com/photobook/controller/response/Response.java index f907597..ea3b6ef 100644 --- a/src/main/java/com/photobook/controller/response/Response.java +++ b/src/main/java/com/photobook/controller/response/Response.java @@ -2,7 +2,6 @@ import java.time.LocalDateTime; -import lombok.Builder; import lombok.Getter; @Getter @@ -10,28 +9,16 @@ public class Response { private final LocalDateTime timestamp = LocalDateTime.now(); - private final int code; + private String message; - private final String message; + private T body; - private final T body; - - @Builder - Response(final int code, final String message, final T body) { - this.code = code; + public Response(String message) { this.message = message; - this.body = body; - } - - public static Response toResponse(int code, String message) { - return toResponse(code, message, null); } - public static Response toResponse(int code, String message, T body) { - return Response.builder() - .code(code) - .message(message) - .body(body) - .build(); + public Response(String message, T body) { + this.message = message; + this.body = body; } } diff --git a/src/main/java/com/photobook/dto/UserDto.java b/src/main/java/com/photobook/dto/UserDto.java index 3e3a5d8..8156ce9 100644 --- a/src/main/java/com/photobook/dto/UserDto.java +++ b/src/main/java/com/photobook/dto/UserDto.java @@ -19,21 +19,21 @@ public class UserDto implements Serializable { private int userId; - @NotBlank + @NotBlank(message = "아이디를 입력하세요.") private String id; - @NotBlank + @NotBlank(message = "비밀번호를 입력하세요.") private String password; - @NotBlank + @NotBlank(message = "이름을 입력하세요.") private String name; - @NotBlank - @Email + @NotBlank(message = "이메일을 입력하세요.") + @Email(message = "이메일 형식이 올바르지 않습니다.") private String email; - @NotNull - @Past + @NotNull(message = "생년월일을 입력하세요.") + @Past(message = "날짜가 올바르지 않습니다.") private LocalDate birth; private String profileImageName; diff --git a/src/main/java/com/photobook/exception/ExceptionController.java b/src/main/java/com/photobook/exception/ExceptionController.java index 1838be5..192ed21 100644 --- a/src/main/java/com/photobook/exception/ExceptionController.java +++ b/src/main/java/com/photobook/exception/ExceptionController.java @@ -24,67 +24,56 @@ @RestControllerAdvice public class ExceptionController { - private static ExceptionType exceptionType(Exception e) { - return new ExceptionType(e.getClass().getSimpleName()); - } - @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.BAD_REQUEST) - public Response handleException(Exception e) { + public Response handleException(Exception e) { log.error("handleException throw Exception : {}", e.getMessage()); - return Response.toResponse(400, e.getMessage(), exceptionType(e)); + return new Response(e.getMessage()); } @ExceptionHandler(ConstraintViolationException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) - public Response handleConstraintViolationException(ConstraintViolationException e) { + public Response handleConstraintViolationException(ConstraintViolationException e) { log.error("handleConstraintViolationException throw ConstraintViolationException : {}", e.getMessage()); - return Response.toResponse(400, e.getMessage(), exceptionType(e)); + return new Response(e.getMessage()); } @ExceptionHandler(IllegalArgumentException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) - public Response handleIllegalArgumentException(IllegalArgumentException e) { + public Response handleIllegalArgumentException(IllegalArgumentException e) { log.error("handleIllegalArgumentException throw IllegalArgumentException : {}", e.getMessage()); - return Response.toResponse(400, e.getMessage(), exceptionType(e)); + return new Response(e.getMessage()); } @ExceptionHandler(UnauthorizedException.class) @ResponseStatus(HttpStatus.UNAUTHORIZED) - public Response handleUnauthorizedException(UnauthorizedException e) { - return Response.toResponse(401, e.getMessage(), exceptionType(e)); + public Response handleUnauthorizedException(UnauthorizedException e) { + return new Response(e.getMessage()); } @ExceptionHandler(DuplicatedException.class) @ResponseStatus(HttpStatus.CONFLICT) - public Response handleDuplicatedException(DuplicatedException e) { - return Response.toResponse(409, e.getMessage(), exceptionType(e)); + public Response handleDuplicatedException(DuplicatedException e) { + return new Response(e.getMessage()); } @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) - public Response handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + public Response handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { BindingResult bindingResult = e.getBindingResult(); - List message = new ArrayList<>(); + List message = new ArrayList<>(); for (FieldError fieldError : bindingResult.getFieldErrors()) { - StringBuilder builder = new StringBuilder(); - - builder.append(fieldError.getField()); - builder.append(" : "); - builder.append(fieldError.getDefaultMessage()); - - message.add(builder); + message.add(fieldError.getDefaultMessage()); } - return Response.toResponse(400, message.toString(), exceptionType(e)); + return new Response(message.toString()); } @ExceptionHandler(AuthenticationException.class) @ResponseStatus(HttpStatus.FORBIDDEN) - public Response handleAuthenticationException(AuthenticationException e) { - return Response.toResponse(403, e.getMessage(), exceptionType(e)); + public Response handleAuthenticationException(AuthenticationException e) { + return new Response(e.getMessage()); } - } diff --git a/src/test/java/com/photobook/utils/PasswordEncoderTest.java b/src/test/java/com/photobook/utils/PasswordEncoderTest.java deleted file mode 100644 index d54ebcc..0000000 --- a/src/test/java/com/photobook/utils/PasswordEncoderTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.photobook.utils; - -import static org.junit.jupiter.api.Assertions.*; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.security.crypto.password.PasswordEncoder; - -@SpringBootTest -class PasswordEncoderTest { - - @Autowired - private PasswordEncoder passwordEncoder; - - @Test - @DisplayName("패스워드 암호화 테스트") - void passwordEncode() { - //given - String rawPwd = "1234"; - - //when - String encodedPwd = passwordEncoder.encode(rawPwd); - - //then - assertAll( - () -> assertNotEquals(rawPwd, encodedPwd), - () -> assertTrue(passwordEncoder.matches(rawPwd, encodedPwd)) - ); - } - -} From f93589687d68f4e9d9627eb66b5dee856d0c527c Mon Sep 17 00:00:00 2001 From: jsy3831 Date: Mon, 27 Sep 2021 18:04:04 +0900 Subject: [PATCH 3/3] =?UTF-8?q?#2=20userService=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80(83%=20methods,?= =?UTF-8?q?=2095%=20lines=20covered)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../photobook/controller/UserController.java | 4 +- .../photobook/exception/ExceptionType.java | 14 --- .../com/photobook/service/UserService.java | 2 +- .../service/impl/UserServiceImpl.java | 14 ++- src/main/resources/ehcache.xml | 16 +++ .../service/impl/UserServiceImplTest.java | 117 ++++++++++++++++-- 6 files changed, 135 insertions(+), 32 deletions(-) delete mode 100644 src/main/java/com/photobook/exception/ExceptionType.java diff --git a/src/main/java/com/photobook/controller/UserController.java b/src/main/java/com/photobook/controller/UserController.java index 0055a52..6b4bbb0 100644 --- a/src/main/java/com/photobook/controller/UserController.java +++ b/src/main/java/com/photobook/controller/UserController.java @@ -89,9 +89,9 @@ public Response checkUserId(@PathVariable @NotBlank String id) { @DeleteMapping("/my-info") @LoginCheck - public Response deleteUser(@LoginUser UserDto loginUser) { + public Response deleteUser(@RequestParam @NotBlank String password, @LoginUser UserDto loginUser) { - userService.deleteUser(loginUser.getId()); + userService.deleteUser(loginUser, password); loginService.removeLoginUserInfo(); diff --git a/src/main/java/com/photobook/exception/ExceptionType.java b/src/main/java/com/photobook/exception/ExceptionType.java deleted file mode 100644 index 76ea3c7..0000000 --- a/src/main/java/com/photobook/exception/ExceptionType.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.photobook.exception; - -import lombok.Getter; - -@Getter -public class ExceptionType { - - private final String type; - - ExceptionType(final String type) { - this.type = type; - } - -} diff --git a/src/main/java/com/photobook/service/UserService.java b/src/main/java/com/photobook/service/UserService.java index 761c06a..40bf082 100644 --- a/src/main/java/com/photobook/service/UserService.java +++ b/src/main/java/com/photobook/service/UserService.java @@ -12,5 +12,5 @@ public interface UserService { void validateUserId(String id); - void deleteUser(String id); + void deleteUser(UserDto userInfo, String password); } diff --git a/src/main/java/com/photobook/service/impl/UserServiceImpl.java b/src/main/java/com/photobook/service/impl/UserServiceImpl.java index 12b911c..17aa59d 100644 --- a/src/main/java/com/photobook/service/impl/UserServiceImpl.java +++ b/src/main/java/com/photobook/service/impl/UserServiceImpl.java @@ -1,5 +1,7 @@ package com.photobook.service.impl; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.InternalAuthenticationServiceException; @@ -64,7 +66,15 @@ public void validateUserId(String id) { } @Override - public void deleteUser(String id) { - userMapper.deleteUser(id); + @CacheEvict(value = "findUserCache", key = "#userInfo.getId()") + public void deleteUser(UserDto userInfo, String password) { + + boolean isPwdMatch = passwordEncoder.matches(password, userInfo.getPassword()); + + if (!isPwdMatch) { + throw new BadCredentialsException("일치하지않는 비밀번호입니다."); + } + + userMapper.deleteUser(userInfo.getId()); } } \ No newline at end of file diff --git a/src/main/resources/ehcache.xml b/src/main/resources/ehcache.xml index 2616924..76a51e8 100644 --- a/src/main/resources/ehcache.xml +++ b/src/main/resources/ehcache.xml @@ -2,8 +2,24 @@ + + + { - //when + // when userServiceImpl.validateLogin("admin", "1234"); }); @@ -78,16 +79,106 @@ public void failureValidateLoginId() { @Test @DisplayName("로그인 검증 실패_비밀번호 불일치") public void failureValidateLoginPwd() { - //given + // given UserDto userInfo = userInfo(); when(userMapper.getUserInfoById("admin")).thenReturn(userInfo); when(passwordEncoder.matches("1234", userInfo.getPassword())).thenReturn(false); - //then + // then assertThrows(BadCredentialsException.class, () -> { - //when + // when userServiceImpl.validateLogin("admin", "1234"); }); } + @Test + @DisplayName("아이디 검증 성공_사용가능한 아이디") + public void successValidateUserId() { + // given + when(userMapper.checkUserId("admin")).thenReturn(false); + + // when + userServiceImpl.validateUserId("admin"); + + // then + verify(userMapper, times(1)).checkUserId("admin"); + } + + @Test + @DisplayName("아이디 검증 실패_중복된 아이디") + public void failureValidateUserId() { + // given + when(userMapper.checkUserId("admin")).thenReturn(true); + + // then + assertThrows(DuplicatedException.class, () -> { + // when + userServiceImpl.validateUserId("admin"); + }); + } + + @Test + @DisplayName("회원가입 성공") + public void successCreateUser() { + // given + UserDto userInfo = userInfo(); + when(userMapper.checkUserId(userInfo.getId())).thenReturn(false); + doNothing().when(userMapper).createUser(userInfo); + + // when + userServiceImpl.createUser(userInfo); + + // then + verify(userMapper, times(1)).createUser(userInfo); + } + + @Test + @DisplayName("회원가입 실패_중복된 아이디") + public void failureCreateUser() { + // given + UserDto userInfo = userInfo(); + when(userMapper.checkUserId(userInfo.getId())).thenReturn(true); + + // then + assertThrows(DuplicatedException.class, () -> { + // when + userServiceImpl.createUser(userInfo); + }); + + // then + verify(userMapper, times(0)).createUser(userInfo); + } + + @Test + @DisplayName("회원탈퇴 성공") + public void successDeleteUser() { + // given + UserDto userInfo = userInfo(); + when(passwordEncoder.matches("1234", userInfo.getPassword())).thenReturn(true); + doNothing().when(userMapper).deleteUser(userInfo.getId()); + + // when + userServiceImpl.deleteUser(userInfo, "1234"); + + // then + verify(userMapper, times(1)).deleteUser(userInfo.getId()); + } + + @Test + @DisplayName("회원탈퇴 실패_비밀번호 불일치") + public void failureDeleteUser() { + // given + UserDto userInfo = userInfo(); + when(passwordEncoder.matches("1234", userInfo.getPassword())).thenReturn(false); + + // then + assertThrows(BadCredentialsException.class, () -> { + // when + userServiceImpl.deleteUser(userInfo, "1234"); + }); + + // then + verify(userMapper, times(0)).deleteUser(userInfo.getId()); + } + } \ No newline at end of file