Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import org.ezcode.codetest.application.usermanagement.user.dto.response.ChangeUserPasswordResponse;
import org.ezcode.codetest.application.usermanagement.user.dto.response.LogoutResponse;
import org.ezcode.codetest.application.usermanagement.user.dto.response.VerifyFindPasswordResponse;
import org.ezcode.codetest.domain.language.model.entity.Language;
import org.ezcode.codetest.domain.language.service.LanguageDomainService;
import org.ezcode.codetest.domain.user.exception.AuthException;
import org.ezcode.codetest.domain.user.exception.UserException;
import org.ezcode.codetest.domain.user.exception.code.AuthExceptionCode;
Expand All @@ -41,6 +43,7 @@
public class AuthService {

private final UserDomainService userDomainService;
private final LanguageDomainService languageDomainService;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

기본 언어 ID 하드코딩(1L) 제거 및 널/예외 처리 보강 필요

회원가입 시 기본 언어를 1L로 고정하는 매직 넘버 사용은 환경별 설정 불가·운영 중 변경 불가·데이터 마이그레이션 시 장애 위험을 키웁니다. 또한 languageDomainService.getLanguage(1L)이 null/예외를 반환할 경우 현재 흐름에서는 조용히 NPE가 터질 수 있습니다. 기본값은 설정값으로 주입하거나, getDefaultLanguage() 같은 도메인 메서드로 캡슐화하고, 조회 실패 시 명시적으로 예외를 던지도록 해주세요.

적용 예(개념안):

