Skip to content
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
9 changes: 8 additions & 1 deletion app/api/routes.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from fastapi import APIRouter, Depends, Body, Query
from app.utils.jwt import verify_jwt
from fastapi.responses import JSONResponse
from sqlalchemy.orm import Session

Expand Down Expand Up @@ -212,6 +213,7 @@ def bookmark_education(
}
),
db: Session = Depends(get_db),
token_data=Depends(verify_jwt),
):
return save_bookmarked_education(data, db)

Expand Down Expand Up @@ -251,6 +253,7 @@ def bookmark_policy(
}
),
db: Session = Depends(get_db),
token_data=Depends(verify_jwt),
):
return save_policy_bookmarks(data, db)

Expand Down Expand Up @@ -360,6 +363,7 @@ def save_resume(
}
),
db: Session = Depends(get_db),
token_data=Depends(verify_jwt),
):
saved = save_resume_to_db(db, data)
return {"resume_id": saved.id, "message": "자기소개서가 저장되었습니다."}
Expand Down Expand Up @@ -401,5 +405,8 @@ def save_resume(
},
},
)
def get_user_resumes(userId: int, db: Session = Depends(get_db)):
def get_user_resumes(
userId: int,
db: Session = Depends(get_db),
token_data=Depends(verify_jwt)):
return get_resumes_by_user_id(db, userId)
12 changes: 12 additions & 0 deletions app/core/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from dotenv import load_dotenv
import os
from pydantic_settings import BaseSettings
import base64

load_dotenv()

Expand All @@ -20,6 +21,17 @@ class Settings(BaseSettings):
JOB_INFO_KEY: str
DATABASE_URL: str

JWT_SECRET_KEY_BASE64: str
JWT_ALGORITHM: str = "HS256"

# ✅ Base64 디코딩된 JWT secret 키
@property
def jwt_secret_bytes(self) -> bytes:
return base64.b64decode(self.JWT_SECRET_KEY_BASE64)

class Config:
env_file = ".env"

class Config:
env_file = ".env"

Expand Down
20 changes: 15 additions & 5 deletions app/core/db.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from sqlalchemy import create_engine, Column, DateTime, func
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from sqlalchemy.orm import sessionmaker

from app.core.config import settings

SQLALCHEMY_DATABASE_URL = settings.DATABASE_URL # .env에서 불러온 URL
SQLALCHEMY_DATABASE_URL = settings.DATABASE_URL
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

# BaseEntity에 해당하는 공통 필드 믹스인
class BaseEntity:
createdAt = Column(DateTime, default=func.now(), nullable=False)
updatedAt = Column(
DateTime, default=func.now(), onupdate=func.now(), nullable=False
)


# 모든 모델이 상속할 Base
Base = declarative_base(cls=BaseEntity)


# DB 세션 dependency
def get_db():
db = SessionLocal()
try:
Expand Down
22 changes: 22 additions & 0 deletions app/db_models/authentication_code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from sqlalchemy import Column, Integer, String, Boolean, DateTime, Enum as SqlEnum
from app.core.db import Base
import enum


# CodeStatus Enum
class CodeStatus(str, enum.Enum):
ACTIVE = "ACTIVE"
EXPIRED = "EXPIRED"


# AuthenticationCode 모델
class AuthenticationCode(Base):
__tablename__ = "AuthenticationCode"

id = Column(Integer, primary_key=True, index=True)

email = Column(String(50), nullable=False)
code = Column(String, unique=True, nullable=False)
isVerified = Column(Boolean, nullable=False)
status = Column(SqlEnum(CodeStatus), nullable=True)
expirationDate = Column(DateTime, nullable=False)
10 changes: 10 additions & 0 deletions app/db_models/base_entity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from sqlalchemy import Column, DateTime, func
from sqlalchemy.ext.declarative import declared_attr
from datetime import datetime


class TimestampMixin:
createdAt = Column(DateTime, default=func.now(), nullable=False)
updatedAt = Column(
DateTime, default=func.now(), onupdate=func.now(), nullable=False
)
21 changes: 21 additions & 0 deletions app/db_models/bookmark.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from app.core.db import Base


class Bookmark(Base):
__tablename__ = "Bookmark"

id = Column(Integer, primary_key=True, index=True)

