Skip to content

Commit

Permalink
#32 [feat] : 유저 온보딩 API를 추가한다
Browse files Browse the repository at this point in the history
  • Loading branch information
bbbang105 committed Sep 18, 2024
1 parent 354af2a commit e613f8f
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/main/java/side/onetime/controller/UserController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package side.onetime.controller;

import lombok.RequiredArgsConstructor;
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;
import side.onetime.dto.UserDto;
import side.onetime.global.common.ApiResponse;
import side.onetime.global.common.constant.SuccessStatus;
import side.onetime.service.UserService;

@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;

// 유저 온보딩 API
@PostMapping("/onboarding")
public ResponseEntity<ApiResponse<UserDto.OnboardUserResponse>> onboardUser(
@RequestBody UserDto.OnboardUserRequest onboardUserRequest) {

UserDto.OnboardUserResponse onboardUserResponse = userService.onboardUser(onboardUserRequest);
return ApiResponse.onSuccess(SuccessStatus._ONBOARD_USER, onboardUserResponse);
}
}
39 changes: 39 additions & 0 deletions src/main/java/side/onetime/domain/User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package side.onetime.domain;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import side.onetime.global.common.dao.BaseEntity;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Table(name = "users")
public class User extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "users_id")
private Long id;

@Column(name = "name", nullable = false, length = 50)
private String name;

@Column(name = "nickname", nullable = false, length = 10)
private String nickname;

@Column(name = "provider", nullable = false, length = 50)
private String provider;

@Column(name = "provider_id", nullable = false, length = 50)
private String providerId;

@Builder
public User(String name, String nickname, String provider, String providerId) {
this.name = name;
this.nickname = nickname;
this.provider = provider;
this.providerId = providerId;
}
}
40 changes: 40 additions & 0 deletions src/main/java/side/onetime/dto/UserDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package side.onetime.dto;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

public class UserDto {
@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class OnboardUserRequest {
private String registerToken;
private String nickname;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class OnboardUserResponse {
private String accessToken;
private String refreshToken;

public static OnboardUserResponse of(String accessToken, String refreshToken) {
return OnboardUserResponse.builder()
.accessToken(accessToken)
.refreshToken(refreshToken)
.build();
}
}
}
12 changes: 12 additions & 0 deletions src/main/java/side/onetime/repository/UserRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package side.onetime.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import side.onetime.domain.User;

import java.util.Optional;

public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findById(Long id);

User findByProviderId(String providerId);
}
65 changes: 65 additions & 0 deletions src/main/java/side/onetime/service/UserService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package side.onetime.service;

import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import side.onetime.domain.RefreshToken;
import side.onetime.domain.User;
import side.onetime.dto.UserDto;
import side.onetime.exception.UserErrorResult;
import side.onetime.exception.UserException;
import side.onetime.repository.RefreshTokenRepository;
import side.onetime.repository.UserRepository;
import side.onetime.util.JwtUtil;

@Service
@RequiredArgsConstructor
public class UserService {

private static final int NICKNAME_LENGTH_LIMIT = 10;

@Value("${jwt.access-token.expiration-time}")
private long ACCESS_TOKEN_EXPIRATION_TIME; // 액세스 토큰 유효기간

@Value("${jwt.refresh-token.expiration-time}")
private long REFRESH_TOKEN_EXPIRATION_TIME; // 리프레쉬 토큰 유효기간

private final RefreshTokenRepository refreshTokenRepository;
private final UserRepository userRepository;
private final JwtUtil jwtUtil;

// 유저 온보딩 메서드
@Transactional
public UserDto.OnboardUserResponse onboardUser(UserDto.OnboardUserRequest onboardUserRequest) {
// 레지스터 토큰을 이용하여 사용자 정보 추출
String registerToken = onboardUserRequest.getRegisterToken();
String provider = jwtUtil.getProviderFromToken(registerToken);
String providerId = jwtUtil.getProviderIdFromToken(registerToken);
String name = jwtUtil.getNameFromToken(registerToken);

if (onboardUserRequest.getNickname().length() > NICKNAME_LENGTH_LIMIT) {
throw new UserException(UserErrorResult._NICKNAME_TOO_LONG);
}

User user = User.builder()
.name(name)
.nickname(onboardUserRequest.getNickname())
.provider(provider)
.providerId(providerId)
.build();
userRepository.save(user);
Long userId = user.getId();

// 액세스 & 리프레쉬 토큰 발급
String accessToken = jwtUtil.generateAccessToken(userId, ACCESS_TOKEN_EXPIRATION_TIME);
String refreshToken = jwtUtil.generateRefreshToken(userId, REFRESH_TOKEN_EXPIRATION_TIME);

// 새로운 리프레쉬 토큰 Redis 저장
RefreshToken newRefreshToken = new RefreshToken(userId, refreshToken);
refreshTokenRepository.save(newRefreshToken);

// 액세스 토큰 반환
return UserDto.OnboardUserResponse.of(accessToken, refreshToken);
}
}

0 comments on commit e613f8f

Please sign in to comment.