Skip to content

Commit

Permalink
added auth for animals create points
Browse files Browse the repository at this point in the history
  • Loading branch information
serikovlearning committed May 5, 2024
1 parent 8679b8e commit afbeed0
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 39 deletions.
77 changes: 76 additions & 1 deletion backend/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ asyncpg = "^0.29.0"
python-multipart = "^0.0.6"
jinja2 = "^3.1.2"
passlib = "^1.7.4"
python-jose = "^3.3.0"


[build-system]
Expand Down
5 changes: 5 additions & 0 deletions backend/routers/animal_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
AnimalFullResponseSchema
)
from backend.schemas.base_schema import BaseOkResponse
from services.shelter_service import ShelterService
from backend.services.animal_service import AnimalService
from backend.services.animal_template_service import AnimalTemplateService


router = APIRouter(
tags=["animals"],
prefix="/animals"
Expand Down Expand Up @@ -48,6 +50,7 @@ async def create_animal(
schema: AnimalCreateSchema
) -> BaseOkResponse:
async with request.app.state.db.get_master_session() as session:
await ShelterService(session).check_is_auth_active(request)
await AnimalService(session).create_new_animal(schema)
return BaseOkResponse()

Expand All @@ -59,6 +62,7 @@ async def update_animal(
schema: AnimalUpdateSchema
) -> BaseOkResponse:
async with request.app.state.db.get_master_session() as session:
await ShelterService(session).check_is_auth_active(request)
await AnimalService(session).update_animal(animal_id, schema)
return BaseOkResponse()

Expand All @@ -69,5 +73,6 @@ async def update_animal(
animal_id: int
) -> BaseOkResponse:
async with request.app.state.db.get_master_session() as session:
await ShelterService(session).check_is_auth_active(request)
await AnimalService(session).delete_animal_by_id(animal_id)
return BaseOkResponse()
5 changes: 2 additions & 3 deletions backend/routers/shelter_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@
@router.get("/check")
async def check_auth(request: Request, response: Response):
async with request.app.state.db.get_master_session() as session:
await ShelterService(session).check_is_auth_active(request, response)
await ShelterService(session).check_is_auth_active(request)
return BaseOkResponse()


@router.post("/auth")
async def auth(request: Request, body: BaseShelterSchema, response: Response):
async with request.app.state.db.get_master_session() as session:
await ShelterService(session).authenticate_shelter(body, response)
return BaseOkResponse()
return await ShelterService(session).authenticate_shelter(body, response)


@router.post("/")
Expand Down
1 change: 1 addition & 0 deletions backend/schemas/animal_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class AnimalCreateSchema(AnimalBaseSchema):
sex: str
age: str
size: str
shelter_id: int


class AnimalUpdateSchema(AnimalBaseSchema):
Expand Down
53 changes: 18 additions & 35 deletions backend/services/shelter_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
from sqlalchemy.ext.asyncio import AsyncSession as Session
from passlib.context import CryptContext

from os import environ
from jose import jwt, JWTError
from jose.exceptions import ExpiredSignatureError

import time
import json

from backend.models.shelter import Shelter
from backend.schemas.shelter_schemas import (
Expand All @@ -30,34 +31,34 @@ async def authenticate_shelter(self, body: BaseShelterSchema, response: Response
body.password, hashed_field=shelter.password
):
return False
self.__prepare_cookie(shelter, response)
return shelter

return self.__generate_session_token(shelter)

def __generate_session_token(self, shelter: Shelter):
expires = time.time() + 3600
token = jwt.encode({"username": shelter.username, "exp": expires}, "salt")
return token

async def create_shelter(self, body: CreateShelterSchema) -> Shelter:
body.username = body.username.strip().lower()
body.password = self.__get_password_hash(body.password)
return await self.dao.create_shelter(body)

async def check_is_auth_active(self, request: Request, response: Response):
async def check_is_auth_active(self, request: Request):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
)

shelter_id = request.cookies.get("shelter-id")
auth_cookie = request.cookies.get("x-auth")

if not shelter_id or not auth_cookie:
response.delete_cookie("shelter-id")
response.delete_cookie("x-auth")
token = request.headers.get("x-auth")
if not token:
raise credentials_exception

shelter = await self.__get_shelter_from_db_by_id(int(shelter_id))
secret_field = self.__prepare_secret_field(shelter)

if not self.__verify_encoded_fields(secret_field, auth_cookie):
response.delete_cookie("shelter-id")
response.delete_cookie("x-auth")
try:
jwt.decode(token, "salt")
except ExpiredSignatureError:
raise credentials_exception
except JWTError:
raise credentials_exception

def __verify_encoded_fields(self, plain_field, hashed_field):
Expand All @@ -71,21 +72,3 @@ async def __get_shelter_from_db(self, username: str):

async def __get_shelter_from_db_by_id(self, id: int):
return await self.dao.get_shelter_from_db_by_id(id)

def __prepare_secret_field(self, shelter):
field_to_select = environ.get("HASH_FIELD", "username")
selected_value = getattr(shelter, field_to_select, field_to_select)
secret = json.dumps(
{
"id": shelter.id,
"secret": selected_value,
}
)

return secret

def __prepare_cookie(self, shelter, response: Response):
secret_field = self.__prepare_secret_field(shelter)
auth_cookie = pwd_context.hash(secret_field)
response.set_cookie(key="x-auth", httponly=True, value=auth_cookie, samesite='none', secure=True)
response.set_cookie(key="shelter-id", httponly=True, value=shelter.id, samesite='none', secure=True)

0 comments on commit afbeed0

Please sign in to comment.