Skip to content

Commit

Permalink
Merge pull request #47 from onetime-with-members/feature/#37/mypage
Browse files Browse the repository at this point in the history
[feat] : 마이페이지에서 유저 정보를 확인 및 수정할 수 있다
  • Loading branch information
bbbang105 authored Sep 29, 2024
2 parents d954a24 + 747be17 commit 4540385
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private void handleAuthentication(HttpServletRequest request, HttpServletRespons

if (existUser == null) {
// 신규 유저 처리
handleNewUser(request, response, provider, providerId, name);
handleNewUser(request, response, provider, providerId, name, email);
} else {
// 기존 유저 처리
handleExistingUser(request, response, existUser);
Expand All @@ -94,9 +94,9 @@ private void handleAuthentication(HttpServletRequest request, HttpServletRespons
}

// 신규 유저 처리
private void handleNewUser(HttpServletRequest request, HttpServletResponse response, String provider, String providerId, String name) throws IOException {
private void handleNewUser(HttpServletRequest request, HttpServletResponse response, String provider, String providerId, String name, String email) throws IOException {
log.info("신규 유저입니다.");
String registerToken = jwtUtil.generateRegisterToken(provider, providerId, name, ACCESS_TOKEN_EXPIRATION_TIME);
String registerToken = jwtUtil.generateRegisterToken(provider, providerId, name, email, ACCESS_TOKEN_EXPIRATION_TIME);
String redirectUri = String.format(REGISTER_TOKEN_REDIRECT_URI, registerToken, URLEncoder.encode(name, StandardCharsets.UTF_8));
getRedirectStrategy().sendRedirect(request, response, redirectUri);
}
Expand Down
24 changes: 20 additions & 4 deletions src/main/java/side/onetime/controller/UserController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@

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 org.springframework.web.bind.annotation.*;
import side.onetime.dto.UserDto;
import side.onetime.global.common.ApiResponse;
import side.onetime.global.common.constant.SuccessStatus;
Expand All @@ -25,4 +22,23 @@ public ResponseEntity<ApiResponse<UserDto.OnboardUserResponse>> onboardUser(
UserDto.OnboardUserResponse onboardUserResponse = userService.onboardUser(onboardUserRequest);
return ApiResponse.onSuccess(SuccessStatus._ONBOARD_USER, onboardUserResponse);
}

// 유저 정보 조회 API
@GetMapping("/profile")
public ResponseEntity<ApiResponse<UserDto.GetUserProfileResponse>> getUserProfile(
@RequestHeader("Authorization") String authorizationHeader) {

UserDto.GetUserProfileResponse getUserProfileResponse = userService.getUserProfile(authorizationHeader);
return ApiResponse.onSuccess(SuccessStatus._GET_USER_PROFILE, getUserProfileResponse);
}

// 유저 정보 수정 API
@PatchMapping("/profile/action-update")
public ResponseEntity<ApiResponse<SuccessStatus>> updateUserProfile(
@RequestHeader("Authorization") String authorizationHeader,
@RequestBody UserDto.UpdateUserProfileRequest updateUserProfileRequest) {

userService.updateUserProfile(authorizationHeader, updateUserProfileRequest);
return ApiResponse.onSuccess(SuccessStatus._UPDATE_USER_PROFILE);
}
}
10 changes: 9 additions & 1 deletion src/main/java/side/onetime/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ public class User extends BaseEntity {
@Column(name = "name", nullable = false, length = 50)
private String name;

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

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

Expand All @@ -30,10 +33,15 @@ public class User extends BaseEntity {
private String providerId;

@Builder
public User(String name, String nickname, String provider, String providerId) {
public User(String name, String email, String nickname, String provider, String providerId) {
this.name = name;
this.email = email;
this.nickname = nickname;
this.provider = provider;
this.providerId = providerId;
}

public void updateNickName(String nickname) {
this.nickname = nickname;
}
}
29 changes: 29 additions & 0 deletions src/main/java/side/onetime/dto/UserDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import side.onetime.domain.User;

public class UserDto {
@Builder
Expand Down Expand Up @@ -37,4 +38,32 @@ public static OnboardUserResponse of(String accessToken, String refreshToken) {
.build();
}
}

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

public static GetUserProfileResponse of(User user) {
return GetUserProfileResponse.builder()
.nickname(user.getNickname())
.email(user.getEmail())
.build();
}
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class UpdateUserProfileRequest {
private String nickname;
}
}
3 changes: 2 additions & 1 deletion src/main/java/side/onetime/exception/UserErrorResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
@RequiredArgsConstructor
public enum UserErrorResult implements BaseErrorCode {
_NOT_FOUND_USER(HttpStatus.NOT_FOUND, "404", "유저를 찾을 수 없습니다."),
_NICKNAME_TOO_LONG(HttpStatus.BAD_REQUEST, "400", "닉네임 길이 제한을 초과했습니다.")
_NICKNAME_TOO_LONG(HttpStatus.BAD_REQUEST, "400", "닉네임 길이 제한을 초과했습니다."),
_NOT_FOUND_REQUEST_NICKNAME(HttpStatus.BAD_REQUEST, "400", "닉네임 요청 값을 찾을 수 없습니다.")
;

private final HttpStatus httpStatus;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public enum SuccessStatus implements BaseCode {
_REISSUE_TOKENS(HttpStatus.CREATED, "201", "토큰 재발행에 성공했습니다."),
// User
_ONBOARD_USER(HttpStatus.CREATED, "201", "유저 온보딩에 성공했습니다."),
_GET_USER_PROFILE(HttpStatus.OK, "200", "유저 정보 조회에 성공했습니다."),
_UPDATE_USER_PROFILE(HttpStatus.OK, "200", "유저 정보 수정에 성공했습니다."),
;

private final HttpStatus httpStatus;
Expand Down
27 changes: 26 additions & 1 deletion src/main/java/side/onetime/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,15 @@ public UserDto.OnboardUserResponse onboardUser(UserDto.OnboardUserRequest onboar
String provider = jwtUtil.getProviderFromToken(registerToken);
String providerId = jwtUtil.getProviderIdFromToken(registerToken);
String name = jwtUtil.getNameFromToken(registerToken);
String email = jwtUtil.getEmailFromToken(registerToken);

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

User user = User.builder()
.name(name)
.email(email)
.nickname(onboardUserRequest.getNickname())
.provider(provider)
.providerId(providerId)
Expand All @@ -62,4 +64,27 @@ public UserDto.OnboardUserResponse onboardUser(UserDto.OnboardUserRequest onboar
// 액세스 토큰 반환
return UserDto.OnboardUserResponse.of(accessToken, refreshToken);
}
}

// 유저 정보 조회 메서드
public UserDto.GetUserProfileResponse getUserProfile(String authorizationHeader) {
User user = jwtUtil.getUserFromHeader(authorizationHeader);

return UserDto.GetUserProfileResponse.of(user);
}

// 유저 정보 수정 메서드
@Transactional
public void updateUserProfile(String authorizationHeader, UserDto.UpdateUserProfileRequest updateUserProfileRequest) {
User user = jwtUtil.getUserFromHeader(authorizationHeader);
String nickname = updateUserProfileRequest.getNickname();

if (nickname == null) {
throw new UserException(UserErrorResult._NOT_FOUND_REQUEST_NICKNAME);
}
if (nickname.length() > NICKNAME_LENGTH_LIMIT) {
throw new UserException(UserErrorResult._NICKNAME_TOO_LONG);
}
user.updateNickName(nickname);
userRepository.save(user);
}
}
31 changes: 25 additions & 6 deletions src/main/java/side/onetime/util/JwtUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,14 @@ public String generateAccessToken(Long userId, long expirationMillis) {
}

// 레지스터 토큰을 발급하는 메서드
public String generateRegisterToken(String provider, String providerId, String name, long expirationMillis) {
public String generateRegisterToken(String provider, String providerId, String name, String email, long expirationMillis) {
log.info("레지스터 토큰이 발행되었습니다.");

return Jwts.builder()
.claim("provider", provider) // 클레임에 provider 추가
.claim("providerId", providerId) // 클레임에 providerId 추가
.claim("name", name) // 클레임에 name 추가
.claim("email", email) // 클레임에 email 추가
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + expirationMillis))
.signWith(this.getSigningKey())
Expand Down Expand Up @@ -92,7 +93,7 @@ public Long getUserIdFromToken(String token) {
}
}

// 토큰에서 유저를 반환하는 메서드
// 헤더에서 유저를 반환하는 메서드
public User getUserFromHeader(String authorizationHeader) {
String token = getTokenFromHeader(authorizationHeader);

Expand Down Expand Up @@ -121,14 +122,14 @@ public String getProviderFromToken(String token) {
// 토큰에서 providerId를 반환하는 메서드
public String getProviderIdFromToken(String token) {
try {
String userId = Jwts.parser()
String providerId = Jwts.parser()
.verifyWith(this.getSigningKey())
.build()
.parseSignedClaims(token)
.getPayload()
.get("providerId", String.class);
log.info("providerId를 반환합니다.");
return userId;
return providerId;
} catch (JwtException | IllegalArgumentException e) {
// 토큰이 유효하지 않은 경우
log.warn("토큰에서 providerId를 반환하는 도중 에러가 발생했습니다.");
Expand All @@ -139,21 +140,39 @@ public String getProviderIdFromToken(String token) {
// 토큰에서 name을 반환하는 메서드
public String getNameFromToken(String token) {
try {
String userId = Jwts.parser()
String name = Jwts.parser()
.verifyWith(this.getSigningKey())
.build()
.parseSignedClaims(token)
.getPayload()
.get("name", String.class);
log.info("name을 반환합니다.");
return userId;
return name;
} catch (JwtException | IllegalArgumentException e) {
// 토큰이 유효하지 않은 경우
log.warn("토큰에서 이름을 반환하는 도중 에러가 발생했습니다.");
throw new TokenException(TokenErrorResult._INVALID_TOKEN);
}
}

// 토큰에서 name을 반환하는 메서드
public String getEmailFromToken(String token) {
try {
String email = Jwts.parser()
.verifyWith(this.getSigningKey())
.build()
.parseSignedClaims(token)
.getPayload()
.get("email", String.class);
log.info("email을 반환합니다.");
return email;
} catch (JwtException | IllegalArgumentException e) {
// 토큰이 유효하지 않은 경우
log.warn("토큰에서 이메일을 반환하는 도중 에러가 발생했습니다.");
throw new TokenException(TokenErrorResult._INVALID_TOKEN);
}
}

// Jwt 토큰의 유효기간을 확인하는 메서드
public boolean isTokenExpired(String token) {
try {
Expand Down

0 comments on commit 4540385

Please sign in to comment.