ADD AccountQueryApiTest, FIX LoginAccountProcessor

- 리뷰 반영, Session 과 관련된 주석 및 파라미터 제거
- LoginAccountProcessor 에서 암호문을 올바르게 검증하도록 수정.
This commit is contained in:
JiwonDev
2021-09-08 16:09:08 +09:00
committed by Jiwon
parent 1f954f92ad
commit 6841f40cc9
6 changed files with 111 additions and 45 deletions

View File

@@ -14,17 +14,10 @@ public final class LoginAccountProcessor {
}
public void login(LoginAccountCommand toCommand) {
var account = accountReader.findByEmail(toCommand.getEmail());
var account = accountReader.findByEmail(toCommand.getEmail())
.orElseThrow(IllegalStateException::new);
if (account.isEmpty()) {
throw new IllegalStateException();
}
final String password = account.get().getPassword();
boolean matches = passwordEncrypter.matches(toCommand.getPassword(),
passwordEncrypter.encode(password));
if (!matches) {
if (!passwordEncrypter.matches(toCommand.getPassword(), account.getPassword())) {
throw new IllegalStateException();
}
}

View File

@@ -1,11 +1,10 @@
package com.yam.app.account.presentation;
import com.yam.app.account.application.AccountFacade;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -24,17 +23,15 @@ public final class AccountQueryApi {
this.accountFacade = accountFacade;
}
@PostMapping("/api/login")
@PostMapping("/api/accounts/login")
public ResponseEntity<Void> login(
@Validated @RequestBody LoginAccountRequest request,
HttpSession session) {
@Valid @RequestBody LoginAccountRequest request) {
try {
accountFacade.login(request);
} catch (IllegalStateException e) {
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}
// SessionUtils.setLoginAccountEmail(session, request.getEmail());
return ResponseEntity.ok().build();
}
}

View File

@@ -2,6 +2,7 @@ package com.yam.app.account.presentation;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import lombok.Data;
@Data
@@ -12,5 +13,7 @@ public final class LoginAccountRequest {
private String email;
@NotBlank
@Pattern(regexp = "^[A-Za-z1-9~!@#$%^&*()+|=]{8,12}$",
message = "비밀번호는 영어와 숫자, 특수문자로 8~12자리 이내로 입력해주세요.")
private String password;
}

View File

@@ -2,7 +2,7 @@ package com.yam.app.account.presentation;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import javax.validation.constraints.Pattern;
import lombok.Data;
@Data
@@ -15,7 +15,9 @@ public final class RegisterAccountRequest {
@NotBlank
private String nickname;
@Size(min = 8, max = 12, message = "비밀번호는 최소 8자, 최대 12자까지 허용됩니다.")
@NotBlank
@Pattern(regexp = "^[A-Za-z1-9~!@#$%^&*()+|=]{8,12}$",
message = "비밀번호는 영어와 숫자, 특수문자로 8~12자리 이내로 입력해주세요.")
private String password;
}

View File

@@ -16,6 +16,7 @@ import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.NullAndEmptySource;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
@@ -212,6 +213,30 @@ final class AccountCommandApiTests {
.andDo(print())
.andExpect(status().isBadRequest());
}
@ParameterizedTest
@ValueSource(strings = {"1", "a", "1a234567890123456"})
@DisplayName("요청 Body 의 비밀번호 형식이 맞지 않은 경우 400 에러를 반환한다.")
void http_json_password_is_invalid(String args) throws Exception {
// Arrange
var request = new RegisterAccountRequest();
request.setEmail("jiwon@naver.com");
request.setNickname("jiwon");
request.setPassword(args);
// Act
final var actions = mockMvc.perform(post(REGISTER_API)
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request))
);
// Assert
actions
.andDo(print())
.andExpect(status().isBadRequest());
}
}
}

View File

@@ -13,6 +13,7 @@ import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.NullAndEmptySource;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
@@ -44,7 +45,7 @@ class AccountQueryApiTest {
doNothing().when(accountFacade).login(request);
//Act
var actions = mockMvc.perform(post("/api/login")
var actions = mockMvc.perform(post("/api/accounts/login")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request))
@@ -56,39 +57,17 @@ class AccountQueryApiTest {
.andExpect(status().isOk());
}
@ParameterizedTest
@NullAndEmptySource
@DisplayName("로그인 요청 JSON 데이터가 null 이거나 비어있다면 400 에러를 반환한다.")
void http_json_value_is_empty_or_null(String args) throws Exception {
//Arrange
var request = new LoginAccountRequest();
request.setEmail(args);
request.setPassword(args);
//Act
var actions = mockMvc.perform(post("/api/login")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request))
);
//Assert
actions
.andDo(print())
.andExpect(status().isBadRequest());
}
@Test
@DisplayName("이메일 비밀번호 유효하지않아 로그인 실패한 경우 401 에러를 반환한다.")
@DisplayName("이메일, 비밀번호 형식은 유효하 로그인 실패한 경우 401 에러를 반환한다.")
void login_fail() throws Exception {
// Arrange
var request = new LoginAccountRequest();
request.setEmail("wejiwef@naver.com");
request.setPassword("DRFTGYHUJIKOL");
request.setPassword("password1!");
doThrow(IllegalStateException.class).when(accountFacade).login(request);
// Act
final var actions = mockMvc.perform(post("/api/login")
final var actions = mockMvc.perform(post("/api/accounts/login")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request))
@@ -99,6 +78,73 @@ class AccountQueryApiTest {
.andDo(print())
.andExpect(status().isUnauthorized());
}
@ParameterizedTest
@ValueSource(strings = {"1", "a", "1a234567890123456"})
@DisplayName("요청 Body 의 비밀번호 형식이 맞지 않은 경우 400 에러를 반환한다.")
void http_json_password_is_invalid(String args) throws Exception {
// Arrange
var request = new LoginAccountRequest();
request.setEmail("jiwon22@gmail.com");
request.setPassword(args);
doThrow(IllegalStateException.class).when(accountFacade).login(request);
// Act
final var actions = mockMvc.perform(post("/api/accounts/login")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request))
);
// Assert
actions
.andDo(print())
.andExpect(status().isBadRequest());
}
@ParameterizedTest
@ValueSource(strings = {"@@@@@@@@@", "@naver.com", "jiwon"})
@DisplayName("요청 Body 의 이메일 형식이 맞지 않은 경우 400 에러를 반환한다.")
void http_json_email_is_invalid() throws Exception {
// Arrange
var request = new LoginAccountRequest();
request.setEmail("DQWJIDWQ291");
request.setPassword("1abcabcabc");
doThrow(IllegalStateException.class).when(accountFacade).login(request);
// Act
final var actions = mockMvc.perform(post("/api/accounts/login")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request))
);
// Assert
actions
.andDo(print())
.andExpect(status().isBadRequest());
}
@ParameterizedTest
@NullAndEmptySource
@DisplayName("요청 Body 의 이메일,비밀번호가 null 이거나 비어있다면 400 에러를 반환한다.")
void http_json_value_is_empty_or_null(String args) throws Exception {
//Arrange
var request = new LoginAccountRequest();
request.setEmail(args);
request.setPassword(args);
//Act
var actions = mockMvc.perform(post("/api/accounts/login")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request))
);
//Assert
actions
.andDo(print())
.andExpect(status().isBadRequest());
}
}
}