├── README.md ├── main.py └── requirements.txt /README.md: -------------------------------------------------------------------------------- 1 | # Fast-API-Tutorial 2 | 3 | # 💻 Launch Your Software Development Career Today! 4 | 5 | 🎓 **No degree? No problem!** My program equips you with everything you need to break into tech and land an entry-level software development role. 6 | 7 | 🚀 **Why Join?** 8 | - 💼 **$70k+ starting salary potential** 9 | - 🕐 **Self-paced:** Complete on your own time 10 | - 🤑 **Affordable:** Low risk compared to expensive bootcamps or degrees 11 | - 🎯 **45,000+ job openings** in the market 12 | 13 | 👉 **[Start your journey today!](https://techwithtim.net/dev)** 14 | No experience needed—just your determination. Future-proof your career and unlock six-figure potential like many of our students have! 15 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from fastapi import Depends, FastAPI, HTTPException, status 2 | from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm 3 | from pydantic import BaseModel 4 | from datetime import datetime, timedelta 5 | from jose import JWTError, jwt 6 | from passlib.context import CryptContext 7 | 8 | SECRET_KEY = "83daa0256a2289b0fb23693bf1f6034d44396675749244721a2b20e896e11662" 9 | ALGORITHM = "HS256" 10 | ACCESS_TOKEN_EXPIRE_MINUTES = 30 11 | 12 | db = { 13 | "tim": { 14 | "username": "tim", 15 | "full_name": "Tim Ruscica", 16 | "email": "tim@gmail.com", 17 | "hashed_password": "$2b$12$HxWHkvMuL7WrZad6lcCfluNFj1/Zp63lvP5aUrKlSTYtoFzPXHOtu", 18 | "disabled": False 19 | } 20 | } 21 | 22 | 23 | class Token(BaseModel): 24 | access_token: str 25 | token_type: str 26 | 27 | 28 | class TokenData(BaseModel): 29 | username: str or None = None 30 | 31 | 32 | class User(BaseModel): 33 | username: str 34 | email: str or None = None 35 | full_name: str or None = None 36 | disabled: bool or None = None 37 | 38 | 39 | class UserInDB(User): 40 | hashed_password: str 41 | 42 | 43 | pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") 44 | oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") 45 | 46 | app = FastAPI() 47 | 48 | 49 | def verify_password(plain_password, hashed_password): 50 | return pwd_context.verify(plain_password, hashed_password) 51 | 52 | 53 | def get_password_hash(password): 54 | return pwd_context.hash(password) 55 | 56 | 57 | def get_user(db, username: str): 58 | if username in db: 59 | user_data = db[username] 60 | return UserInDB(**user_data) 61 | 62 | 63 | def authenticate_user(db, username: str, password: str): 64 | user = get_user(db, username) 65 | if not user: 66 | return False 67 | if not verify_password(password, user.hashed_password): 68 | return False 69 | 70 | return user 71 | 72 | 73 | def create_access_token(data: dict, expires_delta: timedelta or None = None): 74 | to_encode = data.copy() 75 | if expires_delta: 76 | expire = datetime.utcnow() + expires_delta 77 | else: 78 | expire = datetime.utcnow() + timedelta(minutes=15) 79 | 80 | to_encode.update({"exp": expire}) 81 | encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) 82 | return encoded_jwt 83 | 84 | 85 | async def get_current_user(token: str = Depends(oauth2_scheme)): 86 | credential_exception = HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, 87 | detail="Could not validate credentials", headers={"WWW-Authenticate": "Bearer"}) 88 | try: 89 | payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) 90 | username: str = payload.get("sub") 91 | if username is None: 92 | raise credential_exception 93 | 94 | token_data = TokenData(username=username) 95 | except JWTError: 96 | raise credential_exception 97 | 98 | user = get_user(db, username=token_data.username) 99 | if user is None: 100 | raise credential_exception 101 | 102 | return user 103 | 104 | 105 | async def get_current_active_user(current_user: UserInDB = Depends(get_current_user)): 106 | if current_user.disabled: 107 | raise HTTPException(status_code=400, detail="Inactive user") 108 | 109 | return current_user 110 | 111 | 112 | @app.post("/token", response_model=Token) 113 | async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()): 114 | user = authenticate_user(db, form_data.username, form_data.password) 115 | if not user: 116 | raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, 117 | detail="Incorrect username or password", headers={"WWW-Authenticate": "Bearer"}) 118 | access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) 119 | access_token = create_access_token( 120 | data={"sub": user.username}, expires_delta=access_token_expires) 121 | return {"access_token": access_token, "token_type": "bearer"} 122 | 123 | 124 | @app.get("/users/me/", response_model=User) 125 | async def read_users_me(current_user: User = Depends(get_current_active_user)): 126 | return current_user 127 | 128 | 129 | @app.get("/users/me/items") 130 | async def read_own_items(current_user: User = Depends(get_current_active_user)): 131 | return [{"item_id": 1, "owner": current_user}] 132 | 133 | 134 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi 2 | uvicorn[standard] 3 | python-multipart 4 | python-jose[cryptography] 5 | passlib[bcrypt] 6 | --------------------------------------------------------------------------------