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 typing import Optional
from lib import settings
class User(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
name: str
email: str = Field(unique=True)
password: str
avatar_url: str
is_active: bool = Field(default=True)
is_admin: bool = Field(default=False)
created_at: datetime = Field(default_factory=datetime.utcnow)
updated_at: datetime = Field(default_factory=datetime.utcnow)
class UserCredentials(BaseModel):
username: str = Field(description="Username of the user", examples=["admin"])
password: str = Field(description="Password of the user", examples=["password"])
class UserBase(BaseModel):
id: Optional[str] = Field(
default=None,
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(
prefix="/user",
@@ -9,11 +13,41 @@ router = APIRouter(
)
@router.get("/")
async def get_users():
return {"users": ["user1", "user2", "user3"]}
@router.get("/", response_model=list[UserOut])
async def get_users() -> list[UserOut]:
"""Get all users"""
return get_all_users()
@router.post("/login")
async def login():
return {"token": "token"}
@router.post(
"/login",
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(),
)