Skip to content

Commit 2ae5707

Browse files
author
Kevin
committed
feat: Remove deprecated API components and Docker configurations
1 parent 598c860 commit 2ae5707

8 files changed

Lines changed: 0 additions & 801 deletions

File tree

api/auth.py

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +0,0 @@
1-
"""Authentication and authorization utilities"""
2-
3-
import os
4-
from datetime import datetime, timedelta
5-
from typing import Optional
6-
7-
import jwt
8-
from fastapi import Depends, HTTPException, status
9-
from fastapi.security import HTTPBearer
10-
from passlib.context import CryptContext
11-
from sqlalchemy.orm import Session
12-
13-
from api.database import get_db
14-
from api.models import User
15-
16-
# Security configuration
17-
SECRET_KEY = os.getenv("SECRET_KEY", "dev-secret-change-in-production")
18-
ALGORITHM = "HS256"
19-
ACCESS_TOKEN_EXPIRE_MINUTES = 30
20-
21-
security = HTTPBearer()
22-
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
23-
24-
25-
def verify_password(plain_password: str, hashed_password: str) -> bool:
26-
"""Verify a password against its hash"""
27-
return pwd_context.verify(plain_password, hashed_password)
28-
29-
30-
def get_password_hash(password: str) -> str:
31-
"""Hash a password"""
32-
return pwd_context.hash(password)
33-
34-
35-
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
36-
"""Create access token"""
37-
to_encode = data.copy()
38-
if expires_delta:
39-
expire = datetime.utcnow() + expires_delta
40-
else:
41-
expire = datetime.utcnow() + timedelta(minutes=15)
42-
43-
to_encode.update({"exp": expire})
44-
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
45-
return encoded_jwt
46-
47-
48-
def verify_token(token: str = Depends(security), db: Session = Depends(get_db)):
49-
"""Verify JWT token and return user"""
50-
try:
51-
payload = jwt.decode(token.credentials, SECRET_KEY, algorithms=[ALGORITHM])
52-
username: str = payload.get("sub")
53-
if username is None:
54-
raise HTTPException(
55-
status_code=status.HTTP_401_UNAUTHORIZED,
56-
detail="Could not validate credentials"
57-
)
58-
except jwt.PyJWTError:
59-
raise HTTPException(
60-
status_code=status.HTTP_401_UNAUTHORIZED,
61-
detail="Could not validate credentials"
62-
)
63-
64-
user = db.query(User).filter(User.username == username).first()
65-
if user is None:
66-
raise HTTPException(
67-
status_code=status.HTTP_401_UNAUTHORIZED,
68-
detail="User not found"
69-
)
70-
71-
return user
72-
73-
74-
def require_instructor(current_user: User = Depends(verify_token)):
75-
"""Require instructor role"""
76-
if not current_user.is_instructor:
77-
raise HTTPException(
78-
status_code=status.HTTP_403_FORBIDDEN,
79-
detail="Instructor access required"
80-
)
81-
return current_user
82-
)
83-
return current_user

api/database.py

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +0,0 @@
1-
"""Database configuration and session management"""
2-
3-
import os
4-
5-
from sqlalchemy import create_engine
6-
from sqlalchemy.ext.declarative import declarative_base
7-
from sqlalchemy.orm import sessionmaker
8-
from sqlalchemy.pool import StaticPool
9-
10-
# Database URL from environment
11-
DATABASE_URL = os.getenv(
12-
"DATABASE_URL",
13-
"postgresql://fllsim:fllsimpass@localhost:5432/fllsim"
14-
)
15-
16-
# Create engine
17-
if DATABASE_URL.startswith("sqlite"):
18-
engine = create_engine(
19-
DATABASE_URL,
20-
connect_args={"check_same_thread": False},
21-
poolclass=StaticPool
22-
)
23-
else:
24-
engine = create_engine(DATABASE_URL, pool_pre_ping=True)
25-
26-
# Session factory
27-
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
28-
29-
# Base class for models
30-
Base = declarative_base()
31-
32-
async def init_db():
33-
"""Initialize database tables"""
34-
Base.metadata.create_all(bind=engine)
35-
36-
def get_db():
37-
"""Get database session"""
38-
db = SessionLocal()
39-
try:
40-
yield db
41-
finally:
42-
db.close()
43-
db.close()

