Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;

@Controller
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/attendance")
@Slf4j
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;

@Controller
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/attendance/sessions")
@Slf4j
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.sejongisc.backend.user.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.*;
import org.sejongisc.backend.user.entity.Role;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class SignupRequest {

@NotBlank(message = "이름은 필수입니다.")
private String name;

private String email;

@NotBlank(message = "비밀번호는 필수입니다.")
private String password;

@NotNull(message = "역할은 필수입니다.")
private Role role;

@NotBlank(message = "전화번호는 필수입니다.")
@Pattern(regexp = "^[0-9]{10,11}$")
private String phoneNumber;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.sejongisc.backend.user.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Getter;
import org.sejongisc.backend.user.entity.Role;
import org.sejongisc.backend.user.entity.User;

import java.time.LocalDateTime;
import java.util.UUID;

@Getter
public class SignupResponse {
private final UUID userId;
private final String name;
private final String email;
private final Role role;

@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul")
private final LocalDateTime createdAt;

@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul")
private final LocalDateTime updatedAt;

private SignupResponse(UUID userId, String name, String email, Role role, LocalDateTime createdAt, LocalDateTime updatedAt) {
this.userId=userId;
this.name=name;
this.email=email;
this.role=role;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
}

public static SignupResponse from(User user) {
return new SignupResponse(
user.getUserId(),
user.getName(),
user.getEmail(),
user.getRole(),
user.getCreatedDate(),
user.getUpdatedDate()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.sejongisc.backend.user.entity;

public enum AuthProvider {
GOOGLE, GITHUB, KAKAO
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.sejongisc.backend.user.entity;

import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.UuidGenerator;
import org.sejongisc.backend.common.entity.postgres.BasePostgresEntity;

import java.util.UUID;

@Entity
@Table(name = "user_oauth_account")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class UserOauthAccount extends BasePostgresEntity {

@Id
@GeneratedValue(strategy = GenerationType.UUID)
@Column(name = "user_oauth_account_id", columnDefinition = "uuid")
private UUID userOauthAccountId;

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id", nullable = false, columnDefinition = "uuid")
private User user;

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private AuthProvider provider;

@Column(name = "provider_uid", nullable = false)
private String providerUid;
}
Comment on lines +10 to +34
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

중복 엔티티 클래스가 존재합니다 - JPA 매핑 충돌 발생 위험

동일한 테이블(user_oauth_account)에 대한 엔티티 클래스가 이미 backend/src/main/java/org/sejongisc/backend/auth/entity/UserOauthAccount.java에 존재합니다.

두 엔티티의 주요 차이점:

  • 기존 엔티티에는 @UniqueConstraint(columnNames = {"provider", "provider_uid"})가 있지만 새 엔티티에는 없습니다
  • 서로 다른 패키지에 위치: user.entity vs auth.entity

이로 인한 문제:

  • JPA가 동일한 테이블에 대해 어떤 엔티티를 사용할지 결정할 수 없어 충돌이 발생합니다
  • 유니크 제약조건 누락으로 중복 OAuth 계정이 생성될 수 있습니다
  • UserServiceImploauthAccountRepositoryauth.entity.UserOauthAccount를 참조하고 있어 불일치가 발생합니다

다음 스크립트로 중복을 확인하세요:

두 엔티티 중 하나를 제거하거나, 용도가 다르다면 테이블 이름을 변경해야 합니다.


🏁 Script executed:

#!/bin/bash
# Description: 동일한 테이블에 매핑된 엔티티 클래스 확인

# user_oauth_account 테이블에 매핑된 모든 엔티티 검색
rg -n --type=java -C3 '@Table\(name\s*=\s*"user_oauth_account"'

# UserOauthAccount 클래스 정의 위치 확인
fd -e java UserOauthAccount.java

# UserOauthAccount를 사용하는 Repository 확인
rg -n --type=java -C3 'UserOauthAccountRepository'

Length of output: 5862


Now let me verify the specific details by checking the repository and entity usages:Based on my verification using the provided script output and web search findings, I can now generate the rewritten review comment:

중복 엔티티 클래스 제거 필요 - 동일 테이블에 매핑된 두 개의 JPA 엔티티 존재

동일한 테이블에 두 개의 엔티티를 매핑하는 것은 좋지 않은 설계 관행입니다. 현재 user_oauth_account 테이블에 대해 두 엔티티가 존재합니다:

  • backend/src/main/java/org/sejongisc/backend/user/entity/UserOauthAccount.java
  • backend/src/main/java/org/sejongisc/backend/auth/entity/UserOauthAccount.java

주요 문제:

  • auth.entity 버전에는 @UniqueConstraint(columnNames = {"provider", "provider_uid"})가 있지만, 새로운 user.entity 버전에는 없습니다
  • 여러 엔티티 타입을 동일한 데이터베이스 테이블 레코드에 대해 fetch하면 Persistence Context flush 시 불일치가 발생할 수 있습니다
  • UserOauthAccountRepositoryauth.entity.UserOauthAccount를 참조하고 있어, user.entity 버전과의 불일치가 발생합니다

해결 방안:

  1. user.entity.UserOauthAccount 클래스를 삭제하고, 기존 auth.entity.UserOauthAccount만 사용하거나
  2. 두 버전이 서로 다른 목적이 있다면 테이블을 분리하고 명확한 구조 설계 필요
🤖 Prompt for AI Agents
In backend/src/main/java/org/sejongisc/backend/user/entity/UserOauthAccount.java
around lines 10 to 34, there is a duplicate JPA entity mapping the same
user_oauth_account table which conflicts with
backend/src/main/java/org/sejongisc/backend/auth/entity/UserOauthAccount; remove
or consolidate the duplicate: delete this user.entity.UserOauthAccount (or merge
its intent into the auth.entity version), ensure the retained entity contains
the @UniqueConstraint(columnNames = {"provider","provider_uid"}) and all needed
fields/annotations, and update every import/usages (repositories, services,
DTOs) to reference the single entity package so there are no remaining
references to the removed class.

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.sejongisc.backend;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;

@SpringBootTest
@ActiveProfiles("test")
class BackendApplicationTests {

@Test
void contextLoads() {
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ void createSession_fail_noPermission() throws Exception {
}

@Test
@DisplayName("출석 세션 생성 실패: 유혀성 검증 오류")
@DisplayName("출석 세션 생성 실패: 유효성 검증 오류")
@WithMockUser(roles = "PRESIDENT")
void createSession_fail_validation() throws Exception {
//given
Expand Down
Loading