diff --git a/TASKS.md b/TASKS.md index e1c0a09..1fc8437 100644 --- a/TASKS.md +++ b/TASKS.md @@ -16,18 +16,19 @@ This file tracks all active development tasks. It is based on the official `DEVE * **Goal:** Get the basic API, database, and Twitch login flow working. ### To Do -* `[ ]` **1.1: Database Schema:** Define SQLAlchemy models for `User` (id, username, platform, encrypted_tokens) and `Settings`. -* `[ ]` **1.2: Twitch OAuth API:** Create FastAPI endpoints for `/login/twitch` (redirect) and `/auth/twitch/callback` (handles token exchange). + * `[ ]` **1.3: Secure Token Storage:** Implement helper functions to `encrypt` and `decrypt` OAuth tokens before storing them in the database. * `[ ]` **1.4: Basic Session Management:** Create a simple session/JWT system to know *who* is logged in. * `[ ]` **1.5: Login Frontend:** Create a basic `login.html` file with a "Login with Twitch" button. ### In Progress -* `[ ]` **1.0: Project Skeleton** - @ramforth - * *Task:* Setup `main.py`, `requirements.txt`, and `.gitignore`. +* `[ ]` **1.1: Database Schema:** Define SQLAlchemy models for `User` (id, username, platform, encrypted_tokens) and `Settings`. @ramforth +* `[ ]` **1.2: Twitch OAuth API:** Create FastAPI endpoints for `/login/twitch` (redirect) and `/auth/twitch/callback` (handles token exchange).@ramforth + ### Done -* *(Nothing yet!)* +* `[ ]` **1.0: Project Skeleton** - @ramforth + * *Task:* Setup `main.py`, `requirements.txt`, and `.gitignore`. --- diff --git a/database.py b/database.py new file mode 100644 index 0000000..2924262 --- /dev/null +++ b/database.py @@ -0,0 +1,19 @@ +from sqlalchemy import create_engine +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker + +# Define the location of our SQLite database file. +# The ./. indicates it will be in the same directory as our project. +SQLALCHEMY_DATABASE_URL = "sqlite:///./multichat_overlay.db" + +# Create the SQLAlchemy engine. The `connect_args` is needed only for SQLite +# to allow it to be used by multiple threads, which FastAPI does. +engine = create_engine( + SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False} +) + +# Each instance of SessionLocal will be a database session. +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + +# This Base will be used by our model classes to inherit from. +Base = declarative_base() \ No newline at end of file diff --git a/models.py b/models.py new file mode 100644 index 0000000..7a1923d --- /dev/null +++ b/models.py @@ -0,0 +1,27 @@ +from sqlalchemy import Column, Integer, String, Text, ForeignKey +from sqlalchemy.orm import relationship + +from .database import Base + +class User(Base): + __tablename__ = "users" + + id = Column(Integer, primary_key=True, index=True) + # The user's unique ID from the platform (e.g., Twitch ID, YouTube Channel ID) + platform_user_id = Column(String, unique=True, index=True, nullable=False) + username = Column(String, index=True, nullable=False) + platform = Column(String, nullable=False) # e.g., "twitch", "youtube" + + # A JSON string or other format holding the encrypted access and refresh tokens + encrypted_tokens = Column(Text, nullable=False) + + settings = relationship("Setting", back_populates="owner", uselist=False) + +class Setting(Base): + __tablename__ = "settings" + + id = Column(Integer, primary_key=True, index=True) + custom_css = Column(Text, nullable=True) + user_id = Column(Integer, ForeignKey("users.id")) + + owner = relationship("User", back_populates="settings") \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index ed98526..17071cd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ fastapi uvicorn[standard] sqlalchemy -httpx \ No newline at end of file +httpx +cryptography \ No newline at end of file