CoolFace
Apppublic

Prashu15/FeedbackGenerator

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
app.py176 linesDownload Raw Back to root
1from fastapi import FastAPI, UploadFile, File, HTTPException, Depends, status2from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm3from fastapi.responses import JSONResponse, FileResponse4from fastapi.staticfiles import StaticFiles5from pathlib import Path6import os7from feedback_logic import evaluate_assignment8from pydantic import BaseModel9from passlib.context import CryptContext10import sqlite311from jose import JWTError, jwt12from datetime import datetime, timedelta13import secrets14 15app = FastAPI(title="Automatic Feedback Generator")16 17# Mount static files directory18app.mount("/static", StaticFiles(directory="static"), name="static")19 20# Configuration21TEMP_DIR = Path("/tmp/uploads")22TEMP_DIR.mkdir(parents=True, exist_ok=True)23SUPPORTED_FORMATS = {".pdf", ".doc", ".docx", ".png", ".jpg", ".jpeg"}24SECRET_KEY = secrets.token_urlsafe(32)25ALGORITHM = "HS256"26ACCESS_TOKEN_EXPIRE_MINUTES = 3027 28# Database setup29DB_PATH = "/tmp/users.db"30def init_db():31    with sqlite3.connect(DB_PATH) as conn:32        c = conn.cursor()33        c.execute('''CREATE TABLE IF NOT EXISTS users (34            id INTEGER PRIMARY KEY AUTOINCREMENT,35            email TEXT UNIQUE NOT NULL,36            password TEXT NOT NULL,37            name TEXT NOT NULL38        )''')39        conn.commit()40init_db()41 42# Password hashing43pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")44oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")45 46# Pydantic models47class User(BaseModel):48    email: str49    name: str50    password: str51 52class Token(BaseModel):53    access_token: str54    token_type: str55 56# Authentication functions57def verify_password(plain_password, hashed_password):58    return pwd_context.verify(plain_password, hashed_password)59 60def get_password_hash(password):61    return pwd_context.hash(password)62 63def create_access_token(data: dict):64    to_encode = data.copy()65    expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)66    to_encode.update({"exp": expire})67    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)68    return encoded_jwt69 70async def get_current_user(token: str = Depends(oauth2_scheme)):71    credentials_exception = HTTPException(72        status_code=status.HTTP_401_UNAUTHORIZED,73        detail="Could not validate credentials",74        headers={"WWW-Authenticate": "Bearer"},75    )76    try:77        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])78        email: str = payload.get("sub")79        if email is None:80            raise credentials_exception81    except JWTError:82        raise credentials_exception83    with sqlite3.connect(DB_PATH) as conn:84        c = conn.cursor()85        c.execute("SELECT email, name FROM users WHERE email = ?", (email,))86        user = c.fetchone()87        if user is None:88            raise credentials_exception89        return {"email": user[0], "name": user[1]}90 91@app.post("/register/")92async def register(user: User):93    try:94        with sqlite3.connect(DB_PATH) as conn:95            c = conn.cursor()96            hashed_password = get_password_hash(user.password)97            c.execute(98                "INSERT INTO users (email, name, password) VALUES (?, ?, ?)",99                (user.email, user.name, hashed_password)100            )101            conn.commit()102        return {"message": "User registered successfully"}103    except sqlite3.IntegrityError:104        raise HTTPException(status_code=400, detail="Email already registered")105 106@app.post("/token", response_model=Token)107async def login(form_data: OAuth2PasswordRequestForm = Depends()):108    with sqlite3.connect(DB_PATH) as conn:109        c = conn.cursor()110        c.execute("SELECT email, password FROM users WHERE email = ?", (form_data.username,))111        user = c.fetchone()112        if not user or not verify_password(form_data.password, user[1]):113            raise HTTPException(114                status_code=status.HTTP_401_UNAUTHORIZED,115                detail="Incorrect email or password",116                headers={"WWW-Authenticate": "Bearer"},117            )118    access_token = create_access_token(data={"sub": user[0]})119    return {"access_token": access_token, "token_type": "bearer"}120 121@app.post("/evaluate/")122async def evaluate(123    assignment: UploadFile = File(...),124    rubric: UploadFile = File(...),125    current_user: dict = Depends(get_current_user)126):127    try:128        # Validate file extensions129        assignment_ext = os.path.splitext(assignment.filename)[1].lower()130        rubric_ext = os.path.splitext(rubric.filename)[1].lower()131        132        if assignment_ext not in SUPPORTED_FORMATS:133            raise HTTPException(status_code=400, detail=f"Unsupported assignment file format: {assignment_ext}")134        if rubric_ext not in {".pdf", ".doc", ".docx"}:135            raise HTTPException(status_code=400, detail=f"Unsupported rubric file format: {rubric_ext}")136 137        # Save uploaded files temporarily138        assignment_path = TEMP_DIR / assignment.filename139        rubric_path = TEMP_DIR / rubric.filename140 141        try:142            # Write assignment file143            with open(assignment_path, "wb") as f:144                content = await assignment.read()145                if len(content) > 100 * 1024 * 1024:  # Limit to 100MB146                    raise HTTPException(status_code=400, detail="Assignment file too large (max 100MB)")147                f.write(content)148            149            # Write rubric file150            with open(rubric_path, "wb") as f:151                content = await rubric.read()152                if len(content) > 10 * 1024 * 1024:  # Limit to 10MB for rubric153                    raise HTTPException(status_code=400, detail="Rubric file too large (max 10MB)")154                f.write(content)155 156            # Evaluate assignment157            feedback = evaluate_assignment(str(assignment_path), str(rubric_path))158            return JSONResponse(content={"feedback": feedback, "user": current_user["email"]})159        160        finally:161            # Clean up temporary files162            if assignment_path.exists():163                os.remove(assignment_path)164            if rubric_path.exists():165                os.remove(rubric_path)166 167    except Exception as e:168        raise HTTPException(status_code=500, detail=f"Error processing files: {str(e)}")169 170@app.get("/")171async def root():172    return FileResponse("static/index.html")173 174@app.get("/index.html")175async def serve_index():176    return FileResponse("static/index.html")