diff --git a/app/main.py b/app/main.py index 9c4afa0..7ce1364 100644 --- a/app/main.py +++ b/app/main.py @@ -9,22 +9,22 @@ from app.utils import get_password_hash, verify_password # Best workaround found for _id typed as ObjectId (creating Exception bcause JSON doesn't support custom types countrary to BSON, used by Mongo) # also allows to create DTOs at the time, but not at it's best (project structure is chaotic FTM :s) -from app.serializers import * # Import all serializers (detailed in __init__.py) +import app.serializers as serializers # Import all serializers (detailed in __init__.py) -# Import all models (detailed in __init__.py) -from app.models import * +# Import models +from app.models import User, Pin, Friend, Token, TokenData, HTTPError # Import all DTOs (detailed in __init__.py) -from app.dto import * +from app.dto import FriendAddDTO, FriendListDTO, UserDTO, UserRegisterDTO # Contains all constants -from app.config import * +import app.config as config import pymongo # Database setup -client = pymongo.MongoClient(MONGODB_URL, username=MONGODB_USERNAME, password=MONGODB_PASSWORD) -db = client[MONGODB_DATABASE] +client = pymongo.MongoClient(config.MONGODB_URL, username=config.MONGODB_USERNAME, password=config.MONGODB_PASSWORD) +db = client[config.MONGODB_DATABASE] # FastAPI app instance app = FastAPI( @@ -37,7 +37,7 @@ app = FastAPI( ) # OAuth2 scheme -oauth2_scheme = OAuth2PasswordBearer(tokenUrl=TOKEN_URL) +oauth2_scheme = OAuth2PasswordBearer(tokenUrl=config.TOKEN_URL) # Collections users_collection = db["users"] @@ -54,7 +54,7 @@ def create_access_token(data: dict, expires_delta: Optional[timedelta] = None): expire = datetime.now() + timedelta(minutes=15) to_encode.update({"exp": expire}) - encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) + encoded_jwt = jwt.encode(to_encode, config.SECRET_KEY, algorithm=config.ALGORITHM) return encoded_jwt @@ -66,7 +66,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme)) -> User: ) try: - payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) + payload = jwt.decode(token, config.SECRET_KEY, algorithms=[config.ALGORITHM]) username: str = payload.get("sub") if username is None: raise credentials_exception @@ -78,7 +78,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme)) -> User: if user is None: raise credentials_exception - return user_serialize(user) + return serializers.user_serialize(user) # Routes @@ -98,7 +98,7 @@ async def register(user: UserRegisterDTO): hashed_password = get_password_hash(user.password) user_id = users_collection.insert_one({"username": user.username, "password": hashed_password}) - access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) + access_token_expires = timedelta(minutes=config.ACCESS_TOKEN_EXPIRE_MINUTES) access_token = create_access_token(data={"sub": user.username}, expires_delta=access_token_expires) return {"access_token": access_token, "token_type": "bearer", "user_id": str(user_id)} @@ -117,7 +117,7 @@ async def login(form_data: OAuth2PasswordRequestForm = Depends()): headers={"WWW-Authenticate": "Bearer"}, ) - access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) + access_token_expires = timedelta(minutes=config.ACCESS_TOKEN_EXPIRE_MINUTES) access_token = create_access_token(data={"sub": form_data.username}, expires_delta=access_token_expires) return {"access_token": access_token, "token_type": "bearer", "user_id": str(user["_id"])} @@ -139,7 +139,7 @@ async def get_pin(id: str, current_user: User = Depends(get_current_user)): if pin is None: raise HTTPException(status_code=404, detail="Pin not found") - return pin_serialize(pin) + return serializers.pin_serialize(pin) @app.patch( path="/pin/{id}", @@ -165,17 +165,21 @@ async def add_pin(pin: Pin, current_user: User = Depends(get_current_user)): responses={401: {"model": HTTPError}} ) async def list_pins(current_user: User = Depends(get_current_user)): - pins = pins_serialize(pins_collection.find().to_list()) + pins = serializers.pins_serialize(pins_collection.find().to_list()) return pins + +def friend_not_found(): + raise HTTPException(status_code=404, detail="Friend not found") + + @app.get( path="/friend/{id}", responses={401: {"model": HTTPError}, 404: {"model": HTTPError}} ) async def get_friend(id: str, current_user: User = Depends(get_current_user)): friend = friends_collection.find_one({"_id": ObjectId(id)}) - if friend is None: - raise HTTPException(status_code=404, detail="Friend not found") + if friend is None: friend_not_found() return friend @@ -183,9 +187,9 @@ async def get_friend(id: str, current_user: User = Depends(get_current_user)): path="/friend/add", responses={401: {"model": HTTPError}, 409: {"model": HTTPError}} ) -async def add_friend(friendAdd: FriendAddDTO, current_user: User = Depends(get_current_user)): +async def add_friend(friend_to_add: FriendAddDTO, current_user: User = Depends(get_current_user)): # TODO: test if exists - friend: Friend = friendAdd.model_dump() + friend: Friend = friend_to_add.model_dump() print(current_user) @@ -205,8 +209,7 @@ async def add_friend(friendAdd: FriendAddDTO, current_user: User = Depends(get_c ) async def delete_friend(id: str, current_user: User = Depends(get_current_user)): result = friends_collection.delete_one({"_id": ObjectId(id)}) - if result.deleted_count == 0: - raise HTTPException(status_code=404, detail="Friend not found") + if result.deleted_count == 0: friend_not_found() return {"message": "Friend deleted"} @@ -216,8 +219,7 @@ async def delete_friend(id: str, current_user: User = Depends(get_current_user)) ) async def accept_friend(id: str, current_user: User = Depends(get_current_user)): result = friends_collection.update_one({"_id": ObjectId(id)}, {"$set": {"status": "accepted"}}) - if result.matched_count == 0: - raise HTTPException(status_code=404, detail="Friend not found") + if result.matched_count == 0: friend_not_found() return {"message": "Friend request accepted"} @@ -227,8 +229,7 @@ async def accept_friend(id: str, current_user: User = Depends(get_current_user)) ) async def deny_friend(id: str, current_user: User = Depends(get_current_user)): result = friends_collection.update_one({"_id": ObjectId(id)}, {"$set": {"status": "denied"}}) - if result.matched_count == 0: - raise HTTPException(status_code=404, detail="Friend not found") + if result.matched_count == 0: friend_not_found() return {"message": "Friend request denied"} @@ -238,7 +239,7 @@ async def deny_friend(id: str, current_user: User = Depends(get_current_user)): responses={401: {"model": HTTPError}} ) async def list_friends(current_user: User = Depends(get_current_user)): - return FriendListDTO(**friends_serialize(friends_collection.find({"user_id": current_user.uid}).to_list(), friends_collection.find({"friend_user_id": current_user.uid}).to_list())) + return FriendListDTO(**serializers.friends_serialize(friends_collection.find({"user_id": current_user.uid}).to_list(), friends_collection.find({"friend_user_id": current_user.uid}).to_list())) @app.get( path="/users", @@ -247,7 +248,7 @@ async def list_friends(current_user: User = Depends(get_current_user)): ) async def search_users(name: str, current_user: User = Depends(get_current_user)): try: - users = users_serialize(users_collection.find({"username": {"$regex": name, "$options": "i"}}).to_list()) + users = serializers.users_serialize(users_collection.find({"username": {"$regex": name, "$options": "i"}}).to_list()) except pymongo.errors.OperationFailure: raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Regex may be wrongly formatted")