# app/auth.py from fastapi import Depends, HTTPException, Form, Response, status from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from fastapi.templating import Jinja2Templates #from fastapi.responses import HTMLResponse #from fastapi.requests import Request from pydantic import BaseModel from sqlalchemy.orm import Session from models import User from database import get_db import jwt from passlib.context import CryptContext from datetime import datetime, timedelta templates = Jinja2Templates(directory="templates") oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") class AuthViews: def __init__(self): self.pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") self.SECRET_KEY = "your-secret-key" # Replace with your actual secret key self.ALGORITHM = "HS256" self.ACCESS_TOKEN_EXPIRE_MINUTES = 30 def verify_token(token: str = Depends(oauth2_scheme)): try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) return payload.get("sub") except JWTError: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", headers={"WWW-Authenticate": "Bearer"}, ) # User model class UserCreate(BaseModel): username: str password: str email: str def register(self, user: UserCreate, db: Session = Depends(get_db)): # Validate email format and check for existing users db_user = database.get_user_by_email(db, user.email) if db_user: raise HTTPException(status_code=400, detail="Email already registered") # Hash the password hashed_password = self.pwd_context.hash(user.password) # Generate a verification token verification_token = email.generate_verification_token(user.email) # Send a verification email (implement email.send_verification_email) # Create the user in the database user_in_db = models.User(email=user.email, hashed_password=hashed_password) db.add(user_in_db) db.commit() db.refresh(user_in_db) return user_in_db def verify_email(self, verification_token: str, db: Session = Depends(get_db)): # Verify the email using the token (implement email.verify_token) email = email.verify_token(verification_token) if not email: raise HTTPException(status_code=400, detail="Invalid verification token") # Get the user by email user = database.get_user_by_email(db, email) if not user: raise HTTPException(status_code=400, detail="User not found") if user.is_verified: raise HTTPException(status_code=400, detail="Email already verified") # Mark the email as verified user.is_verified = True db.commit() return {"message": "Email verification successful"} # Dependency for verifying the user's token def get_current_user(token: str = Depends(verify_token)): if not token: raise HTTPException(status_code=401, detail="Token not valid") return token # Function to generate JWT tokens def create_access_token(self, data: dict, expires_delta: timedelta): to_encode = data.copy() expire = datetime.utcnow() + expires_delta to_encode.update({"exp": expire}) encoded_jwt = jwt.encode(to_encode, self.SECRET_KEY, algorithm=self.ALGORITHM) return encoded_jwt # Your login route #@app.post("/auth/login", response_model=dict) def login(self, form_data: OAuth2PasswordRequestForm = Depends()): # Check email verification db_user = database.get_user_by_email(db, form_data.username) if not db_user or not self.pwd_context.verify(form_data.password, db_user.hashed_password): raise HTTPException(status_code=400, detail="Incorrect email or password") if not db_user.is_verified: raise HTTPException(status_code=400, detail="Email not verified") # Generate an access token access_token_expires = timedelta(minutes=self.ACCESS_TOKEN_EXPIRE_MINUTES) access_token = create_access_token({"sub": db_user.email}, access_token_expires) return {"access_token": access_token, "token_type": "bearer"} auth_views = AuthViews()