diff --git a/pom.xml b/pom.xml index e068a77..8e3bbfd 100644 --- a/pom.xml +++ b/pom.xml @@ -4,11 +4,11 @@ 4.0.0 kr.codesquad - baeminchan + webApi 1.0.0 jar - baeminchan + webApi 배민찬 서비스 diff --git a/src/main/java/codesquad/configration/JpaEnableConfiguration.java b/src/main/java/codesquad/configuration/JpaEnableConfiguration.java similarity index 90% rename from src/main/java/codesquad/configration/JpaEnableConfiguration.java rename to src/main/java/codesquad/configuration/JpaEnableConfiguration.java index d1cc3e6..53bd428 100644 --- a/src/main/java/codesquad/configration/JpaEnableConfiguration.java +++ b/src/main/java/codesquad/configuration/JpaEnableConfiguration.java @@ -1,4 +1,4 @@ -package codesquad.configration; +package codesquad.configuration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/codesquad/configration/WebMvcConfig.java b/src/main/java/codesquad/configuration/WebMvcConfig.java similarity index 59% rename from src/main/java/codesquad/configration/WebMvcConfig.java rename to src/main/java/codesquad/configuration/WebMvcConfig.java index 081e95c..d7f4863 100644 --- a/src/main/java/codesquad/configration/WebMvcConfig.java +++ b/src/main/java/codesquad/configuration/WebMvcConfig.java @@ -1,11 +1,13 @@ -package codesquad.configration; +package codesquad.configuration; import codesquad.intercepter.AdminInterceptor; -import codesquad.security.ManagerAccountHandlerMethodArgumentResolver; +import codesquad.intercepter.BasicAuthInterceptor; +import codesquad.security.AdminAccountHandlerMethodArgumentResolver; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @@ -29,8 +31,23 @@ public PasswordEncoder passwordEncoder() { } @Bean - public ManagerAccountHandlerMethodArgumentResolver managerAccountHandlerMethodArgumentResolver() { - return new ManagerAccountHandlerMethodArgumentResolver(); + public AdminAccountHandlerMethodArgumentResolver managerAccountHandlerMethodArgumentResolver() { + return new AdminAccountHandlerMethodArgumentResolver(); + } + + @Configuration + @Profile("test") + public class TestWebMvcConfig extends WebMvcConfig{ + + @Bean + public BasicAuthInterceptor basicAuthInterceptor(){ + return new BasicAuthInterceptor(); + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(basicAuthInterceptor()); + } } @Override @@ -38,9 +55,14 @@ public void addArgumentResolvers(List argumentRes argumentResolvers.add(managerAccountHandlerMethodArgumentResolver()); } + @Bean + public AdminInterceptor adminInterceptor(){ + return new AdminInterceptor(); + } + @Override public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(new AdminInterceptor()) + registry.addInterceptor(adminInterceptor()) .addPathPatterns("/admin"); } } diff --git a/src/main/java/codesquad/domain/AccountType.java b/src/main/java/codesquad/domain/AccountType.java index e7f3657..8927fbc 100644 --- a/src/main/java/codesquad/domain/AccountType.java +++ b/src/main/java/codesquad/domain/AccountType.java @@ -2,15 +2,15 @@ public enum AccountType { MEMBER(false), - MANAGER(true); + ADMIN(true); - boolean isManager; + boolean isAdmin; - AccountType(boolean isManager) { - this.isManager = isManager; + AccountType(boolean isAdmin) { + this.isAdmin = isAdmin; } - public boolean isManager() { - return isManager; + public boolean isAdmin() { + return isAdmin; } } diff --git a/src/main/java/codesquad/intercepter/AdminInterceptor.java b/src/main/java/codesquad/intercepter/AdminInterceptor.java index bea49f4..3f07399 100644 --- a/src/main/java/codesquad/intercepter/AdminInterceptor.java +++ b/src/main/java/codesquad/intercepter/AdminInterceptor.java @@ -20,7 +20,7 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons } Account account = (Account) loginAccount; - if (!account.getType().isManager()) { + if (!account.getType().isAdmin()) { throw new UnAuthorizedException("you're not manager"); } return true; diff --git a/src/main/java/codesquad/intercepter/BasicAuthInterceptor.java b/src/main/java/codesquad/intercepter/BasicAuthInterceptor.java new file mode 100644 index 0000000..8c2f80a --- /dev/null +++ b/src/main/java/codesquad/intercepter/BasicAuthInterceptor.java @@ -0,0 +1,60 @@ +package codesquad.intercepter; + +import codesquad.domain.Account; +import codesquad.domain.AccountRepository; +import codesquad.exception.account.UnAuthenticationException; +import codesquad.util.SessionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.nio.charset.Charset; +import java.util.Base64; + +public class BasicAuthInterceptor extends HandlerInterceptorAdapter { + private static final Logger log = LoggerFactory.getLogger(BasicAuthInterceptor.class); + + @Autowired + private AccountRepository accountRepository; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String base64Credentials; + try { + base64Credentials = getEncodedCredentials(request); + String[] credentialValues = getDecodedCredentials(base64Credentials); + String userId = credentialValues[0]; + String password = credentialValues[1]; + log.debug("userId : {}", userId); + log.debug("password : {}", password); + login(request, userId, password); + return true; + } catch (UnAuthenticationException e) { + return true; + } + } + + public String getEncodedCredentials(HttpServletRequest request) { + String authorization = request.getHeader("Authorization"); + if (authorization == null || !authorization.startsWith("Basic")) { + throw new UnAuthenticationException(); + } + return authorization.substring("Basic".length()).trim(); + } + + public String[] getDecodedCredentials(String base64Credentials) { + String credentials = new String(Base64.getDecoder().decode(base64Credentials), Charset.forName("UTF-8")); + return credentials.split(":", 2); + } + + public void login(HttpServletRequest request, String userId, String password) { + Account account = accountRepository.findByUserId(userId).orElseThrow(UnAuthenticationException::new); + + if (account.matchPassword(password)) { + request.getSession().setAttribute(SessionUtils.USER_SESSION_KEY, account); + } + } +} diff --git a/src/main/java/codesquad/intercepter/BasicAuthenticationIntercepter.java b/src/main/java/codesquad/intercepter/BasicAuthenticationIntercepter.java deleted file mode 100644 index d8e33d4..0000000 --- a/src/main/java/codesquad/intercepter/BasicAuthenticationIntercepter.java +++ /dev/null @@ -1,12 +0,0 @@ -package codesquad.intercepter; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; - -public class BasicAuthenticationIntercepter extends HandlerInterceptorAdapter { - - private static final Logger log = LoggerFactory.getLogger(BasicAuthenticationIntercepter.class); - -} diff --git a/src/main/java/codesquad/security/ManagerAccount.java b/src/main/java/codesquad/security/AdminAccount.java similarity index 72% rename from src/main/java/codesquad/security/ManagerAccount.java rename to src/main/java/codesquad/security/AdminAccount.java index 7b4c8f2..21e2552 100644 --- a/src/main/java/codesquad/security/ManagerAccount.java +++ b/src/main/java/codesquad/security/AdminAccount.java @@ -1,8 +1,6 @@ package codesquad.security; -import org.springframework.beans.factory.annotation.Required; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -10,5 +8,5 @@ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) -public @interface ManagerAccount { +public @interface AdminAccount { } \ No newline at end of file diff --git a/src/main/java/codesquad/security/ManagerAccountHandlerMethodArgumentResolver.java b/src/main/java/codesquad/security/AdminAccountHandlerMethodArgumentResolver.java similarity index 82% rename from src/main/java/codesquad/security/ManagerAccountHandlerMethodArgumentResolver.java rename to src/main/java/codesquad/security/AdminAccountHandlerMethodArgumentResolver.java index d5aebca..aefab95 100644 --- a/src/main/java/codesquad/security/ManagerAccountHandlerMethodArgumentResolver.java +++ b/src/main/java/codesquad/security/AdminAccountHandlerMethodArgumentResolver.java @@ -9,10 +9,10 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; -public class ManagerAccountHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { +public class AdminAccountHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter methodParameter) { - return methodParameter.hasParameterAnnotation(ManagerAccount.class); + return methodParameter.hasParameterAnnotation(AdminAccount.class); } @Override @@ -21,7 +21,7 @@ public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception { Account account = SessionUtils.getUserFromSession(nativeWebRequest); - if (!account.getType().isManager()) { + if (!account.getType().isAdmin()) { throw new UnAuthorizedException("You're not manager!"); } return account; diff --git a/src/main/java/codesquad/web/ApiMemberController.java b/src/main/java/codesquad/web/ApiMemberController.java index 71ed0bb..b7c7c12 100644 --- a/src/main/java/codesquad/web/ApiMemberController.java +++ b/src/main/java/codesquad/web/ApiMemberController.java @@ -31,6 +31,7 @@ public class ApiMemberController { @PostMapping("") public ResponseEntity createMember(@Valid @RequestBody AccountRegistrationDTO accountRegistrationDTO) { accountService.save(accountRegistrationDTO); + return makeDefaultResponseEntity("/login", HttpStatus.CREATED); } diff --git a/src/main/java/codesquad/web/ApiMenuCategoryController.java b/src/main/java/codesquad/web/ApiMenuCategoryController.java index b34f930..d536341 100644 --- a/src/main/java/codesquad/web/ApiMenuCategoryController.java +++ b/src/main/java/codesquad/web/ApiMenuCategoryController.java @@ -2,7 +2,7 @@ import codesquad.domain.Account; import codesquad.domain.MenuCategory; -import codesquad.security.ManagerAccount; +import codesquad.security.AdminAccount; import codesquad.service.MenuCategoryService; import codesquad.web.dto.MenuCategoryDTO; import org.springframework.beans.factory.annotation.Autowired; @@ -26,13 +26,13 @@ public List getCategories() { } @PostMapping("") - public ResponseEntity create(@ManagerAccount Account manager, @RequestBody MenuCategoryDTO menuCategoryDTO) { + public ResponseEntity create(@AdminAccount Account manager, @RequestBody MenuCategoryDTO menuCategoryDTO) { MenuCategory createdCategory = menuCategoryService.create(menuCategoryDTO); return makeCreatedResponseEntity(createdCategory); } @DeleteMapping("/{id}") - public MenuCategory delete(@ManagerAccount Account manager, @PathVariable Long id) { + public MenuCategory delete(@AdminAccount Account manager, @PathVariable Long id) { return menuCategoryService.deleteById(id); } } diff --git a/src/main/java/support/domain/AbstractEntity.java b/src/main/java/support/domain/AbstractEntity.java index 0a8cead..e3922dc 100644 --- a/src/main/java/support/domain/AbstractEntity.java +++ b/src/main/java/support/domain/AbstractEntity.java @@ -36,8 +36,10 @@ public AbstractEntity(Long id) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; AbstractEntity that = (AbstractEntity) o; return Objects.equals(id, that.id); } diff --git a/src/main/resources/application-development.properties b/src/main/resources/application-development.properties new file mode 100644 index 0000000..636b224 --- /dev/null +++ b/src/main/resources/application-development.properties @@ -0,0 +1,9 @@ +spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useSSL=false&allowPublicKeyRetrieval=true +spring.datasource.username=minseok +spring.datasource.password=password + +server.port=80 + +spring.jpa.hibernate.ddl-auto=validate + +logging.config=classpath:logback-${spring.profiles.active}.xml diff --git a/src/main/resources/application-local.properties b/src/main/resources/application-local.properties new file mode 100755 index 0000000..2d22f6b --- /dev/null +++ b/src/main/resources/application-local.properties @@ -0,0 +1,6 @@ +spring.jpa.hibernate.ddl-auto=create + +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.format_sql=true +logging.level.org.hibernate.type.descriptor.sql=trace + diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties new file mode 100644 index 0000000..930fb0d --- /dev/null +++ b/src/main/resources/application-prod.properties @@ -0,0 +1,8 @@ +server.port=80 + +spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useSSL=false&allowPublicKeyRetrieval=true +spring.datasource.username=minseok +spring.datasource.password=password +spring.jpa.hibernate.ddl-auto=validate + +logging.config=classpath:logback-${spring.profiles.active}.xml diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a5dd2b0..dba6802 100755 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,15 +1,9 @@ +spring.profiles.active=local + +spring.autoconfigure.exclude= org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration + handlebars.suffix=.hbs handlebars.cache=false handlebars.expose-session-attributes=true -spring.datasource.url=jdbc:mysql://localhost:3306/springboot?useSSL=false&allowPublicKeyRetrieval=true -spring.datasource.username=minseok -spring.datasource.password=password -spring.jpa.hibernate.ddl-auto=create - -spring.jpa.show-sql=true -spring.jpa.properties.hibernate.format_sql=true -logging.level.org.hibernate.type.descriptor.sql=trace -log4j.logger.org.hibernate.type=debug - -spring.autoconfigure.exclude= org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration \ No newline at end of file +logging.config=classpath:logback.xml diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql index 80f0473..bca9bef 100644 --- a/src/main/resources/import.sql +++ b/src/main/resources/import.sql @@ -1,5 +1,5 @@ INSERT INTO account (id, user_id, password, name, email, phone_number, type ,create_at) values (1, 'test@google.com', '$2a$10$75iOIZVohML12YADpMEqre39yvfFQWn8PkoCf0VMct6ItcVVb77B.', '자바지기', 'javajigi@slipp.net', '010-1111-1111', 'MEMBER', CURRENT_TIMESTAMP()); -INSERT INTO account (id, user_id, password, name, email, phone_number, type ,create_at) values (2, 'admin@admin.com', '$2a$10$75iOIZVohML12YADpMEqre39yvfFQWn8PkoCf0VMct6ItcVVb77B.', '관리자', 'admin@admin.com', '010-1111-1111', 'MANAGER', CURRENT_TIMESTAMP()); +INSERT INTO account (id, user_id, password, name, email, phone_number, type ,create_at) values (2, 'admin@admin.com', '$2a$10$75iOIZVohML12YADpMEqre39yvfFQWn8PkoCf0VMct6ItcVVb77B.', '관리자', 'admin@admin.com', '010-1111-1111', 'ADMIN', CURRENT_TIMESTAMP()); INSERT INTO menu_category (name, parent_id, id, create_at) values ('밑반찬', NULL, 1, CURRENT_TIMESTAMP()); INSERT INTO menu_category (name, parent_id, id, create_at) values ('무침', 1, 2, CURRENT_TIMESTAMP()); diff --git a/src/main/resources/logback-development.xml b/src/main/resources/logback-development.xml new file mode 100644 index 0000000..0a52feb --- /dev/null +++ b/src/main/resources/logback-development.xml @@ -0,0 +1,30 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + INFO + + mylog.txt + + + mylog-%d{yyyy-MM-dd}.%i.txt + + + 100MB + + + + [%-5level] %d{HH:mm:ss.SSS} %logger{36} - %msg%n + + + + + + + \ No newline at end of file diff --git a/src/main/resources/logback-prod.xml b/src/main/resources/logback-prod.xml new file mode 100644 index 0000000..0a52feb --- /dev/null +++ b/src/main/resources/logback-prod.xml @@ -0,0 +1,30 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + INFO + + mylog.txt + + + mylog-%d{yyyy-MM-dd}.%i.txt + + + 100MB + + + + [%-5level] %d{HH:mm:ss.SSS} %logger{36} - %msg%n + + + + + + + \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..cc4101d --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,12 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + diff --git a/src/main/resources/static/css/main.css b/src/main/resources/static/css/main.css index 417b06d..1f382e5 100644 --- a/src/main/resources/static/css/main.css +++ b/src/main/resources/static/css/main.css @@ -1427,11 +1427,36 @@ a:focus { right: 0; top: 0; bottom: 0; + visibility: hidden; background-repeat: no-repeat; background-size: cover; background-position: center center; } +#main-visual .img-box .visible{ + visibility: visible; +} + +#main-visual .img-box .prev { + transform: translateX(-100%); + transition: transform 1s; + z-index: -1; + +} + +#main-visual .img-box .current { + transform: none; + transition: transform 1s; +} + +#main-visual .img-box .next { + z-index: -1; + transition: transform 1s; + transform: translateX(100%); +} + + + #main-visual .img-box .img-1 { background-image: url(../img/img-main-visual-slide_1.jpg); } diff --git a/src/main/resources/static/js/main.js b/src/main/resources/static/js/main.js new file mode 100644 index 0000000..788e968 --- /dev/null +++ b/src/main/resources/static/js/main.js @@ -0,0 +1,67 @@ +let sliderCount; +let sliderIndex = 0; +let slider; +let sliderDots; +window.onload = function () { + sliderCount = document.querySelector("ul.img-box").children.length; + slider = document.querySelectorAll(".img-box li.img-item"); + sliderDots = document.querySelector(".dot-btn-box").children; + document.querySelector(".bm-icon.spr-btn-arrow-main-slide.next").addEventListener("click", next); + document.querySelector(".bm-icon.spr-btn-arrow-main-slide.prev").addEventListener("click", prev); +} + +const next = function (e) { + removeClasses(); + sliderIndex = toNext(sliderIndex); + addNextClasses(); +} + +const prev = function (e) { + removeClasses(); + sliderIndex = toPrev(sliderIndex); + addPrevClasses(); +} + +function toPrev(index) { + return (index - 1 + 5) % sliderCount; +} + +function toNext(index) { + return (index +1 ) % sliderCount; +} + +function removeClasses() { + removeAllVisible(); + slider[toPrev(sliderIndex)].classList.remove("prev"); + slider[sliderIndex].classList.remove("current"); + slider[toNext(sliderIndex)].classList.remove("next"); + + sliderDots[sliderIndex].classList.remove("on"); +} + +function removeAllVisible() { + for(let i=0; i주요 프로모션
    -
  • +
  • 장윤주 식단 대공개! 그녀의 건강 반찬을 소개합니다. @@ -838,6 +838,7 @@ + \ No newline at end of file diff --git a/src/test/java/codesquad/ApplicationTest.java b/src/test/java/codesquad/ApplicationTest.java new file mode 100644 index 0000000..ad8893f --- /dev/null +++ b/src/test/java/codesquad/ApplicationTest.java @@ -0,0 +1,16 @@ +package codesquad; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ApplicationTest { + + @Test + public void contextLoads() { + } + +} \ No newline at end of file diff --git a/src/test/java/codesquad/acceptance/CategoryAcceptanceTest.java b/src/test/java/codesquad/acceptance/CategoryAcceptanceTest.java index c2c324f..9e87a12 100644 --- a/src/test/java/codesquad/acceptance/CategoryAcceptanceTest.java +++ b/src/test/java/codesquad/acceptance/CategoryAcceptanceTest.java @@ -23,7 +23,6 @@ @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = RANDOM_PORT) public class CategoryAcceptanceTest extends AcceptanceTest { - //TODO : BasicAuthorizationInterceptor를 통한 AcceptanceTest구현 private static Logger log = LoggerFactory.getLogger(CategoryAcceptanceTest.class); @Autowired @@ -31,7 +30,6 @@ public class CategoryAcceptanceTest extends AcceptanceTest { private static BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); - @Test public void index_test() { ResponseEntity reponse = sendGet("/", String.class); @@ -52,7 +50,8 @@ public void api_create_test() { MenuCategoryDTO category = new MenuCategoryDTO(); category.setName("새로운 자식"); category.setParentId(1l); - ResponseEntity response = sendPost("/api/menuCategory", category, MenuCategory.class); + ResponseEntity response = + sendPostWithDefaultManager("/api/menuCategory", category, MenuCategory.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); assertThat(response.getBody().getName()).isEqualTo("새로운 자식"); @@ -62,7 +61,8 @@ public void api_create_test() { public void api_create_category_test() { MenuCategoryDTO category = new MenuCategoryDTO(); category.setName("새로운 카테고리"); - ResponseEntity response = sendPost("/api/menuCategory", category, MenuCategory.class); + ResponseEntity response = + sendPostWithDefaultManager("/api/menuCategory", category, MenuCategory.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); assertThat(response.getBody().getName()).isEqualTo("새로운 카테고리"); @@ -72,9 +72,10 @@ public void api_create_category_test() { public void api_delete_test() { MenuCategoryDTO category = new MenuCategoryDTO(); category.setName("새로운 삭제된 카테고리"); - ResponseEntity responseByPost = sendPost("/api/menuCategory", category, MenuCategory.class); - - ResponseEntity responseByDelete = sendDelete("/api/menuCategory/" + responseByPost.getBody().getId(), MenuCategory.class); + ResponseEntity responseByPost = + sendPostWithDefaultManager("/api/menuCategory", category, MenuCategory.class); + ResponseEntity responseByDelete = + sendDeleteWithDefaultManager("/api/menuCategory/" + responseByPost.getBody().getId(), MenuCategory.class); assertThat(responseByDelete.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(responseByDelete.getBody().getName()).isEqualTo("새로운 삭제된 카테고리"); diff --git a/src/test/java/codesquad/domain/AccountRepositoryTest.java b/src/test/java/codesquad/domain/AccountRepositoryTest.java index 5ca8a60..2eb22b3 100644 --- a/src/test/java/codesquad/domain/AccountRepositoryTest.java +++ b/src/test/java/codesquad/domain/AccountRepositoryTest.java @@ -4,27 +4,32 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.test.context.junit4.SpringRunner; +import sun.security.util.Password; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) @DataJpaTest +@ComponentScan({"support"}) public class AccountRepositoryTest { @Autowired AccountRepository accountRepository; + private PasswordEncoder encoder= new BCryptPasswordEncoder(); + @Test public void saveTest() { - Account account = new Account("test1@google.com", "!Password1234", "자바지기", "dadadamared@ng.com"); - accountRepository.save(account); assertThat(accountRepository.findAll().size()).isEqualTo(2); } @Test public void findByUserIdTest() { - assertThat(accountRepository.findByUserId("test@google.com").get().getPassword()).isEqualTo("!Password1234"); + assertThat(encoder.matches("!Test1234", accountRepository.findByUserId("test@google.com").get().getPassword())).isEqualTo(true); } } \ No newline at end of file diff --git a/src/test/java/codesquad/domain/AccountValidTest.java b/src/test/java/codesquad/domain/AccountValidTest.java index d64694f..64dba65 100644 --- a/src/test/java/codesquad/domain/AccountValidTest.java +++ b/src/test/java/codesquad/domain/AccountValidTest.java @@ -14,7 +14,7 @@ public class AccountValidTest { - private static final Logger log = LoggerFactory.getLogger(AccountTest.class); + private static final Logger log = LoggerFactory.getLogger(AccountValidTest.class); private static Validator validator; @@ -25,7 +25,7 @@ public static void setup() { @Test public void emptyUserId() { - Account user = new Account("", "12345678", "testName", "test@gmail.com"); + Account user = new Account("", "!Ta12345678", "testName", "test@gmail.com"); Set> constraintViolations = validator.validate(user); assertThat(constraintViolations.size()).isEqualTo(1); diff --git a/src/test/java/codesquad/domain/MenuCategoryRepositoryTest.java b/src/test/java/codesquad/domain/MenuCategoryRepositoryTest.java index 4e0aca8..8d2601f 100644 --- a/src/test/java/codesquad/domain/MenuCategoryRepositoryTest.java +++ b/src/test/java/codesquad/domain/MenuCategoryRepositoryTest.java @@ -24,7 +24,7 @@ public class MenuCategoryRepositoryTest { public void defualt_test() { MenuCategory menuCategory = new MenuCategory(1L, "최상"); categoryRepository.save(menuCategory); - assertThat(categoryRepository.findAll().size()).isEqualTo(19); + assertThat(categoryRepository.findAll().size()).isEqualTo(18); } @Test @@ -60,7 +60,7 @@ public void delete_operate_test() { categoryRepository.delete(fstCategory); log.info("남은 카테고리 : '{}'", categoryRepository.findAll()); - assertThat(categoryRepository.findAll().size()).isEqualTo(14); + assertThat(categoryRepository.findAll().size()).isEqualTo(13); } } \ No newline at end of file diff --git a/src/test/java/codesquad/web/ApiMenuCategoryControllerTest.java b/src/test/java/codesquad/web/ApiMenuCategoryControllerTest.java index 94bf96b..e8ac4c9 100644 --- a/src/test/java/codesquad/web/ApiMenuCategoryControllerTest.java +++ b/src/test/java/codesquad/web/ApiMenuCategoryControllerTest.java @@ -3,7 +3,7 @@ import codesquad.domain.Account; import codesquad.domain.AccountType; import codesquad.domain.MenuCategory; -import codesquad.security.ManagerAccountHandlerMethodArgumentResolver; +import codesquad.security.AdminAccountHandlerMethodArgumentResolver; import codesquad.service.MenuCategoryService; import codesquad.web.dto.MenuCategoryDTO; import com.fasterxml.jackson.databind.ObjectMapper; @@ -32,7 +32,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; @@ -48,9 +47,9 @@ public class ApiMenuCategoryControllerTest { private MenuCategoryService menuCategoryService; @Mock - private ManagerAccountHandlerMethodArgumentResolver managerArgumentResolver; + private AdminAccountHandlerMethodArgumentResolver managerArgumentResolver; - private MockManagerArgumentResolver mockManagerArgumentResolver = new MockManagerArgumentResolver(); + private MockAdminArgumentResolver mockManagerArgumentResolver = new MockAdminArgumentResolver(); private JacksonTester jsonMenuCategoryDTO; @@ -77,7 +76,7 @@ public void setup() { categories.add(fstCategory); categories.add(new MenuCategory(null, "카테고리2")); - manager = new Account("manager@gmail.com", "!Password1234", "manager", "manager@gmail.com", AccountType.MANAGER); + manager = new Account("manager@gmail.com", "!Password1234", "manager", "manager@gmail.com", AccountType.ADMIN); } @Test @@ -120,14 +119,6 @@ public void deleteCategoryTest() throws Exception { //given when(menuCategoryService.deleteById(1l)) .thenReturn(new MenuCategory()); - when(managerArgumentResolver.supportsParameter((MethodParameter) notNull())) - .thenReturn(true); - when(managerArgumentResolver.resolveArgument( - (MethodParameter) notNull() - , (ModelAndViewContainer) notNull() - , (NativeWebRequest) notNull() - , (WebDataBinderFactory) notNull() - )).thenReturn(manager); //when MockHttpServletResponse response = mockMvc.perform( @@ -139,14 +130,14 @@ public void deleteCategoryTest() throws Exception { assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); } - static class MockManagerArgumentResolver extends ManagerAccountHandlerMethodArgumentResolver { + static class MockAdminArgumentResolver extends AdminAccountHandlerMethodArgumentResolver { @Override public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception { - return new Account("managerByMock@gmail.com", "!Password1234", "manager", "manager@gmail.com", AccountType.MANAGER); + return new Account("managerByMock@gmail.com", "!Password1234", "manager", "manager@gmail.com", AccountType.ADMIN); } } } \ No newline at end of file diff --git a/src/test/java/codesquad/web/ApiMenuCategoryControllerWithApplicationContextTest.java b/src/test/java/codesquad/web/ApiMenuCategoryControllerWithApplicationContextTest.java deleted file mode 100644 index c4d1a5b..0000000 --- a/src/test/java/codesquad/web/ApiMenuCategoryControllerWithApplicationContextTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package codesquad.web; - -import codesquad.domain.MenuCategory; -import codesquad.service.MenuCategoryService; -import codesquad.web.dto.MenuCategoryDTO; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.json.JacksonTester; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; - -import java.util.ArrayList; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; - -@RunWith(SpringRunner.class) -@WebMvcTest(value = ApiMenuCategoryController.class, secure = false) -public class ApiMenuCategoryControllerWithApplicationContextTest { - private static Logger log = LoggerFactory.getLogger(ApiMenuCategoryControllerWithApplicationContextTest.class); - - public static final String URI_MENU_CATEGORY = "/api/menuCategory"; - - @Autowired - private MockMvc mockMvc; - - @MockBean - private MenuCategoryService menuCategoryService; - - private JacksonTester jsonMenuCategoryDTO; - private JacksonTester jsonMenuCategory; - - private List categories = new ArrayList<>(); - - @Before - public void setup() { - JacksonTester.initFields(this, ObjectMapper::new); - - MenuCategory fstCategory = new MenuCategory(1l, "카테고리1"); - MenuCategory subCategory = new MenuCategory(2l, "카테고리1의 하위 카테고리"); - fstCategory.addChild(subCategory); - subCategory.setParent(fstCategory); - categories.add(fstCategory); - categories.add(new MenuCategory(3l, "카테고리2")); - } - - @Test - public void create_test_not_manager_fail() throws Exception { - //when - MockHttpServletResponse response = mockMvc.perform( - post(URI_MENU_CATEGORY) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonMenuCategoryDTO.write( - new MenuCategoryDTO(0l, "카테고리2의 하위 카테고리", 3l)) - .getJson())) - .andReturn().getResponse(); - - //then - assertThat(response.getStatus()).isEqualTo(HttpStatus.FORBIDDEN.value()); - } - - @Test - public void delete_test_not_manager_fail() throws Exception { - //when - MockHttpServletResponse response = mockMvc.perform( - delete(URI_MENU_CATEGORY + "/{id}", 1l)) - .andReturn().getResponse(); - - //then - assertThat(response.getStatus()).isEqualTo(HttpStatus.FORBIDDEN.value()); - } - -} diff --git a/src/test/java/support/security/BasicAuthInterceptorTest.java b/src/test/java/support/security/BasicAuthInterceptorTest.java new file mode 100644 index 0000000..e417bca --- /dev/null +++ b/src/test/java/support/security/BasicAuthInterceptorTest.java @@ -0,0 +1,54 @@ +package support.security; + +import codesquad.domain.Account; +import codesquad.domain.AccountRepository; +import codesquad.intercepter.BasicAuthInterceptor; +import codesquad.util.SessionUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.mock.web.MockHttpServletRequest; + +import java.util.Base64; +import java.util.Optional; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class BasicAuthInterceptorTest { + + @Mock + private AccountRepository accountRepository; + + @InjectMocks + private BasicAuthInterceptor basicAuthInterceptor; + + @Test + public void preHandleTest() throws Exception { + //given + String userId = "userId"; + String password = "password"; + MockHttpServletRequest request = basicAuthHttpRequest(userId, password); + Account loginAccount = new Account(userId, password, "name", "javajigi@slipp.net"); + when(accountRepository.findByUserId(userId)).thenReturn(Optional.of(loginAccount)); + + //when + basicAuthInterceptor.preHandle(request, null, null); + + //then + assertThat(request.getSession().getAttribute(SessionUtils.USER_SESSION_KEY), is(loginAccount)); + + } + + private MockHttpServletRequest basicAuthHttpRequest(String userId, String password) { + String encodedBasicAuth = Base64.getEncoder() + .encodeToString(String.format("%s:%s", userId, password).getBytes()); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("Authorization", "Basic " + encodedBasicAuth); + return request; + } +} diff --git a/src/test/java/support/test/AcceptanceTest.java b/src/test/java/support/test/AcceptanceTest.java index d532125..75e1991 100644 --- a/src/test/java/support/test/AcceptanceTest.java +++ b/src/test/java/support/test/AcceptanceTest.java @@ -1,24 +1,64 @@ package support.test; +import codesquad.domain.Account; +import codesquad.domain.AccountRepository; +import codesquad.exception.account.UnAuthenticationException; +import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.http.*; +import org.springframework.test.context.junit4.SpringRunner; -public class AcceptanceTest { +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public abstract class AcceptanceTest { + private static final String DEFAULT_MANAGER_ACCOUNT_EMAIL = "admin@admin.com"; @Autowired - TestRestTemplate template; + private TestRestTemplate testRestTemplate; + + @Autowired + private AccountRepository accountRepository; + + public TestRestTemplate template() { + return testRestTemplate; + } + + public TestRestTemplate basicAuthTemplate() { + return basicAuthTemplate(getDefaultManager()); + } + + private Account getDefaultManager() { + return accountRepository.findByUserId(DEFAULT_MANAGER_ACCOUNT_EMAIL).orElseThrow(UnAuthenticationException::new); + } + + public TestRestTemplate basicAuthTemplate(Account account) { + return testRestTemplate.withBasicAuth(account.getUserId(), account.getPassword()); + } protected ResponseEntity sendPost(String uri, Object object, Class responseType) { - return template.exchange(uri, HttpMethod.POST, createHttpEntity(object), responseType); + return template().exchange(uri, HttpMethod.POST, createHttpEntity(object), responseType); } protected ResponseEntity sendGet(String uri, Class responseType) { - return template.getForEntity(uri, responseType); + return template().getForEntity(uri, responseType); } protected ResponseEntity sendDelete(String uri, Class responseType) { - return template.exchange(uri, HttpMethod.DELETE, createHttpEntity(null), responseType); + return template().exchange(uri, HttpMethod.DELETE, createHttpEntity(null), responseType); + } + + protected ResponseEntity sendPostWithDefaultManager(String uri, Object object, Class responseType) { + return basicAuthTemplate().exchange(uri, HttpMethod.POST, createHttpEntity(object), responseType); + } + + protected ResponseEntity sendGetWithDefaultManager(String uri, Class responseType) { + return basicAuthTemplate().getForEntity(uri, responseType); + } + + protected ResponseEntity sendDeleteWithDefaultManager(String uri, Class responseType) { + return basicAuthTemplate().exchange(uri, HttpMethod.DELETE, createHttpEntity(null), responseType); } protected HttpEntity createHttpEntity(Object object) { diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100755 index 0000000..50fa960 --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,9 @@ +spring.profiles.active=test + +spring.autoconfigure.exclude= org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration + +handlebars.suffix=.hbs +handlebars.cache=false +handlebars.expose-session-attributes=true + +logging.config=classpath:logback.xml