Skip to content

Commit

Permalink
user information api ready
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexTraveylan committed Aug 22, 2024
1 parent da89e90 commit 8740c86
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 18 deletions.
79 changes: 75 additions & 4 deletions app/api/user_information/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
from fastapi import APIRouter, Depends, status

from app.api.user_information.models import USER_INFORMATION_SERVICE, UserInformation
from app.api.user_information.schema import UserInformationSchemaIn
from app.api.user_information.schema import (
UserInformationSchemaIn,
UserInformationSchemaOut,
)
from app.auth.models import User
from app.auth.token import get_current_user
from app.database.unit_of_work import unit_api
from app.exceptions import CannotCreateStillExistsException
from app.exceptions import CannotCreateStillExistsException, RessourceNotFoundException

user_information_router = APIRouter(
tags=["User Information"],
Expand All @@ -16,7 +19,7 @@


@user_information_router.post("/", status_code=status.HTTP_201_CREATED)
def read_users_me(
def create_users_informations(
current_user: Annotated[User, Depends(get_current_user)],
user_information: UserInformationSchemaIn,
) -> UserInformation:
Expand All @@ -36,4 +39,72 @@ def read_users_me(

item = USER_INFORMATION_SERVICE.create(session, item)

return item
session.expunge(item)

return item


@user_information_router.get("/", status_code=status.HTTP_200_OK)
def read_users_informations(
current_user: Annotated[User, Depends(get_current_user)],
) -> UserInformationSchemaOut:
with unit_api("Trying to read user informations") as session:
user_informations = USER_INFORMATION_SERVICE.get_or_none(
session, user_id=current_user.id
)

if user_informations is None:
raise RessourceNotFoundException("User has no user informations")

session.expunge(user_informations)

return user_informations.to_decrypted()


@user_information_router.put("/", status_code=status.HTTP_200_OK)
def update_users_informations(
current_user: Annotated[User, Depends(get_current_user)],
user_information: UserInformationSchemaIn,
) -> UserInformationSchemaOut:
with unit_api("Trying to update user informations") as session:
user_informations = USER_INFORMATION_SERVICE.get_or_none(
session, user_id=current_user.id
)

if user_informations is None:
raise RessourceNotFoundException("User has no user informations")

encrypted_informations = UserInformation(
name=user_information.name,
first_name=user_information.first_name,
email=user_information.email,
)

new_user_informations = USER_INFORMATION_SERVICE.update(
session,
user_informations.id,
encrypted_name=encrypted_informations.name,
encrypted_first_name=encrypted_informations.first_name,
encrypted_email=encrypted_informations.email,
)

session.expunge(new_user_informations)

return new_user_informations.to_decrypted()


@user_information_router.delete("/", status_code=status.HTTP_204_NO_CONTENT)
def delete_users_informations(
current_user: Annotated[User, Depends(get_current_user)],
) -> None:
with unit_api("Trying to delete user informations") as session:
user_informations = USER_INFORMATION_SERVICE.get_or_none(
session, user_id=current_user.id
)

if user_informations is None:
raise RessourceNotFoundException("User has no user informations")

USER_INFORMATION_SERVICE.delete(session, user_informations.id)

return None
18 changes: 16 additions & 2 deletions app/api/user_information/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from sqlalchemy import Column, ForeignKey, Integer
from sqlmodel import Field

from app.api.user_information.schema import UserInformationSchemaOut
from app.commun.crypto import decrypt, encrypt
from app.commun.validator import validate_email, validate_username
from app.database.model_base import BaseSQLModel
Expand All @@ -23,7 +24,10 @@ class UserInformation(BaseSQLModel, table=True):
)

@cached_property
def email(self) -> str:
def email(self) -> str | None:
if self.encrypted_email is None:
return None

return decrypt(self.encrypted_email)

@cached_property
Expand All @@ -35,7 +39,10 @@ def first_name(self) -> str:
return decrypt(self.encrypted_first_name)

@field_validator("encrypted_email")
def email_format(cls, value: str) -> str:
def email_format(cls, value: str | None) -> str | None:
if value is None:
return None

value = validate_email(value)

return encrypt(value)
Expand All @@ -52,6 +59,13 @@ def first_name_format(cls, value: str) -> str:

return encrypt(value)

def to_decrypted(self) -> UserInformationSchemaOut:
return UserInformationSchemaOut(
name=self.name,
first_name=self.first_name,
is_email=False if self.encrypted_email is None else True,
)


class UserInformationService(Repository[UserInformation]):
__model__ = UserInformation
Expand Down
6 changes: 6 additions & 0 deletions app/api/user_information/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ class UserInformationSchemaIn(BaseModel):
name: str
first_name: str
email: Optional[str]


class UserInformationSchemaOut(BaseModel):
name: str
first_name: str
is_email: bool
19 changes: 18 additions & 1 deletion app/auth/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
get_current_user,
)
from app.database.unit_of_work import unit_api
from app.exceptions import CannotCreateStillExistsException, UnauthorizedException
from app.exceptions import (
CannotCreateStillExistsException,
RessourceNotFoundException,
UnauthorizedException,
)

auth_router = APIRouter(
tags=["Authentication"],
Expand Down Expand Up @@ -56,3 +60,16 @@ def read_users_me(
current_user: Annotated[User, Depends(get_current_user)],
) -> User:
return current_user


@auth_router.delete("/users/me/")
def delete_users_me(
current_user: Annotated[User, Depends(get_current_user)],
) -> None:
with unit_api("Trying to delete user") as session:
is_deleted = USER_SERVICE.delete(session, current_user.id)

if is_deleted is False:
raise RessourceNotFoundException("Cannot delete user")

return None
15 changes: 4 additions & 11 deletions app/auth/models.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from functools import cached_property
from typing import Optional

from pydantic import field_validator
from sqlmodel import Field

from app.commun.crypto import decrypt, encrypt, get_password_hash
from app.commun.crypto import get_password_hash
from app.commun.validator import validate_password, validate_username
from app.database.model_base import BaseSQLModel
from app.database.repository import Repository
Expand All @@ -14,18 +13,12 @@ class User(BaseSQLModel, table=True):
__tablename__ = "users"

id: Optional[int] = Field(default=None, primary_key=True)
encrypted_username: str = Field(unique=True, alias="username")
username: str = Field(unique=True)
hashed_password: str = Field(alias="password")

@cached_property
def username(self) -> str:
return decrypt(self.encrypted_username)

@field_validator("encrypted_username")
@field_validator("username")
def username_format(cls, value: str) -> str:
value = validate_username(value)

return encrypt(value)
return validate_username(value)

@field_validator("hashed_password")
def password_format(cls, value: str) -> str:
Expand Down
8 changes: 8 additions & 0 deletions app/database/unit_of_work.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from app.exceptions import (
CannotCreateStillExistsException,
ParentsListMakerException,
RessourceNotFoundException,
UnauthorizedException,
)
from app.settings import DB_URL
Expand Down Expand Up @@ -52,6 +53,13 @@ def unit_api(attempt_message: str):
status_code=status.HTTP_403_FORBIDDEN,
detail=f"{attempt_message} FAILED : {str(e)}",
)
except RessourceNotFoundException as e:
session.rollback()
logger.exception(e)
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"{attempt_message} FAILED : {str(e)}",
)
except UnauthorizedException as e:
session.rollback()
logger.exception(e)
Expand Down
4 changes: 4 additions & 0 deletions app/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ class UnauthorizedException(APIException):

class CannotCreateStillExistsException(APIException):
pass


class RessourceNotFoundException(APIException):
pass

0 comments on commit 8740c86

Please sign in to comment.