Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Refactor]: 소셜 회원가입 API 리팩토링 #158

Merged
merged 1 commit into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ dependencies {

}

test {
useJUnitPlatform()
}

tasks.named('bootBuildImage') {
builder = 'paketobuildpacks/builder-jammy-base:latest'
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package io.sobok.SobokSobok.auth.application;

import io.sobok.SobokSobok.auth.application.util.UserServiceUtil;
import io.sobok.SobokSobok.auth.domain.Role;
import io.sobok.SobokSobok.auth.domain.SocialInfo;
import io.sobok.SobokSobok.auth.domain.User;
import io.sobok.SobokSobok.auth.infrastructure.UserRepository;
import io.sobok.SobokSobok.auth.ui.dto.SocialLoginRequest;
import io.sobok.SobokSobok.auth.ui.dto.SocialLoginResponse;
import io.sobok.SobokSobok.auth.ui.dto.SocialSignupRequest;
import io.sobok.SobokSobok.auth.ui.dto.SocialSignupResponse;
import io.sobok.SobokSobok.exception.ErrorCode;
import io.sobok.SobokSobok.exception.model.ConflictException;
import io.sobok.SobokSobok.security.jwt.Jwt;
import io.sobok.SobokSobok.security.jwt.JwtProvider;

Expand All @@ -23,39 +21,34 @@
@RequiredArgsConstructor
public class SocialService {

private final UserCreator userCreator;

private final UserRepository userRepository;

private final JwtProvider jwtProvider;

@Transactional
public SocialSignupResponse signup(SocialSignupRequest request) {
if (userRepository.existsBySocialInfoSocialId(request.socialId())) {
throw new ConflictException(ErrorCode.ALREADY_EXISTS_USER);
}

if (userRepository.existsByUsername(request.username())) {
throw new ConflictException(ErrorCode.ALREADY_USING_USERNAME);
}
UserServiceUtil.checkAlreadySignupSocialId(userRepository, request.socialId());
UserServiceUtil.checkAlreadyUsedNickname(userRepository, request.nickname());

User signupUser = userRepository.save(User.builder()
.username(request.username())
.socialInfo(SocialInfo.builder()
.socialId(request.socialId())
.build())
.deviceToken(request.deviceToken())
.roles(Role.USER.name())
.platform(request.platform())
.build());
User signupUser = userCreator.create(
request.nickname(),
request.socialId(),
request.platform(),
request.deviceToken(),
Role.USER.name()
);
dev-Crayon marked this conversation as resolved.
Show resolved Hide resolved

Jwt jwt = jwtProvider.getUserJwt(signupUser.getSocialInfo().getSocialId());

return SocialSignupResponse.builder()
.id(signupUser.getId())
.username(signupUser.getUsername())
.socialId(signupUser.getSocialInfo().getSocialId())
.accessToken(jwt.accessToken())
.refreshToken(jwt.refreshToken())
.build();
return SocialSignupResponse.of(
signupUser.getId(),
signupUser.getUsername(),
signupUser.getSocialInfo().getSocialId(),
jwt.accessToken(),
jwt.refreshToken()
);
}

@Transactional
Expand All @@ -70,7 +63,7 @@ public SocialLoginResponse login(SocialLoginRequest request) {
loginUser.updateDeviceToken(request.deviceToken());
}

if (!request.platform().equals(loginUser.getPlatform())) {
if (!request.platform().equals(loginUser.getSocialInfo().getPlatform())) {
loginUser.updatePlatform(request.platform());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.sobok.SobokSobok.auth.application;

import io.sobok.SobokSobok.auth.domain.Platform;
import io.sobok.SobokSobok.auth.domain.SocialInfo;
import io.sobok.SobokSobok.auth.domain.User;
import io.sobok.SobokSobok.auth.infrastructure.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class UserCreator {

private UserRepository userRepository;

public User create(final String username, final String socialId, final Platform platform, final String deviceToken, final String roles) {
SocialInfo socialInfo = SocialInfo.newInstance(socialId, platform);
return User.newInstance(username, socialInfo, deviceToken, roles);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public void changeUsername(Long userId, String username) {
User user = UserServiceUtil.findUserById(userRepository, userId);

if (duplicateNickname(username)) {
throw new ConflictException(ErrorCode.ALREADY_USING_USERNAME);
throw new ConflictException(ErrorCode.ALREADY_USING_NICKNAME);
}

user.changeUsername(username);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,26 @@
import io.sobok.SobokSobok.auth.domain.User;
import io.sobok.SobokSobok.auth.infrastructure.UserRepository;
import io.sobok.SobokSobok.exception.ErrorCode;
import io.sobok.SobokSobok.exception.model.ConflictException;
import io.sobok.SobokSobok.exception.model.NotFoundException;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class UserServiceUtil {

public static void checkAlreadySignupSocialId(UserRepository userRepository, String socialId) {
if (userRepository.existsBySocialInfoSocialId(socialId)) {
throw new ConflictException(ErrorCode.ALREADY_EXISTS_USER);
}
}

public static void checkAlreadyUsedNickname(UserRepository userRepository, String nickname) {
if (userRepository.existsByUsername(nickname)) {
throw new ConflictException(ErrorCode.ALREADY_USING_NICKNAME);
}
}

public static User findUserById(UserRepository userRepository, Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new NotFoundException(ErrorCode.UNREGISTERED_USER));
Expand Down
21 changes: 16 additions & 5 deletions src/main/java/io/sobok/SobokSobok/auth/domain/SocialInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -17,12 +16,24 @@ public class SocialInfo {
@Column(nullable = false)
private String socialId;

public void removeSocialInfo() {
this.socialId = "";
@Column
@Enumerated(EnumType.STRING)
private Platform platform;

public static SocialInfo newInstance(String socialId, Platform platform) {
return new SocialInfo(socialId, platform);
}

@Builder
public SocialInfo(String socialId) {
private SocialInfo(String socialId, Platform platform) {
this.socialId = socialId;
this.platform = platform;
}

public void changeSocialPlatform(Platform platform) {
this.platform = platform;
}

public void removeSocialInfo() {
this.socialId = "";
}
}
12 changes: 5 additions & 7 deletions src/main/java/io/sobok/SobokSobok/auth/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,15 @@ public class User extends BaseEntity implements UserDetails {
@Column
private String leaveReason;

@Column
@Enumerated(EnumType.STRING)
private Platform platform;
public static User newInstance(String username, SocialInfo socialInfo, String deviceToken, String roles) {
return new User(username, socialInfo, deviceToken, roles);
}

@Builder
public User(String username, SocialInfo socialInfo, String deviceToken, String roles, Platform platform) {
private User(String username, SocialInfo socialInfo, String deviceToken, String roles) {
this.username = username;
this.socialInfo = socialInfo;
this.deviceToken = deviceToken;
this.roles = roles;
this.platform = platform;
}

public void updateDeviceToken(String newDeviceToken) {
Expand All @@ -71,7 +69,7 @@ public void changeUsername(String username) {
}

public void updatePlatform(Platform platform) {
this.platform = platform;
this.socialInfo.changeSocialPlatform(platform);
}

public void deleteUser(String leaveReason) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,25 @@
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public record SocialSignupRequest(

@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank
@NotBlank(message = "소셜 아이디가 입력되지 않았습니다.")
String socialId,

@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank
String username,
@NotBlank(message = "닉네임이 입력되지 않았습니다.")
@Size(min = 2, max = 10, message = "닉네임은 2글자 이상 10글자 이하만 가능합니다.")
String nickname,

@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank
@NotBlank(message = "디바이스 토큰이 입력되지 않았습니다.")
String deviceToken,

@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull
@NotNull(message = "사용자의 모바일 플랫폼이 입력되지 않았습니다.")
Platform platform
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,13 @@ public record SocialSignupResponse(

String refreshToken
) {
public static SocialSignupResponse of(
final Long id,
final String username,
final String socialId,
final String accessToken,
final String refreshToken
) {
return new SocialSignupResponse(id, username, socialId, accessToken, refreshToken);
}
}
4 changes: 4 additions & 0 deletions src/main/java/io/sobok/SobokSobok/common/dto/ApiResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ public static <T> ApiResponse<T> success(SuccessCode successCode, T data) {
public static <T> ApiResponse<T> error(ErrorCode errorCode) {
return new ApiResponse<>(errorCode.getCode().value(), errorCode.getMessage(), null);
}

public static <T> ApiResponse<T> error(ErrorCode errorCode, String message) {
return new ApiResponse<>(errorCode.getCode().value(), message, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice
@Slf4j
public class ControllerExceptionAdvice {
Expand Down Expand Up @@ -43,6 +48,19 @@ protected ResponseEntity<ApiResponse<Void>> handleHttpRequestMethodNotSupportedE
);
}

@ExceptionHandler(MethodArgumentNotValidException.class)
protected ResponseEntity<ApiResponse<Void>> handleMethodArgumentNotValidException(final MethodArgumentNotValidException exception) {
StringBuilder sb = new StringBuilder();
for (FieldError error : exception.getBindingResult().getFieldErrors()) {
sb.append(error.getField()).append(": ").append(error.getDefaultMessage()).append(" ");
}

return new ResponseEntity<>(
ApiResponse.error(ErrorCode.BAD_REQUEST_EXCEPTION, sb.toString()),
HttpStatus.BAD_REQUEST
);
}

/**
* external Error
*/
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/sobok/SobokSobok/exception/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public enum ErrorCode {
UNREGISTERED_TOKEN(HttpStatus.NOT_FOUND, "등록되지 않은 토큰입니다."),
NOT_LOGGED_IN_USER(HttpStatus.NOT_FOUND, "로그인되지 않은 사용자입니다."),
ALREADY_EXISTS_USER(HttpStatus.CONFLICT, "이미 회원가입이 완료된 사용자입니다."),
ALREADY_USING_USERNAME(HttpStatus.CONFLICT, "이미 사용중인 username입니다."),
ALREADY_USING_NICKNAME(HttpStatus.CONFLICT, "이미 사용중인 닉네임입니다."),
EMPTY_DEVICE_TOKEN(HttpStatus.NOT_FOUND, "디바이스 토큰이 존재하지 않습니다."),

// jwt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ public void sendNotificationByTokenWithFriendData(PushNotificationRequest reques
private void sendNotification(PushNotificationRequest request, String friendId) {
User user = UserServiceUtil.findUserById(userRepository, request.userId());
Message.Builder messageBuilder;
if (user.getPlatform().equals(Platform.ANDROID)) {
if (user.getSocialInfo().getPlatform().equals(Platform.ANDROID)) {
messageBuilder = Message.builder()
.setToken(user.getDeviceToken())
.putData("title", request.title())
.putData("body", request.body() == null ? "" : request.body())
.putData("type", request.type());
} else if (user.getPlatform().equals(Platform.iOS)) {
} else if (user.getSocialInfo().getPlatform().equals(Platform.iOS)) {
messageBuilder = Message.builder()
.setToken(user.getDeviceToken())
.setNotification(buildNotification(request))
Expand Down
Loading