forked from Me1tingPot/BE
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from JangYouJung/feature/Me1tingPot#56
[Feature] λ§μ΄νμ΄μ§ νλ‘ν μ¬μ§ μΆκ°/μμ ꡬν λ° νμκ°μ μ΄λ©μΌ μΈμ¦ ꡬν
- Loading branch information
Showing
27 changed files
with
637 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
src/main/java/meltingpot/server/auth/controller/MailController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package meltingpot.server.auth.controller; | ||
|
||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.responses.ApiResponse; | ||
import io.swagger.v3.oas.annotations.responses.ApiResponses; | ||
import jakarta.validation.Valid; | ||
import lombok.RequiredArgsConstructor; | ||
import meltingpot.server.auth.controller.dto.MailVerificationRequestDto; | ||
import meltingpot.server.auth.controller.dto.VerificationCodeRequestDto; | ||
import meltingpot.server.auth.service.MailService; | ||
import meltingpot.server.exception.DuplicateException; | ||
import meltingpot.server.exception.MailVerificationException; | ||
import meltingpot.server.util.ResponseCode; | ||
import meltingpot.server.util.ResponseData; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.http.ResponseEntity; | ||
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.RestController; | ||
|
||
@RequiredArgsConstructor | ||
@RestController | ||
@RequestMapping("/api/v1/mail") | ||
public class MailController { | ||
private final MailService mailService; | ||
private final Logger logger = LoggerFactory.getLogger(this.getClass()); | ||
|
||
// μ νμ μΈμ¦ λ©μΌ μ μ‘ | ||
@PostMapping("") | ||
@Operation(summary="μ΄λ©μΌ μΈμ¦λ²νΈ μ μ‘ [μμ]", description="[μ΄λ©μΌ μΈμ¦ μμ ꡬν SMTP]\n μ λ ₯ λ°μ μ΄λ©μΌλ‘ μΈμ¦ λ²νΈλ₯Ό μ μ‘ν©λλ€.") | ||
@ApiResponses(value = { | ||
@ApiResponse(responseCode = "MAIL_VERIFICATION_SEND_SUCCESS", description = "μ΄λ©μΌ μΈμ¦λ²νΈ μ μ‘ μ±κ³΅"), | ||
@ApiResponse(responseCode = "VERIFICATION_CODE_ALREADY_EXIST", description = "μ΄λ―Έ μμ±ν μΈμ¦ λ²νΈκ° μμ΅λλ€"), | ||
@ApiResponse(responseCode = "MAIL_SEND_FAIL", description = "μ΄λ©μΌ μ μ‘ μ€ν¨") | ||
}) | ||
public ResponseEntity<ResponseData> sendVerificationMail( | ||
@RequestBody @Valid MailVerificationRequestDto request | ||
) { | ||
try{ | ||
logger.info("MAIL_VERIFICATION_SEND_SUCCESS (200 OK)"); | ||
return ResponseData.toResponseEntity(mailService.sendVerificationMail(request)); | ||
|
||
}catch(MailVerificationException e){ | ||
return ResponseData.toResponseEntity(e.getResponseCode()); | ||
} | ||
} | ||
|
||
@PostMapping("verification") | ||
@Operation(summary="μ΄λ©μΌ μΈμ¦λ²νΈ νμΈ", description="μ΄λ©μΌ μΈμ¦ λ²νΈλ₯Ό μ λ ₯ λ°κ³ μ¬λ°λ₯Έ λ²νΈμΈμ§ νμΈν©λλ€." ) | ||
@ApiResponses(value = { | ||
@ApiResponse(responseCode = "MAIL_VERIFICATION_CHECK_SUCCESS", description = "μΈμ¦λ²νΈκ° μΌμΉν©λλ€"), | ||
@ApiResponse(responseCode = "AUTHENTICATION_NOT_FOUND", description = "λ©μΌ μΈμ¦ μ 보λ₯Ό μ°Ύμ μ μμ΅λλ€"), | ||
@ApiResponse(responseCode = "AUTH_TIME_OUT", description = "μΈμ¦ μκ°μ μ΄κ³Όνμ΅λλ€"), | ||
@ApiResponse(responseCode = "AUTH_NUMBER_INCORRECT", description = "μΈμ¦ λ²νΈκ° νλ Έμ΅λλ€"), | ||
}) | ||
public ResponseEntity<ResponseData> checkVerification( | ||
@RequestBody @Valid VerificationCodeRequestDto request | ||
) { | ||
try{ | ||
logger.info("VERIFICATION_CHECK_SUCCESS (200 OK)"); | ||
return ResponseData.toResponseEntity( mailService.checkVerification(request)); | ||
|
||
}catch(MailVerificationException e){ | ||
return ResponseData.toResponseEntity(e.getResponseCode()); | ||
} | ||
} | ||
|
||
// μ΄λ©μΌ μ€λ³΅ νμΈ | ||
@PostMapping("duplication") | ||
@Operation(summary="μ΄λ©μΌ μ€λ³΅ 체ν¬", description="μ΄λ―Έ κ°μ ν μ΄λ©μΌμΈμ§ νμΈνλ API μ λλ€.\n" ) | ||
public ResponseEntity<ResponseData> checkEmail( | ||
@RequestBody @Valid MailVerificationRequestDto request) { | ||
try{ | ||
mailService.checkUserName(request.email()); | ||
return ResponseData.toResponseEntity(ResponseCode.MAIL_AVAILABLE); | ||
}catch (DuplicateException e){ | ||
return ResponseData.toResponseEntity(ResponseCode.EMAIL_DUPLICATION); | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
src/main/java/meltingpot/server/auth/controller/dto/MailVerificationRequestDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package meltingpot.server.auth.controller.dto; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.Pattern; | ||
import meltingpot.server.util.VerificationUtil; | ||
|
||
public record MailVerificationRequestDto( | ||
@NotBlank(message = "email is required") | ||
@Pattern(regexp = VerificationUtil.USERNAME_REGEXP) | ||
String email | ||
) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
src/main/java/meltingpot/server/auth/controller/dto/VerificationCodeRequestDto.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package meltingpot.server.auth.controller.dto; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.Pattern; | ||
import meltingpot.server.util.VerificationUtil; | ||
|
||
public record VerificationCodeRequestDto( | ||
@NotBlank(message = "email is required") | ||
@Pattern(regexp = VerificationUtil.USERNAME_REGEXP) | ||
String email, | ||
@NotBlank | ||
String code | ||
) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 121 additions & 0 deletions
121
src/main/java/meltingpot/server/auth/service/MailService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package meltingpot.server.auth.service; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import meltingpot.server.auth.controller.dto.MailVerificationRequestDto; | ||
import meltingpot.server.auth.controller.dto.VerificationCodeRequestDto; | ||
import meltingpot.server.domain.entity.Constants; | ||
import meltingpot.server.domain.entity.MailVerification; | ||
import meltingpot.server.domain.repository.AccountRepository; | ||
import meltingpot.server.domain.repository.MailVerificationRepository; | ||
import meltingpot.server.exception.DuplicateException; | ||
import meltingpot.server.exception.MailVerificationException; | ||
import meltingpot.server.util.MailUtil; | ||
import meltingpot.server.util.ResponseCode; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
import java.security.NoSuchAlgorithmException; | ||
import java.security.SecureRandom; | ||
import java.time.LocalDateTime; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.Random; | ||
|
||
@RequiredArgsConstructor | ||
@Service | ||
public class MailService { | ||
private final MailVerificationRepository mailVerificationRepository; | ||
private final MailUtil mailUtil; | ||
private final AccountRepository accountRepository; | ||
|
||
// μΈμ¦ μ½λ μμ± | ||
private String createCode() { | ||
try { | ||
Random rand = SecureRandom.getInstanceStrong(); | ||
StringBuilder code = new StringBuilder(); | ||
|
||
for (int i = 0; i < 6; i++) { | ||
// 0~9κΉμ§ λμ μμ± | ||
String num = Integer.toString(rand.nextInt(10)); | ||
code.append(num); | ||
} | ||
|
||
return code.toString(); | ||
|
||
} catch (NoSuchAlgorithmException e) { | ||
e.printStackTrace(); | ||
return null; | ||
} | ||
} | ||
|
||
// μΈμ¦ λ©μΌ λ°μ‘ | ||
@Transactional | ||
public ResponseCode sendVerificationMail(MailVerificationRequestDto request) { | ||
String email = request.email(); | ||
|
||
// μ΄λ―Έ μ ν¨ν μΈμ¦ μ λ³΄κ° μλ κ²½μ° | ||
Optional<MailVerification> oldMailVerification = mailVerificationRepository.findByEmailAndExpiredAtIsAfterNowAndVerifiedFalse(email,LocalDateTime.now()); | ||
if(oldMailVerification.isPresent()){ | ||
throw new MailVerificationException(ResponseCode.VERIFICATION_CODE_ALREADY_EXIST); | ||
} | ||
|
||
String code = createCode(); | ||
Map<String,String> mailValues = Map.of("code", code); | ||
|
||
String title = "[λ©ν ν] μ΄λ©μΌ μΈμ¦μ μν μΈμ¦ λ²νΈ μλ΄"; | ||
|
||
// λ©μΌ μ μ‘ | ||
mailUtil.sendMimeMessageMailWithValues(title, email, "EmailAuthenticationForm.html", mailValues); | ||
|
||
LocalDateTime expiredAt = LocalDateTime.now().plusMinutes(Constants.AUTH_TIME_LIMIT); | ||
|
||
MailVerification mailVerification = MailVerification.builder() | ||
.email(email) | ||
.expiredAt(expiredAt) | ||
.authenticationNumber(code) | ||
.build(); | ||
|
||
mailVerificationRepository.save(mailVerification); | ||
|
||
return ResponseCode.MAIL_VERIFICATION_SEND_SUCCESS; | ||
|
||
} | ||
|
||
|
||
// μΈμ¦ λ²νΈ νμΈ | ||
@Transactional | ||
public ResponseCode checkVerification(VerificationCodeRequestDto request) { | ||
|
||
// νμ¬ μ ν¨ν μΈμ¦ μ 보 κ°μ Έμ€κΈ° | ||
MailVerification mailVerification = mailVerificationRepository.findByEmailAndExpiredAtIsAfterNowAndVerifiedFalse(request.email(), LocalDateTime.now()) | ||
.orElseThrow( // μΈμ¦ μ λ³΄κ° μλ κ²½μ° | ||
()->new MailVerificationException(ResponseCode.AUTHENTICATION_NOT_FOUND) | ||
); | ||
|
||
// μΈμ¦ λ²νΈ μ ν¨ κΈ°κ°μ μ΄κ³Όν κ²½μ° | ||
if(LocalDateTime.now().isAfter(mailVerification.getExpiredAt())){ | ||
throw new MailVerificationException(ResponseCode.AUTH_TIME_OUT); | ||
} | ||
|
||
// μΈμ¦ λ²νΈκ° νλ¦° κ²½μ° | ||
if(!mailVerification.getAuthenticationNumber().equals(request.code())){ | ||
throw new MailVerificationException(ResponseCode.AUTH_NUMBER_INCORRECT); | ||
} | ||
|
||
// μΈμ¦μ μ±κ³΅ν κ²½μ°: μ ν μκ° λ΄μ μΈμ¦ λ²νΈλ₯Ό μ¬λ°λ₯΄κ² μ λ ₯ν κ²½μ° | ||
mailVerification.setVerified(true); | ||
mailVerificationRepository.save(mailVerification); | ||
|
||
return ResponseCode.MAIL_VERIFICATION_CHECK_SUCCESS; | ||
|
||
} | ||
|
||
// νμκ°μ μ μ΄λ©μΌ μ ν¨μ± νμΈ | ||
@Transactional(readOnly = true) | ||
public void checkUserName(String username) { | ||
if(accountRepository.existsByUsername(username)){ | ||
throw new DuplicateException(ResponseCode.EMAIL_DUPLICATION); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.