Skip to content

Commit

Permalink
Merge pull request #103 from TEAM-MODDY/feat/#101
Browse files Browse the repository at this point in the history
#101 [feat] 전화번호 인증 api 구현
  • Loading branch information
KWY0218 authored Jan 12, 2024
2 parents d1fc6f9 + 979056e commit 63dfb07
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public enum ErrorCode {
INVALID_TOKEN_EXCEPTION(HttpStatus.BAD_REQUEST, "유효하지 않은 토큰을 입력했습니다."),
EMPTY_KAKAO_CODE_EXCEPTION(HttpStatus.BAD_REQUEST, "카카오 코드 값을 입력해 주세요."),
INVALID_KAKAO_CODE_EXCEPTION(HttpStatus.BAD_REQUEST, "유효하지 않은 카카오 코드를 입력했습니다."),
NOT_MATCH_VERIFICATION_CODE_EXCEPTION(HttpStatus.BAD_REQUEST, "인증번호가 일치하지 않습니다."),
EXPIRE_VERIFICATION_CODE_EXCEPTION(HttpStatus.BAD_REQUEST, "만료된 인증 코드입니다."),

// 401
TOKEN_NOT_CONTAINED_EXCEPTION(HttpStatus.UNAUTHORIZED, "Access Token이 필요합니다."),
Expand All @@ -30,6 +32,7 @@ public enum ErrorCode {
NOT_FOUND_APPLICATION_EXCEPTION(HttpStatus.NOT_FOUND, "해당 지원서를 찾을 수 없습니다."),
NOT_FOUND_RESOURCE_EXCEPTION(HttpStatus.NOT_FOUND, "해당 자원을 찾을 수 없습니다."),
NOT_FOUND_REGION_EXCEPTION(HttpStatus.NOT_FOUND, "해당 지역을 찾을 수 없습니다."),
NOT_FOUND_VERIFICATION_CODE_EXCEPTION(HttpStatus.NOT_FOUND, "인증 코드가 존재하지 않습니다."),

// 405 METHOD_NOT_ALLOWED
METHOD_NOT_ALLOWED_EXCEPTION(HttpStatus.METHOD_NOT_ALLOWED, "지원하지 않는 메소드 입니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public enum SuccessCode {
OFFER_ACCEPT_SUCCESS(HttpStatus.OK, "제안서 승락 성공입니다."),
POST_OFFER_SUCCESS(HttpStatus.OK, "제안서 작성 성공입니다."),
SEND_VERIFICATION_CODE_SUCCESS(HttpStatus.OK, "전화번호 인증 요청 성공입니다."),
FIND_REGION_LIST_SUCCESS(HttpStatus.OK, "희망 지역 리스트 조회 성공입니다.");
FIND_REGION_LIST_SUCCESS(HttpStatus.OK, "희망 지역 리스트 조회 성공입니다."),
VERIFICATION_CODE_MATCH_SUCCESS(HttpStatus.OK, "전화번호 인증 성공입니다.");

private final HttpStatus httpStatus;
private final String message;
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/com/moddy/server/controller/auth/AuthController.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.moddy.server.common.util.SmsUtil;
import com.moddy.server.config.resolver.kakao.KakaoCode;
import com.moddy.server.controller.auth.dto.request.PhoneNumberRequestDto;
import com.moddy.server.controller.auth.dto.request.VerifyCodeRequestDto;
import com.moddy.server.controller.auth.dto.response.LoginResponseDto;
import com.moddy.server.controller.auth.dto.response.RegionResponse;
import com.moddy.server.controller.designer.dto.request.DesignerCreateRequest;
Expand Down Expand Up @@ -37,6 +38,7 @@

import static com.moddy.server.common.exception.enums.SuccessCode.SEND_VERIFICATION_CODE_SUCCESS;
import static com.moddy.server.common.exception.enums.SuccessCode.SOCIAL_LOGIN_SUCCESS;
import static com.moddy.server.common.exception.enums.SuccessCode.VERIFICATION_CODE_MATCH_SUCCESS;

@Tag(name = "Auth Controller", description = "로그인 및 회원 가입 관련 API 입니다.")
@RestController
Expand Down Expand Up @@ -120,4 +122,22 @@ public SuccessNonDataResponse sendVerificationCodeMessageToUser(@RequestBody Pho
return SuccessNonDataResponse.success(SEND_VERIFICATION_CODE_SUCCESS);
}

@Operation(summary = "전화번호 인증 API", description = "전화번호 인증 API")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "전화번호 인증 성공입니다."),
@ApiResponse(
responseCode = "400",
description = "1. 인증번호가 일치하지 않습니다."
+ "2. 만료된 인증 코드입니다.",
content = @Content(schema = @Schema(implementation = ErrorResponse.class))
),
@ApiResponse(responseCode = "404", description = "인증 코드가 존재하지 않습니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "500", description = "서버 내부 오류", content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
@PostMapping("/phoneNumber/verify")
public SuccessNonDataResponse verifyCode(@RequestBody VerifyCodeRequestDto verifyCodeRequestDto) {
authService.verifyCode(verifyCodeRequestDto.phoneNumber(), verifyCodeRequestDto.verifyCode());
return SuccessNonDataResponse.success(VERIFICATION_CODE_MATCH_SUCCESS);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.moddy.server.controller.auth.dto.request;

public record VerifyCodeRequestDto(String phoneNumber, String verifyCode) {
}
2 changes: 2 additions & 0 deletions src/main/java/com/moddy/server/domain/BaseTimeEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.springframework.data.annotation.CreatedDate;
Expand All @@ -11,6 +12,7 @@

import java.time.LocalDateTime;

@Getter
@SuperBuilder
@MappedSuperclass
@NoArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

@Entity
@Builder
@Getter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class UserVerification extends BaseTimeEntity {
Expand All @@ -22,4 +28,9 @@ public class UserVerification extends BaseTimeEntity {
private String phoneNumber;
@NotNull
private String verificationCode;

public boolean isExpireCode(LocalDateTime now) {
long minutesDifference = ChronoUnit.MINUTES.between(this.getCreatedAt(), now);
return minutesDifference >= 3;
}
}
21 changes: 21 additions & 0 deletions src/main/java/com/moddy/server/service/auth/AuthService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.moddy.server.service.auth;

import com.moddy.server.common.dto.TokenPair;
import com.moddy.server.common.exception.model.BadRequestException;
import com.moddy.server.common.exception.model.NotFoundException;
import com.moddy.server.common.util.SmsUtil;
import com.moddy.server.common.util.VerificationCodeGenerator;
Expand All @@ -18,10 +19,14 @@
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.moddy.server.common.exception.enums.ErrorCode.EXPIRE_VERIFICATION_CODE_EXCEPTION;
import static com.moddy.server.common.exception.enums.ErrorCode.NOT_FOUND_VERIFICATION_CODE_EXCEPTION;
import static com.moddy.server.common.exception.enums.ErrorCode.NOT_MATCH_VERIFICATION_CODE_EXCEPTION;
import static com.moddy.server.common.exception.enums.ErrorCode.USER_NOT_FOUND_EXCEPTION;

@Service
Expand Down Expand Up @@ -79,4 +84,20 @@ public void sendVerificationCodeMessageToUser(String phoneNumber) {
.build();
userVerificationRepository.save(newUserVerification);
}

@Transactional
public void verifyCode(String phoneNumber, String verificationCode) {
UserVerification userVerification = userVerificationRepository.findByPhoneNumber(phoneNumber)
.orElseThrow(() -> new NotFoundException(NOT_FOUND_VERIFICATION_CODE_EXCEPTION));

if (userVerification.isExpireCode(LocalDateTime.now())) {
userVerificationRepository.deleteByPhoneNumber(phoneNumber);
throw new BadRequestException(EXPIRE_VERIFICATION_CODE_EXCEPTION);
}

if (!verificationCode.equals(userVerification.getVerificationCode()))
throw new BadRequestException(NOT_MATCH_VERIFICATION_CODE_EXCEPTION);

userVerificationRepository.deleteByPhoneNumber(phoneNumber);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.moddy.server.domain.verify;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.time.LocalDateTime;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

class UserVerificationTest {

@Test
@DisplayName("테이블 생성 시간이 2000년 2월 3일 6시 30분이고, 이후에 3분이 지났으면 true를 반환한다.")
void isExpireCodeTest() {
// given
UserVerification userVerification = UserVerification
.builder()
.createdAt(LocalDateTime.of(2000, 2, 3, 6, 30))
.build();
LocalDateTime now = LocalDateTime.of(2000, 2, 3, 6, 33);

// when
boolean isExpire = userVerification.isExpireCode(now);

// then
assertThat(isExpire).isTrue();
}

@Test
@DisplayName("테이블 생성 시간이 2000년 2월 3일 6시 30분이고, 이후에 2분이 지났으면 false를 반환한다.")
void isExpireCodeTest2() {
// given
UserVerification userVerification = UserVerification
.builder()
.createdAt(LocalDateTime.of(2000, 2, 3, 6, 30))
.build();
LocalDateTime now = LocalDateTime.of(2000, 2, 3, 6, 32);

// when
boolean isExpire = userVerification.isExpireCode(now);

// then
assertThat(isExpire).isFalse();
}
}

0 comments on commit 63dfb07

Please sign in to comment.