user_id = Column(Integer, ForeignKey("User.id", ondelete="CASCADE"), nullable=False)
user = relationship("User", back_populates="bookmarks")

jobId = Column(Integer, nullable=True)
companyName = Column(String, nullable=True)
jobTitle = Column(String, nullable=True)
pay = Column(String, nullable=True)
time = Column(String, nullable=True)
location = Column(String, nullable=True)
deadline = Column(String, nullable=True)
registrationDate = Column(String, nullable=True)
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
from sqlalchemy import Column, Integer, String, Text, ForeignKey
from app.core.db import Base
from sqlalchemy.orm import relationship
from app.core.db import Base


class EducationInfo(Base):
__tablename__ = "EducationInfo"

id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("User.id", ondelete="CASCADE"), nullable=False)
title = Column(String(100), nullable=False)
url = Column(Text, nullable=False)

user_id = Column(Integer, ForeignKey("User.id", ondelete="CASCADE"), nullable=False)
user = relationship("User", back_populates="educationInfos")

title = Column(String(50), nullable=False)
url = Column(Text, nullable=True)
7 changes: 4 additions & 3 deletions app/db_models/policy.py → app/db_models/policy_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ class PolicyInfo(Base):
__tablename__ = "PolicyInfo"

id = Column(Integer, primary_key=True, index=True)

user_id = Column(Integer, ForeignKey("User.id", ondelete="CASCADE"), nullable=False)
user = relationship("User", back_populates="policyInfos")

category = Column(String(50), nullable=False)
title = Column(String(100), nullable=False)
title = Column(String(50), nullable=False)
description = Column(Text, nullable=True)
url = Column(Text, nullable=True)

user = relationship("User", back_populates="policyInfos")
16 changes: 16 additions & 0 deletions app/db_models/refresh_token.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.orm import relationship
from app.core.db import Base
from datetime import datetime


class RefreshToken(Base):
__tablename__ = "RefreshToken"

id = Column(Integer, primary_key=True, index=True)

refreshToken = Column(String(512), nullable=False)

expiryDate = Column(DateTime, nullable=False)

user = relationship("User", back_populates="refreshToken", uselist=False)
40 changes: 28 additions & 12 deletions app/db_models/resume.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,42 @@
from sqlalchemy import Column, Integer, String, ForeignKey, Text, Enum
from sqlalchemy import Column, Integer, String, Text, Enum as SqlEnum, ForeignKey
from sqlalchemy.orm import relationship
from app.core.db import Base
import enum


# Java의 ResumeCategory enum과 동일하게 정의
# ------------------ ResumeCategory Enum ------------------


class ResumeCategory(str, enum.Enum):
GENERAL = "GENERAL"
TECH = "TECH"
CAREER = "CAREER"
ACADEMIC = "ACADEMIC"
GROWTH = "GROWTH"
MOTIVATION = "MOTIVATION"
ASPIRATION = "ASPIRATION"
STRENGTH = "STRENGTH"
PROJECT_EXPERIENCE = "PROJECT_EXPERIENCE"

@property
def display_name(self):
return {
"GROWTH": "성장과정",
"MOTIVATION": "지원동기",
"ASPIRATION": "입사포부",
"STRENGTH": "강점약점",
"PROJECT_EXPERIENCE": "프로젝트경험",
}[self.value]


# ------------------ Resume 모델 ------------------


class Resume(Base):
__tablename__ = "Resume"

id = Column(Integer, primary_key=True, index=True)
user_id = Column(
Integer, ForeignKey("User.id", ondelete="CASCADE"), nullable=False
) # 테이블명 수정
title = Column(String(255), nullable=False)
content = Column(Text, nullable=False)
resume_category = Column(String(50), nullable=False)

user_id = Column(Integer, ForeignKey("User.id", ondelete="CASCADE"), nullable=False)
user = relationship("User", back_populates="resumes")

title = Column(String(50), nullable=False)
content = Column(Text, nullable=False)

resumeCategory = Column(SqlEnum(ResumeCategory), nullable=False)
56 changes: 39 additions & 17 deletions app/db_models/user.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,44 @@
# app/db_models/user.py

from sqlalchemy import Column, Integer, String, Enum, ForeignKey
from sqlalchemy import Column, Integer, String, Enum as SqlEnum, ForeignKey
from sqlalchemy.orm import relationship
from app.core.db import Base
import enum
from app.core.db import Base

