Skip to content

Commit

Permalink
Merge pull request #10 from Hey-Porori/setting
Browse files Browse the repository at this point in the history
�Feat: 토큰 재발급 API 추가
  • Loading branch information
minsu20 authored Aug 12, 2023
2 parents 6b6a700 + 7a7f869 commit 6b97cef
Show file tree
Hide file tree
Showing 25 changed files with 606 additions and 295 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package porori.backend.user.domain.user.application.dto.res;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import porori.backend.user.global.dto.TokenInfoResponse;

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ReissueTokenResponse {

private String accessToken;
private String refreshToken;

public static ReissueTokenResponse from(TokenInfoResponse tokenInfoResponse) {
return ReissueTokenResponse.builder()
.accessToken(tokenInfoResponse.getAccessToken())
.refreshToken(tokenInfoResponse.getRefreshToken())
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,13 @@ public class UserResponseDto {
public static class LoginResponse {
private String accessToken;
private String refreshToken;
private Long userId;
private String process;
private boolean registrationStatus;

public static LoginResponse from(TokenInfoResponse tokenInfoResponse, String process, Long userId) {
public static LoginResponse from(TokenInfoResponse tokenInfoResponse, boolean registrationStatus) {
return LoginResponse.builder()
.accessToken(tokenInfoResponse.getAccessToken())
.refreshToken(tokenInfoResponse.getRefreshToken())
.process(process)
.userId(userId)
.registrationStatus(registrationStatus)
.build();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package porori.backend.user.domain.user.application.service;


import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import porori.backend.user.domain.user.application.dto.res.ReissueTokenResponse;
import porori.backend.user.global.config.security.exception.NotFoundRefreshTokenException;
import porori.backend.user.global.config.security.jwt.TokenUtil;
import porori.backend.user.global.dto.TokenInfoResponse;

import javax.transaction.Transactional;

@Service
@Transactional
@RequiredArgsConstructor
public class ReissueTokenService {

private final TokenUtil tokenUtil;

public ReissueTokenResponse reissueToken(String token) {
// refresh 토큰이 유효한지 확인
if (token != null && tokenUtil.verifyToken(token)) {

// 토큰 새로 받아오기
TokenInfoResponse newToken = tokenUtil.tokenReissue(token);

return ReissueTokenResponse.from(newToken);
}
throw new NotFoundRefreshTokenException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,20 @@
import porori.backend.user.domain.user.domain.entity.User;
import porori.backend.user.domain.user.domain.service.UserQueryService;
import porori.backend.user.domain.user.domain.service.UserValidationService;
import porori.backend.user.global.config.security.jwt.TokenProvider;
import porori.backend.user.global.config.security.jwt.TokenUtil;

import javax.transaction.Transactional;

@Service
@RequiredArgsConstructor
@Transactional
public class UserInfoService {
private final TokenProvider tokenProvider;
private final TokenUtil tokenUtil;
private final UserValidationService userValidationService;
private final UserQueryService userQueryService;

public UserResponseDto.GetUserInfoResponse getUserInfo(UserRequestDto.GetUserInfoRequest getUserInfoRequest) {
Authentication authentication = tokenProvider.getAuthentication(getUserInfoRequest.getAccessToken());
User user = userValidationService.validateAppleId(authentication.getName());
public UserResponseDto.GetUserInfoResponse getUserInfo(String appleId) {
User user = userValidationService.validateAppleId(appleId);
return UserResponseDto.GetUserInfoResponse.from(user);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import porori.backend.user.domain.user.application.dto.res.UserResponseDto;
import porori.backend.user.domain.user.application.mapper.UserMapper;
import porori.backend.user.domain.user.domain.entity.User;
import porori.backend.user.domain.user.domain.entity.UserConstant;
import porori.backend.user.domain.user.domain.service.UserSaveService;
import porori.backend.user.domain.user.domain.service.UserValidationService;
import porori.backend.user.global.config.security.jwt.TokenProvider;
import porori.backend.user.global.config.security.jwt.TokenUtil;
import porori.backend.user.global.config.security.utils.AuthenticationUtil;
import porori.backend.user.global.dto.TokenInfoResponse;
import porori.backend.user.global.exception.ConnException;

Expand All @@ -30,36 +32,37 @@ public class UserLoginService {
private final UserSaveService userSaveService;
private final UserValidationService userValidationService;

private final TokenProvider tokenProvider;
private final TokenUtil tokenUtil;
public final UserMapper userMapper;

public UserResponseDto.LoginResponse login(UserRequestDto.LoginRequest loginRequest) {
//1. 프론트에게 받은 액세스 토큰 이용해서 사용자 정보 가져오기
String token = loginRequest.getToken();
String appleId = appleService.verifyIdentityToken(token).orElseThrow(() -> new ConnException());
User user = userSaveService.saveUser(appleId);
boolean isSignedUp = user.getNickName() != null;
boolean registrationStatus = user.getRegistrationStatus().equals(UserConstant.RegistrationStatus.COMPLETED);
//3. security 처리
AuthenticationUtil.makeAuthentication(user);
//4. token 만들기
TokenInfoResponse tokenResponse = tokenUtil.createToken(user, registrationStatus);
//5. refresh token 저장
tokenUtil.storeRefreshToken(user.getAppleId(), tokenResponse);

//2. 스프링 시큐리티 처리
List<GrantedAuthority> authorities = userMapper.initAuthorities();
OAuth2User userDetails = userMapper.createOAuth2UserByApple(authorities, appleId);
OAuth2AuthenticationToken auth = userMapper.configureAuthentication(userDetails, authorities);

//3. JWT 토큰 생성
TokenInfoResponse tokenInfoResponse = tokenProvider.createToken(auth, isSignedUp, user.getUserId());
return UserResponseDto.LoginResponse.from(tokenInfoResponse, isSignedUp ? LOGIN_SUCCESS.getMessage() : SIGN_UP_ING.getMessage(), user.getUserId());
return UserResponseDto.LoginResponse.from(tokenResponse, registrationStatus);
}


public UserResponseDto.LoginResponse testLogin(UserRequestDto.TestLoginRequest testLoginRequest) {
User user = userValidationService.validateAppleId(testLoginRequest.getAppleId());

boolean registrationStatus = user.getRegistrationStatus().equals(UserConstant.RegistrationStatus.COMPLETED);
//3. security 처리
AuthenticationUtil.makeAuthentication(user);
//4. token 만들기
TokenInfoResponse tokenResponse = tokenUtil.createToken(user, registrationStatus);
//5. refresh token 저장
tokenUtil.storeRefreshToken(user.getAppleId(), tokenResponse);

List<GrantedAuthority> authorities = userMapper.initAuthorities();
OAuth2User userDetails = userMapper.createOAuth2UserByUser(authorities, user);
OAuth2AuthenticationToken auth = userMapper.configureAuthentication(userDetails, authorities);

TokenInfoResponse tokenInfoResponse = tokenProvider.createToken(auth, true, user.getUserId());
return UserResponseDto.LoginResponse.from(tokenInfoResponse, LOGIN_SUCCESS.getMessage(), user.getUserId());
return UserResponseDto.LoginResponse.from(tokenResponse, registrationStatus);
}
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
package porori.backend.user.domain.user.application.service;

import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;
import porori.backend.user.domain.user.application.dto.req.UserRequestDto;
import porori.backend.user.domain.user.application.dto.res.UserResponseDto;
import porori.backend.user.domain.user.application.mapper.UserMapper;
import porori.backend.user.domain.user.domain.entity.User;
import porori.backend.user.domain.user.domain.entity.UserConstant.RegistrationStatus;
import porori.backend.user.domain.user.domain.service.UserSaveService;
import porori.backend.user.domain.user.domain.service.UserValidationService;
import porori.backend.user.global.config.security.jwt.TokenProvider;
import porori.backend.user.global.config.security.jwt.TokenUtil;
import porori.backend.user.global.config.security.utils.AuthenticationUtil;
import porori.backend.user.global.dto.TokenInfoResponse;

import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static porori.backend.user.domain.user.domain.entity.UserConstant.Role.ROLE_USER;
import static porori.backend.user.domain.user.presentation.constant.Process.LOGIN_SUCCESS;

@Service
@RequiredArgsConstructor
Expand All @@ -35,39 +23,39 @@ public class UserSignUpService {
private final UserAppleService appleService;
private final UserSaveService userSaveService;
private final UserValidationService userValidationService;
private final TokenProvider tokenProvider;
private final TokenUtil tokenUtil;
private final AuthenticationUtil authenticationUtil;
private final UserMapper userMapper;

public UserResponseDto.LoginResponse signup(UserRequestDto.AdditionInfoRequest additionInfoRequest) {
//추가 정보 입력 시
//1. 프론트엔드에게 받은 (자체) 액세스 토큰 이용해서 사용자 이메일 가져오기
Authentication authentication = tokenProvider.getAuthentication(additionInfoRequest.getAccessToken());
User user = userValidationService.validateAppleId(authentication.getName());

//2. 추가 정보 저장
user.signup(additionInfoRequest.getName(), additionInfoRequest.getNickName(), additionInfoRequest.getPhoneNumber(), additionInfoRequest.getGender(), additionInfoRequest.getAddress(), additionInfoRequest.getImageUrl(), additionInfoRequest.getEmail());
userSaveService.saveUser(user);

//3. 스프링 시큐리티 처리
List<GrantedAuthority> authorities = userMapper.initAuthorities();
OAuth2User userDetails = userMapper.createOAuth2UserByUser(authorities, user);
OAuth2AuthenticationToken auth = userMapper.configureAuthentication(userDetails, authorities);

//4. JWT 토큰 생성
TokenInfoResponse tokenInfoResponse = tokenProvider.createToken(auth, true, user.getUserId());
return UserResponseDto.LoginResponse.from(tokenInfoResponse, LOGIN_SUCCESS.getMessage(), user.getUserId());
//1. 유저 찾기
String socialId = tokenUtil.getAppleId(additionInfoRequest.getAccessToken());
User user = userValidationService.validateAppleId(socialId);
//2. signUp 처리
user.signup(additionInfoRequest);
//3. security 처리
AuthenticationUtil.makeAuthentication(user);
//4. token 만들기
TokenInfoResponse tokenResponse = tokenUtil.createToken(user, true);
//5. refresh token 저장
tokenUtil.storeRefreshToken(user.getAppleId(), tokenResponse);

return UserResponseDto.LoginResponse.from(tokenResponse, true);
}

public UserResponseDto.LoginResponse testSignUp(UserRequestDto.TestSignUpRequest signUpRequest) {
User user=new User(signUpRequest);
User user = new User(signUpRequest);
user.updateRegistrationStatus();
userSaveService.saveUser(user);

List<GrantedAuthority> authorities = userMapper.initAuthorities();
OAuth2User userDetails = userMapper.createOAuth2UserByUser(authorities, user);
OAuth2AuthenticationToken auth = userMapper.configureAuthentication(userDetails, authorities);

TokenInfoResponse tokenInfoResponse = tokenProvider.createToken(auth, true, user.getUserId());
return UserResponseDto.LoginResponse.from(tokenInfoResponse, LOGIN_SUCCESS.getMessage(), user.getUserId());
//2. signUp 처리;
//3. security 처리
AuthenticationUtil.makeAuthentication(user);
//4. token 만들기
TokenInfoResponse tokenResponse = tokenUtil.createToken(user, true);
//5. refresh token 저장
tokenUtil.storeRefreshToken(user.getAppleId(), tokenResponse);

return UserResponseDto.LoginResponse.from(tokenResponse, true);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import porori.backend.user.domain.user.application.dto.req.UserRequestDto;
import porori.backend.user.domain.user.domain.entity.UserConstant.RegistrationStatus;
import porori.backend.user.domain.user.domain.entity.UserConstant.Role;

import javax.persistence.*;
Expand Down Expand Up @@ -32,6 +33,9 @@ public class User {
private Role role;
private boolean withdrawalStatus;

@Enumerated(EnumType.STRING)
private RegistrationStatus registrationStatus;

@Builder
public User(String appleId, Role role) {
this.appleId = appleId;
Expand All @@ -51,14 +55,19 @@ public User(UserRequestDto.TestSignUpRequest signUpRequest) {
this.role=Role.ROLE_USER;
}

public void signup(String name, String nickName, String phoneNumber, boolean gender, String address, String imageUrl, String email) {
this.name = name;
this.nickName = nickName;
this.phoneNumber = phoneNumber;
this.gender = gender;
this.address = address;
this.imageUrl = imageUrl;
this.email = email;
public void signup(UserRequestDto.AdditionInfoRequest additionInfoRequest) {
this.name = additionInfoRequest.getName();
this.nickName = additionInfoRequest.getNickName();
this.phoneNumber = additionInfoRequest.getPhoneNumber();
this.gender = additionInfoRequest.getGender();
this.address = additionInfoRequest.getAddress();
this.imageUrl = additionInfoRequest.getImageUrl();
this.email = additionInfoRequest.getEmail();
this.registrationStatus=RegistrationStatus.COMPLETED;
}

public void updateRegistrationStatus(){
this.registrationStatus=RegistrationStatus.COMPLETED;
}

public void withdraw(){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,9 @@ public class UserConstant {
public enum Role {
ROLE_USER, ROLE_ADMIN
}

@Getter
public enum RegistrationStatus {
COMPLETED, UNCOMPLETED;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import porori.backend.user.domain.user.application.dto.req.UserRequestDto.*;
import porori.backend.user.domain.user.application.dto.res.ReissueTokenResponse;
import porori.backend.user.domain.user.application.dto.res.UserResponseDto;
import porori.backend.user.domain.user.application.dto.res.UserResponseDto.LoginResponse;
import porori.backend.user.domain.user.application.service.UserDeleteService;
import porori.backend.user.domain.user.application.service.UserInfoService;
import porori.backend.user.domain.user.application.service.UserLoginService;
import porori.backend.user.domain.user.application.service.UserSignUpService;
import porori.backend.user.domain.user.application.service.*;
import porori.backend.user.global.config.security.dto.CustomUser;
import porori.backend.user.global.dto.ResponseDto;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import static porori.backend.user.domain.user.presentation.constant.EUserResponseMessage.*;
Expand All @@ -30,9 +31,10 @@ public class UserController {
private final UserSignUpService userSignUpService;
private final UserDeleteService userDeleteService;
private final UserInfoService userInfoService;
private final ReissueTokenService reissueTokenService;


@ApiOperation(value = "애플 로그인", notes = "애ㅇ 로그인을 합니다.")
@ApiOperation(value = "애플 로그인", notes = "애플 로그인을 합니다.")
@PostMapping("/auth/apple")
public ResponseEntity<ResponseDto<LoginResponse>> login(@Valid @RequestBody LoginRequest loginRequest) {
return ResponseEntity.ok(ResponseDto.create(HttpStatus.OK.value(), LOGIN_SUCCESS.getMessage(), this.userLoginService.login(loginRequest)));
Expand All @@ -54,9 +56,10 @@ public ResponseEntity<ResponseDto> delete(@Valid @RequestBody DeleteAccountReque


@ApiOperation(value = "사용자 정보 보기", notes = "사용자 정보를 확인합니다.")
@PostMapping("/token/me")
public ResponseEntity<ResponseDto<UserResponseDto.GetUserInfoResponse>> getUserInfo(@Valid @RequestBody GetUserInfoRequest getUserInfoRequest) {
return ResponseEntity.ok(ResponseDto.create(HttpStatus.OK.value(), GET_USERINFO_SUCCESS.getMessage(),userInfoService.getUserInfo(getUserInfoRequest)));
@GetMapping("/token/me")
public ResponseEntity<ResponseDto<UserResponseDto.GetUserInfoResponse>> getUserInfo(
@AuthenticationPrincipal CustomUser customUser) {
return ResponseEntity.ok(ResponseDto.create(HttpStatus.OK.value(), GET_USERINFO_SUCCESS.getMessage(),userInfoService.getUserInfo(customUser.getAppleId())));
}

@ApiOperation(value = "(테스트)회원가입", notes = "회원가입을 합니다")
Expand All @@ -79,8 +82,20 @@ public ResponseEntity<ResponseDto<LoginResponse>> jwtTokenTest() {

@ApiOperation(value="커뮤니티 회원 정보 보기" , notes="커뮤니티 회원 정보 보기")
@PostMapping("/communities/info")
public ResponseEntity<ResponseDto<UserResponseDto.GetCommunityUserInfoResponse>> getCommunityUserInfo(@Valid @RequestBody GetCommunityUserInfoRequest getCommunityUserInfoRequest){
public ResponseEntity<ResponseDto<UserResponseDto.GetCommunityUserInfoResponse>> getCommunityUserInfo(
@Valid @RequestBody GetCommunityUserInfoRequest getCommunityUserInfoRequest){
return ResponseEntity.ok(ResponseDto.create(HttpStatus.OK.value(), GET_COMMUNITY_USERINFO_SUCCESS.getMessage(), this.userInfoService.getCommunityUserInfo(getCommunityUserInfoRequest)));
}

@GetMapping("/reissue")
public ResponseEntity<ResponseDto<ReissueTokenResponse>> reissue(HttpServletRequest request) {

// 헤더로부터 RefreshToken 추출.
String token = request.getHeader("RefreshToken");
// 토큰 재발행
ReissueTokenResponse reissueToken = reissueTokenService.reissueToken(token);

return ResponseEntity.ok(ResponseDto.create(HttpStatus.OK.value(), REISSUE_TOKEN_SUCCESS.getMessage(), reissueToken));
}
}

Loading

0 comments on commit 6b97cef

Please sign in to comment.