Skip to content

Commit

Permalink
Merge pull request #25 from HumzahJavid/SEPP-34-refactor-code-and-add…
Browse files Browse the repository at this point in the history
…itional-cleanup

SEPP-34 Refactor code and additional cleanup
  • Loading branch information
HumzahJavid authored Jun 3, 2022
2 parents 9f2476a + e2a7f24 commit 6c62566
Show file tree
Hide file tree
Showing 12 changed files with 168 additions and 202 deletions.
Empty file added dating_app/api/user/__init__.py
Empty file.
74 changes: 74 additions & 0 deletions dating_app/api/user/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
from fastapi import APIRouter, Form, Response, status

import dating_app.services as services
from dating_app.db import mongo
from dating_app.schemas.User import (
LoginResponse,
LoginResponseBase,
RegisterResponse,
RegisterResponseBase,
UserCreate,
UserModel,
)

router = APIRouter()


@router.post(
"/register",
status_code=status.HTTP_201_CREATED,
response_model=RegisterResponse,
responses=RegisterResponseBase.Config.schema_extra, # type: ignore
)
async def register(
response: Response,
email: str = Form(...),
password: str = Form(...),
confirmPassword: str = Form(...),
):
user = UserCreate(
email=email, password=password, confirmed_password=confirmPassword
)
db = mongo.get_db()
print(db["users"])

register_response = await services.create_user(db, user)

if "already in use." in register_response.message:
response.status_code = status.HTTP_409_CONFLICT

return register_response


@router.post(
"/login",
status_code=status.HTTP_200_OK,
response_model=LoginResponse,
responses=LoginResponseBase.Config.schema_extra, # type: ignore
)
async def login(
response: Response,
email: str = Form(...),
password: str = Form(...),
):

user_form = UserModel(email=email, password=password)
db = mongo.get_db()
print(db["users"])
login_response = await services.authenticate_user(db, user_form)
print(f"user is {login_response}")
if "Invalid" in login_response.message:
print(f"Invalid credentials 401: {email}")
response.status_code = status.HTTP_401_UNAUTHORIZED
else:
response.set_cookie(key="X-Authorization", value=email, httponly=True)

return login_response


@router.post("/logout", status_code=status.HTTP_200_OK)
async def logout(response: Response):
db = mongo.get_db()
logout_response = await services.logout(db)
print(logout_response)
return logout_response
3 changes: 3 additions & 0 deletions dating_app/db/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from dating_app.db.database import MongoDB

mongo = MongoDB()
3 changes: 3 additions & 0 deletions dating_app/db/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ async def startup_db_client(self) -> None:
async def shutdown_db_client(self) -> None:
self.mongodb_client.close()
self.mongodb = None

def get_db(self):
return self.mongodb
84 changes: 5 additions & 79 deletions dating_app/main.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
from pathlib import Path
from typing import Any, Dict, List, Optional

from fastapi import APIRouter, FastAPI, Form, Request, Response, status
from fastapi import APIRouter, FastAPI, Form, Request, status
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from pydantic import EmailStr

import dating_app.services as services
from dating_app.api.chat import chat
from dating_app.api.user import user
from dating_app.core import websocket
from dating_app.db.database import MongoDB
from dating_app.schemas.User import (
LoginResponse,
LoginResponseBase,
RegisterResponse,
RegisterResponseBase,
UserCreate,
UserModel,
UserPublic,
UserSearch,
)
from dating_app.db import mongo
from dating_app.schemas.User import UserPublic, UserSearch

BASE_PATH = Path(__file__).resolve().parent
templates = Jinja2Templates(directory=BASE_PATH / "templates")
Expand All @@ -28,94 +20,28 @@
app = FastAPI()
app.mount("/static", StaticFiles(directory=BASE_PATH / "static"), name="static")
api_router = APIRouter()
mongo = MongoDB()


@app.on_event("startup")
async def startup_db_client() -> None:
global mongo
await mongo.startup_db_client()


@app.on_event("shutdown")
async def shutdown_db_client() -> None:
global mongo
await mongo.shutdown_db_client()


# @app.get("/")
@api_router.get("/", status_code=200)
async def root(request: Request):
return templates.TemplateResponse("index.html", {"request": request})


@api_router.get("/items/{item_id}")
async def read_item(request: Request, item_id: int):
return templates.TemplateResponse(
"items.html", {"request": request, "item_id": item_id}
)


# @app.get("/")
@api_router.get("/searchpage", status_code=200)
async def search_page(request: Request):
return templates.TemplateResponse("search.html", {"request": request})


@api_router.post(
"/login",
status_code=status.HTTP_200_OK,
response_model=LoginResponse,
responses=LoginResponseBase.Config.schema_extra, # type: ignore
)
async def login(
response: Response,
email: str = Form(...),
password: str = Form(...),
):

user_form = UserModel(email=email, password=password)
login_response = await services.authenticate_user(mongo.mongodb, user_form)
print(f"user is {login_response}")
if "Invalid" in login_response.message:
print(f"Invalid credentials 401: {email}")
response.status_code = status.HTTP_401_UNAUTHORIZED
else:
response.set_cookie(key="X-Authorization", value=email, httponly=True)

