-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
184 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |