diff --git a/resource-server/src/main/java/com/inhabas/api/web/SignUpController.java b/resource-server/src/main/java/com/inhabas/api/web/SignUpController.java index 112c2c47..f5665f63 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/SignUpController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/SignUpController.java @@ -18,7 +18,9 @@ import org.springframework.web.bind.annotation.*; import javax.validation.Valid; +import java.util.ArrayList; import java.util.List; +import java.util.Optional; @Tag(name = "회원가입", description = "회원가입 기간이 아니면 403 Forbidden") @RestController @@ -123,10 +125,11 @@ public ResponseEntity saveAnswers( @PutMapping("/signUp") @Operation(summary = "회원가입을 완료한다") @ApiResponse(responseCode = "204") - public ResponseEntity finishSignUp(@Authenticated Long memberId, @Valid @RequestBody List answers) { + public ResponseEntity finishSignUp(@Authenticated Long memberId, @Valid @RequestBody Optional> answers) { - signUpService.completeSignUp(answers, memberId); + signUpService.completeSignUp(answers.orElse(new ArrayList<>()), memberId); return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/signUp/SignUpIntegrationTest.java b/resource-server/src/test/java/com/inhabas/api/domain/signUp/SignUpIntegrationTest.java index a19f7d47..5403ddc2 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/signUp/SignUpIntegrationTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/signUp/SignUpIntegrationTest.java @@ -8,6 +8,7 @@ import com.inhabas.api.auth.domain.oauth2.majorInfo.domain.MajorInfo; import com.inhabas.api.auth.domain.oauth2.majorInfo.repository.MajorInfoRepository; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; +import com.inhabas.api.auth.domain.oauth2.member.domain.service.MemberService; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.MemberType; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; @@ -23,8 +24,9 @@ import com.inhabas.api.domain.signUpSchedule.repository.SignUpScheduleRepository; import com.inhabas.testAnnotataion.CustomSpringBootTest; import com.inhabas.testAnnotataion.WithMockJwtAuthenticationToken; -import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.security.core.GrantedAuthority; @@ -32,13 +34,13 @@ import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.RequestPostProcessor; +import org.springframework.transaction.annotation.Transactional; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.Optional; import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; import static org.assertj.core.api.Assertions.assertThat; @@ -47,54 +49,80 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @CustomSpringBootTest(classes = ApiApplication.class) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class SignUpIntegrationTest { @Autowired private MockMvc mockMvc; - @Autowired private TokenUtil tokenUtil; - @Autowired private ObjectMapper objectMapper; - @Autowired private QuestionnaireRepository questionnaireRepository; - @Autowired private MajorInfoRepository majorInfoRepository; - @Autowired private MemberRepository memberRepository; - @Autowired private SignUpScheduleRepository scheduleRepository; + @Autowired + private TokenUtil tokenUtil; + @Autowired + private ObjectMapper objectMapper; + @Autowired + private QuestionnaireRepository questionnaireRepository; + @Autowired + private MajorInfoRepository majorInfoRepository; + @Autowired + private MemberRepository memberRepository; + @Autowired + private MemberService memberService; + @Autowired + private SignUpScheduleRepository scheduleRepository; - @BeforeEach - public void setUp() { + private static final String ROLE_PREFIX = "ROLE_"; + + private String token; + @BeforeAll + public void setUp() { + 면접질문_설정(); + 전공정보_설정(); + 회원가입_가능한_기간(); + token = OAuth인증된_JWT_TOKEN(SIGNING_UP); } + @Test + @Transactional @WithMockJwtAuthenticationToken(memberRole = NOT_APPROVED) public void 미승인회원_회원가입_비정상_접근() throws Exception { forbiddenWhenAccessEverySignUpApi(NOT_APPROVED); } + @Test + @Transactional @WithMockJwtAuthenticationToken(memberRole = DEACTIVATED) public void 비활동회원_회원가입_비정상_접근() throws Exception { forbiddenWhenAccessEverySignUpApi(DEACTIVATED); } + @Test + @Transactional @WithMockJwtAuthenticationToken(memberRole = BASIC) public void 기존_일반회원_회원가입_비정상_접근() throws Exception { forbiddenWhenAccessEverySignUpApi(BASIC); } + @Test + @Transactional @WithMockJwtAuthenticationToken(memberRole = EXECUTIVES) public void 회장단_회원가입_비정상_접근() throws Exception { forbiddenWhenAccessEverySignUpApi(EXECUTIVES); } @Test + @Transactional @WithMockJwtAuthenticationToken(memberRole = SIGNING_UP) public void 회원가입_기간이_아닙니다() throws Exception { /* 유동현은 IBAS 에 회원 가입하기 위해 - 소셜 로그인 후 회원 가입용 임시 토큰을 발급 받았다.*/ - String token = OAuth인증된_JWT_TOKEN(SIGNING_UP); + 소셜 로그인 후 회원 가입용 임시 토큰을 발급 받았다. + 회원가입이 불가능한 때에 요청을 보낸경우 */ + scheduleRepository.deleteAll(); + 회원가입_불가능한_기간(); /* OAuth2 인증이 완료되면 자동으로 회원가입 페이지로 리다이렉트 된다. - 이 때, 회원가입을 완료하지 않고 임시저장했던 프로필 정보가 있는지 불러오길 시도하지만 - 신규회원 가입이기 때문에, 소셜 이메일을 제외하고는 아무것도 받지 못한다. */ + 이 때, 회원가입을 완료하지 않고 임시저장했던 프로필 정보가 있는지 불러온다. */ String response = mockMvc.perform(get("/signUp").with(accessToken(token))) .andExpect(status().isForbidden()) .andReturn().getResponse().getContentAsString(StandardCharsets.UTF_8); @@ -102,25 +130,18 @@ public void setUp() { } @Test + @Transactional @WithMockJwtAuthenticationToken(memberRole = SIGNING_UP) public void OAuth2_인증_후_비회원_신규_학생_회원가입() throws Exception { - - //given - 면접질문_설정(); - 전공정보_설정(); - 회원가입_가능한_기간(); - - /* 유동현은 IBAS 에 회원 가입하기 위해 소셜 로그인 후 회원 가입용 임시 토큰을 발급 받았다.*/ - String token = OAuth인증된_JWT_TOKEN(SIGNING_UP); /* OAuth2 인증이 완료되면 자동으로 회원가입 페이지로 리다이렉트 된다. 이 때, 회원가입을 완료하지 않고 임시저장했던 프로필 정보가 있는지 불러오길 시도하지만 신규회원 가입이기 때문에, 소셜 이메일을 제외하고는 아무것도 받지 못한다. */ mockMvc.perform(get("/signUp").with(accessToken(token))) - .andExpect(status().isOk()) - .andExpect(content().string("{\"email\":\"my@gmail.com\",\"memberType\":\"UNDERGRADUATE\"}")); + .andExpect(status().isOk()) + .andExpect(content().string("{\"name\":null,\"major\":null,\"phoneNumber\":null,\"studentId\":null,\"memberType\":null,\"grade\":null}")); /* 개인정보 입력을 위해, 전공 정보들이 로딩된다. */ mockMvc.perform(get("/signUp/majorInfo").with(accessToken(token))) @@ -140,7 +161,7 @@ public void setUp() { .andExpect(status().isNoContent()); /* 다음 페이지에서 면접용 질문 리스트가 로딩된다. */ - String questionList = mockMvc.perform(get("/signUp/questionnaire").with(accessToken(token))) + String questionList = mockMvc.perform(get("/signUp/questionnaires").with(accessToken(token))) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(StandardCharsets.UTF_8); assertThat(questionList).isEqualTo("[" + @@ -154,7 +175,7 @@ public void setUp() { /* 기존에 작성했던 답변을 가져오지만, 기존 답변이 없다. */ mockMvc.perform(get("/signUp/answers").with(accessToken(token))) .andExpect(status().isOk()) - .andExpect(content().string("[]")); + .andExpect(content().string("[{\"questionId\":1,\"content\":null},{\"questionId\":2,\"content\":null},{\"questionId\":3,\"content\":null},{\"questionId\":4,\"content\":null},{\"questionId\":5,\"content\":null}]")); /* 면접 질문에 대답하고 임시저장 버튼을 클릭한다. */ mockMvc.perform(post("/signUp/answers").with(accessToken(token)) @@ -168,27 +189,29 @@ public void setUp() { .andExpect(status().isNoContent()); /* 회원가입 신청을 완료한다. */ - mockMvc.perform(put("/signUp").with(accessToken(token))) + mockMvc.perform(put("/signUp").with(accessToken(token)) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(Arrays.asList( + new AnswerDto(1L, ""), + new AnswerDto(2L, "아몰랑"), + new AnswerDto(3L, "아아몰랑"), + new AnswerDto(4L, "아모른다구"), + new AnswerDto(5L, "ㅎ"))))) .andExpect(status().isNoContent()); //then - Member 유동현 = memberRepository.findByProviderAndUid(OAuth2Provider.GOOGLE, new UID("1234")).orElseThrow(); + Member 유동현 = memberRepository.findByProviderAndUid(OAuth2Provider.NAVER, new UID("N8ojJQXxxSxtO0CmEH3xtt5Y6ER09UEsRozkpbGAdOI")).orElseThrow(); assertThat(유동현.getIbasInformation().getRole()).isEqualTo(NOT_APPROVED); } @Test + @Transactional @WithMockJwtAuthenticationToken(memberRole = SIGNING_UP) public void OAuth2_인증_후_비회원_신규_교수_회원가입() throws Exception { - - //given - 전공정보_설정(); - 회원가입_가능한_기간(); - /* 유동현 교수는 IBAS 에 회원 가입하기 위해 소셜 로그인 후 회원 가입용 임시 토큰을 발급 받았다.*/ - String token = OAuth인증된_JWT_TOKEN(SIGNING_UP); /* OAuth2 인증이 완료되면 자동으로 회원가입 페이지로 리다이렉트 된다. */ @@ -218,10 +241,10 @@ public void setUp() { /* 회원가입 신청을 완료한다. */ mockMvc.perform(put("/signUp").with(accessToken(token))) - .andExpect(status().isNoContent()); + .andExpect(status().isNoContent()); //then - Member 유동현_교수 = memberRepository.findByProviderAndUid(OAuth2Provider.GOOGLE, new UID("1234")).orElseThrow(); + Member 유동현_교수 = memberRepository.findByProviderAndUid(OAuth2Provider.NAVER, new UID("N8ojJQXxxSxtO0CmEH3xtt5Y6ER09UEsRozkpbGAdOI")).orElseThrow(); assertThat(유동현_교수.getIbasInformation().getRole()).isEqualTo(NOT_APPROVED); } @@ -238,6 +261,9 @@ private void forbiddenWhenAccessEverySignUpApi(Role role) throws Exception { mockMvc.perform(post("/signUp/answers").with(accessToken(token))) .andExpect(status().isForbidden()); } + + + // setUp public static RequestPostProcessor accessToken(String accessToken) { return request -> { request.addHeader("Authorization", "Bearer " + accessToken); @@ -246,7 +272,7 @@ public static RequestPostProcessor accessToken(String accessToken) { } private String OAuth인증된_JWT_TOKEN(Role role) { - List grantedAuthorities = List.of(new SimpleGrantedAuthority(role.toString())); + List grantedAuthorities = List.of(new SimpleGrantedAuthority(ROLE_PREFIX+ role.toString())); Map nameAttributeKey = Map.of( "message", "success", "response", Map.of( @@ -257,8 +283,7 @@ public static RequestPostProcessor accessToken(String accessToken) { ) ); OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo("NAVER", nameAttributeKey); - memberRepository.saveAndFlush(new Member(oAuth2UserInfo)); - Optional test = memberRepository.findByProviderAndUid(OAuth2Provider.NAVER, new UID("N8ojJQXxxSxtO0CmEH3xtt5Y6ER09UEsRozkpbGAdOI")); + memberService.updateSocialAccountInfo(oAuth2UserInfo); CustomOAuth2User customOAuth2User = new CustomOAuth2User(grantedAuthorities, nameAttributeKey, "response", 1L); return tokenUtil.createAccessToken(new OAuth2AuthenticationToken(customOAuth2User, grantedAuthorities, "NAVER")); @@ -274,6 +299,7 @@ public static RequestPostProcessor accessToken(String accessToken) { new Questionnaire(4L, "추후 희망하는 진로가 무엇이며, 동아리 활동이 진로에 어떠한 영향을 줄 것이라고 생각하나요?"), new Questionnaire(5L, "어떤 경로로 IBAS를 알게 되셨나요?"))); } + private void 전공정보_설정() { majorInfoRepository.saveAll( Arrays.asList( @@ -293,4 +319,9 @@ private String jsonOf(Object o) throws JsonProcessingException { new SignUpSchedule(1, now.minusDays(1L), now.plusDays(1L), now.plusDays(1L), now.plusDays(2L), now.plusDays(3L))); } + private void 회원가입_불가능한_기간() { + LocalDateTime now = LocalDateTime.now(); + scheduleRepository.save( + new SignUpSchedule(1, now.minusDays(2L), now.minusDays(1L), now.plusDays(1L), now.plusDays(2L), now.plusDays(3L))); + } }