return login_response


@api_router.post("/logout", status_code=status.HTTP_200_OK)
async def logout(response: Response):
logout_response = await services.logout(mongo.mongodb)
print(logout_response)
return logout_response


@api_router.post(
"/register",
status_code=status.HTTP_201_CREATED,
response_model=RegisterResponse,
responses=RegisterResponseBase.Config.schema_extra, # type: ignore
)
async def register(
response: Response,
email: str = Form(...),
password: str = Form(...),
confirmPassword: str = Form(...),
):
user = UserCreate(
email=email, password=password, confirmed_password=confirmPassword
)
register_response = await services.create_user(mongo.mongodb, user)

if "already in use." in register_response.message:
response.status_code = status.HTTP_409_CONFLICT

return register_response


@api_router.get(
"/all", response_description="List all other Users", response_model=List[UserPublic]
)
Expand Down Expand Up @@ -144,7 +70,6 @@ async def search(
# https://stackoverflow.com/questions/4260280/if-else-in-a-list-comprehension
processed_fields = [element if element else None for element in fields]
email, name, gender = processed_fields
# if search by email, redirect to find_one by email endpoint?

# initialise to run server side validation
search_criteria: UserSearch = UserSearch(
Expand Down Expand Up @@ -207,6 +132,7 @@ async def update_user_me(


api_router.include_router(websocket.router)
api_router.include_router(user.router, prefix="/api/user", tags=["user"])
api_router.include_router(chat.router, prefix="/api/chat", tags=["chat"])
app.include_router(api_router)

Expand Down
29 changes: 2 additions & 27 deletions dating_app/schemas/ChatModel.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,7 @@
from bson import ObjectId
from fastapi import Body
from pydantic import BaseModel, Field
from pydantic import BaseModel


# https://www.mongodb.com/developer/quickstart/python-quickstart-fastapi/#the-_id-attribute-and-objectids
class PyObjectId(ObjectId):
@classmethod
def __get_validators__(cls):
yield cls.validate

@classmethod
def validate(cls, v):
if not ObjectId.is_valid(v):
raise ValueError("Invalid objectid")
return ObjectId(v)

@classmethod
def __modify_schema__(cls, field_schema):
field_schema.update(type="string")


class MongoModel(BaseModel):
id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")

class Config:
allow_population_by_field_name = True
arbitrary_types_allowed = True
json_encoders = {ObjectId: str}
from dating_app.schemas.MongoModel import MongoModel


class InitiateChat(MongoModel):
Expand Down
32 changes: 32 additions & 0 deletions dating_app/schemas/MongoModel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""
MongoModel handles Creating MongoDB compatible pydantic models
https://www.mongodb.com/developer/quickstart/python-quickstart-fastapi/#the-_id-attribute-and-objectids
"""
from bson import ObjectId
from pydantic import BaseModel, Field


class PyObjectId(ObjectId):
@classmethod
def __get_validators__(cls):
yield cls.validate

@classmethod
def validate(cls, v):
if not ObjectId.is_valid(v):
raise ValueError("Invalid objectid")
return ObjectId(v)

@classmethod
def __modify_schema__(cls, field_schema):
field_schema.update(type="string")


class MongoModel(BaseModel):
id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")

class Config:
allow_population_by_field_name = True
arbitrary_types_allowed = True
json_encoders = {ObjectId: str}
46 changes: 1 addition & 45 deletions dating_app/schemas/User.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,9 @@
from enum import Enum
from typing import Optional

from bson import ObjectId
from pydantic import BaseModel, EmailStr, Field


# https://www.mongodb.com/developer/quickstart/python-quickstart-fastapi/#the-_id-attribute-and-objectids
class PyObjectId(ObjectId):
@classmethod
def __get_validators__(cls):
yield cls.validate

@classmethod
def validate(cls, v):
if not ObjectId.is_valid(v):
raise ValueError("Invalid objectid")
return ObjectId(v)

@classmethod
def __modify_schema__(cls, field_schema):
field_schema.update(type="string")


class MongoModel(BaseModel):
id: PyObjectId = Field(default_factory=PyObjectId, alias="_id")

class Config:
allow_population_by_field_name = True
arbitrary_types_allowed = True
json_encoders = {ObjectId: str}
from dating_app.schemas.MongoModel import MongoModel


class UserModel(MongoModel):
Expand Down Expand Up @@ -129,22 +104,3 @@ class Config:
"200": {"model": LoginResponse200},
"401": {"model": LoginResponse401},
}


""""
class Filter(BaseModel):
foo: str
bar: str
class Payload(BaseModel):
baz: str
bat: str
def get_payload(payload: Payload):
return {}
@router.post('/')
def test(filter: Filter = Depends(), payload: dict = Depends(get_payload)):
pass
"""
Loading

0 comments on commit 6c62566

Please sign in to comment.