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
13 changes: 9 additions & 4 deletions db.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from models import Base # ensure models are imported so metadata knows all tables
import os

DATABASE_URL = "mysql+mysqlconnector://noteflow:NoteFlow123!@localhost/noteflow"
engine = create_engine(DATABASE_URL)
DATABASE_URL = os.getenv("DATABASE_URL", "mysql+mysqlconnector://noteflow:NoteFlow123!@localhost/noteflow")

engine = create_engine(DATABASE_URL, pool_pre_ping=True)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

# 데이터베이스 의존성
def init_db():
Base.metadata.create_all(bind=engine)

def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
db.close()
52 changes: 22 additions & 30 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,56 +1,48 @@
# src/main.py
# Backend/main.py
import os
from dotenv import load_dotenv
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles

from db import init_db
from routers.auth import router as auth_router
from routers.note import router as note_router
from routers.folder import router as folder_router
from fastapi.staticfiles import StaticFiles
from routers.file import router as file_router
import logging
import uvicorn
from routers.folder import router as folder_router
from routers.checklist import router as checklist_router
from routers.file import router as file_router

# 1) 환경변수 로드
load_dotenv()
import uvicorn

# 2) 로깅 설정
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
load_dotenv()

# 3) FastAPI 앱 생성
app = FastAPI()

# 4) CORS 설정
origins = [
"http://localhost:5174",
]

app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_origins=["*"], # 개발 중 전체 허용
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

# 5) 라우터 등록
# 정적 파일(업로드) 서빙
os.makedirs(os.path.join(os.path.dirname(__file__), "uploads"), exist_ok=True)
app.mount("/static", StaticFiles(directory=os.path.join(os.path.dirname(__file__), "uploads")), name="static")

# 라우터 등록
app.include_router(auth_router)
app.include_router(note_router)
app.include_router(folder_router)
app.include_router(folder_router)
app.include_router(file_router)
app.include_router(checklist_router)

# 6) 루트 엔드포인트
@app.get("/")
def read_root():
def root():
return {"message": "mini"}

# 7) 실행 설정
# 앱 시작 시(uvicorn main:app) 한 번만 테이블 생성 (개발용)
init_db()

if __name__ == "__main__":
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8080,
reload=True,
env_file=".env"
)
uvicorn.run("main:app", host="0.0.0.0", port=8080, reload=True)
9 changes: 8 additions & 1 deletion models/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
from .user import User
from .base import Base
from .user import User
from .folder import Folder
from .note import Note
from .file import File
from .checklist import Checklist

__all__ = ["Base", "User", "Folder", "Note", "File", "Checklist"]
5 changes: 3 additions & 2 deletions models/base.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
from sqlalchemy.orm import declarative_base

Base = declarative_base()
35 changes: 13 additions & 22 deletions models/checklist.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,17 @@
from sqlalchemy import Column, Integer, String, Enum, TIMESTAMP, text
from sqlalchemy import Column, Integer, String, Boolean, TIMESTAMP, ForeignKey, text
from sqlalchemy.orm import relationship
from .base import Base

class User(Base):
__tablename__ = "user"
class Checklist(Base):
__tablename__ = "checklist"

u_id = Column(Integer, primary_key=True, autoincrement=True) # PK
id = Column(String(50), unique=True, nullable=False) # 로그인 ID
email = Column(String(150), unique=True, nullable=False)
password = Column(String(255), nullable=False)
provider = Column(
Enum("local", "google", "kakao", "naver", name="provider_enum"),
nullable=False,
server_default="local",
)
created_at = Column(
TIMESTAMP, nullable=False, server_default=text("CURRENT_TIMESTAMP")
)
updated_at = Column(
TIMESTAMP,
nullable=False,
server_default=text("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"),
)
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("user.u_id", ondelete="CASCADE"), nullable=False)
title = Column(String(255), nullable=False)
is_clear = Column(Boolean, nullable=False, server_default=text("0"))
created_at = Column(TIMESTAMP, nullable=False, server_default=text("CURRENT_TIMESTAMP"))
updated_at = Column(TIMESTAMP, nullable=False,
server_default=text("CURRENT_TIMESTAMP"),
onupdate=text("CURRENT_TIMESTAMP"))

# 역참조: checklist 목록
checklists = relationship("Checklist", back_populates="user", cascade="all, delete-orphan")
user = relationship("User", back_populates="checklists")
21 changes: 13 additions & 8 deletions models/file.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
from sqlalchemy import Column, Integer, String, ForeignKey, TIMESTAMP, text
from sqlalchemy.orm import relationship
from .base import Base

