diff --git a/app/routes/auth.py b/app/routes/auth.py index c3af68e..b29c68e 100644 --- a/app/routes/auth.py +++ b/app/routes/auth.py @@ -7,8 +7,8 @@ import pymongo import app.config as config from app.models import User, Token, HTTPError from app.dto import UserRegisterDTO -from app.serializers import user_serialize -from app.utils import get_current_user, create_access_token, get_password_hash, verify_password +from app.routes.utils import get_current_user, create_access_token +from app.utils import get_password_hash, verify_password # Database setup client = pymongo.MongoClient(config.MONGODB_URL, username=config.MONGODB_USERNAME, password=config.MONGODB_PASSWORD) diff --git a/app/routes/friends.py b/app/routes/friends.py index a95b427..e9b9f3f 100644 --- a/app/routes/friends.py +++ b/app/routes/friends.py @@ -7,7 +7,7 @@ import pymongo from app.dto import FriendAddDTO from app.models import HTTPError, User, Friend -from app.utils import friend_not_found, get_current_user, objectid_misformatted +from .utils import friend_not_found, get_current_user, objectid_misformatted import app.config as config # Best workaround found for _id typed as ObjectId (creating Exception bcause JSON doesn't support custom types countrary to BSON, used by Mongo) diff --git a/app/routes/pins.py b/app/routes/pins.py index 38c85eb..b406694 100644 --- a/app/routes/pins.py +++ b/app/routes/pins.py @@ -7,7 +7,7 @@ import pymongo from app.dto import PinDTO from app.models import HTTPError from app.models.user import User -from app.utils import get_current_user, objectid_misformatted +from .utils import get_current_user, objectid_misformatted import app.config as config # Best workaround found for _id typed as ObjectId (creating Exception bcause JSON doesn't support custom types countrary to BSON, used by Mongo) diff --git a/app/routes/users.py b/app/routes/users.py index 308d9ab..f9e7772 100644 --- a/app/routes/users.py +++ b/app/routes/users.py @@ -8,7 +8,7 @@ import pymongo from app.dto import UserDTO from app.models import HTTPError, User -from app.utils import get_current_user, objectid_misformatted +from .utils import get_current_user, objectid_misformatted import app.config as config # Database setup diff --git a/app/routes/utils.py b/app/routes/utils.py new file mode 100644 index 0000000..a9b3267 --- /dev/null +++ b/app/routes/utils.py @@ -0,0 +1,66 @@ +from fastapi import Depends, HTTPException, status +from fastapi.security import OAuth2PasswordBearer +from joserfc import jwt +from joserfc.errors import JoseError +from joserfc.jwk import OctKey +from datetime import datetime, timedelta +from app.models import User +from app.models.token_data import TokenData +from app.serializers import user_serialize +import pymongo +import app.config as config + +# Database setup +client = pymongo.MongoClient(config.MONGODB_URL, username=config.MONGODB_USERNAME, password=config.MONGODB_PASSWORD) +db = client[config.MONGODB_DATABASE] + +users_collection = db["users"] + +oauth2_scheme = OAuth2PasswordBearer(tokenUrl=config.TOKEN_URL) + +async def get_current_user(token: str = Depends(oauth2_scheme)) -> User: + credentials_exception = HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Could not validate credentials", + headers={"WWW-Authenticate": "Bearer"}, + ) + + try: + payload = jwt.decode(token, OctKey.import_key(config.SECRET_KEY)) + username: str = payload.claims["sub"] + expire_date = payload.claims["exp"] + if username is None or int(datetime.now().timestamp()) > expire_date: + raise credentials_exception + token_data = TokenData(username=username) + except JoseError: + raise credentials_exception + + user = users_collection.find_one({"username": token_data.username}) + if user is None: + raise credentials_exception + + return user_serialize(user) + +def create_access_token(data: dict, expires_delta: timedelta): + to_encode = data.copy() + + expire = datetime.now() + expires_delta + + to_encode.update({"exp": expire}) + header = {"alg": config.ALGORITHM} + encoded_jwt = jwt.encode(header, to_encode, OctKey.import_key(config.SECRET_KEY)) + + return encoded_jwt + +# Exceptions +def friend_not_found(): + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="Friend not found" + ) + +def objectid_misformatted(): + raise HTTPException( + status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, + detail="The ObjectID is misformatted" + ) \ No newline at end of file diff --git a/app/utils.py b/app/utils.py index 349e7ec..90221dc 100644 --- a/app/utils.py +++ b/app/utils.py @@ -1,74 +1,7 @@ import hashlib -from fastapi import Depends, HTTPException, status -from fastapi.security import OAuth2PasswordBearer -from joserfc import jwt -from joserfc.errors import JoseError -from joserfc.jwk import OctKey -from datetime import datetime, timedelta - -import pymongo -from app.models import User -import app.config as config -from app.models.token_data import TokenData -from app.serializers import user_serialize - -# Database setup -client = pymongo.MongoClient(config.MONGODB_URL, username=config.MONGODB_USERNAME, password=config.MONGODB_PASSWORD) -db = client[config.MONGODB_DATABASE] - -users_collection = db["users"] def verify_password(plain_password, hashed_password): return hashlib.sha256(plain_password.encode()).hexdigest() == hashed_password def get_password_hash(password): - return hashlib.sha256(password.encode()).hexdigest() - -oauth2_scheme = OAuth2PasswordBearer(tokenUrl=config.TOKEN_URL) - -async def get_current_user(token: str = Depends(oauth2_scheme)) -> User: - credentials_exception = HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail="Could not validate credentials", - headers={"WWW-Authenticate": "Bearer"}, - ) - - try: - payload = jwt.decode(token, OctKey.import_key(config.SECRET_KEY)) - username: str = payload.claims["sub"] - expire_date = payload.claims["exp"] - if username is None or int(datetime.now().timestamp()) > expire_date: - raise credentials_exception - token_data = TokenData(username=username) - except JoseError: - raise credentials_exception - - user = users_collection.find_one({"username": token_data.username}) - if user is None: - raise credentials_exception - - return user_serialize(user) - -def create_access_token(data: dict, expires_delta: timedelta): - to_encode = data.copy() - - expire = datetime.now() + expires_delta - - to_encode.update({"exp": expire}) - header = {"alg": config.ALGORITHM} - encoded_jwt = jwt.encode(header, to_encode, OctKey.import_key(config.SECRET_KEY)) - - return encoded_jwt - -# Exceptions -def friend_not_found(): - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail="Friend not found" - ) - -def objectid_misformatted(): - raise HTTPException( - status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, - detail="The ObjectID is misformatted" - ) \ No newline at end of file + return hashlib.sha256(password.encode()).hexdigest() \ No newline at end of file