mirror of
https://github.com/fastapi-admin/fastapi-admin.git
synced 2026-03-13 10:32:25 +08:00
update docs
This commit is contained in:
@@ -3,8 +3,6 @@ import os
|
||||
import aioredis
|
||||
import uvicorn
|
||||
from fastapi import FastAPI
|
||||
from fastapi_admin.app import app as admin_app
|
||||
from fastapi_admin.providers.login import UsernamePasswordProvider
|
||||
from starlette.middleware.cors import CORSMiddleware
|
||||
from starlette.responses import RedirectResponse
|
||||
from starlette.staticfiles import StaticFiles
|
||||
@@ -13,6 +11,8 @@ from tortoise.contrib.fastapi import register_tortoise
|
||||
from examples import settings
|
||||
from examples.constants import BASE_DIR
|
||||
from examples.models import User
|
||||
from fastapi_admin.app import app as admin_app
|
||||
from fastapi_admin.providers.login import UsernamePasswordProvider
|
||||
|
||||
login_provider = UsernamePasswordProvider(user_model=User)
|
||||
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import datetime
|
||||
|
||||
from fastapi_admin.providers.login import AbstractUser
|
||||
from tortoise import Model, fields
|
||||
|
||||
from examples.enums import Action, ProductType, Status
|
||||
from fastapi_admin.providers.login import AbstractUser
|
||||
|
||||
|
||||
class User(AbstractUser):
|
||||
last_login = fields.DatetimeField(
|
||||
description="Last Login", default=datetime.datetime.now
|
||||
)
|
||||
last_login = fields.DatetimeField(description="Last Login", default=datetime.datetime.now)
|
||||
email = fields.CharField(max_length=200)
|
||||
avatar = fields.CharField(max_length=200, default="")
|
||||
intro = fields.TextField(default="")
|
||||
created_at = fields.DatetimeField(auto_now_add=True)
|
||||
@@ -38,9 +37,7 @@ class Product(Model):
|
||||
|
||||
class Config(Model):
|
||||
label = fields.CharField(max_length=200)
|
||||
key = fields.CharField(
|
||||
max_length=20, unique=True, description="Unique key for config"
|
||||
)
|
||||
key = fields.CharField(max_length=20, unique=True, description="Unique key for config")
|
||||
value = fields.JSONField()
|
||||
status: Status = fields.IntEnumField(Status, default=Status.on)
|
||||
|
||||
|
||||
@@ -5,20 +5,19 @@ from typing import Callable, Type
|
||||
import bcrypt
|
||||
from aioredis import Redis
|
||||
from fastapi import Depends
|
||||
from fastapi_admin import constants
|
||||
from fastapi_admin.depends import get_redis
|
||||
from fastapi_admin.template import templates
|
||||
from pydantic import EmailStr
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import RedirectResponse
|
||||
from starlette.status import HTTP_303_SEE_OTHER, HTTP_401_UNAUTHORIZED
|
||||
from tortoise import Model, fields
|
||||
|
||||
from fastapi_admin import constants
|
||||
from fastapi_admin.depends import get_redis
|
||||
from fastapi_admin.template import templates
|
||||
|
||||
|
||||
class LoginProvider:
|
||||
def __init__(
|
||||
self, login_path="/login", logout_path="/logout", template="login.html"
|
||||
):
|
||||
def __init__(self, login_path="/login", logout_path="/logout", template="login.html"):
|
||||
self.template = template
|
||||
self.logout_path = logout_path
|
||||
self.login_path = login_path
|
||||
@@ -69,7 +68,7 @@ class UsernamePasswordProvider(LoginProvider):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
user_model: Type[UserMixin],
|
||||
user_model: Type[AbstractUser],
|
||||
login_path="/login",
|
||||
logout_path="/logout",
|
||||
template="login.html",
|
||||
@@ -90,9 +89,7 @@ class UsernamePasswordProvider(LoginProvider):
|
||||
status_code=HTTP_401_UNAUTHORIZED,
|
||||
context={"request": request, "error": _("login_failed")},
|
||||
)
|
||||
response = RedirectResponse(
|
||||
url=request.app.admin_path, status_code=HTTP_303_SEE_OTHER
|
||||
)
|
||||
response = RedirectResponse(url=request.app.admin_path, status_code=HTTP_303_SEE_OTHER)
|
||||
if remember_me == "on":
|
||||
expire = 3600 * 24 * 30
|
||||
response.set_cookie("remember_me", "on")
|
||||
@@ -107,9 +104,7 @@ class UsernamePasswordProvider(LoginProvider):
|
||||
path=request.app.admin_path,
|
||||
httponly=True,
|
||||
)
|
||||
await redis.set(
|
||||
constants.LOGIN_USER.format(token=token), user.pk, expire=expire
|
||||
)
|
||||
await redis.set(constants.LOGIN_USER.format(token=token), user.pk, expire=expire)
|
||||
return response
|
||||
|
||||
async def logout(self, request: Request, redis: Redis = Depends(get_redis)):
|
||||
@@ -139,15 +134,13 @@ class UsernamePasswordProvider(LoginProvider):
|
||||
return response
|
||||
else:
|
||||
if path == self.login_path:
|
||||
return RedirectResponse(
|
||||
url=request.app.admin_path, status_code=HTTP_303_SEE_OTHER
|
||||
)
|
||||
return RedirectResponse(url=request.app.admin_path, status_code=HTTP_303_SEE_OTHER)
|
||||
request.state.user = user
|
||||
|
||||
response = await call_next(request)
|
||||
return response
|
||||
|
||||
def check_password(self, user: UserMixin, password: str):
|
||||
def check_password(self, user: AbstractUser, password: str):
|
||||
return bcrypt.checkpw(password.encode(), user.password.encode())
|
||||
|
||||
def hash_password(self, password: str):
|
||||
@@ -160,6 +153,6 @@ class UsernamePasswordProvider(LoginProvider):
|
||||
email=email,
|
||||
)
|
||||
|
||||
async def update_password(self, user: UserMixin, password: str):
|
||||
async def update_password(self, user: AbstractUser, password: str):
|
||||
user.password = self.hash_password(password)
|
||||
await user.save(update_fields=["password"])
|
||||
|
||||
@@ -13,11 +13,6 @@ from fastapi_admin.template import render_values, templates
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/maintenance")
|
||||
async def maintenance(request: Request):
|
||||
return templates.TemplateResponse("errors/maintenance.html", context={"request": request})
|
||||
|
||||
|
||||
@router.get("/list/{resource}")
|
||||
async def list_view(
|
||||
request: Request,
|
||||
@@ -25,7 +20,7 @@ async def list_view(
|
||||
resources=Depends(get_resources),
|
||||
model_resource: ModelResource = Depends(get_model_resource),
|
||||
resource: str = Path(...),
|
||||
page_size: Optional[int] = None,
|
||||
page_size: int = 10,
|
||||
page_num: int = 1,
|
||||
):
|
||||
fields_name = model_resource.get_fields_name()
|
||||
|
||||
6
poetry.lock
generated
6
poetry.lock
generated
@@ -98,7 +98,7 @@ tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>
|
||||
|
||||
[[package]]
|
||||
name = "babel"
|
||||
version = "2.9.0"
|
||||
version = "2.9.1"
|
||||
description = "Internationalization utilities"
|
||||
category = "main"
|
||||
optional = false
|
||||
@@ -978,8 +978,8 @@ attrs = [
|
||||
{file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"},
|
||||
]
|
||||
babel = [
|
||||
{file = "Babel-2.9.0-py2.py3-none-any.whl", hash = "sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5"},
|
||||
{file = "Babel-2.9.0.tar.gz", hash = "sha256:da031ab54472314f210b0adcff1588ee5d1d1d0ba4dbd07b94dba82bde791e05"},
|
||||
{file = "Babel-2.9.1-py2.py3-none-any.whl", hash = "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9"},
|
||||
{file = "Babel-2.9.1.tar.gz", hash = "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0"},
|
||||
]
|
||||
bcrypt = [
|
||||
{file = "bcrypt-3.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6"},
|
||||
|
||||
Reference in New Issue
Block a user