class File(Base):
__tablename__ = 'file'
__tablename__ = "file"

id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey('user.u_id', ondelete='CASCADE'), nullable=False)
folder_id = Column(Integer, ForeignKey('folder.id', ondelete='SET NULL'), nullable=True)
note_id = Column(Integer, ForeignKey('note.id', ondelete='SET NULL'), nullable=True) # ✅ 첨부된 노트 ID
original_name = Column(String(255), nullable=False) # 유저가 업로드한 원본 파일 이름
saved_path = Column(String(512), nullable=False) # 서버에 저장된(실제) 경로
content_type = Column(String(100), nullable=False) # MIME 타입
created_at = Column(TIMESTAMP, nullable=False, server_default=text('CURRENT_TIMESTAMP'))
user_id = Column(Integer, ForeignKey("user.u_id", ondelete="CASCADE"), nullable=False)
folder_id = Column(Integer, ForeignKey("folder.id", ondelete="SET NULL"), nullable=True)
note_id = Column(Integer, ForeignKey("note.id", ondelete="SET NULL"), nullable=True)
original_name = Column(String(255), nullable=False)
saved_path = Column(String(512), nullable=False)
content_type = Column(String(100), nullable=False)
created_at = Column(TIMESTAMP, nullable=False, server_default=text("CURRENT_TIMESTAMP"))

# relations
user = relationship("User", back_populates="files")
note = relationship("Note", back_populates="files")
18 changes: 12 additions & 6 deletions models/folder.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
from sqlalchemy import Column, Integer, String, ForeignKey, TIMESTAMP, text
from sqlalchemy.orm import relationship
from .base import Base

class Folder(Base):
__tablename__ = 'folder'
__tablename__ = "folder"

id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey('user.u_id', ondelete='CASCADE'), nullable=False)
user_id = Column(Integer, ForeignKey("user.u_id", ondelete="CASCADE"), nullable=False)
name = Column(String(100), nullable=False)
parent_id = Column(Integer, ForeignKey('folder.id', ondelete='SET NULL'), nullable=True)
created_at = Column(TIMESTAMP, nullable=False, server_default=text('CURRENT_TIMESTAMP'))
parent_id = Column(Integer, ForeignKey("folder.id", ondelete="SET NULL"), nullable=True)
created_at = Column(TIMESTAMP, nullable=False, server_default=text("CURRENT_TIMESTAMP"))
updated_at = Column(TIMESTAMP, nullable=False,
server_default=text('CURRENT_TIMESTAMP'),
onupdate=text('CURRENT_TIMESTAMP'))
server_default=text("CURRENT_TIMESTAMP"),
onupdate=text("CURRENT_TIMESTAMP"))

# relations
user = relationship("User")
parent = relationship("Folder", remote_side=[id], backref="children")
notes = relationship("Note", back_populates="folder", cascade="all, delete")
20 changes: 13 additions & 7 deletions models/note.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
from sqlalchemy import Column, Integer, String, Text, Boolean, ForeignKey, TIMESTAMP, text
from sqlalchemy.orm import relationship
from .base import Base

class Note(Base):
__tablename__ = 'note'
__tablename__ = "note"

id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey('user.u_id', ondelete='CASCADE'), nullable=False)
folder_id = Column(Integer, ForeignKey('folder.id', ondelete='SET NULL'), nullable=True)
user_id = Column(Integer, ForeignKey("user.u_id", ondelete="CASCADE"), nullable=False)
folder_id = Column(Integer, ForeignKey("folder.id", ondelete="SET NULL"), nullable=True)
title = Column(String(255), nullable=False)
content = Column(Text)
is_favorite = Column(Boolean, nullable=False, server_default=text('FALSE'))
is_favorite = Column(Boolean, nullable=False, server_default=text("FALSE"))
last_accessed = Column(TIMESTAMP, nullable=True)
created_at = Column(TIMESTAMP, nullable=False, server_default=text('CURRENT_TIMESTAMP'))
created_at = Column(TIMESTAMP, nullable=False, server_default=text("CURRENT_TIMESTAMP"))
updated_at = Column(TIMESTAMP, nullable=False,
server_default=text('CURRENT_TIMESTAMP'),
onupdate=text('CURRENT_TIMESTAMP'))
server_default=text("CURRENT_TIMESTAMP"),
onupdate=text("CURRENT_TIMESTAMP"))

