-
Notifications
You must be signed in to change notification settings - Fork 1
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 #98 from JangYouJung/develop
[ Feature ] ์ด๋ฉ์ผ ์ธ์ฆ ๊ตฌํ ๋ฐ ์ฌ์ฉ์ ํ๋กํ ์ด๋ฏธ์ง ์ถ๊ฐ/์ญ์ ๊ตฌํ
- Loading branch information
Showing
21 changed files
with
457 additions
and
30 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,7 +34,6 @@ jobs: | |
port: 22 | ||
uploads: | | ||
./build/libs/ => /root/apache-tomcat-10.1.24/build-target/ | ||
- name: Change old WAR to new WAR | ||
uses: appleboy/[email protected] | ||
with: | ||
|
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 | ||
) { | ||
} |
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
14 changes: 14 additions & 0 deletions
14
src/main/java/meltingpot/server/domain/entity/Constants.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.domain.entity; | ||
|
||
public final class Constants { | ||
|
||
// ์ด๋ฉ์ผ ์ธ์ฆ ์๋ ์ ํ ํ์ | ||
public static final Integer LIMIT_ATTEMPT_COUNT = 5; | ||
|
||
// ์ด๋ฉ์ผ ์ธ์ฆ ์ ํ ์ฟจํ์ ์๊ฐ(๋ถ) | ||
public static final Integer COOL_TIME_MINUTE = 5; | ||
|
||
// ์ด๋ฉ์ผ ์ธ์ฆ ๋ฒํธ ํ์ธ ์ ํ ์๊ฐ(๋ถ) | ||
public static final Integer AUTH_TIME_LIMIT = 10; | ||
|
||
} |
Oops, something went wrong.