api/main.py

Lines changed: 0 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -1,146 +0,0 @@
1-
"""
2-
FLL-Sim Educational Platform API
3-
FastAPI-based REST API for the FLL-Sim educational platform
4-
"""
5-
6-
import logging
7-
import os
8-
import sys
9-
from contextlib import asynccontextmanager
10-
from pathlib import Path
11-
12-
from fastapi import Depends, FastAPI, HTTPException, status
13-
from fastapi.middleware.cors import CORSMiddleware
14-
from fastapi.middleware.gzip import GZipMiddleware
15-
from fastapi.responses import JSONResponse
16-
from fastapi.security import HTTPBearer
17-
18-
# Add project src to path for imports
19-
project_root = Path(__file__).parent.parent
20-
sys.path.insert(0, str(project_root / "src"))
21-
22-
from api.auth import verify_token
23-
from api.database import get_db, init_db
24-
from api.models import User
25-
from api.routers import analytics, auth, missions, simulations, students
26-
from fll_sim.education.educational_platform import EducationalPlatform
27-
from fll_sim.utils.logger import FLLLogger
28-
29-
# Configure logging
30-
logging.basicConfig(level=logging.INFO)
31-
logger = FLLLogger('FLLSimAPI')
32-
33-
# Security
34-
security = HTTPBearer()
35-
36-
@asynccontextmanager
37-
async def lifespan(app: FastAPI):
38-
"""Application lifespan events"""
39-
# Startup
40-
logger.info("Starting FLL-Sim API...")
41-
await init_db()
42-
logger.info("Database initialized")
43-
44-
# Initialize educational platform
45-
app.state.edu_platform = EducationalPlatform()
46-
logger.info("Educational platform initialized")
47-
48-
yield
49-
50-
# Shutdown
51-
logger.info("Shutting down FLL-Sim API...")
52-
53-
# Create FastAPI application
54-
app = FastAPI(
55-
title="FLL-Sim Educational Platform API",
56-
description="REST API for the FLL-Sim educational robotics platform",
57-
version="1.0.0",
58-
docs_url="/docs",
59-
redoc_url="/redoc",
60-
lifespan=lifespan
61-
)
62-
63-
# Add middleware
64-
app.add_middleware(
65-
CORSMiddleware,
66-
allow_origins=os.getenv("CORS_ORIGINS", "http://localhost:3000").split(","),
67-
allow_credentials=True,
68-
allow_methods=["*"],
69-
allow_headers=["*"],
70-
)
71-
app.add_middleware(GZipMiddleware, minimum_size=1000)
72-
73-
# Include routers
74-
app.include_router(auth.router, prefix="/api/v1/auth", tags=["Authentication"])
75-
app.include_router(students.router, prefix="/api/v1/students", tags=["Students"])
76-
app.include_router(missions.router, prefix="/api/v1/missions", tags=["Missions"])
77-
app.include_router(simulations.router, prefix="/api/v1/simulations", tags=["Simulations"])
78-
app.include_router(analytics.router, prefix="/api/v1/analytics", tags=["Analytics"])
79-
80-
@app.get("/")
81-
async def root():
82-
"""Root endpoint"""
83-
return {
84-
"message": "FLL-Sim Educational Platform API",
85-
"version": "1.0.0",
86-
"docs": "/docs"
87-
}
88-
89-
@app.get("/health")
90-
async def health_check():
91-
"""Health check endpoint"""
92-
try:
93-
# Check database connection
94-
db = next(get_db())
95-
db.execute("SELECT 1")
96-
97-
return {
98-
"status": "healthy",
99-
"database": "connected",
100-
"version": "1.0.0"
101-
}
102-
except Exception as e:
103-
logger.error(f"Health check failed: {e}")
104-
raise HTTPException(
105-
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
106-
detail="Service unhealthy"
107-
)
108-
109-
@app.get("/api/v1/platform/status")
110-
async def platform_status(current_user: User = Depends(verify_token)):
111-
"""Get educational platform status"""
112-
try:
113-
edu_platform = app.state.edu_platform
114-
115-
return {
116-
"platform_active": True,
117-
"active_sessions": len(edu_platform.active_sessions),
118-
"available_missions": len(edu_platform.mission_builder.missions),
119-
"system_status": "operational"
120-
}
121-
except Exception as e:
122-
logger.error(f"Platform status error: {e}")
123-
raise HTTPException(
124-
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
125-
detail="Failed to get platform status"
126-
)
127-
128-
@app.exception_handler(Exception)
129-
async def global_exception_handler(request, exc):
130-
"""Global exception handler"""
131-
logger.error(f"Unhandled exception: {exc}")
132-
return JSONResponse(
133-
status_code=500,
134-
content={"detail": "Internal server error"}
135-
)
136-
137-
if __name__ == "__main__":
138-
import uvicorn
139-
uvicorn.run(
140-
"main:app",
141-
host="0.0.0.0",
142-
port=8000,
143-
reload=True,
144-
log_level="info"
145-
)
146-
)

