8000 Add files via upload · django-myblog/web-with-fastapi@c6f7466 · GitHub
[go: up one dir, main page]

Skip to content

Commit c6f7466

Browse files
authored
Add files via upload
1 parent 69253c9 commit c6f7466

File tree

63 files changed

+4199
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+4199
-0
lines changed
1.1 KB
Binary file not shown.

ch08/planner/auth/__init__.py

Whitespace-only changes.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

ch08/planner/auth/authenticate.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from auth.jwt_handler import verify_access_token
2+
from fastapi import Depends, HTTPException, status
3+
from fastapi.security import OAuth2PasswordBearer
4+
5+
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/user/signin")
6+
7+
8+
async def authenticate(token: str = Depends(oauth2_scheme)) -> str:
9+
if not token:
10+
raise HTTPException(
11+
status_code=status.HTTP_403_FORBIDDEN,
12+
detail="Sign in for access"
13+
)
14+
15+
decoded_token = await verify_access_token(token)
16+
return decoded_token["user"]

ch08/planner/auth/hash_password.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from passlib.context import CryptContext
2+
3+
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
4+
5+
6+
class HashPassword:
7+
def create_hash(self, password: str) -> str:
8+
return pwd_context.hash(password)
9+
10+
def verify_hash(self, plain_password: str, hashed_password: str) -> bool:
11+
return pwd_context.verify(plain_password, hashed_password)

ch08/planner/auth/jwt_handler.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import time
2+
from datetime import datetime
3+
4+
from database.connection import Settings
5+
from fastapi import HTTPException, status
6+
from jose import jwt, JWTError
7+
from models.users import User
8+
9+
settings = Settings()
10+
11+
12+
def create_access_token(user: str) -> str:
13+
payload = {
14+
"user": user,
15+
"expires": time.time() + 3600
16+
}
17+
18+
token = jwt.encode(payload, settings.SECRET_KEY, algorithm="HS256")
19+
return token
20+
21+
22+
async def verify_access_token(token: str) -> dict:
23+
try:
24+
data = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
25+
26+
expire = data.get("expires")
27+
28+
if expire is None:
29+
raise HTTPException(
30+
status_code=status.HTTP_400_BAD_REQUEST,
31+
detail="No access token supplied"
32+
)
33+
if datetime.utcnow() > datetime.utcfromtimestamp(expire):
34+
raise HTTPException(
35+
status_code=status.HTTP_403_FORBIDDEN,
36+
detail="Token expired!"
37+
)
38+
user_exist = await User.find_one(User.email == data["user"])
39+
if not user_exist:
40+
raise HTTPException(
41+
status_code=status.HTTP_400_BAD_REQUEST,
42+
detail="Invalid token"
43+
)
44+
45+
return data
46+
47+
except JWTError:
48+
raise HTTPException(
49+
status_code=status.HTTP_400_BAD_REQUEST,
50+
detail="Invalid token"
51+
)

ch08/planner/database/__init__.py

Whitespace-only changes.
Binary file not shown.
Binary file not shown.

ch08/planner/database/connection.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
from typing import Optional, Any, List
2+
3+
from beanie import init_beanie, PydanticObjectId
4+
from models.events import Event
5+
from models.users import User
6+
from motor.motor_asyncio import AsyncIOMotorClient
7+
from pydantic import BaseSettings, BaseModel
8+
9+
10+
class Settings(BaseSettings):
11+
DATABASE_URL: Optional[str] = None
12+
SECRET_KEY: Optional[str] = "default"
13+
14+
async def initialize_database(self):
15+
client = AsyncIOMotorClient(self.DATABASE_URL)
16+
await init_beanie(database=client.get_default_database(),
17+
document_models=[Event, User])
18+
19+
class Config:
20+
env_file = ".env"
21+
22+
23+
class Database:
24+
def __init__(self, model):
25+
self.model = model
26+
27+
async def save(self, document):
28+
await document.create()
29+
return
30+
31+
async def get(self, id: PydanticObjectId) -> bool:
32+
doc = await self.model.get(id)
33+
if doc:
34+
return doc
35+
return False
36+
37+
async def get_all(self) -> List[Any]:
38+
docs = await self.model.find_all().to_list()
39+
return docs
40+
41+
async def update(self, id: PydanticObjectId, body: BaseModel) -> Any:
42+
doc_id = id
43+
des_body = body.dict()
44+
45+
des_body = {k: v for k, v in des_body.items() if v is not None}
46+
update_query = {"$set": {
47+
field: value for field, value in des_body.items()
48+
}}
49+
50+
doc = await self.get(doc_id)
51+
if not doc:
52+
return False
53+
await doc.update(update_query)
54+
return doc
55+
56+
async def delete(self, id: PydanticObjectId) -> bool:
57+
doc = await self.get(id)
58+
if not doc:
59+
return False
60+
await doc.delete()
61+
return True

0 commit comments

Comments
 (0)
0