· 3 years ago · Jun 06, 2022, 05:30 PM
1from datetime import datetime, timedelta
2
3from fastapi import status, Depends, FastAPI, HTTPException
4from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
5
6from jose import JWTError, jwt
7from passlib.context import CryptContext
8
9from sqlalchemy.orm import Session
10from pydantic import BaseModel
11
12import crud
13import models
14import schemas
15from database import SessionLocal, engine
16
17
18SECRET_KEY = "e0bdaabe97705f5f4ba3636761ef4e470f74c0cf2fb1d39f5a89faca2ee19d13"
19ALGORITHM = "HS256"
20ACCESS_TOKEN_EXPIRE_MINUTES = 30
21
22
23class Token(BaseModel):
24 access_token: str
25 token_type: str
26
27
28class TokenData(BaseModel):
29 email: str | None = None
30
31
32models.Base.metadata.create_all(bind=engine)
33pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
34oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
35app = FastAPI()
36
37
38def get_db():
39 db = SessionLocal()
40 try:
41 yield db
42 finally:
43 db.close()
44
45
46def create_access_token(data: dict, expires_delta: timedelta | None = None):
47 to_encode = data.copy()
48 if expires_delta:
49 expire = datetime.utcnow() + expires_delta
50 else:
51 expire = datetime.utcnow() + timedelta(minutes=15)
52 to_encode.update({"exp": expire})
53 encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
54 return encoded_jwt
55
56
57async def get_current_athlete(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
58 credentials_exception = HTTPException(
59 status_code=status.HTTP_401_UNAUTHORIZED,
60 detail="Could not validate credentials",
61 headers={"WWW-Authenticate": "Bearer"},
62 )
63 try:
64 payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
65 email: str = payload.get("sub")
66 if email is None:
67 raise credentials_exception
68 token_data = TokenData(email=email)
69 except JWTError:
70 raise credentials_exception
71 athlete = crud.get_athlete_by_email(db, token_data.email)
72 if athlete is None:
73 raise credentials_exception
74 return athlete
75
76
77@app.post("/token", response_model=Token)
78async def login(form_data: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)):
79 athlete = crud.get_athlete_by_email(db, form_data.username)
80 if athlete is None or not pwd_context.verify(form_data.password, athlete.hashed_password):
81 raise HTTPException(
82 status_code=status.HTTP_401_UNAUTHORIZED,
83 detail="Incorrect username or password",
84 headers={"WWW-Authenticate": "Bearer"},
85 )
86
87 access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
88 access_token = create_access_token(
89 data={"sub": athlete.email}, expires_delta=access_token_expires
90 )
91 return {"access_token": access_token, "token_type": "bearer"}
92
93
94@app.get("/profile")
95async def profile(athlete: schemas.Athlete = Depends(get_current_athlete)):
96 return athlete
97
98
99@app.post("/register")
100async def register(athlete: schemas.AthleteCreate, db: Session = Depends(get_db)):
101 crud.create_athlete(db, athlete, pwd_context.hash(athlete.password))
102