Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fastapi import Depends, HTTPException, Form, status
|
2 |
+
from fastapi.security import OAuth2PasswordBearer
|
3 |
+
from pydantic import BaseModel
|
4 |
+
from sqlalchemy.orm import Session
|
5 |
+
from database import get_user_by_email, get_user_by_verification_token
|
6 |
+
from models import User
|
7 |
+
from passlib.context import CryptContext
|
8 |
+
from datetime import datetime, timedelta
|
9 |
+
import jwt
|
10 |
+
import os
|
11 |
+
from emailx import send_verification_email, generate_verification_token
|
12 |
+
|
13 |
+
# Configuration
|
14 |
+
SECRET_KEY = os.environ['my_secret_key']
|
15 |
+
ALGORITHM = "HS256"
|
16 |
+
ACCESS_TOKEN_EXPIRE_MINUTES = 30
|
17 |
+
|
18 |
+
# Password context
|
19 |
+
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
20 |
+
|
21 |
+
# OAuth2 scheme
|
22 |
+
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
|
23 |
+
|
24 |
+
class TokenData(BaseModel):
|
25 |
+
token: str
|
26 |
+
|
27 |
+
class UserCreate(BaseModel):
|
28 |
+
username: str
|
29 |
+
email: str
|
30 |
+
password: str
|
31 |
+
confirm_password: str
|
32 |
+
|
33 |
+
def create_access_token(data: dict, expires_delta: timedelta = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)):
|
34 |
+
to_encode = data.copy()
|
35 |
+
expire = datetime.utcnow() + expires_delta
|
36 |
+
to_encode.update({"exp": expire})
|
37 |
+
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
38 |
+
return encoded_jwt
|
39 |
+
|
40 |
+
def verify_token(token: str = Depends(oauth2_scheme)):
|
41 |
+
try:
|
42 |
+
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
|
43 |
+
return payload.get("sub")
|
44 |
+
except jwt.ExpiredSignatureError:
|
45 |
+
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Token has expired")
|
46 |
+
except jwt.PyJWTError:
|
47 |
+
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials")
|
48 |
+
|
49 |
+
def authenticate_user(db: Session, email: str, password: str):
|
50 |
+
user = get_user_by_email(db, email)
|
51 |
+
if not user or not pwd_context.verify(password, user.hashed_password):
|
52 |
+
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect email or password")
|
53 |
+
return user
|
54 |
+
|
55 |
+
def register_user(user_data: UserCreate, db: Session):
|
56 |
+
if get_user_by_email(db, user_data.email):
|
57 |
+
raise HTTPException(status_code=400, detail="Email already registered")
|
58 |
+
|
59 |
+
hashed_password = pwd_context.hash(user_data.password)
|
60 |
+
verification_token = generate_verification_token(user_data.email)
|
61 |
+
reset_link = f"https://yourdomain.com/verify?token={verification_token}"
|
62 |
+
send_verification_email(user_data.email, reset_link)
|
63 |
+
|
64 |
+
new_user = User(
|
65 |
+
email=user_data.email,
|
66 |
+
username=user_data.username,
|
67 |
+
hashed_password=hashed_password,
|
68 |
+
email_verification_token=verification_token
|
69 |
+
)
|
70 |
+
db.add(new_user)
|
71 |
+
db.commit()
|
72 |
+
db.refresh(new_user)
|
73 |
+
return new_user
|
74 |
+
|
75 |
+
def reset_password(user: User, db: Session):
|
76 |
+
verification_token = generate_verification_token(user.email)
|
77 |
+
reset_link = f"https://yourdomain.com/reset-password?token={verification_token}"
|
78 |
+
send_verification_email(user.email, reset_link)
|
79 |
+
|
80 |
+
user.email_verification_token = verification_token
|
81 |
+
db.commit()
|
82 |
+
|
83 |
+
def get_current_user(token: str = Depends(verify_token)):
|
84 |
+
return token
|