Add comprehensive database integration, authentication, and admin dashboard
This commit introduces major enhancements to Talk2Me: ## Database Integration - PostgreSQL support with SQLAlchemy ORM - Redis integration for caching and real-time analytics - Automated database initialization scripts - Migration support infrastructure ## User Authentication System - JWT-based API authentication - Session-based web authentication - API key authentication for programmatic access - User roles and permissions (admin/user) - Login history and session tracking - Rate limiting per user with customizable limits ## Admin Dashboard - Real-time analytics and monitoring - User management interface (create, edit, delete users) - System health monitoring - Request/error tracking - Language pair usage statistics - Performance metrics visualization ## Key Features - Dual authentication support (token + user accounts) - Graceful fallback for missing services - Non-blocking analytics middleware - Comprehensive error handling - Session management with security features ## Bug Fixes - Fixed rate limiting bypass for admin routes - Added missing email validation method - Improved error handling for missing database tables - Fixed session-based authentication for API endpoints 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
149
init_auth_db.py
Normal file
149
init_auth_db.py
Normal file
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Initialize authentication database and create default admin user"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import getpass
|
||||
from flask import Flask
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
# Add parent directory to path
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from config import init_app as init_config
|
||||
from database import db, init_db
|
||||
from auth_models import User, bcrypt
|
||||
from auth import create_user
|
||||
|
||||
def create_admin_user():
|
||||
"""Create the default admin user"""
|
||||
# Skip if running non-interactively
|
||||
if not sys.stdin.isatty():
|
||||
print("Running non-interactively, skipping interactive admin creation.")
|
||||
return True
|
||||
|
||||
print("\n=== Talk2Me Admin User Setup ===\n")
|
||||
|
||||
# Get admin credentials
|
||||
while True:
|
||||
email = input("Admin email: ").strip()
|
||||
if '@' in email and '.' in email:
|
||||
break
|
||||
print("Please enter a valid email address.")
|
||||
|
||||
while True:
|
||||
username = input("Admin username: ").strip()
|
||||
if len(username) >= 3:
|
||||
break
|
||||
print("Username must be at least 3 characters.")
|
||||
|
||||
while True:
|
||||
password = getpass.getpass("Admin password (min 8 chars): ")
|
||||
if len(password) >= 8:
|
||||
password_confirm = getpass.getpass("Confirm password: ")
|
||||
if password == password_confirm:
|
||||
break
|
||||
print("Passwords don't match. Try again.")
|
||||
else:
|
||||
print("Password must be at least 8 characters.")
|
||||
|
||||
full_name = input("Full name (optional): ").strip() or None
|
||||
|
||||
# Create admin user
|
||||
print("\nCreating admin user...")
|
||||
user, error = create_user(
|
||||
email=email,
|
||||
username=username,
|
||||
password=password,
|
||||
full_name=full_name,
|
||||
role='admin',
|
||||
is_verified=True
|
||||
)
|
||||
|
||||
if error:
|
||||
print(f"Error creating admin: {error}")
|
||||
return False
|
||||
|
||||
# Set higher rate limits for admin
|
||||
user.rate_limit_per_minute = 300
|
||||
user.rate_limit_per_hour = 5000
|
||||
user.rate_limit_per_day = 50000
|
||||
|
||||
# Add all permissions
|
||||
user.permissions = ['all']
|
||||
|
||||
db.session.commit()
|
||||
|
||||
print(f"\n✅ Admin user created successfully!")
|
||||
print(f" Email: {user.email}")
|
||||
print(f" Username: {user.username}")
|
||||
print(f" API Key: {user.api_key}")
|
||||
print(f"\n📝 Save your API key securely. You can use it to authenticate API requests.")
|
||||
print(f"\n🔐 Login at: http://localhost:5005/login")
|
||||
print(f"📊 Admin dashboard: http://localhost:5005/admin/users")
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def init_database():
|
||||
"""Initialize the database with all tables"""
|
||||
# Create Flask app
|
||||
app = Flask(__name__)
|
||||
|
||||
# Initialize configuration
|
||||
init_config(app)
|
||||
|
||||
# Initialize bcrypt
|
||||
bcrypt.init_app(app)
|
||||
|
||||
# Initialize database
|
||||
init_db(app)
|
||||
|
||||
with app.app_context():
|
||||
print("Creating database tables...")
|
||||
|
||||
# Import all models to ensure they're registered
|
||||
from auth_models import User, LoginHistory, UserSession, RevokedToken
|
||||
from database import Translation, Transcription, UserPreferences, UsageAnalytics, ApiKey
|
||||
|
||||
# Create all tables
|
||||
db.create_all()
|
||||
print("✅ Database tables created successfully!")
|
||||
|
||||
# Check if admin user already exists
|
||||
admin_exists = User.query.filter_by(role='admin').first()
|
||||
|
||||
if admin_exists:
|
||||
print(f"\n⚠️ Admin user already exists: {admin_exists.username}")
|
||||
# Skip creating new admin if running non-interactively
|
||||
if not sys.stdin.isatty():
|
||||
print("Running non-interactively, skipping admin user creation.")
|
||||
return
|
||||
create_new = input("Create another admin user? (y/n): ").lower().strip()
|
||||
if create_new != 'y':
|
||||
print("\nExiting without creating new admin.")
|
||||
return
|
||||
|
||||
# Create admin user
|
||||
if not create_admin_user():
|
||||
print("\n❌ Failed to create admin user.")
|
||||
sys.exit(1)
|
||||
|
||||
print("\n✨ Authentication system initialized successfully!")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
init_database()
|
||||
except KeyboardInterrupt:
|
||||
print("\n\nSetup cancelled by user.")
|
||||
sys.exit(0)
|
||||
except Exception as e:
|
||||
print(f"\n❌ Error during setup: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
Reference in New Issue
Block a user