Loginauth / main.py
Gregniuki's picture
Update main.py
1deefa3
raw
history blame
7.81 kB
#main.py
from fastapi import FastAPI, Form, Depends, HTTPException, status
from fastapi.requests import Request
from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session
from auth import verify_token, oauth2_scheme, auth_views, register, UserCreate, authenticate_user, get_user_by_verification_token
from database import get_db, get_user_by_email
from datetime import timedelta
#from typing import Optional
#import auth
#import tts
import os
my_secret_key = os.environ['my_secret_key']
app = FastAPI()
#router = APIRouter()
templates = Jinja2Templates(directory="templates")
# Include the authentication router with the prefix '/auth'
#app.include_router(auth.router, prefix="")
# Include the TTS router with the prefix '/tts'
#app.include_router(tts.router, prefix="/tts")
# 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
# Route for the landing page
@app.get("/", response_class=HTMLResponse)
async def landing(request: Request):
return templates.TemplateResponse("landing.html", {"request": request})
# Your other routes and app configuration go here
@app.get("/login", response_class=HTMLResponse)
async def login(request: Request):
return templates.TemplateResponse("login.html", {"request": request})
@app.post("/login")
async def login_post(
request: Request,
email: str = Form(...),
password: str = Form(...),
db: Session = Depends(get_db)
):
if not email or not password:
raise HTTPException(status_code=400, detail="Invalid email or password")
user = authenticate_user(db, email, password)
if user and user.is_verified: # Check if user is verified
access_token = auth_views.create_access_token(
data={"sub": user.email},
expires_delta=timedelta(minutes=auth_views.ACCESS_TOKEN_EXPIRE_MINUTES)
)
# Redirect the user to the protected route with the token in the URL
url = app.url_path_for("get_protected") # Ensure you have a name="get_protected" in your app.get("/protected") decorator
#return RedirectResponse(url=f"/protected?token={access_token}", status_code=status.HTTP_303_SEE_OTHER)
#return RedirectResponse(f"{url}?token={access_token}")
response = RedirectResponse(f"{url}?token={access_token}", status_code=status.HTTP_303_SEE_OTHER)
response.set_cookie(key="access_token", value=f"Bearer {access_token}", httponly=True)
# response.set_cookie(key="access_token", value=access_token, httponly=True)
return response
elif user and not user.is_verified: # User is not verified
raise HTTPException(
status_code=400,
detail="You must verify your email before accessing this resource."
)
else:
# If authentication fails, return to the login page with an error message
return templates.TemplateResponse(
"login.html",
{"request": request, "error_message": "Invalid email or password"}
)
@app.get("/register", response_class=HTMLResponse)
async def register_get(request: Request):
return templates.TemplateResponse("register.html", {"request": request})
@app.post("/register", response_class=HTMLResponse)
async def register_post(
request: Request,
username: str = Form(...),
email: str = Form(...),
password: str = Form(...),
confirm_password: str = Form(...),
db: Session = Depends(get_db)
):
if password != confirm_password:
# Return to the registration page with an error
return templates.TemplateResponse("register.html", {
"request": request,
"error_message": "Passwords do not match."
})
try:
user = UserCreate(username=username, email=email, password=password, confirm_password=confirm_password)
register(user, db) # If this function raises an HTTPException, it should be handled
except HTTPException as e:
# Return to the registration page with the error detail
return templates.TemplateResponse("register.html", {
"request": request,
"error_message": e.detail
})
# Redirect to the successful registration page
response = RedirectResponse("/registration_successful", status_code=status.HTTP_302_FOUND)
return response
@app.get("/registration_successful", response_class=HTMLResponse)
async def registration_successful(request: Request):
# Render the successful registration page
return templates.TemplateResponse("registration_successful.html", {"request": request})
@app.get("/verify/{verification_token}", response_class=HTMLResponse)
async def verify_email(verification_token: str, db: Session = Depends(get_db)):
user = get_user_by_verification_token(db, verification_token)
if not user:
raise HTTPException(status_code=400, detail="Invalid verification token")
if user.is_verified:
raise HTTPException(status_code=400, detail="Email already verified")
user.is_verified = True
user.email_verification_token = None # Clear the verification token
db.commit()
# Create access token for the user after successful verification
access_token = auth_views.create_access_token(data={"sub": user.email}, expires_delta=timedelta(minutes=auth_views.ACCESS_TOKEN_EXPIRE_MINUTES))
# Redirect to the protected route with the token as a query parameter (or as required by your front-end/client)
return RedirectResponse(url=f"/protected?token={access_token}")
#from jwt import decode, PyJWTError # make sure jwt is imported
@app.get("/protected", response_class=HTMLResponse)
async def get_protected(
request: Request,
token: str = Depends(verify_token), # Use Depends to inject the token after verification
db: Session = Depends(get_db)
):
user_email = token # As verify_token returns the 'sub' which is user email
db_user = get_user_by_email(db, user_email)
if db_user is None or not db_user.is_verified:
raise HTTPException(status_code=401, detail="User not found or not verified in the database")
# Render a template response
return templates.TemplateResponse("protected.html", {"request": request, "user": db_user.username})
#@app.get("/protected", response_class=HTMLResponse)
#async def get_protected(request: Request, token: Optional[str] = None, db: Session = Depends(get_db)):
# Try to get the token from the query parameter first, then fall back to the cookie
# token = token or request.cookies.get("access_token")
# if not token:
# raise HTTPException(status_code=401, detail="Not authenticated")
# try:
# payload = decode(token, auth_views.SECRET_KEY, algorithms=[auth_views.ALGORITHM])
# user_email = payload.get("sub")
# if user_email is None:
# raise HTTPException(status_code=401, detail="Not authenticated")
# except PyJWTError:
# raise HTTPException(status_code=401, detail="Could not validate credentials")
# db_user = get_user_by_email(db, user_email)
# if db_user is None or not db_user.is_verified:
# raise HTTPException(status_code=401, detail="User not found or not verified in the database")
# return templates.TemplateResponse("protected.html", {"request": request, "user": db_user.username})
#async def get_protected(
# request: Request,
# token: str = Query(None), # Accept token from query parameters
# db: Session = Depends(get_db)
#):
# Now pass both the request and token to the protected_route function
# return await protected_route(request, token, db)