Skip to content

Commit 0cc848a

Browse files
authored
feat: userDevice 로깅 추가 (#320)
Co-authored-by: 나용준 <[email protected]>
1 parent 64e58bd commit 0cc848a

File tree

6 files changed

+45
-15
lines changed

6 files changed

+45
-15
lines changed

src/main/java/ssu/eatssu/domain/auth/security/CustomUserDetails.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.springframework.security.core.GrantedAuthority;
66
import org.springframework.security.core.authority.SimpleGrantedAuthority;
77
import org.springframework.security.core.userdetails.UserDetails;
8+
import ssu.eatssu.domain.user.entity.DeviceType;
89
import ssu.eatssu.domain.user.entity.User;
910

1011
import java.util.ArrayList;
@@ -17,12 +18,14 @@ public class CustomUserDetails implements UserDetails {
1718
private final String email;
1819
private final String credentials;
1920
private final GrantedAuthority role;
21+
private final DeviceType deviceType;
2022

2123
public CustomUserDetails(User user) {
2224
this.id = user.getId();
2325
this.email = user.getEmail();
2426
this.credentials = user.getCredentials();
2527
this.role = user.getRole();
28+
this.deviceType = user.getDeviceType();
2629
}
2730

2831
@Override

src/main/java/ssu/eatssu/domain/auth/security/JwtTokenProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ public Authentication getAuthentication(String token) throws JsonProcessingExcep
146146
UserPrincipalDto userPrincipalDto = objectMapper.readValue(claims.getSubject(), UserPrincipalDto.class);
147147

148148
CustomUserDetails principal = new CustomUserDetails(userPrincipalDto.getId(), userPrincipalDto.getEmail(), "",
149-
authorities.get(0));
149+
authorities.get(0),userPrincipalDto.getDeviceType());
150150

151151
return new UsernamePasswordAuthenticationToken(principal, token, authorities);
152152
}

src/main/java/ssu/eatssu/domain/auth/security/UserPrincipalDto.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import lombok.Builder;
55
import lombok.Getter;
66
import lombok.NoArgsConstructor;
7+
import ssu.eatssu.domain.user.entity.DeviceType;
78

89
@Getter
910
@Builder
@@ -12,13 +13,15 @@
1213
public class UserPrincipalDto {
1314
private Long id;
1415
private String email;
16+
private DeviceType deviceType;
1517
private String role;
1618

1719
public static UserPrincipalDto from(CustomUserDetails userDetails) {
1820
return UserPrincipalDto.builder()
1921
.id(userDetails.getId())
2022
.email(userDetails.getEmail())
23+
.deviceType(userDetails.getDeviceType())
2124
.role(userDetails.getRole().getAuthority())
2225
.build();
2326
}
24-
}
27+
}

src/main/java/ssu/eatssu/domain/auth/service/OAuthService.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import ssu.eatssu.domain.auth.security.JwtTokenProvider;
1313
import ssu.eatssu.domain.auth.util.RandomNicknameUtil;
1414
import ssu.eatssu.domain.user.dto.Tokens;
15+
import ssu.eatssu.domain.user.entity.DeviceType;
1516
import ssu.eatssu.domain.user.entity.User;
1617
import ssu.eatssu.domain.user.repository.UserRepository;
1718
import ssu.eatssu.domain.user.service.UserService;
@@ -38,10 +39,17 @@ public Tokens kakaoLogin(KakaoLoginRequest request) {
3839
return generateOauthJwtTokens(user.getEmail(), KAKAO, request.providerId());
3940
}
4041

42+
/**
43+
* V1 -> V2로 넘어가면서 DeviceType(IOS,ANDROID) 정보를 추가로 받게 되었고, 기존에 가입한 유저들은 추가로 기입해 주게 됩니다.
44+
*/
4145
public Tokens kakaoLoginV2(KakaoLoginRequestV2 request) {
4246
User user = userRepository.findByProviderId(request.providerId())
4347
.orElseGet(() -> userService.joinV2(request.email(), KAKAO, request.providerId(),request.deviceType()));
4448

49+
if (user.getDeviceType() == null) {
50+
user.updateDeviceType(request.deviceType());
51+
}
52+
4553
return generateOauthJwtTokens(user.getEmail(), KAKAO, request.providerId());
4654
}
4755

@@ -57,6 +65,9 @@ public Tokens appleLogin(AppleLoginRequest request) {
5765
return generateOauthJwtTokens(user.getEmail(), APPLE, oAuthInfo.providerId());
5866
}
5967

