Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/TeamUStory/UStory-Backend
Browse files Browse the repository at this point in the history
…into develop
  • Loading branch information
GiJungPark committed Jul 5, 2024
2 parents 9ca4e6c + bda293d commit 5aa6b9a
Show file tree
Hide file tree
Showing 17 changed files with 96 additions and 62 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ jobs:
sudo docker pull ${{ secrets.DOCKER_REPO }}/ustory
sudo docker-compose up -d
sudo docker image prune -a -f
# sudo docker run --name github-actions-demo --rm -d -p 8080:8080 ${{ secrets.DOCKER_REPO }}/ustory


# NOTE: The Gradle Wrapper is the default and recommended way to run Gradle (https://docs.gradle.org/current/userguide/gradle_wrapper.html).
# If your project does not have the Gradle Wrapper configured, you can use the following configuration to run Gradle with a specified version.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.elice.ustory.domain.user.constant;

public class EmailMessageConstants {
public static final String NOT_FOUND_USER_EMAIL = "존재하지 않는 email입니다: %s";
public static final String EMAIL_VERIFICATION_SENT = "가입된 이메일이라면 인증코드가 발송됩니다.";
public static final String EMAIL_VERIFICATION_FAILED = "가입되지 않은 이메일이므로 메일이 발송되지 않았습니다. 보안을 위해, 사용자에게 해당 이메일의 가입 여부를 반환하지 않습니다.";
public static final String EMAIL_CODE_NOT_MATCH = "인증 코드 요청이 주어진 이메일이지만, 인증 코드가 일치하지 않습니다.";
public static final String EMAIL_CODE_VALID = "이메일과 인증 코드가 일치하여, 유효한 인증 코드로 검증되었습니다.";
public static final String EMAIL_CODE_NONE = "인증 코드 요청이 오지 않은 이메일입니다.";
public static final String EMAIL_CODE_NONE_DETAIL = "인증 코드 요청이 오지 않은 이메일입니다. 보안을 위해, 사용자에게 해당 이메일의 가입 여부를 반환하지 않습니다.";
public static final String EMAIL_IN_USE = "사용중인_이메일";
public static final String EMAIL_SOFT_DELETED = "탈퇴된_이메일";
public static final String SUCCESS = "SUCCESS";
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.elice.ustory.domain.user.entity;
package com.elice.ustory.domain.user.constant;

public class RegexPatterns {
public static final String EMAIL_REG = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.elice.ustory.domain.user.constant;

public class UserMessageConstants {
public static final String NOT_FOUND_USER_ID_MESSAGE = "존재하지 않는 userId입니다: %d";
public static final String NOT_FOUND_USER_EMAIL_MESSAGE = "존재하지 않는 email입니다: %s";
public static final String NOT_VALID_NICKNAME_MESSAGE = "사용할 수 없는 nickname입니다: %s";
public static final String DUPLICATE_EMAIL_MESSAGE = "이미 가입된 email입니다: %s";
public static final String NOT_CREATED_DIARY_MESSAGE = "다음의 email로 가입 중인 유저의, 개인 다이어리를 생성하는 과정에서 문제가 발생하였습니다. 가입 정보는 저장되지 않습니다: %s";
public static final String UNAUTHORIZED_MESSAGE = "헤더에 토큰이 입력되지 않았습니다.";
public static final String NOT_VALID_PASSWORD_MESSAGE = "비밀번호 확인이 일치하지 않습니다.";
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ public ResponseEntity<ValidateNicknameResponse> validateNickname(@Valid @Request
return ResponseEntity.ok(validateNicknameResponse);
}

@Operation(summary = "Send Mail To Validate Email For Sign-Up API", description = "회원가입 시 이메일 검증을 위한 인증코드를 해당 메일로 발송한다. 이미 가입된 이메일인 경우 예외 발생.")
@Operation(summary = "Send Mail To Validate Email For Sign-Up API",
description = "회원가입 시 이메일 검증을 위한 인증코드를 해당 메일로 발송한다. 이미 가입된 이메일인 경우 예외 발생." +
"<br>detailMessage는 둘 중 하나: '사용중인\\_이메일' 또는 '탈퇴된\\_이메일'")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Ok", content = @Content(mediaType = "application/json", schema = @Schema(implementation = AuthCodeCreateResponse.class))),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.elice.ustory.domain.user.dto;

import com.elice.ustory.domain.user.entity.RegexPatterns;
import com.elice.ustory.domain.user.constant.RegexPatterns;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Pattern;
import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.elice.ustory.domain.user.dto;

import com.elice.ustory.domain.user.entity.RegexPatterns;
import com.elice.ustory.domain.user.constant.RegexPatterns;
import jakarta.validation.constraints.Pattern;
import lombok.Data;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.elice.ustory.domain.user.dto;

import com.elice.ustory.domain.user.entity.RegexPatterns;
import com.elice.ustory.domain.user.constant.RegexPatterns;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.*;
import lombok.Data;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.elice.ustory.domain.user.dto;

import com.elice.ustory.domain.user.entity.RegexPatterns;
import jakarta.validation.constraints.Pattern;
import lombok.Data;

@Data
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.elice.ustory.domain.user.dto.auth;

import com.elice.ustory.domain.user.entity.RegexPatterns;
import com.elice.ustory.domain.user.constant.RegexPatterns;
import jakarta.validation.constraints.Pattern;
import lombok.*;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.elice.ustory.domain.user.dto.auth;

import com.elice.ustory.domain.user.entity.RegexPatterns;
import com.elice.ustory.domain.user.constant.RegexPatterns;
import jakarta.validation.constraints.Pattern;
import lombok.AllArgsConstructor;
import lombok.Builder;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.elice.ustory.domain.user.dto.auth;

import com.elice.ustory.domain.user.entity.RegexPatterns;
import com.elice.ustory.domain.user.constant.RegexPatterns;
import jakarta.validation.constraints.Pattern;
import lombok.Getter;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.elice.ustory.domain.user.dto.auth;

import com.elice.ustory.domain.user.entity.RegexPatterns;
import com.elice.ustory.domain.user.constant.RegexPatterns;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Pattern;
import lombok.Getter;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

import com.elice.ustory.domain.user.entity.Users;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
Expand All @@ -13,4 +14,9 @@ public interface UserRepository extends JpaRepository<Users, Long> {
Optional<Users> findByEmail(String loginEmail);
boolean existsByEmail(String loginEmail);

@Query(value = "SELECT COUNT(*) FROM users u WHERE u.email = :email", nativeQuery = true)
int countByEmailWithSoftDeleted(@Param("email") String email);

@Query(value = "SELECT COUNT(*) FROM users u WHERE u.nickname = :nickname", nativeQuery = true)
int countByNicknameWithSoftDeleted(@Param("nickname") String nickname);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.elice.ustory.domain.user.service;

import com.elice.ustory.domain.user.constant.EmailMessageConstants;
import com.elice.ustory.domain.user.dto.auth.*;
import com.elice.ustory.domain.user.entity.EmailConfig;
import com.elice.ustory.domain.user.entity.Users;
import com.elice.ustory.domain.user.repository.UserRepository;
import com.elice.ustory.global.exception.model.ConflictException;
import com.elice.ustory.global.exception.model.NotFoundException;
import com.elice.ustory.global.exception.model.ValidationException;
import com.elice.ustory.global.jwt.JwtTokenProvider;
import com.elice.ustory.global.redis.email.AuthCode;
import com.elice.ustory.global.redis.email.AuthCodeForChangePwd;
Expand All @@ -32,6 +33,7 @@ public class EmailService {
private final AuthCodeRepository authCodeRepository;
private final AuthCodeForChangePwdRepository authCodeForChangePwdRepository;
private final EmailConfig emailConfig;

private String fromEmail;

@PostConstruct
Expand Down Expand Up @@ -65,8 +67,10 @@ public void sendMail(String toEmail, String title, String content) throws Messag

public AuthCodeCreateResponse sendValidateSignupMail(String toEmail) throws MessagingException {
// 0. 이메일 중복 체크
if (validateEmail(toEmail).getIsSuccess() == false) {
throw new ValidationException("이미 가입된 이메일입니다.");

EmailVerifyResponse emailVerifyResponse = validateEmail(toEmail);
if (emailVerifyResponse.getIsSuccess() == false) {
throw new ConflictException(emailVerifyResponse.getStatus());
};

// 1. 메일 내용 생성
Expand Down Expand Up @@ -115,17 +119,17 @@ public AuthCodeVerifyResponse verifySignupAuthCode(AuthCodeVerifyRequest authCod
if (!foundAuthCode.equals(givenAuthCode)) {
return AuthCodeVerifyResponse.builder()
.isValid(false)
.message("인증 코드 요청이 주어진 이메일이지만, 인증 코드가 일치하지 않습니다.")
.message(EmailMessageConstants.EMAIL_CODE_NOT_MATCH)
.build();
}
return AuthCodeVerifyResponse.builder()
.isValid(true)
.message("이메일과 인증 코드가 일치하여, 유효한 인증 코드로 검증되었습니다.")
.message(EmailMessageConstants.EMAIL_CODE_VALID)
.build();
} else {
return AuthCodeVerifyResponse.builder()
.isValid(false)
.message("인증 코드 요청이 오지 않은 이메일입니다.")
.message(EmailMessageConstants.EMAIL_CODE_NONE)
.build();
}
}
Expand All @@ -134,13 +138,21 @@ public EmailVerifyResponse validateEmail(String email) {
if (userRepository.existsByEmail(email)) {
return EmailVerifyResponse.builder()
.isSuccess(false)
.status("EMAIL_DUPLICATE")
.status(EmailMessageConstants.EMAIL_IN_USE)
.build();
}

int emailCountWithSoftDeleted = userRepository.countByEmailWithSoftDeleted(email);
if (emailCountWithSoftDeleted > 0) {
return EmailVerifyResponse.builder()
.isSuccess(false)
.status(EmailMessageConstants.EMAIL_SOFT_DELETED)
.build();
}

return EmailVerifyResponse.builder()
.isSuccess(true)
.status("SUCCESS")
.status(EmailMessageConstants.SUCCESS)
.build();
}

Expand All @@ -149,9 +161,9 @@ public ChangePwdCallResponse sendValidateUserMailForPwd(ChangePwdCallRequest cha
String toEmail = changePwdCallRequest.getToEmail();
if (!userRepository.existsByEmail(toEmail)) {
return ChangePwdCallResponse.builder()
.message("가입된 이메일이라면 인증코드가 발송됩니다.")
.message(EmailMessageConstants.EMAIL_VERIFICATION_SENT)
.fromEmail(null)
.toEmail("가입되지 않은 이메일이므로 메일이 발송되지 않았습니다. 보안을 위해, 사용자에게 해당 이메일의 가입 여부를 반환하지 않습니다.")
.toEmail(EmailMessageConstants.EMAIL_VERIFICATION_FAILED)
.title(null)
.authCode(null)
.build();
Expand Down Expand Up @@ -182,7 +194,7 @@ public ChangePwdCallResponse sendValidateUserMailForPwd(ChangePwdCallRequest cha

// 4. api 결괏값 반환
return ChangePwdCallResponse.builder()
.message("가입된 이메일이라면 인증코드가 발송됩니다.")
.message(EmailMessageConstants.EMAIL_VERIFICATION_SENT)
.fromEmail(fromEmail)
.toEmail(toEmail)
.title(title)
Expand All @@ -206,21 +218,21 @@ public ChangePwdVerifyResponse verifyChangePwdCode(ChangePwdVerifyRequest change
} else {
// jwt 발급 시작: 이메일 인증 성공 시, 비밀번호 재설정을 위한 임시 토큰 발급
Users currentUser = userRepository.findByEmail(toMail)
.orElseThrow(() -> new NotFoundException("사용자를 찾을 수 없습니디"));
.orElseThrow(() -> new NotFoundException(String.format(EmailMessageConstants.NOT_FOUND_USER_EMAIL, toMail)));
Long userId = currentUser.getId();
String accessToken = jwtTokenProvider.createAccessToken(userId);
// jwt 발급 끝

return ChangePwdVerifyResponse.builder()
.accessToken(accessToken)
.isValid(true)
.message("이메일과 인증 코드가 일치하여, 유효한 인증 코드로 검증되었습니다.")
.message(EmailMessageConstants.EMAIL_CODE_VALID)
.build();
}
} else {
return ChangePwdVerifyResponse.builder()
.isValid(false)
.message("인증 코드 요청이 오지 않은 이메일입니다. 보안을 위해, 사용자에게 해당 이메일의 가입 여부를 반환하지 않습니다.")
.message(EmailMessageConstants.EMAIL_CODE_NONE_DETAIL)
.build();
}
}
Expand Down
Loading

0 comments on commit 5aa6b9a

Please sign in to comment.