# ------------------ ENUM 정의 ------------------


# enum 들 정의
class Gender(str, enum.Enum):
MALE = "MALE"
FEMALE = "FEMALE"


class Region(str, enum.Enum):
SEOUL = "SEOUL"
BUSAN = "BUSAN"
# etc...
GYEONGGI = "GYEONGGI"
INCHEON = "INCHEON"
GANGWON = "GANGWON"
DAEJEON = "DAEJEON"
SEJONG = "SEJONG"
CHUNGBUK = "CHUNGBUK"


class FinalEdu(str, enum.Enum):
HIGH_SCHOOL = "HIGH_SCHOOL"
ASSOCIATE = "ASSOCIATE"
BACHELOR = "BACHELOR"
MASTER = "MASTER"
DOCTOR = "DOCTOR"

@property
def description(self):
return {
"HIGH_SCHOOL": "고등학교 졸업",
"ASSOCIATE": "전문대학 졸업",
"BACHELOR": "대학교 졸업",
"MASTER": "석사 학위",
"DOCTOR": "박사 학위",
}[self.value]


class UserStatus(str, enum.Enum):
ACTIVE = "ACTIVE"
Expand All @@ -35,29 +50,36 @@ class Role(str, enum.Enum):
ADMIN = "ADMIN"


# User 모델
# ------------------ User 모델 정의 ------------------


class User(Base):
__tablename__ = "User" # ERD에 맞게 수정
__tablename__ = "User"

id = Column(Integer, primary_key=True, index=True)
name = Column(String(20), nullable=False)
primaryEmail = Column(String(50), unique=True)
password = Column(String(100), nullable=False)
age = Column(Integer, nullable=False)
gender = Column(Enum(Gender), nullable=False)
region = Column(Enum(Region), nullable=False)
gender = Column(SqlEnum(Gender), nullable=False)
region = Column(SqlEnum(Region), nullable=False)
job = Column(String(50), nullable=False)
career = Column(Integer, nullable=False)
finalEdu = Column(Enum(FinalEdu), nullable=False)
status = Column(Enum(UserStatus), nullable=False)
role = Column(Enum(Role), nullable=True)
finalEdu = Column(SqlEnum(FinalEdu), nullable=False)
status = Column(SqlEnum(UserStatus), nullable=False)
role = Column(SqlEnum(Role), nullable=True)
refresh_token_id = Column(Integer, ForeignKey("RefreshToken.id"), nullable=True)
refreshToken = relationship("RefreshToken", back_populates="user", uselist=False)

resumes = relationship(
"Resume", back_populates="user", cascade="all, delete-orphan"
bookmarks = relationship(
"Bookmark", back_populates="user", cascade="all, delete-orphan"
)
policyInfos = relationship(
"PolicyInfo", back_populates="user", cascade="all, delete-orphan"
)
educationInfos = relationship(
"EducationInfo", back_populates="user", cascade="all, delete-orphan"
)
policyInfos = relationship(
"PolicyInfo", back_populates="user", cascade="all, delete-orphan"
resumes = relationship(
"Resume", back_populates="user", cascade="all, delete-orphan"
)
2 changes: 1 addition & 1 deletion app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from app.api import routes
from fastapi.middleware.cors import CORSMiddleware
from app.core.db import engine
from app.db_models.education import EducationInfo
from app.db_models.education_info import EducationInfo
from app.db_models.user import User # 새로 만들 예정
from app.core.db import Base

Expand Down
10 changes: 10 additions & 0 deletions app/models/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from pydantic import BaseModel
from datetime import datetime


class TimestampMixin(BaseModel):
createdAt: datetime
updatedAt: datetime

class Config:
orm_mode = True
3 changes: 2 additions & 1 deletion app/models/eduSchemas.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from pydantic import BaseModel
from typing import List
from app.models.common import TimestampMixin


class EducationSearchRequest(BaseModel):
Expand All @@ -26,6 +27,6 @@ class EducationItem(BaseModel):
url: str


class EducationBookmarkRequest(BaseModel):
class EducationBookmarkRequest(TimestampMixin):
user_id: int
bookmarks: List[EducationItem]
Loading