68+
/**
69+
* V1 -> V2로 넘어가면서 DeviceType(IOS,ANDROID) 정보를 추가로 받게 되었고, 기존에 가입한 유저들은 추가로 기입해 주게 됩니다.
70+
*/
6071
public Tokens appleLoginV2(AppleLoginRequestV2 request) {
6172
OAuthInfo oAuthInfo = appleAuthenticator.getOAuthInfoByIdentityToken(request.identityToken());
6273

@@ -65,6 +76,10 @@ public Tokens appleLoginV2(AppleLoginRequestV2 request) {
6576

6677
updateAppleUserEmail(user, oAuthInfo.email());
6778

79+
if (user.getDeviceType() == null) {
80+
user.updateDeviceType(request.deviceType());
81+
}
82+
6883
return generateOauthJwtTokens(user.getEmail(), APPLE, oAuthInfo.providerId());
6984
}
7085

@@ -113,5 +128,4 @@ private Tokens generateOauthJwtTokens(String email, OAuthProvider provider, Stri
113128
private String makeOauthCredentials(OAuthProvider provider, String providerId) {
114129
return provider + providerId;
115130
}
116-
117131
}

src/main/java/ssu/eatssu/domain/user/entity/User.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,6 @@ public void updateDepartment(Department department) {
124124
this.department = department;
125125
}
126126

127+
// 회원 가입 v2 마이그레이션을 위한 메서드 (원래는 가입시 DeviceType을 받아야 합니다.)
128+
public void updateDeviceType(DeviceType deviceType) { this.deviceType = deviceType; }
127129
}

src/main/java/ssu/eatssu/global/log/ControllerLogAspect.java

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@
1111
import org.aspectj.lang.reflect.MethodSignature;
1212
import org.springframework.security.core.Authentication;
1313
import org.springframework.security.core.context.SecurityContextHolder;
14-
import org.springframework.security.core.userdetails.UserDetails;
1514
import org.springframework.stereotype.Component;
1615
import org.springframework.web.context.request.RequestContextHolder;
1716
import org.springframework.web.context.request.ServletRequestAttributes;
1817
import ssu.eatssu.domain.auth.security.CustomUserDetails;
1918
import ssu.eatssu.domain.slack.service.SlackErrorNotifier;
2019
import ssu.eatssu.global.handler.response.BaseException;
21-
import ssu.eatssu.global.handler.response.BaseResponseStatus;
2220
import ssu.eatssu.global.log.annotation.LogMask;
2321

2422
import java.lang.reflect.Field;
@@ -27,7 +25,6 @@
2725
import java.util.stream.Collectors;
2826
import java.util.stream.IntStream;
2927

30-
3128
@Aspect
3229
@Component
3330
@Slf4j
@@ -54,10 +51,11 @@ public Object logApi(ProceedingJoinPoint joinPoint) throws Throwable {
5451
Object[] args = joinPoint.getArgs();
5552

5653
String userId = getUserIdFromSecurityContext();
54+
String deviceType = getDeviceTypeFromSecurityContext();
5755

58-
String userIdLog = "userId=" + userId;
56+
String userLog = "userId=" + userId + ", deviceType=" + deviceType;
5957

60-
// 나머지 요청 인자
58+
// 나머지 요청 인자 조합
6159
String otherArgsJson = IntStream.range(0, args.length)
6260
.filter(i -> !(args[i] instanceof HttpServletRequest))
6361
.filter(i -> !(args[i] instanceof CustomUserDetails))
@@ -81,7 +79,7 @@ public Object logApi(ProceedingJoinPoint joinPoint) throws Throwable {
8179
})
8280
.collect(Collectors.joining(", "));
8381

84-
String argsJson = userIdLog + (otherArgsJson.isEmpty() ? "" : ", " + otherArgsJson);
82+
String argsJson = userLog + (otherArgsJson.isEmpty() ? "" : ", " + otherArgsJson);
8583

8684
log.info("REQUEST {} {} args={}", method, uri, argsJson);
8785

@@ -113,23 +111,33 @@ public Object logApi(ProceedingJoinPoint joinPoint) throws Throwable {
113111
}
114112

115113
private String getCauseMessage(Throwable e) {
116-
if (e instanceof BaseException) {
117-
BaseException baseException = (BaseException) e;
114+
if (e instanceof BaseException baseException) {
118115
return baseException.getStatus().getMessage();
119116
}
120-
String message = e.getMessage();
121-
return message != null ? message : e.getClass().getSimpleName();
117+
return e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName();
122118
}
123119

124120
private String getUserIdFromSecurityContext() {
125121
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
126-
if (authentication != null && authentication.isAuthenticated() && authentication.getPrincipal() instanceof CustomUserDetails) {
127-
CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
122+
if (authentication != null && authentication.isAuthenticated() &&
123+
authentication.getPrincipal() instanceof CustomUserDetails userDetails) {
128124
return String.valueOf(userDetails.getId());
129125
}
130126
return "anonymous";
131127
}
132128

129+
private String getDeviceTypeFromSecurityContext() {
130+
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
131+
if (authentication != null && authentication.isAuthenticated() &&
132+
authentication.getPrincipal() instanceof CustomUserDetails userDetails) {
133+
134+
return userDetails.getDeviceType() != null
135+
? userDetails.getDeviceType().name()
136+
: "null";
137+
}
138+
return "unknown";
139+
}
140+
133141
private Map<String, Object> toSafeMap(Object arg) {
134142
Map<String, Object> result = new HashMap<>();
135143
for (Field field : arg.getClass().getDeclaredFields()) {

0 commit comments

Comments
 (0)