api/models.py

Lines changed: 0 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +0,0 @@
1-
"""Database models for FLL-Sim API"""
2-
3-
from sqlalchemy import (Boolean, Column, DateTime, ForeignKey, Integer, String,
4-
Text)
5-
from sqlalchemy.orm import relationship
6-
from sqlalchemy.sql import func
7-
8-
from api.database import Base
9-
10-
11-
class User(Base):
12-
"""User model"""
13-
__tablename__ = "users"
14-
15-
id = Column(Integer, primary_key=True, index=True)
16-
username = Column(String(50), unique=True, index=True, nullable=False)
17-
email = Column(String(100), unique=True, index=True, nullable=False)
18-
hashed_password = Column(String(255), nullable=False)
19-
full_name = Column(String(100))
20-
is_active = Column(Boolean, default=True)
21-
is_student = Column(Boolean, default=True)
22-
is_instructor = Column(Boolean, default=False)
23-
grade_level = Column(String(20))
24-
class_section = Column(String(50))
25-
created_at = Column(DateTime(timezone=True), server_default=func.now())
26-
27-
# Relationships
28-
simulation_results = relationship("SimulationResult", back_populates="user")
29-
progress_records = relationship("ProgressRecord", back_populates="user")
30-
31-
32-
class Mission(Base):
33-
"""Mission model"""
34-
__tablename__ = "missions"
35-
36-
id = Column(Integer, primary_key=True, index=True)
37-
name = Column(String(100), nullable=False)
38-
description = Column(Text)
39-
difficulty_level = Column(Integer, default=1)
40-
season = Column(String(50))
41-
objectives = Column(Text) # JSON string
42-
scoring_criteria = Column(Text) # JSON string
43-
is_active = Column(Boolean, default=True)
44-
created_at = Column(DateTime(timezone=True), server_default=func.now())
45-
46-
# Relationships
47-
simulation_results = relationship("SimulationResult", back_populates="mission")
48-
49-
50-
class SimulationResult(Base):
51-
"""Simulation result model"""
52-
__tablename__ = "simulation_results"
53-
54-
id = Column(Integer, primary_key=True, index=True)
55-
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
56-
mission_id = Column(Integer, ForeignKey("missions.id"))
57-
score = Column(Integer, default=0)
58-
completion_time = Column(Integer) # seconds
59-
success = Column(Boolean, default=False)
60-
program_code = Column(Text)
61-
error_log = Column(Text)
62-
robot_path = Column(Text) # JSON string
63-
created_at = Column(DateTime(timezone=True), server_default=func.now())
64-
65-
# Relationships
66-
user = relationship("User", back_populates="simulation_results")
67-
mission = relationship("Mission", back_populates="simulation_results")
68-
69-
70-
class ProgressRecord(Base):
71-
"""Student progress tracking"""
72-
__tablename__ = "progress_records"
73-
74-
id = Column(Integer, primary_key=True, index=True)
75-
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
76-
activity_type = Column(String(50)) # tutorial, mission, visual_programming
77-
activity_id = Column(String(100))
78-
status = Column(String(20)) # started, completed, failed
79-
progress_data = Column(Text) # JSON string
80-
notes = Column(Text)
81-
created_at = Column(DateTime(timezone=True), server_default=func.now())
82-
83-
# Relationships
84-
user = relationship("User", back_populates="progress_records")
85-
user = relationship("User", back_populates="progress_records")

0 commit comments

Comments
 (0)