From 1b31d4bf30f5029ebfd43ac7653459f47a94d554 Mon Sep 17 00:00:00 2001 From: agent-bot Date: Mon, 17 Aug 2026 16:56:46 +0000 Subject: [PATCH] WIP checkpoint: Scaffold FastAPI backend project structure --- backend/app/models/__init__.py | 6 ++++++ backend/app/models/asset.py | 36 ++++++++++++++++++++++++++++++++++ backend/app/models/session.py | 18 +++++++++++++++++ backend/app/models/user.py | 15 ++++++++++++++ backend/app/models/world.py | 27 +++++++++++++++++++++++++ 5 files changed, 102 insertions(+) create mode 100644 backend/app/models/__init__.py create mode 100644 backend/app/models/asset.py create mode 100644 backend/app/models/session.py create mode 100644 backend/app/models/user.py create mode 100644 backend/app/models/world.py diff --git a/backend/app/models/__init__.py b/backend/app/models/__init__.py new file mode 100644 index 0000000..96e2dc3 --- /dev/null +++ b/backend/app/models/__init__.py @@ -0,0 +1,6 @@ +from app.models.user import User +from app.models.session import Session +from app.models.world import World +from app.models.asset import Asset + +__all__ = ["User", "Session", "World", "Asset"] diff --git a/backend/app/models/asset.py b/backend/app/models/asset.py new file mode 100644 index 0000000..ba27c53 --- /dev/null +++ b/backend/app/models/asset.py @@ -0,0 +1,36 @@ +from sqlalchemy import Column, Integer, String, ForeignKey, Text, DateTime, Enum as SAEnum +from sqlalchemy.orm import relationship +from sqlalchemy.sql import func +import enum + +from app.database import Base + + +class AssetType(str, enum.Enum): + IMAGE = "image" + AUDIO = "audio" + VIDEO = "video" + DOCUMENT = "document" + MODEL_3D = "model_3d" + OTHER = "other" + + +class Asset(Base): + __tablename__ = "assets" + + id = Column(Integer, primary_key=True, index=True) + name = Column(String(255), nullable=False) + description = Column(Text, nullable=True) + asset_type = Column(SAEnum(AssetType), nullable=False) + file_path = Column(String(512), nullable=False) + file_size = Column(Integer, nullable=True) + mime_type = Column(String(128), nullable=True) + metadata_json = Column(Text, nullable=True) + world_id = Column(Integer, ForeignKey("worlds.id"), nullable=True) + owner_id = Column(Integer, ForeignKey("users.id"), nullable=False) + is_public = Column(Integer, default=0, nullable=False) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) + + owner = relationship("User", back_populates="assets") + world = relationship("World", back_populates="assets") diff --git a/backend/app/models/session.py b/backend/app/models/session.py new file mode 100644 index 0000000..6f94edb --- /dev/null +++ b/backend/app/models/session.py @@ -0,0 +1,18 @@ +from sqlalchemy import Column, String, DateTime, ForeignKey, Boolean +from sqlalchemy.orm import relationship +from sqlalchemy.sql import func +from app.database import Base + + +class Session(Base): + __tablename__ = "sessions" + + id = Column(String, primary_key=True) + user_id = Column(String, ForeignKey("users.id", ondelete="CASCADE"), nullable=False) + token = Column(String, unique=True, index=True, nullable=False) + expires_at = Column(DateTime(timezone=True), nullable=False) + is_active = Column(Boolean, default=True) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) + + user = relationship("User", back_populates="sessions") diff --git a/backend/app/models/user.py b/backend/app/models/user.py new file mode 100644 index 0000000..626a2e0 --- /dev/null +++ b/backend/app/models/user.py @@ -0,0 +1,15 @@ +from sqlalchemy import Column, Integer, String, Boolean, DateTime +from sqlalchemy.sql import func +from app.database import Base + + +class User(Base): + __tablename__ = "users" + + id = Column(Integer, primary_key=True, index=True) + username = Column(String(50), unique=True, index=True, nullable=False) + email = Column(String(120), unique=True, index=True, nullable=False) + hashed_password = Column(String(255), nullable=False) + is_active = Column(Boolean, default=True) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column(DateTime(timezone=True), onupdate=func.now()) diff --git a/backend/app/models/world.py b/backend/app/models/world.py new file mode 100644 index 0000000..97e37fc --- /dev/null +++ b/backend/app/models/world.py @@ -0,0 +1,27 @@ +from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, Enum +from sqlalchemy.orm import relationship +from sqlalchemy.sql import func +import enum + +from app.database import Base + + +class WorldVisibility(enum.Enum): + PUBLIC = "public" + PRIVATE = "private" + FRIENDS_ONLY = "friends_only" + + +class World(Base): + __tablename__ = "worlds" + + id = Column(Integer, primary_key=True, index=True) + name = Column(String(255), nullable=False) + description = Column(Text, nullable=True) + owner_id = Column(Integer, ForeignKey("users.id"), nullable=False) + visibility = Column(Enum(WorldVisibility), default=WorldVisibility.PUBLIC) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column(DateTime(timezone=True), onupdate=func.now()) + + owner = relationship("User", back_populates="worlds") + assets = relationship("Asset", back_populates="world", cascade="all, delete-orphan")