Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.12.2-slim-bookworm AS base
FROM python:3.12-slim-bookworm AS base
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y --no-install-recommends curl git build-essential \
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ py-upgrade: ## Upgrade project py files with pyupgrade library for python versio

.PHONY: lint
lint: ## Lint project code.
poetry run ruff --fix .
poetry run ruff check --fix .

.PHONY: slim-build
slim-build: ## with power of docker-slim build smaller and safer images
Expand Down
4 changes: 4 additions & 0 deletions app/api/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
from app.models.user import User
from app.schemas.user import UserSchema, UserResponse, UserLogin, TokenResponse
from app.services.auth import create_access_token
from app.utils.logging import AppLogger

logger = AppLogger().get_logger()

router = APIRouter(prefix="/v1/user")


@router.post("/", status_code=status.HTTP_201_CREATED, response_model=UserResponse)
async def create_user(payload: UserSchema, request: Request, db_session: AsyncSession = Depends(get_db)):
logger.info(f"Creating user: {payload}")
_user: User = User(**payload.model_dump())
await _user.save(db_session)

Expand Down
10 changes: 6 additions & 4 deletions app/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import bcrypt
from passlib.context import CryptContext
from pydantic import SecretStr
from sqlalchemy import String, LargeBinary, select
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.ext.asyncio import AsyncSession
Expand All @@ -25,11 +26,12 @@ def password(self):
return self._password.decode("utf-8")

@password.setter
def password(self, password: str):
self._password = bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt())
def password(self, password: SecretStr):
_password_string = password.get_secret_value()
self._password = bcrypt.hashpw(_password_string.encode("utf-8"), bcrypt.gensalt())

def check_password(self, password: str):
return pwd_context.verify(password, self.password)
def check_password(self, password: SecretStr):
return pwd_context.verify(password.get_secret_value(), self.password)

@classmethod
async def find(cls, database_session: AsyncSession, where_conditions: list[Any]):
Expand Down
14 changes: 7 additions & 7 deletions app/schemas/user.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
from uuid import UUID

from pydantic import BaseModel, Field, EmailStr, ConfigDict
from pydantic import BaseModel, Field, EmailStr, ConfigDict, SecretStr

config = ConfigDict(from_attributes=True)


# TODO: add pydantic field validator for strong password
class UserSchema(BaseModel):
model_config = config
email: EmailStr = Field(title="User’s email", description="User’s email")
first_name: str = Field(title="User’s first name", description="User’s first name")
last_name: str = Field(title="User’s last name", description="User’s last name")
password: str = Field(title="User’s password", description="User’s password")
email: EmailStr = Field(title="User’s email", description="User’s email", examples=["john@domain.com"])
first_name: str = Field(title="User’s first name", description="User’s first name", examples=["John"])
last_name: str = Field(title="User’s last name", description="User’s last name", examples=["Doe"])
password: SecretStr = Field(title="User’s password", description="User’s password", examples=["@SuperSecret123"])


class UserResponse(BaseModel):
Expand All @@ -29,5 +29,5 @@ class TokenResponse(BaseModel):

class UserLogin(BaseModel):
model_config = config
email: EmailStr = Field(title="User’s email", description="User’s email")
password: str = Field(title="User’s password", description="User’s password")
email: EmailStr = Field(title="User’s email", description="User’s email", examples=["john@domain.com"])
password: SecretStr = Field(title="User’s password", description="User’s password", examples=["@SuperSecret123"])
Loading