Skip to content

Commit

Permalink
feat: 이메일 인증을 완료한 사용자의 인증 상태를 변경하는 기능을 추가합니다. (#120)
Browse files Browse the repository at this point in the history
* release : 유저 서비스 내 이메일 중복 검증, 임시 회원가입, 회원가입 기능 추가 (#87)

* feat: init project

* fix: add multi platform (#39)

* feat : 회원가입 API를 추가합니다. (회원가입에 요구되는 서브 태스크인 이메일 중복확인 API도 함께 추가) (#60)

* feat : 유저 도메인 정의

* feat : 유저 서비스 내 글로벌 예외처리 추가

* refactor : 이메일 중복 DTO 수정

* feat : 인수/통합 테스트 템플릿 추가

* refactor : NoArgsConstructor 접근 제어자 변경

* refactor : 회원가입 쓰기 작업 시 Transactional 옵션 변경

* test : 회원가입 성공 인수 테스트 작성

* feat: set gradle project

* feat: create createUser interface

* feat: add generated ignore

* feat: set gRPC settings

* feat: add ports setting

* feat: create gRPC client method

* refactor : VO를 class에서 record로 변경

* refactor : create_social_user.proto 필드 네이밍 수정

* refactor : send_email_auth.proto 생성

* refactor : UserApi 엔드포인트 및 네이밍 변경

* refactor : 불필요한 파일 제거

* feat : 공통 환경 설정 및 패스워드 인코더 추가

* refactor : dto 패키지 변경

* feat : PasswordEncoder 인터페이스 추가

* feat : gRPC Client, Eureka 연동

* feat : 유저 임시 가입 유스케이스, 비즈니스 로직 추가

* refactor : 정적 컨텐츠 VO 래핑 추가

* refactor : 불필요한 테스트 제거

* fix : grpc import syntax in build.gradle

* refactor : 주석 제거

* refactor : GRPC -> Grpc 네이밍 변경

* refactor : application.yml 환경변수화

* refactor : User DDL 수정

* refactor : JoinRequest내 불필요한 필드 제거

* refactor : EurekaServiceName Enum 필드 Getter 추가

* refactor : User Entity Role 기본 값 추가

* refactor : Eureka Client defaultZone 수정

* refactor : Clean Broken Code

* fix: add builder (#86)

* feat: add envs (#91)

* fix : build.gradle (#92)

* refactor : build script (#94)

* feat: send_email_auth.proto, update_user_auth-status.proto

* refactor : GUpdateUserAuthStatusRequest 필드 수정

* refactor : GSendEmailAuthRequest Protobuf 필드 수정

* refactor : ExceptionType 수정

* refactor : gRPC Client AUTH-SERVICE 추가

* feat : AuthService -> UserService 인증상태 변경 기능 추가

* refactor : gRPC통신 간 예외처리 추가

* refactor : gRPC Client, Server 네이밍 변경

* refactor : gRPC Server 반환 구문 추가

* refactor : private method 래핑 해제

* refactor : 톰캣 및 gRPC서버 포트 변경

* refactor : typo

* refactor : broken typo and transactional

* refactor : eureka url

* refactor : 유레카 유틸라이저 제거

* refactor : 조건절 분기문 리팩터링

* refactor : 패스워드 유틸라이저
  • Loading branch information
K-Diger authored Jan 26, 2024
1 parent 9e0dd40 commit 516f3bc
Show file tree
Hide file tree
Showing 17 changed files with 142 additions and 91 deletions.
4 changes: 1 addition & 3 deletions src/common-module/src/main/proto/send_email_auth.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ service GAuthService {
}

message GSendEmailAuthRequest {
int64 id = 1;
string email = 2;
string nickname = 3;
string email = 1;
}

message GSendEmailAuthResponse {
Expand Down
16 changes: 16 additions & 0 deletions src/common-module/src/main/proto/update_user_auth-status.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
syntax = "proto3";

option java_multiple_files = true;
option java_package = "org.palette.grpc";

service GUserService {
rpc updateUserAuthStatus (GUpdateUserAuthStatusRequest) returns (GUpdateUserAuthStatusResponse) {}
}

message GUpdateUserAuthStatusRequest {
string email = 1;
}

message GUpdateUserAuthStatusResponse {
bool message = 1;
}
2 changes: 1 addition & 1 deletion src/user-service/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ repositories {
extra["springCloudVersion"] = "2023.0.0"

dependencies {
implementation ("net.devh:grpc-spring-boot-starter:2.15.0.RELEASE")
implementation("net.devh:grpc-spring-boot-starter:2.15.0.RELEASE")
implementation(project(":common-module"))

implementation("org.springframework.boot:spring-boot-starter-web")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.palette.easeluserservice.common;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class PasswordUtilizer {

private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

public static String hashPassword(String password) {
return encoder.encode(password);
}

public static boolean checkPassword(String rawPassword, String encodedPassword) {
return encoder.matches(rawPassword, encodedPassword);
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
package org.palette.easeluserservice.config;

import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@EnableDiscoveryClient
@EnableJpaAuditing
@EnableAsync
public class ApplicationConfig {

@Bean
public static BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,66 +9,59 @@
public enum ExceptionType {

// 400
USER_000001(
"USER_000001",
USER_400_000001(
"USER_400_000001",
"INCORRECT_PARAMETER",
"요청 파라미터가 올바르지 않습니다.",
HttpStatus.BAD_REQUEST
),

// 401
USER_000002(
"USER_000002",
USER_401_000001(
"USER_401_000001",
"MISSED AUTHENTICATION",
"해당 요청은 인증이 필요합니다.",
HttpStatus.UNAUTHORIZED
),

// 403
USER_000003(
"USER_000003",
USER_403_000001(
"USER_403_000001",
"NOT ALLOWED PERMISSION",
"해당 요청에 대한 권한이 없습니다.",
HttpStatus.FORBIDDEN
),


// 404
USER_000004(
"USER_000004",
USER_404_000001(
"USER_404_000001",
"NOT FOUNDED",
"해당 리소스가 존재하지 않습니다.",
HttpStatus.NOT_FOUND
),

// 405
USER_000005(
"USER_000005",
USER_405_000001(
"USER_403_000005",
"NOT ALLOWED METHOD",
"올바르지 않은 요청 메서드입니다.",
HttpStatus.METHOD_NOT_ALLOWED
),

// 409
USER_000006(
"USER_000006",
USER_409_000001(
"USER_409_000001",
"DUPLICATED",
"중복된 리소스가 있습니다.",
HttpStatus.CONFLICT
),

USER_000007(
"USER_000007",
"BROKEN_TOKEN",
"요청 토큰이 올바르지 않습니다.",
HttpStatus.BAD_REQUEST
),

USER_000008(
"USER_000008",
"EXPIRED_TOKEN",
"요청 토큰이 만료되었습니다.",
HttpStatus.FORBIDDEN
// 500
USER_500_000001(
"AUTH_500_000001",
"INTERNAL SERVER ERROR",
"서버 간 통신 중 예기치 못한 오류가 발생했습니다.",
HttpStatus.INTERNAL_SERVER_ERROR
),

;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class GlobalExceptionHandler {
MethodArgumentTypeMismatchException.class,
})
public ResponseEntity<ExceptionResponse> handleRequestValidationException(Exception e) {
ExceptionType exceptionType = ExceptionType.USER_000001;
ExceptionType exceptionType = ExceptionType.USER_404_000001;
ExceptionResponse exceptionResponse = ExceptionResponse.builder()
.code(exceptionType.getCode())
.message(exceptionType.getMessage())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,29 @@
package org.palette.easeluserservice.external;

import io.grpc.StatusRuntimeException;
import lombok.RequiredArgsConstructor;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.palette.easeluserservice.exception.BaseException;
import org.palette.easeluserservice.exception.ExceptionType;
import org.palette.easeluserservice.persistence.User;
import org.palette.grpc.GAuthServiceGrpc;
import org.palette.grpc.GSendEmailAuthRequest;
import org.palette.grpc.GSendEmailAuthResponse;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class GrpcAuth {
public class GrpcAuthClient {

@GrpcClient("auth-service")
private GAuthServiceGrpc.GAuthServiceBlockingStub gAuthServiceBlockingStub;

public GSendEmailAuthResponse sendEmailAuth(User user) {
// TODO: 매개변수 및 반환값 변경, 예외처리
public void sendEmailAuth(User user) {
try {
return gAuthServiceBlockingStub.sendEmailAuth(
gAuthServiceBlockingStub.sendEmailAuth(
GSendEmailAuthRequest.newBuilder()
.setId(user.getId())
.setEmail(user.getEmail())
.setNickname(user.getProfile().nickname())
.build()
);
} catch (final StatusRuntimeException e) {
System.out.println(e.getMessage());
return null;
throw new BaseException(ExceptionType.USER_500_000001);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.palette.easeluserservice.external;

import io.grpc.stub.StreamObserver;
import lombok.RequiredArgsConstructor;
import net.devh.boot.grpc.server.service.GrpcService;
import org.palette.easeluserservice.persistence.User;
import org.palette.easeluserservice.service.UserService;
import org.palette.grpc.GUpdateUserAuthStatusRequest;
import org.palette.grpc.GUpdateUserAuthStatusResponse;
import org.palette.grpc.GUserServiceGrpc;
import org.springframework.transaction.annotation.Transactional;

@GrpcService
@RequiredArgsConstructor
public class GrpcServerByAuthService extends GUserServiceGrpc.GUserServiceImplBase {

private final UserService userService;

@Transactional
@Override
public void updateUserAuthStatus(
GUpdateUserAuthStatusRequest request,
StreamObserver<GUpdateUserAuthStatusResponse> responseObserver
) {
User user = userService.loadByEmail(request.getEmail());

userService.updateUserAuthStatus(user);

GUpdateUserAuthStatusResponse response = GUpdateUserAuthStatusResponse.newBuilder()
.setMessage(true)
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@

import io.grpc.StatusRuntimeException;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.palette.easeluserservice.exception.BaseException;
import org.palette.easeluserservice.exception.ExceptionType;
import org.palette.easeluserservice.persistence.User;
import org.palette.grpc.GCreateUserRequest;
import org.palette.grpc.GCreateUserResponse;
import org.palette.grpc.GSocialServiceGrpc;
import org.springframework.stereotype.Component;

@Component
public class GrpcSocial {
public class GrpcSocialClient {

@GrpcClient("social-service")
private GSocialServiceGrpc.GSocialServiceBlockingStub gSocialServiceBlockingStub;

public GCreateUserResponse createSocialUser(User user) {
// TODO: 매개변수 및 반환값 변경, 예외처리
try {
return gSocialServiceBlockingStub.createUser(
GCreateUserRequest.newBuilder()
Expand All @@ -26,8 +27,7 @@ public GCreateUserResponse createSocialUser(User user) {
.setIsActive(user.getIsActivated())
.build());
} catch (final StatusRuntimeException e) {
System.out.println(e.getMessage());
return null;
throw new BaseException(ExceptionType.USER_500_000001);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ public class User {
@Column(name = "deleted_at")
private LocalDateTime deletedAt = null;

public void updateToAuthed() {
this.authed = true;
}

public Boolean isUserNotAuthed() {
return !this.getAuthed();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@

import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;

import static org.palette.easeluserservice.config.ApplicationConfig.bCryptPasswordEncoder;
import org.palette.easeluserservice.common.PasswordUtilizer;

@Embeddable
public record Password(
@Column(name = "password", nullable = false, length = 100)
String value
) {
public Password(String value) {
this.value = bCryptPasswordEncoder().encode(value);
this.value = PasswordUtilizer.hashPassword(value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,25 @@ public User createCompletedUser(
return user;
}

public void updateUserAuthStatus(User user) {
user.updateToAuthed();
}

public void isEmailAlreadyExists(String requestedEmail) {
if (userJpaRepository.existsByEmail(requestedEmail)) throw new BaseException(ExceptionType.USER_000006);
if (userJpaRepository.existsByEmail(requestedEmail)) {
throw new BaseException(ExceptionType.USER_409_000001);
}
}

public void isUsernameAlreadyExists(String requestedUsername) {
if (userJpaRepository.existsByUsername(requestedUsername)) throw new BaseException(ExceptionType.USER_000006);
if (userJpaRepository.existsByUsername(requestedUsername)) {
throw new BaseException(ExceptionType.USER_409_000001);
}
}

public Optional<User> loadByEmail(String email) {
return userJpaRepository.findByEmail(email);
public User loadByEmail(String email) {
return userJpaRepository.findByEmail(email).orElseThrow(() ->
new BaseException(ExceptionType.USER_404_000001)
);
}
}
Loading

0 comments on commit 516f3bc

Please sign in to comment.