Skip to content

Commit

Permalink
Merge pull request #91 from Yanol-Market/feature/88
Browse files Browse the repository at this point in the history
Feature/88 상품등록을 위한 야놀자 로그인
  • Loading branch information
cyPark95 authored Jan 16, 2024
2 parents ee6e2c8 + 22d313d commit e2724ee
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 19 deletions.
14 changes: 14 additions & 0 deletions src/main/java/site/goldenticket/common/api/RestTemplateConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package site.goldenticket.common.api;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@Configurable
public class RestTemplateConfig {

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package site.goldenticket.common.api;

import java.util.Optional;

public interface RestTemplateService {

<T, R> Optional<T> get(String url, R request, Class<T> type);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package site.goldenticket.common.api;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import site.goldenticket.common.exception.CustomException;

import java.util.Optional;

import static org.springframework.http.MediaType.APPLICATION_JSON;
import static site.goldenticket.common.response.ErrorCode.COMMON_SYSTEM_ERROR;

@Slf4j
@Component
@RequiredArgsConstructor
public class RestTemplateServiceImpl implements RestTemplateService {

private final RestTemplate restTemplate;

@Override
public <T, R> Optional<T> get(String url, R request, Class<T> type) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(APPLICATION_JSON);
HttpEntity<R> entity = new HttpEntity<>(request, headers);

try {
return Optional.ofNullable(restTemplate.postForObject(url, entity, type));
} catch (HttpClientErrorException e) {
log.error("RestTemplate Get Exception Message = {}", e.getMessage());
return Optional.empty();
} catch (Exception e) {
log.error("RestTemplate Get Exception", e);
throw new CustomException(COMMON_SYSTEM_ERROR);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public enum ErrorCode {
// User
ALREADY_EXIST_EMAIL(BAD_REQUEST, "이미 사용중인 이메일입니다. 이미 가입하신 적이 있다면 로그인을 시도해주세요"),
ALREADY_EXIST_NICKNAME(BAD_REQUEST, "이미 사용중인 아이디입니다."),
NOT_FOUND_USER(BAD_REQUEST, "존재하지 않는 사용자입니다."),
ALREADY_REGISTER_YANOLJA_ID(BAD_REQUEST, "이미 등록된 야놀자 아이디가 존재합니다."),

// Reservation
RESERVATION_NOT_FOUND(NOT_FOUND, "예약 정보가 존재하지 않습니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
Expand All @@ -14,6 +15,7 @@
import java.util.List;

import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static site.goldenticket.common.response.ErrorCode.COMMON_JSON_PROCESSING_ERROR;
import static site.goldenticket.common.response.ErrorCode.COMMON_RESOURCE_NOT_FOUND;

@Slf4j
Expand All @@ -31,7 +33,7 @@ public ResponseEntity<CommonResponse<Void>> handleCustomException(CustomExceptio
);
}

@ExceptionHandler(MethodArgumentNotValidException.class)
@ExceptionHandler({MethodArgumentNotValidException.class})
public ResponseEntity<CommonResponse<Void>> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
log.error("[HandleMethodArgumentNotValidException]", e);
BindingResult bindingResult = e.getBindingResult();
Expand All @@ -53,6 +55,12 @@ public ResponseEntity<CommonResponse<Void>> handleNoResourceFoundException(NoRes
return ResponseEntity.badRequest().body(CommonResponse.error(COMMON_RESOURCE_NOT_FOUND.getMessage()));
}

@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<CommonResponse<Void>> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
log.error("[HttpMessageNotReadableException] Message = {}", e.getMessage());
return ResponseEntity.badRequest().body(CommonResponse.error(COMMON_JSON_PROCESSING_ERROR.getMessage()));
}

@ExceptionHandler(value = Exception.class)
public ResponseEntity<CommonResponse<Void>> handleException(Exception e) {
log.error("[Exception] Message = {}", e.getMessage(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import site.goldenticket.common.api.RestTemplateService;
import site.goldenticket.common.exception.CustomException;
import site.goldenticket.common.security.authentication.dto.AuthenticationToken;
import site.goldenticket.common.security.authentication.dto.LoginRequest;
Expand All @@ -22,7 +19,6 @@

import java.util.UUID;

import static org.springframework.http.MediaType.APPLICATION_JSON;
import static site.goldenticket.common.response.ErrorCode.LOGIN_FAIL;

@Slf4j
Expand All @@ -32,6 +28,7 @@ public class SecurityService implements UserDetailsService {

private final UserRepository userRepository;
private final TokenService tokenService;
private final RestTemplateService restTemplateService;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Expand All @@ -47,17 +44,11 @@ public AuthenticationToken reissue(ReissueRequest reissueRequest) {
}

public YanoljaUserResponse fetchYanoljaUser(LoginRequest loginRequest) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(APPLICATION_JSON);
HttpEntity<LoginRequest> request = new HttpEntity<>(loginRequest, headers);

try {
return restTemplate.postForObject("http://localhost:8080/dummy/yauser", request, YanoljaUserResponse.class);
} catch (HttpClientErrorException e) {
log.error("Yanolja API Connect Error Message = {}", e.getMessage());
throw new CustomException(LOGIN_FAIL);
}
return restTemplateService.get(
"http://localhost:8080/dummy/yauser",
loginRequest,
YanoljaUserResponse.class
).orElseThrow(() -> new CustomException(LOGIN_FAIL));
}

public AuthenticationToken generateToken(Long yanoljaId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import site.goldenticket.common.response.CommonResponse;
import site.goldenticket.common.security.authentication.dto.LoginRequest;
import site.goldenticket.domain.security.PrincipalDetails;
import site.goldenticket.domain.user.dto.JoinRequest;
import site.goldenticket.domain.user.dto.JoinResponse;
import site.goldenticket.domain.user.service.UserService;
Expand Down Expand Up @@ -33,4 +36,12 @@ public ResponseEntity<CommonResponse<JoinResponse>> join(@RequestBody @Validated
JoinResponse response = userService.join(joinRequest);
return new ResponseEntity<>(CommonResponse.ok(response), CREATED);
}

@PostMapping("/yanolja-login")
public ResponseEntity<CommonResponse<Long>> yanoljaLogin(
@RequestBody LoginRequest loginRequest,
@AuthenticationPrincipal PrincipalDetails principalDetails
) {
return ResponseEntity.ok(CommonResponse.ok(userService.yanoljaLogin(loginRequest, principalDetails.getUserId())));
}
}
12 changes: 12 additions & 0 deletions src/main/java/site/goldenticket/domain/user/entity/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@
import lombok.ToString;
import org.hibernate.annotations.SQLRestriction;
import site.goldenticket.common.entiy.BaseTimeEntity;
import site.goldenticket.common.exception.CustomException;

import java.util.Objects;

import static jakarta.persistence.CascadeType.ALL;
import static jakarta.persistence.EnumType.STRING;
import static jakarta.persistence.FetchType.LAZY;
import static jakarta.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PROTECTED;
import static site.goldenticket.common.response.ErrorCode.ALREADY_REGISTER_YANOLJA_ID;
import static site.goldenticket.domain.user.entity.RoleType.ROLE_USER;

@Getter
Expand Down Expand Up @@ -70,4 +74,12 @@ private User(
public void registerAlertSetting(Agreement agreement) {
this.agreement = agreement;
}

public void registerYanoljaId(Long yanoljaId) {
if (!Objects.isNull(this.yanoljaId)) {
throw new CustomException(ALREADY_REGISTER_YANOLJA_ID);
}

this.yanoljaId = yanoljaId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import site.goldenticket.common.api.RestTemplateService;
import site.goldenticket.common.exception.CustomException;
import site.goldenticket.common.security.authentication.dto.LoginRequest;
import site.goldenticket.domain.security.dto.YanoljaUserResponse;
import site.goldenticket.domain.user.dto.JoinRequest;
import site.goldenticket.domain.user.dto.JoinResponse;
import site.goldenticket.domain.user.entity.User;
import site.goldenticket.domain.user.repository.UserRepository;

import static site.goldenticket.common.response.ErrorCode.ALREADY_EXIST_EMAIL;
import static site.goldenticket.common.response.ErrorCode.ALREADY_EXIST_NICKNAME;
import static site.goldenticket.common.response.ErrorCode.*;

@Slf4j
@Service
Expand All @@ -22,6 +24,7 @@ public class UserService {

private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final RestTemplateService restTemplateService;

public boolean isExistEmail(String email) {
log.info("Duplicated Check Email = {}", email);
Expand All @@ -44,6 +47,14 @@ public JoinResponse join(JoinRequest joinRequest) {
return JoinResponse.from(user);
}

@Transactional
public Long yanoljaLogin(LoginRequest loginRequest, Long userId) {
YanoljaUserResponse yanoljaUser = getYanoljaUser(loginRequest);
User user = findById(userId);
user.registerYanoljaId(yanoljaUser.id());
return yanoljaUser.id();
}

private void joinValidate(JoinRequest joinRequest) {
if (isExistEmail(joinRequest.email())) {
throw new CustomException(ALREADY_EXIST_EMAIL);
Expand All @@ -53,4 +64,17 @@ private void joinValidate(JoinRequest joinRequest) {
throw new CustomException(ALREADY_EXIST_NICKNAME);
}
}

private YanoljaUserResponse getYanoljaUser(LoginRequest loginRequest) {
return restTemplateService.get(
"http://localhost:8080/dummy/yauser",
loginRequest,
YanoljaUserResponse.class
).orElseThrow(() -> new CustomException(LOGIN_FAIL));
}

private User findById(Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new CustomException(NOT_FOUND_USER));
}
}

0 comments on commit e2724ee

Please sign in to comment.