# relations
user = relationship("User", back_populates="notes")
folder = relationship("Folder", back_populates="notes")
files = relationship("File", back_populates="note", cascade="all, delete")
23 changes: 13 additions & 10 deletions models/user.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
from sqlalchemy import Column, Integer, String, Enum, TIMESTAMP, text
from sqlalchemy.orm import relationship
from .base import Base

class User(Base):
__tablename__ = 'user'
__tablename__ = "user"

u_id = Column(Integer, primary_key=True, autoincrement=True)
id = Column(String(50), nullable=False, unique=True)
id = Column(String(50), nullable=False, unique=True) # 로그인 ID 또는 소셜 ID
email = Column(String(150), nullable=False, unique=True)
password = Column(String(255), nullable=False)
provider = Column(
Enum('local','google','kakao','naver', name='provider_enum'),
nullable=False,
server_default=text("'local'")
)
created_at = Column(TIMESTAMP, nullable=False, server_default=text('CURRENT_TIMESTAMP'))
provider = Column(Enum("local", "google", "kakao", "naver", name="provider_enum"),
nullable=False, server_default=text("'local'"))
created_at = Column(TIMESTAMP, nullable=False, server_default=text("CURRENT_TIMESTAMP"))
updated_at = Column(TIMESTAMP, nullable=False,
server_default=text('CURRENT_TIMESTAMP'),
onupdate=text('CURRENT_TIMESTAMP'))
server_default=text("CURRENT_TIMESTAMP"),
onupdate=text("CURRENT_TIMESTAMP"))

# relations
notes = relationship("Note", back_populates="user", cascade="all, delete-orphan")
files = relationship("File", back_populates="user", cascade="all, delete-orphan")
checklists = relationship("Checklist", back_populates="user", cascade="all, delete-orphan")
2 changes: 2 additions & 0 deletions routers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from .auth import router as auth_router
from .checklist import router as checklist_router

routers = [
auth_router,
checklist_router
]
45 changes: 12 additions & 33 deletions routers/checklist.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,26 @@
# 변경/설명:
# - POST /checklists : 생성 전용
# - PATCH /checklists/{id}/clear : is_clear 0/1 설정
# - get_current_user는 user.u_id 제공 가정
# Backend/routers/checklist.py
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from db import get_db
from models.checklist import Checklist
from utils.jwt_utils import get_current_user

from app.schemas.checklist import ChecklistCreate, ChecklistClearUpdate
from app.models import Checklist # Checklist(u_id, checklist_title, is_clear)
from app.dependencies import get_db, get_current_user

router = APIRouter(prefix="/checklists", tags=["checklists"])
router = APIRouter(prefix="/api/v1/checklists", tags=["Checklists"])

@router.post("", status_code=status.HTTP_201_CREATED)
def create_checklist(
req: ChecklistCreate,
db: Session = Depends(get_db),
user=Depends(get_current_user),
):
obj = Checklist(
u_id=user.u_id, # ← 프로젝트의 사용자 키에 맞게
checklist_title=req.checklist_title,
is_clear=0 # 기본 0(미완)
)
def create_checklist(title: str, db: Session = Depends(get_db), user=Depends(get_current_user)):
obj = Checklist(user_id=user.u_id, title=title, is_clear=False)
db.add(obj)
db.commit()
db.refresh(obj)
return {"id": obj.id, "checklist_title": obj.checklist_title, "is_clear": obj.is_clear}
return {"id": obj.id, "title": obj.title, "is_clear": obj.is_clear}

@router.patch("/{checklist_id}/clear")
def set_clear_state(
checklist_id: int,
req: ChecklistClearUpdate, # {"is_clear": 0 | 1}
db: Session = Depends(get_db),
user=Depends(get_current_user),
):
obj = (
db.query(Checklist)
.filter(Checklist.id == checklist_id, Checklist.u_id == user.u_id)
.first()
)
def set_clear_state(checklist_id: int, is_clear: bool, db: Session = Depends(get_db), user=Depends(get_current_user)):
obj = db.query(Checklist).filter(Checklist.id == checklist_id, Checklist.user_id == user.u_id).first()
if not obj:
raise HTTPException(status_code=404, detail="Checklist not found")
obj.is_clear = int(req.is_clear) # 0/1 저장
obj.is_clear = bool(is_clear)
db.commit()
db.refresh(obj)
return {"id": obj.id, "is_clear": obj.is_clear}
return {"id": obj.id, "is_clear": obj.is_clear}
Loading
Loading