* Add email OTP authentication system and private room management ## Authentication System - Implement email OTP-based authentication with User and OTPToken models - Add auth.py module with OTP generation, email sending, and session management - Create authentication endpoints: /auth/send-otp, /auth/verify-otp, /auth/claim-name, /auth/status, /auth/logout - Add authentication modal UI with email verification and display name claiming - Support SMTP configuration via environment variables (optional) ## Room Privacy & Ownership - Add is_private, is_archived, owner_id, and forked_from_id fields to Room model - Implement private rooms (single-user, owner-only access) - Add room forking: users can fork public rooms to public or private - Add room archive/delete endpoints (owner-only operations) - Implement access control for private room viewing ## UI Improvements - Add public/private room tabs in sidebar - Show authentication prompt in private rooms tab for non-authenticated users - Add room action buttons (fork, archive, delete) with proper permissions - Update homepage with statistics (public/private rooms, active users, active rooms) - Remove model/voice from URL query strings, use localStorage exclusively ## Database Migration - Create migration 2025011100 for User, OTPToken tables and Room model updates - Add indexes for email, display_name, is_private, is_archived, owner_id ## Breaking Changes - URL parameters now only include username (model/voice moved to localStorage) - Private rooms require authentication to access - Room creation can now require authentication (for private rooms) * Update README with authentication and private room documentation * Simplify README to be less verbose * Add missing session import to fix linter errors * Fix migration dependency to resolve multiple heads conflict * asdf * Fix SQLAlchemy auto-correlation error in homepage statistics query * Change tagline from AI-Powered to Machine Learning Powered * Add dedicated authentication page instead of modal - Create new /auth route with full-page authentication flow - Remove modal code from index.html - Update Sign in link to point to /auth page - Auth page has 4-step flow: email, OTP, display name, success - Better UX with gradient background and cleaner design * Fix migration: remove batch_alter_table to avoid circular dependency - Use op.add_column() directly instead of batch_alter_table() - Remove foreign key constraints (defined in models, not needed in migration) - User and OTPToken tables created by db.create_all() in make init-db - Fixes CircularDependencyError during migration * Fix migration: check if columns exist before adding - Use inspector to check existing columns and indexes - Only add columns/indexes if they don't already exist - Handles case where db.create_all() was run before migration - Fixes 'duplicate column name' error * Add profile page, room browsing, and updated_at timestamp Features: - Profile page with username change and dark/light mode settings - Browse page for discovering public and private rooms - Room updated_at timestamp (integer Unix epoch) that updates on new messages - Dynamic room tabs based on current room type (public/private) - Fork and delete room actions moved to right sidebar utility belt - Remove archive feature and success alerts from room actions Technical changes: - Add updated_at column to Room model (integer timestamp) - Add /profile route with authentication requirement - Add /browse route for room discovery - Add API endpoints for username availability check and update - Update room.updated_at on message creation in app.py:1189 - Wider right sidebar (25% instead of 15%) for better button layout - Profile link on homepage and browse page for authenticated users --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: russell@unturf. <russell@unturf.com>
58 lines
1.9 KiB
Python
58 lines
1.9 KiB
Python
"""Add authentication system with User, OTPToken models and Room ownership fields
|
|
|
|
Revision ID: 2025011100
|
|
Revises: 5d93cdf18549
|
|
Create Date: 2025-01-11 00:00:00.000000
|
|
|
|
"""
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.dialects import sqlite
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision = "2025011100"
|
|
down_revision = "5d93cdf18549"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade():
|
|
# Add new columns to Room table
|
|
# Note: User and OTPToken tables are created by db.create_all() in make init-db
|
|
# Check if columns exist before adding (in case db.create_all() was run first)
|
|
|
|
conn = op.get_bind()
|
|
inspector = sa.inspect(conn)
|
|
columns = [col['name'] for col in inspector.get_columns('room')]
|
|
|
|
if 'is_private' not in columns:
|
|
op.add_column('room', sa.Column('is_private', sa.Boolean(), nullable=False, server_default='0'))
|
|
|
|
if 'is_archived' not in columns:
|
|
op.add_column('room', sa.Column('is_archived', sa.Boolean(), nullable=False, server_default='0'))
|
|
|
|
if 'owner_id' not in columns:
|
|
op.add_column('room', sa.Column('owner_id', sa.Integer(), nullable=True))
|
|
|
|
if 'created_at' not in columns:
|
|
op.add_column('room', sa.Column('created_at', sa.DateTime(), nullable=False, server_default=sa.text('CURRENT_TIMESTAMP')))
|
|
|
|
if 'forked_from_id' not in columns:
|
|
op.add_column('room', sa.Column('forked_from_id', sa.Integer(), nullable=True))
|
|
|
|
# Create indexes (check if they exist first)
|
|
indexes = [idx['name'] for idx in inspector.get_indexes('room')]
|
|
|
|
if 'ix_room_is_private' not in indexes:
|
|
op.create_index(op.f('ix_room_is_private'), 'room', ['is_private'], unique=False)
|
|
|
|
if 'ix_room_is_archived' not in indexes:
|
|
op.create_index(op.f('ix_room_is_archived'), 'room', ['is_archived'], unique=False)
|
|
|
|
if 'ix_room_owner_id' not in indexes:
|
|
op.create_index(op.f('ix_room_owner_id'), 'room', ['owner_id'], unique=False)
|
|
|
|
|
|
def downgrade():
|
|
pass
|