  • 설정: app.user.default-language-id 프로퍼티로 주입
  • 또는 도메인: languageDomainService.getDefaultLanguage() 제공
  • 가입 시: 조회 실패 시 의미 있는 예외(예: Language 관련 도메인 예외) 발생
- Language language = languageDomainService.getLanguage(1L); //기본적으로 1번 언어로 가입 시 세팅
+ // TODO: 설정 기반 혹은 도메인 메서드로 기본 언어 조회 + 예외 처리
+ Language language = languageDomainService.getDefaultLanguage(); // 존재하지 않으면 도메인 예외

Also applies to: 86-94

private final JwtUtil jwtUtil;
private final RedisTemplate<String, String> redisTemplate;
private final MailService mailService;
Expand Down Expand Up @@ -80,12 +83,14 @@ private void userRegisterationProcess(SignupRequest request) {
//3. 만약 아예 첫 가입 유저일 때
private void createNewUser(SignupRequest request, String encodedPassword) {
String nickname = userDomainService.generateUniqueNickname();
Language language = languageDomainService.getLanguage(1L); //기본적으로 1번 언어로 가입 시 세팅
User newUser = User.emailUser(
request.getEmail(),
encodedPassword,
request.getUsername(),
nickname,
request.getAge()
request.getAge(),
language
);

userDomainService.createUser(newUser);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public record ModifyUserInfoRequest(
String introduction,

@Schema(description = "나이", example = "28")
Integer age
Integer age,

@Schema(description = "언어 id", example = "1")
Long languageId
Comment on lines +20 to +23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

languageId/age 유효성 명시 및 널 처리 정책 확립 필요

  • 요청 스키마에 languageId가 추가되었지만 유효성 제약이 없어 잘못된 값(음수, 0 등) 입력을 허용합니다. 또한 필수 여부가 불명확합니다.
  • age 역시 음수 등을 허용할 여지가 있습니다.
  • 서비스 계층에서 languageId == null일 때 업데이트를 스킵하는지(현 행위 유지) 또는 기본 언어로 강제 설정하는지 정책 확인이 필요합니다.

아래와 같이 Bean Validation을 추가하고(널 허용 시 Positive만, 필수라면 NotNull+Positive), 컨트롤러/서비스에서 null 처리 분기 유지를 확인해 주세요.

적용 diff(선택 1: languageId 선택 입력, null 시 미변경):

 	@Schema(description = "나이", example = "28")
-	Integer age,
+	@jakarta.validation.constraints.PositiveOrZero
+	Integer age,
 
 	@Schema(description = "언어 id", example = "1")
-	Long languageId
+	@jakarta.validation.constraints.Positive
+	Long languageId

적용 diff(선택 2: languageId 필수 입력):

 	@Schema(description = "나이", example = "28")
-	Integer age,
+	@jakarta.validation.constraints.PositiveOrZero
+	Integer age,
 
 	@Schema(description = "언어 id", example = "1")
-	Long languageId
+	@jakarta.validation.constraints.NotNull
+	@jakarta.validation.constraints.Positive
+	Long languageId

서비스 레벨 null 처리 검증 스크립트:


🏁 Script executed:

#!/bin/bash
# ModifyUserInfoRequest.languageId 사용부에서 null 분기 여부 확인
rg -nC2 -P --type=java '\blanguageId\(\)' src/main/java | sed -n '1,200p'

Length of output: 5229


ModifyUserInfoRequest DTO에 유효성 제약 추가 필요

서비스 레이어의 모든 사용처(예: UserService, SubmissionService, DiscussionService 등)에서 request.languageId()를 null 체크 없이 바로 languageDomainService.getLanguage(...)에 전달하고 있어, null 또는 0 이하 값 입력 시 NPE 또는 잘못된 조회가 발생할 수 있습니다. 또한 age 필드도 음수 입력을 방지할 유효성 검증이 빠져 있습니다.

수정 제안:

  • languageId는 필수 입력이므로 @NotNull@Positive 애노테이션 추가
  • age는 선택 입력(널 허용)이지만 음수 방지를 위해 @PositiveOrZero 애노테이션 추가

해당 DTO 파일:

  • src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/request/ModifyUserInfoRequest.java

적용 예시(diff):

  @Schema(description = "나이", example = "28")
- Integer age,
+ @jakarta.validation.constraints.PositiveOrZero
+ Integer age,

  @Schema(description = "언어 id", example = "1")
- Long languageId
+ @jakarta.validation.constraints.NotNull
+ @jakarta.validation.constraints.Positive
+ Long languageId

— 이후 컨트롤러/서비스 레이어에서 @Valid 검증이 정상 동작하는지, 검증 실패 시 적절한 에러 응답이 내려가는지 확인 부탁드립니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Integer age,
@Schema(description = "언어 id", example = "1")
Long languageId
@Schema(description = "나이", example = "28")
@jakarta.validation.constraints.PositiveOrZero
Integer age,
@Schema(description = "언어 id", example = "1")
@jakarta.validation.constraints.NotNull
@jakarta.validation.constraints.Positive
Long languageId
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/request/ModifyUserInfoRequest.java
around lines 20-23, the DTO lacks validation: languageId is treated as required
by services but can be null/<=0 causing NPE or bad lookups, and age can be
negative. Add javax.validation annotations: mark languageId with @NotNull and
@Positive, and mark age (which remains nullable) with @PositiveOrZero; also add
the necessary imports for these annotations. After updating the DTO, ensure
controller methods accept @Valid for this request so validation triggers and
returns appropriate error responses.

) {
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package org.ezcode.codetest.application.usermanagement.user.dto.response;

import java.util.List;

import org.ezcode.codetest.domain.language.model.entity.Language;
import org.ezcode.codetest.domain.user.model.entity.User;
import org.ezcode.codetest.domain.user.model.enums.AuthType;
import org.ezcode.codetest.domain.user.model.enums.Tier;
import org.ezcode.codetest.domain.user.model.enums.UserRole;

Expand Down Expand Up @@ -47,10 +51,18 @@ public class UserInfoResponse {
@Schema(description = "사용자가 푼 문제 총 개수", example = "1235")
private final int totalSolvedCount;

@Schema(description = "사용자가 선택한 언어. 기본적으로 1번 언어로 세팅됩니다", example = "1")
private final Language language;

@Schema(description = "사용자가 가입한 경로(자체/소셜)의 리스트를 보여줍니다", example = "[GOOGLE, GITHUB, EMAIL]")
private final List<AuthType> userAuthTypes;

Comment on lines +54 to +59
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

DTO에서 JPA 엔티티(Language) 직접 노출 금지: ID 또는 전용 DTO로 교체 필요

Language 엔티티를 응답 DTO에 직접 담으면 LAZY 프록시 직렬화 문제, 과다한 필드 노출, 순환 참조 위험이 있습니다. 또한 @Schema example = "1"은 타입이 Language인 현재 정의와 충돌합니다. API 안정성과 성능을 위해 languageId(Long)로 대체하거나 LanguageResponse 같은 전용 응답 DTO를 사용하세요.

ID만 노출하는 간단한 변경 예:

- @Schema(description = "사용자가 선택한 언어. 기본적으로 1번 언어로 세팅됩니다", example = "1")
- private final Language language;
+ @Schema(description = "사용자가 선택한 언어 ID. 기본값은 시스템 설정에 따릅니다", example = "1")
+ private final Long languageId;

auth 타입 리스트는 그대로 유지 가능:

 @Schema(description = "사용자가 가입한 경로(자체/소셜)의 리스트를 보여줍니다", example = "[GOOGLE, GITHUB, EMAIL]")
 private final List<AuthType> userAuthTypes;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Schema(description = "사용자가 선택한 언어. 기본적으로 1번 언어로 세팅됩니다", example = "1")
private final Language language;
@Schema(description = "사용자가 가입한 경로(자체/소셜)의 리스트를 보여줍니다", example = "[GOOGLE, GITHUB, EMAIL]")
private final List<AuthType> userAuthTypes;
@Schema(description = "사용자가 선택한 언어 ID. 기본값은 시스템 설정에 따릅니다", example = "1")
private final Long languageId;
@Schema(description = "사용자가 가입한 경로(자체/소셜)의 리스트를 보여줍니다", example = "[GOOGLE, GITHUB, EMAIL]")
private final List<AuthType> userAuthTypes;

@Builder
public UserInfoResponse(String username, String email, String nickname, UserRole userRole, Tier tier,
Integer age, String githubUrl, String blogUrl, String profileImageUrl, String introduction, boolean verified,
int totalSolvedCount) {
int totalSolvedCount,
Language language,
List<AuthType> userAuthTypes) {
this.username = username;
Comment on lines 60 to 66
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Builder 시그니처/할당 업데이트 필요(Language → languageId)

위 제안대로 languageId로 바꾸는 경우 Builder 파라미터와 필드 할당도 함께 수정되어야 합니다.

- int totalSolvedCount,
- Language language,
- List<AuthType> userAuthTypes) {
+ int totalSolvedCount,
+ Long languageId,
+ List<AuthType> userAuthTypes) {
    ...
-   this.language = language;
+   this.languageId = languageId;
    this.userAuthTypes = userAuthTypes;

Also applies to: 78-79

🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/usermanagement/user/dto/response/UserInfoResponse.java
around lines 60-66 (and also update the corresponding constructor/assignments at
lines 78-79), the builder parameter and assignments still use Language language
while the field was renamed to languageId; update the builder signature to
accept Long languageId (or the appropriate type) and change the constructor body
to assign this.languageId = languageId (and any other occurrences in those
lines) so the constructor parameter and field assignment match the new
name/type.

this.email = email;
this.nickname = nickname;
Expand All @@ -63,6 +75,8 @@ public UserInfoResponse(String username, String email, String nickname, UserRole
this.userRole = userRole;
this.verified = verified;
this.totalSolvedCount = totalSolvedCount;
this.language = language;
this.userAuthTypes = userAuthTypes;
}

public static UserInfoResponse fromEntity(User user) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;

import org.ezcode.codetest.application.usermanagement.user.dto.response.GrantAdminRoleResponse;
import org.ezcode.codetest.application.usermanagement.user.dto.response.UserDailySolvedHistoryResponse;
import org.ezcode.codetest.application.usermanagement.user.dto.response.UserProfileImageResponse;
import org.ezcode.codetest.application.usermanagement.user.dto.response.UserReviewTokenResponse;
import org.ezcode.codetest.application.usermanagement.user.model.UsersByWeek;
import org.ezcode.codetest.domain.language.model.entity.Language;
import org.ezcode.codetest.domain.language.service.LanguageDomainService;
import org.ezcode.codetest.domain.submission.dto.DailyCorrectCount;
import org.ezcode.codetest.domain.submission.dto.WeeklySolveCount;
import org.ezcode.codetest.application.usermanagement.user.dto.request.ChangeUserPasswordRequest;
Expand All @@ -23,6 +26,7 @@
import org.ezcode.codetest.domain.user.exception.code.UserExceptionCode;
import org.ezcode.codetest.domain.user.model.entity.AuthUser;
import org.ezcode.codetest.domain.user.model.entity.User;
import org.ezcode.codetest.domain.user.model.entity.UserAuthType;
import org.ezcode.codetest.domain.user.model.enums.AuthType;
import org.ezcode.codetest.domain.user.model.enums.UserRole;
import org.ezcode.codetest.domain.user.service.MailService;
Expand All @@ -46,6 +50,7 @@
public class UserService {

private final UserDomainService userDomainService;
private final LanguageDomainService languageDomainService;
private final SubmissionDomainService submissionDomainService;
private final RedisTemplate<String, String> redisTemplate;
private final S3Uploader s3Uploader;
Expand All @@ -55,6 +60,9 @@ public UserInfoResponse getUserInfo(AuthUser authUser) {
log.info("authUserEmail: {}, authUserID : {}", authUser.getEmail(), authUser.getId());
User user = userDomainService.getUserById(authUser.getId());
int userSubmissionCount = submissionDomainService.findSubmissionCountByUserId(user.getId());
List<UserAuthType> userAuthTypes = userDomainService.getUserAuthTypesByUser(user);
List<AuthType> authTypes = userAuthTypes.stream()
.map(UserAuthType::getAuthType).toList();

return UserInfoResponse.builder()
.username(user.getUsername())
Expand All @@ -69,19 +77,23 @@ public UserInfoResponse getUserInfo(AuthUser authUser) {
.tier(user.getTier())
.verified(user.isVerified())
.totalSolvedCount(userSubmissionCount)
.language(user.getLanguage())
.userAuthTypes(authTypes)
.build();
}

@Transactional
public UserInfoResponse modifyUserInfo(AuthUser authUser, ModifyUserInfoRequest request, MultipartFile image) {
User user = userDomainService.getUserById(authUser.getId());
Language findLangauge = languageDomainService.getLanguage(request.languageId());

user.modifyUserInfo(
request.nickname(),
request.githubUrl(),
request.blogUrl(),
request.introduction(),
request.age());
request.age(),
findLangauge);

Comment on lines +88 to 97
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

오타 및 널 처리 보강: findLangauge → findLanguage, languageId가 null일 때 안전 처리

변수명이 findLangauge로 오타입니다. 또한 request.languageId()가 null이면 현재는 NPE가 발생합니다(도메인 서비스 호출 시). null이면 기존 언어 유지가 의도라면 안전하게 처리하세요.

- Language findLangauge = languageDomainService.getLanguage(request.languageId());
+ Long languageId = request.languageId();
+ Language findLanguage = (languageId == null) ? null : languageDomainService.getLanguage(languageId);
   ...
-   request.age(),
-   findLangauge);
+   request.age(),
+   findLanguage);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Language findLangauge = languageDomainService.getLanguage(request.languageId());
user.modifyUserInfo(
request.nickname(),
request.githubUrl(),
request.blogUrl(),
request.introduction(),
request.age());
request.age(),
findLangauge);
Long languageId = request.languageId();
Language findLanguage = (languageId == null)
? null
: languageDomainService.getLanguage(languageId);
user.modifyUserInfo(
request.nickname(),
request.githubUrl(),
request.blogUrl(),
request.introduction(),
request.age(),
findLanguage);
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/application/usermanagement/user/service/UserService.java
around lines 88 to 97, rename the misspelled variable findLangauge to
findLanguage and add a null-safe handling for request.languageId(): only call
languageDomainService.getLanguage(...) when request.languageId() is non-null,
otherwise obtain and pass the user's existing language (or null if the domain
allows keeping current value) into user.modifyUserInfo so no NPE occurs; ensure
the variable name is updated where used and that modifyUserInfo receives the
correct language reference.

if (image != null && !image.isEmpty()) {
String profileImageUrl = uploadProfileImage(image);
Expand All @@ -105,6 +117,7 @@ public UserInfoResponse modifyUserInfo(AuthUser authUser, ModifyUserInfoRequest
.githubUrl(user.getGithubUrl())
.userRole(user.getRole())
.tier(user.getTier())
.language(user.getLanguage())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,23 @@
import java.util.List;

import org.ezcode.codetest.common.base.entity.BaseEntity;
import org.ezcode.codetest.domain.language.model.entity.Language;
import org.ezcode.codetest.domain.user.model.enums.Tier;
import org.ezcode.codetest.domain.user.model.enums.UserRole;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Builder;
Expand Down Expand Up @@ -72,17 +75,20 @@ public class User extends BaseEntity {
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<UserAuthType> userAuthTypes = new ArrayList<>();

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "language_id")
private Language language;

private boolean verified; //이메일 인증 여부

private boolean gitPushStatus; //깃허브 자동 push 여부


/*
처음 유저 생성(가입) 시에는 기본 정보만 받음
- 이메일, 비번, 이름, 별명, 나이
-> 이후 회원정보 업데이트할 때, 원하는 정보를 입력할 수 있도록 함
*/
public static User emailUser(String email, String password, String username, String nickname, Integer age){
public static User emailUser(String email, String password, String username, String nickname, Integer age, Language language) {
return User.builder()
.email(email)
.password(password)
Expand All @@ -94,14 +100,15 @@ public static User emailUser(String email, String password, String username, Str
.isDeleted(false)
.verified(false)
.gitPushStatus(false)
.language(language)
.build();
}

/*
OAuth2로 로그인한 유저 저장
구글 이외의 다른 소셜 로그인 확장 가능성을 고려해 socialUser 이름 유지
*/
public static User socialUser(String email, String username, String nickname, String password){
public static User socialUser(String email, String username, String nickname, String password, Language language) {
return User.builder()
.email(email)
.username(username)
Expand All @@ -112,11 +119,12 @@ public static User socialUser(String email, String username, String nickname, St
.isDeleted(false)
.verified(false)
.gitPushStatus(false)
.language(language)
.build();
}

//깃허브 아이디와 url을 함께 저장하기 위해 따로 저장
public static User githubUser(String email, String username, String nickname, String password, String githubUrl){
public static User githubUser(String email, String username, String nickname, String password, String githubUrl, Language language){
return User.builder()
.email(email)
.username(username)
Expand All @@ -128,13 +136,14 @@ public static User githubUser(String email, String username, String nickname, St
.verified(false)
.githubUrl(githubUrl)
.gitPushStatus(false)
.language(language)
.build();
}


@Builder
public User(String email, String password, String username, String nickname,
Integer age, Tier tier, UserRole role, boolean isDeleted, boolean verified, String githubUrl, boolean gitPushStatus) {
Integer age, Tier tier, UserRole role, boolean isDeleted, boolean verified, String githubUrl, boolean gitPushStatus, Language language) {
this.email = email;
this.password = password;
this.username = username;
Expand All @@ -146,18 +155,20 @@ public User(String email, String password, String username, String nickname,
this.verified = verified;
this.githubUrl = githubUrl;
this.gitPushStatus = gitPushStatus;
this.language = language;
}

/*
유저 정보 업데이트
- 만약 입력 값이 없다면, 기존 값 유지
*/
public void modifyUserInfo(String nickname, String githubUrl, String blogUrl, String introduction, Integer age){
public void modifyUserInfo(String nickname, String githubUrl, String blogUrl, String introduction, Integer age, Language language) {
this.nickname = (nickname == null || nickname.isBlank()) ? this.nickname : nickname;
this.githubUrl = (githubUrl == null || githubUrl.isBlank()) ? this.githubUrl : githubUrl;
this.blogUrl = (blogUrl == null || blogUrl.isBlank()) ? this.blogUrl : blogUrl;
this.introduction = (introduction == null || introduction.isBlank()) ? this.introduction : introduction;
this.age = (age == null) ? this.age : age;
this.language = (language == null) ? this.language : language;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
import java.util.UUID;

import org.ezcode.codetest.application.usermanagement.user.dto.response.OAuth2Response;
import org.ezcode.codetest.domain.language.model.entity.Language;

public class UserFactory {
public static User createSocialUser(
OAuth2Response response,
String nickname,
String provider
String provider,
Language language
) {
//나중에 확장성 고려해서 switch문 사용
return switch (provider.toLowerCase()) {
Expand All @@ -18,13 +20,16 @@ public static User createSocialUser(
response.getName(),
nickname,
UUID.randomUUID().toString(),
response.getGithubUrl()
response.getGithubUrl(),
language

);
default -> User.socialUser(
response.getEmail(),
response.getName(),
nickname,
UUID.randomUUID().toString()
UUID.randomUUID().toString(),
language
);
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ public interface UserAuthTypeRepository {
void createUserAuthType(UserAuthType userAuthType);

List<AuthType> getUserAuthType(User user);

List<UserAuthType> getUserAuthTypesByUser(User user);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import org.ezcode.codetest.application.usermanagement.user.dto.response.GithubOAuth2Response;
import org.ezcode.codetest.application.usermanagement.user.dto.response.GoogleOAuth2Response;
import org.ezcode.codetest.application.usermanagement.user.dto.response.OAuth2Response;
import org.ezcode.codetest.domain.language.model.entity.Language;
import org.ezcode.codetest.domain.language.service.LanguageDomainService;
import org.ezcode.codetest.domain.user.exception.UserException;
import org.ezcode.codetest.domain.user.exception.code.UserExceptionCode;
import org.ezcode.codetest.domain.user.model.entity.CustomOAuth2User;
Expand Down Expand Up @@ -33,6 +35,7 @@ public class CustomOAuth2UserService extends DefaultOAuth2UserService {
private final UserRepository userRepository;
private final UserAuthTypeRepository userAuthTypeRepository;
private final UserDomainService userDomainService;
private final LanguageDomainService languageDomainService;
private final UserGithubService userGithubService;

@Override
Expand Down Expand Up @@ -82,7 +85,8 @@ private void processUser(

private void createNewUser(OAuth2Response response, AuthType authType, String provider) {
String nickname = userDomainService.generateUniqueNickname();
User newUser = UserFactory.createSocialUser(response, nickname, provider);
Language language = languageDomainService.getLanguage(1L); //기본적으로 1번 언어로 가입 시 세팅
User newUser = UserFactory.createSocialUser(response, nickname, provider, language);
newUser.setVerified();
newUser.setReviewToken(20);
userRepository.createUser(newUser);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,5 +128,8 @@ public User getUserByEmail(String email) {
return userRepository.getUserByEmail(email);
}

public List<UserAuthType> getUserAuthTypesByUser(User user) {
return userAuthTypeRepository.getUserAuthTypesByUser(user);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,11 @@ public List<AuthType> getUserAuthType(User user) {
.map(UserAuthType::getAuthType).toList();
}

@Override
public List<UserAuthType> getUserAuthTypesByUser(User user) {
userAuthTypeJpaRepository.findUserAuthTypeByUser(user).stream()
.map(UserAuthType::getAuthType).toList();
return List.of();
}
Comment on lines +30 to +35
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

반환 타입 불일치 및 잘못된 반환값(항상 빈 리스트) — 기능 불능 버그

  • 시그니처는 List<UserAuthType> 반환인데, 구현은 map(UserAuthType::getAuthType)List<AuthType>를 생성해 버립니다.
  • 더 나아가 해당 결과도 무시하고 List.of()를 반환하여 항상 빈 결과를 돌려줍니다.

이는 상위 서비스(UserDomainService#getUserAuthTypesByUser) 기능을 무력화합니다. 아래처럼 엔티티 리스트를 그대로 반환하도록 수정해 주세요.

 	@Override
 	public List<UserAuthType> getUserAuthTypesByUser(User user) {
-		userAuthTypeJpaRepository.findUserAuthTypeByUser(user).stream()
-			.map(UserAuthType::getAuthType).toList();
-		return List.of();
+		return userAuthTypeJpaRepository.findUserAuthTypeByUser(user);
 	}

검증 스크립트(간단 동작 확인: List.of()가 더 이상 존재하지 않는지 확인):

#!/bin/bash
rg -n 'getUserAuthTypesByUser\(User user\)' -n -C2 src/main/java
rg -nP 'return\s+List\.of\(\)\s*;' src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserAuthTypeRepositoryImpl.java
🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/user/UserAuthTypeRepositoryImpl.java
around lines 30-35, the method currently maps repository results to AuthType and
then ignores it, returning List.of() (always empty) which breaks functionality;
change the implementation to return the List<UserAuthType> obtained from
userAuthTypeJpaRepository.findUserAuthTypeByUser(user) (e.g., collect the stream
into a List and return it) and remove the incorrect map and the hardcoded
List.of() so the actual entity list is returned to callers.


}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.ezcode.codetest.presentation.usermanagement;

import org.ezcode.codetest.application.submission.dto.response.language.LanguageResponse;
import org.ezcode.codetest.application.usermanagement.user.dto.request.ModifyUserInfoRequest;
import org.ezcode.codetest.application.usermanagement.user.dto.request.ChangeUserPasswordRequest;
import org.ezcode.codetest.application.usermanagement.user.dto.response.ChangeUserPasswordResponse;
Expand All @@ -16,13 +17,9 @@
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
Expand Down Expand Up @@ -99,5 +96,4 @@ public ResponseEntity<UserDailySolvedHistoryResponse> getUserDailySolvedHistory(
){
return ResponseEntity.status(HttpStatus.OK).body(userService.getUserDailySolvedHistory(authUser));
}

}
Loading
Loading