|
|
|
from fastapi import APIRouter, Depends, HTTPException, Form, Response, status, FastAPI |
|
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm |
|
from pydantic import BaseModel |
|
from sqlalchemy.orm import Session |
|
from app.models import User |
|
from app.database import get_db |
|
from jose import jwt |
|
from passlib.context import CryptContext |
|
from datetime import datetime, timedelta |
|
|
|
router = APIRouter() |
|
app = FastAPI() |
|
templates = Jinja2Templates(directory="templates") |
|
class AuthViews: |
|
def __init__(self): |
|
self.pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") |
|
self.SECRET_KEY = "your-secret-key" |
|
self.ALGORITHM = "HS256" |
|
self.ACCESS_TOKEN_EXPIRE_MINUTES = 30 |
|
|
|
def register(self, user: UserCreate, db: Session = Depends(get_db)): |
|
|
|
db_user = database.get_user_by_email(db, user.email) |
|
if db_user: |
|
raise HTTPException(status_code=400, detail="Email already registered") |
|
|
|
|
|
hashed_password = self.pwd_context.hash(user.password) |
|
|
|
|
|
verification_token = email.generate_verification_token(user.email) |
|
|
|
|
|
|
|
|
|
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)): |
|
|
|
email = email.verify_token(verification_token) |
|
if not email: |
|
raise HTTPException(status_code=400, detail="Invalid verification token") |
|
|
|
|
|
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") |
|
|
|
|
|
user.is_verified = True |
|
db.commit() |
|
return {"message": "Email verification successful"} |
|
|
|
|
|
def login(self, form_data: OAuth2PasswordRequestForm = Depends()): |
|
|
|
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") |
|
|
|
|
|
access_token_expires = timedelta(minutes=self.ACCESS_TOKEN_EXPIRE_MINUTES) |
|
access_token = jwt.encode( |
|
{"sub": db_user.email, "exp": datetime.utcnow() + access_token_expires}, |
|
self.SECRET_KEY, |
|
algorithm=self.ALGORITHM, |
|
) |
|
|
|
return {"access_token": access_token, "token_type": "bearer"} |
|
|
|
|
|
|
|
from app.models import User |
|
from app.database import get_user_by_email |
|
|
|
|
|
|
|
|
|
|
|
auth_views = AuthViews() |
|
|
|
@app.get("/login", response_class=HTMLResponse) |
|
async def login(request: Request): |
|
return templates.TemplateResponse("login.html", {"request": request}) |
|
|
|
@app.get("/register", response_class=HTMLResponse) |
|
async def register(request: Request): |
|
return templates.TemplateResponse("register.html", {"request": request}) |
|
|
|
@app.get("/verify/{verification_token}", response_class=HTMLResponse) |
|
async def verify_email(verification_token: str, request: Request): |
|
|
|
return templates.TemplateResponse("verify.html", {"request": request}) |
|
|
|
|
|
@app.get("/protected", response_model=str) |
|
async def protected_route(request: Request, token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)): |
|
|
|
user = verify_token(token, SECRET_KEY, ALGORITHM) |
|
if user is None: |
|
raise HTTPException(status_code=401, detail="Invalid or expired token") |
|
|
|
|
|
db_user = get_user_by_email(db, user) |
|
|
|
if db_user is None: |
|
raise HTTPException(status_code=401, detail="User not found in the database") |
|
|
|
|
|
return templates.TemplateResponse("protected.html", {"request": request, "user": db_user.username}) |