Files
Wu Clan 5c7d6659cf Reconstruct RBAC authentication logic (#264)
* Reconstruct RBAC authentication logic

* fix typo

* Migrate casbin sqla Adapter to redis

* Delete casbin model conf file

* Add permission dependencies

* Add request permission depends on execution condition

* Update openapi authorization method

* Add request permission identity

* Add request permission dependency description

* Migrate casbin redis adapter to sqla

* Update menu model and add function

* Fix menu permission identification

* Update user partial interface permissions

* Update menu table SQL

* Add role menu permission description to README

* fix README typo

* Simplify permission dependency injection

* Fix menu authorization store

* Fix interface permission dependency order

* Update role menu permission flag

* Update the background permission logic of the interface
2024-01-08 09:35:47 +08:00

88 lines
2.6 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import annotations
import math
from typing import TYPE_CHECKING, Dict, Generic, Sequence, TypeVar
from fastapi import Depends, Query
from fastapi_pagination import pagination_ctx
from fastapi_pagination.bases import AbstractPage, AbstractParams, RawParams
from fastapi_pagination.ext.sqlalchemy import paginate
from fastapi_pagination.links.bases import create_links
from pydantic import BaseModel
if TYPE_CHECKING:
from sqlalchemy import Select
from sqlalchemy.ext.asyncio import AsyncSession
T = TypeVar('T')
DataT = TypeVar('DataT')
SchemaT = TypeVar('SchemaT')
class _Params(BaseModel, AbstractParams):
page: int = Query(1, ge=1, description='Page number')
size: int = Query(20, gt=0, le=100, description='Page size') # 默认 20 条记录
def to_raw_params(self) -> RawParams:
return RawParams(
limit=self.size,
offset=self.size * (self.page - 1),
)
class _Page(AbstractPage[T], Generic[T]):
items: Sequence[T] # 数据
total: int # 总数据数
page: int # 第n页
size: int # 每页数量
total_pages: int # 总页数
links: Dict[str, str | None] # 跳转链接
__params_type__ = _Params # 使用自定义的Params
@classmethod
def create(
cls,
items: Sequence[T],
total: int,
params: _Params,
) -> _Page[T]:
page = params.page
size = params.size
total_pages = math.ceil(total / params.size)
links = create_links(
**{
'first': {'page': 1, 'size': f'{size}'},
'last': {'page': f'{math.ceil(total / params.size)}', 'size': f'{size}'} if total > 0 else None,
'next': {'page': f'{page + 1}', 'size': f'{size}'} if (page + 1) <= total_pages else None,
'prev': {'page': f'{page - 1}', 'size': f'{size}'} if (page - 1) >= 1 else None,
}
).model_dump()
return cls(items=items, total=total, page=params.page, size=params.size, total_pages=total_pages, links=links)
class _PageData(BaseModel, Generic[DataT]):
page_data: DataT | None = None
async def paging_data(db: AsyncSession, select: Select, page_data_schema: SchemaT) -> dict:
"""
基于 SQLAlchemy 创建分页数据
:param db:
:param select:
:param page_data_schema:
:return:
"""
_paginate = await paginate(db, select)
page_data = _PageData[_Page[page_data_schema]](page_data=_paginate).model_dump()['page_data']
return page_data
# 分页依赖注入
DependsPagination = Depends(pagination_ctx(_Page))