From cb2c807406a5f607da95c55e10457ad0d514de83 Mon Sep 17 00:00:00 2001 From: Alix JEUDI--LEMOINE Date: Fri, 22 Nov 2024 11:06:37 +0100 Subject: [PATCH] :art: Complete project restructuring --- app/__init__.py | 0 app/config.py | 13 ++++++ main.py => app/main.py | 59 ++++++++-------------------- app/models/__init__.py | 5 +++ app/models/friend.py | 5 +++ app/models/pin.py | 5 +++ app/models/token.py | 5 +++ app/models/token_data.py | 5 +++ app/models/user.py | 7 ++++ app/serializers/__init__.py | 3 ++ app/serializers/friend_serializer.py | 8 ++++ app/serializers/pin_serializer.py | 10 +++++ app/serializers/user_serializer.py | 8 ++++ app/utils.py | 7 ++++ 14 files changed, 97 insertions(+), 43 deletions(-) create mode 100644 app/__init__.py create mode 100644 app/config.py rename main.py => app/main.py (84%) create mode 100644 app/models/__init__.py create mode 100644 app/models/friend.py create mode 100644 app/models/pin.py create mode 100644 app/models/token.py create mode 100644 app/models/token_data.py create mode 100644 app/models/user.py create mode 100644 app/serializers/__init__.py create mode 100644 app/serializers/friend_serializer.py create mode 100644 app/serializers/pin_serializer.py create mode 100644 app/serializers/user_serializer.py create mode 100644 app/utils.py diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/config.py b/app/config.py new file mode 100644 index 0000000..35c3f53 --- /dev/null +++ b/app/config.py @@ -0,0 +1,13 @@ +# Constants for PyMongo +MONGODB_URL = "mongodb://localhost:27017/" +MONGODB_USERNAME = "mongoadmin" +MONGODB_PASSWORD = "secret" +MONGODB_DATABASE = "memorymap" + +# Constants for JWT +SECRET_KEY = "_2YfT44$xF.Tg_xI63UH3D7:N+>pZN2';j%>7H@?e0:Xor'pV[" # temporary of course :) +ALGORITHM = "HS256" # TODO: check if broken (don't believe) +ACCESS_TOKEN_EXPIRE_MINUTES = 30 # TODO: check what to add here / maybe need to evaluate criticity of that? + +# Constants for OAuth2 +TOKEN_URL = "login" # Path to the auth \ No newline at end of file diff --git a/main.py b/app/main.py similarity index 84% rename from main.py rename to app/main.py index 811adcc..4591398 100644 --- a/main.py +++ b/app/main.py @@ -1,63 +1,31 @@ from fastapi import FastAPI, Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm -from pydantic import BaseModel, Field from typing import Optional -from jose import JWTError, jwt from datetime import datetime, timedelta from pymongo import MongoClient +from jose import JWTError, jwt from bson.objectid import ObjectId +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 serializers import friends_serialize, pins_serialize, users_serialize +from app.serializers import * # Import all serializers (detailed in __init__.py) -import hashlib +# Import all models (detailed in __init__.py) +from app.models import * -# Constants for JWT -SECRET_KEY = "_2YfT44$xF.Tg_xI63UH3D7:N+>pZN2';j%>7H@?e0:Xor'pV[" # temporary of course :) -ALGORITHM = "HS256" # TODO: check if broken (don't believe) -ACCESS_TOKEN_EXPIRE_MINUTES = 30 # TODO: check what to add here / maybe need to evaluate criticity of that? +# Contains all constants +from app.config import * # Database setup -client = MongoClient("mongodb://localhost:27017/", username="mongoadmin", password="secret") -db = client["memorymap"] +client = MongoClient(MONGODB_URL, username=MONGODB_USERNAME, password=MONGODB_PASSWORD) +db = client[MONGODB_DATABASE] # FastAPI app instance app = FastAPI() # OAuth2 scheme -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login") - -# Pydantic models -class User(BaseModel): - uid: str = Field(..., alias="_id") - username: str - password: str - -class Token(BaseModel): - access_token: str - token_type: str - -class TokenData(BaseModel): - username: Optional[str] = None - -class Pin(BaseModel): - title: str - description: str - -class Friend(BaseModel): - user_id: str - -# Collections -users_collection = db["users"] -pins_collection = db["pins"] -friends_collection = db["friends"] - -# Utility functions -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=TOKEN_URL) def create_access_token(data: dict, expires_delta: Optional[timedelta] = None): to_encode = data.copy() @@ -94,6 +62,11 @@ async def get_current_user(token: str = Depends(oauth2_scheme)): return user +# Collections +users_collection = db["users"] +pins_collection = db["pins"] +friends_collection = db["friends"] + # Routes - TODO: find workaround to display 401/409/... HTTP error codes in openapi.json @app.post("/register", response_model=Token) async def register(user: User): diff --git a/app/models/__init__.py b/app/models/__init__.py new file mode 100644 index 0000000..957a693 --- /dev/null +++ b/app/models/__init__.py @@ -0,0 +1,5 @@ +from .friend import Friend +from .pin import Pin +from .token_data import TokenData +from .token import Token +from .user import User \ No newline at end of file diff --git a/app/models/friend.py b/app/models/friend.py new file mode 100644 index 0000000..7a0402e --- /dev/null +++ b/app/models/friend.py @@ -0,0 +1,5 @@ +from pydantic import BaseModel + + +class Friend(BaseModel): + user_id: str \ No newline at end of file diff --git a/app/models/pin.py b/app/models/pin.py new file mode 100644 index 0000000..fef490b --- /dev/null +++ b/app/models/pin.py @@ -0,0 +1,5 @@ +from pydantic import BaseModel + +class Pin(BaseModel): + title: str + description: str \ No newline at end of file diff --git a/app/models/token.py b/app/models/token.py new file mode 100644 index 0000000..15aaf02 --- /dev/null +++ b/app/models/token.py @@ -0,0 +1,5 @@ +from pydantic import BaseModel + +class Token(BaseModel): + access_token: str + token_type: str \ No newline at end of file diff --git a/app/models/token_data.py b/app/models/token_data.py new file mode 100644 index 0000000..3b3b8f5 --- /dev/null +++ b/app/models/token_data.py @@ -0,0 +1,5 @@ +from pydantic import BaseModel +from typing import Optional + +class TokenData(BaseModel): + username: Optional[str] = None \ No newline at end of file diff --git a/app/models/user.py b/app/models/user.py new file mode 100644 index 0000000..9d14049 --- /dev/null +++ b/app/models/user.py @@ -0,0 +1,7 @@ +from pydantic import BaseModel, Field + + +class User(BaseModel): + uid: str = Field(..., alias="_id") + username: str + password: str \ No newline at end of file diff --git a/app/serializers/__init__.py b/app/serializers/__init__.py new file mode 100644 index 0000000..21a8ed4 --- /dev/null +++ b/app/serializers/__init__.py @@ -0,0 +1,3 @@ +from .friend_serializer import * +from .pin_serializer import * +from .user_serializer import * \ No newline at end of file diff --git a/app/serializers/friend_serializer.py b/app/serializers/friend_serializer.py new file mode 100644 index 0000000..314a796 --- /dev/null +++ b/app/serializers/friend_serializer.py @@ -0,0 +1,8 @@ +def friends_serialize(friends: list) -> list: + serialized_friends: list = [] + for friend in friends: + serialized_friends.append({ + "id": str(friend["_id"]), + "user_id": friend["user_id"] + }) + return serialized_friends \ No newline at end of file diff --git a/app/serializers/pin_serializer.py b/app/serializers/pin_serializer.py new file mode 100644 index 0000000..a6af7cb --- /dev/null +++ b/app/serializers/pin_serializer.py @@ -0,0 +1,10 @@ +def pins_serialize(pins: list) -> list: + serialized_pins: list = [] + for pin in pins: + serialized_pins.append({ + "id": str(pin["_id"]), + "title": pin["title"], + "description": pin["description"] + + }) + return serialized_pins \ No newline at end of file diff --git a/app/serializers/user_serializer.py b/app/serializers/user_serializer.py new file mode 100644 index 0000000..0dd5a55 --- /dev/null +++ b/app/serializers/user_serializer.py @@ -0,0 +1,8 @@ +def users_serialize(users: list) -> list: + serialized_users: list = [] + for user in users: + serialized_users.append({ + "id": str(user["_id"]), + "username": user["username"] + }) + return serialized_users \ No newline at end of file diff --git a/app/utils.py b/app/utils.py new file mode 100644 index 0000000..90221dc --- /dev/null +++ b/app/utils.py @@ -0,0 +1,7 @@ +import hashlib + +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() \ No newline at end of file