mirror of
https://github.com/wowlikon/LiB.git
synced 2026-02-04 04:31:09 +00:00
Расширение фронтэнда
This commit is contained in:
@@ -2,15 +2,15 @@
|
||||
from datetime import timedelta
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from fastapi import APIRouter, Body, Depends, HTTPException, status
|
||||
from fastapi.security import OAuth2PasswordRequestForm
|
||||
from sqlmodel import Session, select
|
||||
|
||||
from library_service.models.db import Role, User
|
||||
from library_service.models.dto import Token, UserCreate, UserRead, UserUpdate, UserList, RoleRead, RoleList
|
||||
from library_service.settings import get_session
|
||||
from library_service.auth import (ACCESS_TOKEN_EXPIRE_MINUTES, RequireAdmin,
|
||||
RequireAuth, authenticate_user, get_password_hash,
|
||||
from library_service.auth import (ACCESS_TOKEN_EXPIRE_MINUTES, RequireAdmin, RequireAuth,
|
||||
authenticate_user, get_password_hash, decode_token,
|
||||
create_access_token, create_refresh_token)
|
||||
|
||||
router = APIRouter(prefix="/auth", tags=["authentication"])
|
||||
@@ -49,7 +49,7 @@ def register(user_data: UserCreate, session: Session = Depends(get_session)):
|
||||
hashed_password=get_password_hash(user_data.password)
|
||||
)
|
||||
|
||||
default_role = session.exec(select(Role).where(Role.name == "user")).first()
|
||||
default_role = session.exec(select(Role).where(Role.name == "member")).first()
|
||||
if default_role:
|
||||
db_user.roles.append(default_role)
|
||||
|
||||
@@ -93,13 +93,62 @@ def login(
|
||||
)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/refresh",
|
||||
response_model=Token,
|
||||
summary="Обновление токена",
|
||||
description="Получение новой пары токенов (Access + Refresh) используя действующий Refresh токен",
|
||||
)
|
||||
def refresh_token(
|
||||
refresh_token: str = Body(..., embed=True),
|
||||
session: Session = Depends(get_session),
|
||||
):
|
||||
"""Эндпоинт для обновления токенов."""
|
||||
try:
|
||||
token_data = decode_token(refresh_token, expected_type="refresh")
|
||||
except HTTPException:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="Invalid refresh token",
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
|
||||
user = session.get(User, token_data.user_id)
|
||||
if not user:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="User not found",
|
||||
)
|
||||
|
||||
if not user.is_active:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail="User is inactive",
|
||||
)
|
||||
|
||||
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
|
||||
new_access_token = create_access_token(
|
||||
data={"sub": user.username, "user_id": user.id},
|
||||
expires_delta=access_token_expires,
|
||||
)
|
||||
new_refresh_token = create_refresh_token(
|
||||
data={"sub": user.username, "user_id": user.id}
|
||||
)
|
||||
|
||||
return Token(
|
||||
access_token=new_access_token,
|
||||
refresh_token=new_refresh_token,
|
||||
token_type="bearer",
|
||||
)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/me",
|
||||
response_model=UserRead,
|
||||
summary="Текущий пользователь",
|
||||
description="Получить информацию о текущем авторизованном пользователе",
|
||||
)
|
||||
def read_users_me(current_user: RequireAuth):
|
||||
def get_my_profile(current_user: RequireAuth):
|
||||
"""Эндпоинт получения информации о себе"""
|
||||
return UserRead(
|
||||
**current_user.model_dump(), roles=[role.name for role in current_user.roles]
|
||||
@@ -142,14 +191,17 @@ def update_user_me(
|
||||
)
|
||||
def read_users(
|
||||
admin: RequireAdmin,
|
||||
session: Session = Depends(get_session),
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
session: Session = Depends(get_session),
|
||||
):
|
||||
"""Эндпоинт получения списка всех пользователей"""
|
||||
users = session.exec(select(User).offset(skip).limit(limit)).all()
|
||||
return UserList(
|
||||
users=[UserRead(**user.model_dump()) for user in users],
|
||||
users=[
|
||||
UserRead(**user.model_dump(), roles=[r.name for r in user.roles])
|
||||
for user in users
|
||||
],
|
||||
total=len(users),
|
||||
)
|
||||
|
||||
@@ -243,11 +295,14 @@ def remove_role_from_user(
|
||||
description="Возвращает список ролей",
|
||||
)
|
||||
def get_roles(
|
||||
auth: RequireAuth,
|
||||
session: Session = Depends(get_session),
|
||||
):
|
||||
"""Эндпоинт получения списа ролей"""
|
||||
user_roles = [role.name for role in auth.roles]
|
||||
exclude = {"payroll"} if "admin" in user_roles else set()
|
||||
roles = session.exec(select(Role)).all()
|
||||
return RoleList(
|
||||
roles=[RoleRead(**role.model_dump()) for role in roles],
|
||||
roles=[RoleRead(**role.model_dump(exclude=exclude)) for role in roles],
|
||||
total=len(roles),
|
||||
)
|
||||
|
||||
@@ -67,7 +67,7 @@ def filter_books(
|
||||
|
||||
@router.post(
|
||||
"/",
|
||||
response_model=Book,
|
||||
response_model=BookRead,
|
||||
summary="Создать книгу",
|
||||
description="Добавляет книгу в систему",
|
||||
)
|
||||
@@ -149,6 +149,7 @@ def update_book(
|
||||
|
||||
db_book.title = book.title or db_book.title
|
||||
db_book.description = book.description or db_book.description
|
||||
db_book.status = book.status or db_book.status
|
||||
session.commit()
|
||||
session.refresh(db_book)
|
||||
return db_book
|
||||
@@ -170,7 +171,7 @@ def delete_book(
|
||||
if not book:
|
||||
raise HTTPException(status_code=404, detail="Book not found")
|
||||
book_read = BookRead(
|
||||
id=(book.id or 0), title=book.title, description=book.description
|
||||
id=(book.id or 0), title=book.title, description=book.description, status=book.status
|
||||
)
|
||||
session.delete(book)
|
||||
session.commit()
|
||||
|
||||
@@ -36,12 +36,36 @@ async def root(request: Request):
|
||||
return templates.TemplateResponse(request, "index.html")
|
||||
|
||||
|
||||
@router.get("/genre/create", include_in_schema=False)
|
||||
async def create_genre(request: Request):
|
||||
"""Эндпоинт страницы создания жанра"""
|
||||
return templates.TemplateResponse(request, "create_genre.html")
|
||||
|
||||
|
||||
@router.get("/genre/{genre_id}/edit", include_in_schema=False)
|
||||
async def edit_genre(request: Request, genre_id: int):
|
||||
"""Эндпоинт страницы редактирования жанра"""
|
||||
return templates.TemplateResponse(request, "edit_genre.html")
|
||||
|
||||
|
||||
@router.get("/authors", include_in_schema=False)
|
||||
async def authors(request: Request):
|
||||
"""Эндпоинт страницы выбора автора"""
|
||||
return templates.TemplateResponse(request, "authors.html")
|
||||
|
||||
|
||||
@router.get("/author/create", include_in_schema=False)
|
||||
async def create_author(request: Request):
|
||||
"""Эндпоинт страницы создания автора"""
|
||||
return templates.TemplateResponse(request, "create_author.html")
|
||||
|
||||
|
||||
@router.get("/author/{author_id}/edit", include_in_schema=False)
|
||||
async def edit_author(request: Request, author_id: int):
|
||||
"""Эндпоинт страницы редактирования автора"""
|
||||
return templates.TemplateResponse(request, "edit_author.html")
|
||||
|
||||
|
||||
@router.get("/author/{author_id}", include_in_schema=False)
|
||||
async def author(request: Request, author_id: int):
|
||||
"""Эндпоинт страницы автора"""
|
||||
@@ -54,16 +78,28 @@ async def books(request: Request):
|
||||
return templates.TemplateResponse(request, "books.html")
|
||||
|
||||
|
||||
@router.get("/book/create", include_in_schema=False)
|
||||
async def create_book(request: Request):
|
||||
"""Эндпоинт страницы создания книги"""
|
||||
return templates.TemplateResponse(request, "create_book.html")
|
||||
|
||||
|
||||
@router.get("/book/{book_id}/edit", include_in_schema=False)
|
||||
async def edit_book(request: Request, book_id: int):
|
||||
"""Эндпоинт страницы редактирования книги"""
|
||||
return templates.TemplateResponse(request, "edit_book.html")
|
||||
|
||||
|
||||
@router.get("/book/{book_id}", include_in_schema=False)
|
||||
async def book(request: Request, book_id: int):
|
||||
"""Эндпоинт страницы книги"""
|
||||
return templates.TemplateResponse(request, "book.html")
|
||||
|
||||
|
||||
@router.get("/auth", include_in_schema=False)
|
||||
async def auth(request: Request):
|
||||
"""Эндпоинт страницы авторизации"""
|
||||
return templates.TemplateResponse(request, "auth.html")
|
||||
@router.get("/auth", include_in_schema=False)
|
||||
async def auth(request: Request):
|
||||
"""Эндпоинт страницы авторизации"""
|
||||
return templates.TemplateResponse(request, "auth.html")
|
||||
|
||||
|
||||
@router.get("/profile", include_in_schema=False)
|
||||
@@ -72,6 +108,12 @@ async def profile(request: Request):
|
||||
return templates.TemplateResponse(request, "profile.html")
|
||||
|
||||
|
||||
@router.get("/users", include_in_schema=False)
|
||||
async def users(request: Request):
|
||||
"""Эндпоинт страницы управления пользователями"""
|
||||
return templates.TemplateResponse(request, "users.html")
|
||||
|
||||
|
||||
@router.get("/api", include_in_schema=False)
|
||||
async def api(request: Request, app=Depends(lambda: get_app())):
|
||||
"""Страница с сылками на документацию API"""
|
||||
|
||||
Reference in New Issue
Block a user