o2o-castad-backend/app/user/models.py

160 lines
5.2 KiB
Python

"""
User 모듈 SQLAlchemy 모델 정의
카카오 소셜 로그인 기반 사용자 관리 모델입니다.
주의: 이 모델은 현재 개발 중이므로 create_db_tables()에서 import하지 않습니다.
테이블 생성이 필요할 때 app/database/session.py의 create_db_tables()에
아래 import를 추가하세요:
from app.user.models import User # noqa: F401
"""
from datetime import datetime
from typing import Optional
from sqlalchemy import BigInteger, Boolean, DateTime, Index, String, func
from sqlalchemy.orm import Mapped, mapped_column
from app.database.session import Base
class User(Base):
"""
사용자 테이블 (카카오 소셜 로그인)
카카오 로그인을 통해 인증된 사용자 정보를 저장합니다.
Attributes:
id: 고유 식별자 (자동 증가)
kakao_id: 카카오 고유 ID (필수, 유니크)
email: 이메일 주소 (선택, 카카오에서 제공 시)
nickname: 카카오 닉네임 (선택)
profile_image_url: 카카오 프로필 이미지 URL (선택)
thumbnail_image_url: 카카오 썸네일 이미지 URL (선택)
is_active: 계정 활성화 상태 (기본 True)
is_admin: 관리자 여부 (기본 False)
last_login_at: 마지막 로그인 일시
created_at: 계정 생성 일시
updated_at: 계정 정보 수정 일시
카카오 API 응답 필드 매핑:
- kakao_id: id (카카오 회원번호)
- email: kakao_account.email
- nickname: kakao_account.profile.nickname 또는 properties.nickname
- profile_image_url: kakao_account.profile.profile_image_url
- thumbnail_image_url: kakao_account.profile.thumbnail_image_url
"""
__tablename__ = "user"
__table_args__ = (
Index("idx_user_kakao_id", "kakao_id", unique=True),
Index("idx_user_email", "email"),
Index("idx_user_is_active", "is_active"),
Index("idx_user_created_at", "created_at"),
{
"mysql_engine": "InnoDB",
"mysql_charset": "utf8mb4",
"mysql_collate": "utf8mb4_unicode_ci",
},
)
# ==========================================================================
# 기본 식별자
# ==========================================================================
id: Mapped[int] = mapped_column(
BigInteger,
primary_key=True,
nullable=False,
autoincrement=True,
comment="고유 식별자",
)
# ==========================================================================
# 카카오 소셜 로그인 필수 정보
# ==========================================================================
kakao_id: Mapped[int] = mapped_column(
BigInteger,
nullable=False,
unique=True,
comment="카카오 고유 ID (회원번호)",
)
# ==========================================================================
# 카카오에서 제공하는 사용자 정보 (선택적)
# ==========================================================================
email: Mapped[Optional[str]] = mapped_column(
String(255),
nullable=True,
comment="이메일 주소 (카카오 계정 이메일, 동의 시 제공)",
)
nickname: Mapped[Optional[str]] = mapped_column(
String(100),
nullable=True,
comment="카카오 닉네임",
)
profile_image_url: Mapped[Optional[str]] = mapped_column(
String(2048),
nullable=True,
comment="카카오 프로필 이미지 URL",
)
thumbnail_image_url: Mapped[Optional[str]] = mapped_column(
String(2048),
nullable=True,
comment="카카오 썸네일 이미지 URL",
)
# ==========================================================================
# 계정 상태 관리
# ==========================================================================
is_active: Mapped[bool] = mapped_column(
Boolean,
nullable=False,
default=True,
comment="계정 활성화 상태 (비활성화 시 로그인 차단)",
)
is_admin: Mapped[bool] = mapped_column(
Boolean,
nullable=False,
default=False,
comment="관리자 권한 여부",
)
# ==========================================================================
# 시간 정보
# ==========================================================================
last_login_at: Mapped[Optional[datetime]] = mapped_column(
DateTime,
nullable=True,
comment="마지막 로그인 일시",
)
created_at: Mapped[datetime] = mapped_column(
DateTime,
nullable=False,
server_default=func.now(),
comment="계정 생성 일시",
)
updated_at: Mapped[datetime] = mapped_column(
DateTime,
nullable=False,
server_default=func.now(),
onupdate=func.now(),
comment="계정 정보 수정 일시",
)
def __repr__(self) -> str:
return (
f"<User("
f"id={self.id}, "
f"kakao_id={self.kakao_id}, "
f"nickname='{self.nickname}', "
f"is_active={self.is_active}"
f")>"
)