|
from fastapi import Depends, HTTPException, Form, status |
|
from fastapi.security import OAuth2PasswordBearer |
|
from pydantic import BaseModel |
|
from sqlalchemy.orm import Session |
|
from database import get_user_by_email, get_user_by_verification_token |
|
from models import User |
|
from passlib.context import CryptContext |
|
from datetime import datetime, timedelta |
|
import jwt |
|
import os |
|
from emailx import send_verification_email, generate_verification_token |
|
|
|
|
|
SECRET_KEY = os.environ['my_secret_key'] |
|
ALGORITHM = "HS256" |
|
ACCESS_TOKEN_EXPIRE_MINUTES = 30 |
|
|
|
|
|
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") |
|
|
|
|
|
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") |
|
|
|
class TokenData(BaseModel): |
|
token: str |
|
|
|
class UserCreate(BaseModel): |
|
username: str |
|
email: str |
|
password: str |
|
confirm_password: str |
|
|
|
def create_access_token(data: dict, expires_delta: timedelta = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)): |
|
to_encode = data.copy() |
|
expire = datetime.utcnow() + expires_delta |
|
to_encode.update({"exp": expire}) |
|
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) |
|
return encoded_jwt |
|
|
|
def verify_token(token: str = Depends(oauth2_scheme)): |
|
try: |
|
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) |
|
return payload.get("sub") |
|
except jwt.ExpiredSignatureError: |
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Token has expired") |
|
except jwt.PyJWTError: |
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials") |
|
|
|
def authenticate_user(db: Session, email: str, password: str): |
|
user = get_user_by_email(db, email) |
|
if not user or not pwd_context.verify(password, user.hashed_password): |
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect email or password") |
|
return user |
|
|
|
def register_user(user_data: UserCreate, db: Session): |
|
if get_user_by_email(db, user_data.email): |
|
raise HTTPException(status_code=400, detail="Email already registered") |
|
|
|
hashed_password = pwd_context.hash(user_data.password) |
|
verification_token = generate_verification_token(user_data.email) |
|
reset_link = f"https://yourdomain.com/verify?token={verification_token}" |
|
send_verification_email(user_data.email, reset_link) |
|
|
|
new_user = User( |
|
email=user_data.email, |
|
username=user_data.username, |
|
hashed_password=hashed_password, |
|
email_verification_token=verification_token |
|
) |
|
db.add(new_user) |
|
db.commit() |
|
db.refresh(new_user) |
|
return new_user |
|
|
|
def reset_password(user: User, db: Session): |
|
verification_token = generate_verification_token(user.email) |
|
reset_link = f"https://yourdomain.com/reset-password?token={verification_token}" |
|
send_verification_email(user.email, reset_link) |
|
|
|
user.email_verification_token = verification_token |
|
db.commit() |
|
|
|
def get_current_user(token: str = Depends(verify_token)): |
|
return token |