Add User login route

This commit is contained in:
Esa Kataja
2024-11-09 16:25:05 +02:00
parent aecf382070
commit e620d5c19e
2 changed files with 90 additions and 19 deletions
+48 -11
View File
@@ -1,15 +1,52 @@
from sqlmodel import Field, SQLModel from pydantic import BaseModel, Field
from datetime import datetime from datetime import datetime
from typing import Optional from typing import Optional
from lib import settings
class User(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True) class UserCredentials(BaseModel):
name: str username: str = Field(description="Username of the user", examples=["admin"])
email: str = Field(unique=True) password: str = Field(description="Password of the user", examples=["password"])
password: str
avatar_url: str
is_active: bool = Field(default=True) class UserBase(BaseModel):
is_admin: bool = Field(default=False) id: Optional[str] = Field(
created_at: datetime = Field(default_factory=datetime.utcnow) default=None,
updated_at: datetime = Field(default_factory=datetime.utcnow) description="UUID representation of the user",
examples=["123e4567-e89b-12d3-a456-426655440000"],
)
username: str = Field(description="Username of the user", examples=["Palli-Pate"])
email: Optional[str] = Field(
default=None, description="Email of the user", examples=["[email protected]"]
)
avatar_url: str = Field(
default=settings.default_avatar_url, description="Avatar URL of the user"
)
is_active: bool = Field(
default=True, description="Whether the user is active or not"
)
is_admin: bool = Field(
default=False, description="Whether the user is an admin or not"
)
last_login: Optional[datetime] = Field(
default=None,
description="Last login date of the user",
examples=[datetime.utcnow()],
)
created_at: datetime = Field(
default_factory=datetime.utcnow, description="Creation date of the user"
)
modified_at: datetime = Field(
default_factory=datetime.utcnow, description="Modification date of the user"
)
class UserIn(UserBase):
password: Optional[str] = Field(
default=None, description="Password of the user", examples=["password"]
)
class UserOut(UserBase):
pass
+42 -8
View File
@@ -1,6 +1,10 @@
from fastapi import APIRouter from fastapi import APIRouter, Response
import bcrypt
from models.user import UserIn, UserOut, UserCredentials
from models.general import Message
from lib.database import get_all_users, get_user_by_username
from models import User
router = APIRouter( router = APIRouter(
prefix="/user", prefix="/user",
@@ -9,11 +13,41 @@ router = APIRouter(
) )
@router.get("/") @router.get("/", response_model=list[UserOut])
async def get_users(): async def get_users() -> list[UserOut]:
return {"users": ["user1", "user2", "user3"]} """Get all users"""
return get_all_users()
@router.post("/login") @router.post(
async def login(): "/login",
return {"token": "token"} responses={
200: {"model": UserOut, "description": "Login successful"},
400: {"model": Message},
404: {"model": Message},
},
)
async def login(user: UserCredentials):
"""Login a user"""
user_from_db: UserIn = get_user_by_username(user.username)
if user_from_db is None:
return Response(
status_code=404,
media_type="application/json",
content=Message(
message="User not found", message_type="error"
).model_dump_json(),
)
password = user.password.encode("utf-8")
if bcrypt.checkpw(password, user_from_db.password.encode("utf-8")):
return UserOut(**user_from_db.model_dump())
return Response(
status_code=400,
media_type="application/json",
content=Message(
message="Invalid password", message_type="error"
).model_dump_json(),
)