项目初次搭建
This commit is contained in:
19
app/api/common/upload_file.py
Normal file
19
app/api/common/upload_file.py
Normal file
@ -0,0 +1,19 @@
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter
|
||||
from fastapi import UploadFile
|
||||
import os
|
||||
|
||||
upload = APIRouter()
|
||||
|
||||
|
||||
@upload.post("/")
|
||||
def upload_file(files: List[UploadFile]):
|
||||
paths = []
|
||||
for file in files:
|
||||
path = os.path.join("images", file.filename)
|
||||
with open(path, "wb") as f:
|
||||
for line in file.file:
|
||||
f.write(line)
|
||||
paths.append(path)
|
||||
return paths
|
34
app/api/sys/login_api.py
Normal file
34
app/api/sys/login_api.py
Normal file
@ -0,0 +1,34 @@
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.orm import Session
|
||||
from app.db.db_session import get_db
|
||||
from app.model.schemas.sys_user_schemas import SysUserLogin
|
||||
from app.common import reponse_code as rc
|
||||
from app.model.crud import sys_user_crud as us
|
||||
from app.common.bcrypt_pw import verify_password
|
||||
from app.common.jwt_check import generate_token
|
||||
from app.common.redis_cli import redis_conn
|
||||
"""
|
||||
用户登录统一接口
|
||||
"""
|
||||
|
||||
login = APIRouter()
|
||||
|
||||
|
||||
@login.post("/")
|
||||
def login_check(user: SysUserLogin, session: Session = Depends(get_db)):
|
||||
"""
|
||||
登录验证,并返回token
|
||||
:param session:
|
||||
:param user: 登录参数信息
|
||||
:return: response
|
||||
"""
|
||||
query_user = us.get_user_by_username(username=user.username, session=session)
|
||||
if query_user is None:
|
||||
return rc.response_error('您输入的用户名不正确')
|
||||
if not verify_password(user.password, query_user.password):
|
||||
return rc.response_error("您输入的密码不正确")
|
||||
if not query_user.user_status == '0':
|
||||
return rc.response_error(msg="登录失败,账号已被禁用,请联系管理员")
|
||||
token = generate_token(query_user.id, query_user.username)
|
||||
redis_conn.set(query_user.id, token)
|
||||
return rc.response_success(msg="登录成功", data=token)
|
84
app/api/sys/sys_user_api.py
Normal file
84
app/api/sys/sys_user_api.py
Normal file
@ -0,0 +1,84 @@
|
||||
from fastapi import APIRouter, Depends
|
||||
from app.model.schemas.sys_user_schemas import SysUserOut, SysUserIN, SysUserPager
|
||||
from app.common import reponse_code as rc
|
||||
from app.model.crud import sys_user_crud as us
|
||||
from app.model.model import SysUser
|
||||
from app.common.redis_cli import redis_conn
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
from app.db.db_session import get_db
|
||||
"""
|
||||
用户管理模块
|
||||
"""
|
||||
user = APIRouter()
|
||||
|
||||
|
||||
@user.post("/pager")
|
||||
def user_pager(user: SysUserPager, session: Session = Depends(get_db)):
|
||||
pager = us.user_pager(user, session)
|
||||
return rc.response_success_pager(pager)
|
||||
|
||||
|
||||
@user.post("/")
|
||||
def add_user(user: SysUserIN, session: Session = Depends(get_db)):
|
||||
"""
|
||||
新增用户
|
||||
:param session:
|
||||
:param user: 用户信息
|
||||
:return:
|
||||
"""
|
||||
if us.check_username(user.username, session):
|
||||
return rc.response_error(msg="该用户名已存在!")
|
||||
else:
|
||||
user_in= SysUser(**user.dict())
|
||||
user_in.user_status = '0'
|
||||
if us.add_user(user_in, session):
|
||||
return rc.response_success(msg="保存成功")
|
||||
else:
|
||||
return rc.response_error(msg="保存失败")
|
||||
|
||||
|
||||
@user.get("/{id}")
|
||||
def get_user(id: int, session: Session = Depends(get_db)):
|
||||
"""
|
||||
根据用户id获取用户信息
|
||||
:param session:
|
||||
:param id: 用户id
|
||||
:return: 用户信息
|
||||
"""
|
||||
user = us.get_user_by_id(id, session)
|
||||
if user is None:
|
||||
return rc.response_success(data=None)
|
||||
user_out = SysUserOut(**dict(user))
|
||||
return rc.response_success(data=user_out.dict())
|
||||
|
||||
|
||||
@user.post("/stop/{id}")
|
||||
def stop_user(id: int, session: Session = Depends(get_db)):
|
||||
"""
|
||||
停用用户。修改用户状态,并删除保存过的登录redis
|
||||
:param session:
|
||||
:param id:
|
||||
:return:
|
||||
"""
|
||||
user = us.get_user_by_id(id, session)
|
||||
if user is None:
|
||||
return rc.response_error("用户查询错误,请稍后再试")
|
||||
us.stop_user(user)
|
||||
redis_conn.delete(id)
|
||||
return rc.response_success("停用用户成功")
|
||||
|
||||
|
||||
@user.post("/start/{id}")
|
||||
def start_user(id: int, session: Session = Depends(get_db)):
|
||||
"""
|
||||
启用用户。修改用户状态
|
||||
:param session:
|
||||
:param id:
|
||||
:return:
|
||||
"""
|
||||
user = us.get_user_by_id(id, session)
|
||||
if user is None:
|
||||
return rc.response_error("用户查询错误,请稍后再试")
|
||||
us.start_user(user)
|
||||
return rc.response_success("启用用户成功")
|
23
app/application/app.py
Normal file
23
app/application/app.py
Normal file
@ -0,0 +1,23 @@
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
from app.application.token_middleware import TokenMiddleware
|
||||
from app.application.logger_middleware import LoggerMiddleware
|
||||
|
||||
my_app = FastAPI()
|
||||
|
||||
|
||||
'''
|
||||
添加CROS中间件,允许跨域请求
|
||||
'''
|
||||
my_app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
#注意中间的顺序,这个地方是倒序执行的
|
||||
my_app.add_middleware(LoggerMiddleware)
|
||||
my_app.add_middleware(TokenMiddleware)
|
23
app/application/logger_middleware.py
Normal file
23
app/application/logger_middleware.py
Normal file
@ -0,0 +1,23 @@
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from urllib.request import Request
|
||||
|
||||
from app.common.jwt_check import check_token
|
||||
|
||||
from app.common.logger_config import logger_http
|
||||
|
||||
|
||||
class LoggerMiddleware(BaseHTTPMiddleware):
|
||||
def __init__(self, app):
|
||||
super().__init__(app)
|
||||
|
||||
async def dispatch(self, request: Request, call_next):
|
||||
method = request.method
|
||||
path = request.url.path
|
||||
token = request.headers.get("Authorization")
|
||||
user_id = None
|
||||
if token:
|
||||
decoded_payload = check_token(token)
|
||||
user_id = decoded_payload['user_id']
|
||||
logger_http.info(f"Path: {path},UserId: {user_id}, Method: {method}")
|
||||
response = await call_next(request)
|
||||
return response
|
33
app/application/token_middleware.py
Normal file
33
app/application/token_middleware.py
Normal file
@ -0,0 +1,33 @@
|
||||
from fastapi import status
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from urllib.request import Request
|
||||
from jwt import PyJWTError
|
||||
from common import reponse_code as rc
|
||||
from common import jwt_check as jc
|
||||
|
||||
|
||||
|
||||
class TokenMiddleware(BaseHTTPMiddleware):
|
||||
|
||||
def __init__(self, app):
|
||||
super().__init__(app)
|
||||
|
||||
async def dispatch(self, request: Request, call_next):
|
||||
"""
|
||||
验证token中间件
|
||||
:param request: Request请求
|
||||
:param call_next:
|
||||
:return:
|
||||
"""
|
||||
token = request.headers.get('Authorization')
|
||||
path = request.url.path
|
||||
if '/login' in path:
|
||||
response = await call_next(request)
|
||||
return response
|
||||
if not token:
|
||||
return rc.response_code_view(status.HTTP_401_UNAUTHORIZED, "缺少Token,请重新验证")
|
||||
try:
|
||||
jc.check_token(token)
|
||||
return await call_next(request)
|
||||
except PyJWTError as error:
|
||||
return rc.response_code_view(status.HTTP_401_UNAUTHORIZED, "Token错误或失效,请重新验证")
|
13
app/common/bcrypt_pw.py
Normal file
13
app/common/bcrypt_pw.py
Normal file
@ -0,0 +1,13 @@
|
||||
import bcrypt
|
||||
|
||||
#使用bcrypt对密码进行加密
|
||||
def hash_password(password):
|
||||
# 生成盐值并使用 bcrypt 加密密码
|
||||
salt = bcrypt.gensalt()
|
||||
hashed = bcrypt.hashpw(password.encode('utf-8'), salt)
|
||||
return hashed
|
||||
|
||||
|
||||
def verify_password(provided_password, stored_password):
|
||||
# 验证提供的密码是否与存储的哈希值匹配
|
||||
return bcrypt.checkpw(provided_password.encode('utf-8'), stored_password.encode('utf-8'))
|
50
app/common/jwt_check.py
Normal file
50
app/common/jwt_check.py
Normal file
@ -0,0 +1,50 @@
|
||||
import datetime
|
||||
|
||||
import jwt
|
||||
from app.common.redis_cli import redis_conn
|
||||
|
||||
# 过期时间,单位S
|
||||
exp = 6000
|
||||
|
||||
# 加密秘钥
|
||||
secret_key = 'syg15684712291'
|
||||
|
||||
|
||||
def generate_token(user_id: int, username: str):
|
||||
"""
|
||||
根据用户id和用户名生成一个token
|
||||
:param user_id: 用户id
|
||||
:param username: 用户名
|
||||
:return: token
|
||||
"""
|
||||
payload = {
|
||||
'user_id': user_id,
|
||||
'username': username,
|
||||
'exp': datetime.datetime.utcnow() + datetime.timedelta(exp)
|
||||
}
|
||||
|
||||
# 生成token
|
||||
token = jwt.encode(payload, secret_key, algorithm='HS256')
|
||||
|
||||
return token
|
||||
|
||||
|
||||
def check_token(token: str):
|
||||
"""
|
||||
验证token
|
||||
:param token: token
|
||||
:return: True or False
|
||||
"""
|
||||
try:
|
||||
decoded_payload = jwt.decode(token, secret_key, algorithms=['HS256'])
|
||||
user_id = decoded_payload['user_id']
|
||||
token_redis = redis_conn.get(user_id)
|
||||
if token_redis is None:
|
||||
raise jwt.ExpiredSignatureError("Expired Token")
|
||||
if token_redis != token:
|
||||
raise jwt.ExpiredSignatureError("Invalid Token")
|
||||
return decoded_payload
|
||||
except jwt.ExpiredSignatureError:
|
||||
raise jwt.ExpiredSignatureError("Expired Token")
|
||||
except jwt.InvalidTokenError:
|
||||
raise jwt.InvalidTokenError("Invalid Token")
|
33
app/common/logger_config.py
Normal file
33
app/common/logger_config.py
Normal file
@ -0,0 +1,33 @@
|
||||
import logging
|
||||
import os
|
||||
from logging.handlers import TimedRotatingFileHandler
|
||||
|
||||
from app.config.config_reader import log_dir
|
||||
|
||||
|
||||
file_suffix = "%Y-%m-%d"
|
||||
os.makedirs(log_dir, exist_ok=True)
|
||||
|
||||
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||
|
||||
#所有http请求的日志
|
||||
logger_http = logging.getLogger("api_log")
|
||||
logger_http.setLevel(logging.DEBUG)
|
||||
# 创建一个TimedRotatingFileHandler,指定日志文件名、轮转周期和备份数量
|
||||
api_log_file = os.path.join(log_dir, 'api.log')
|
||||
api_handler = TimedRotatingFileHandler(api_log_file, when="midnight", interval=1, backupCount=30)
|
||||
api_handler.setFormatter(formatter)
|
||||
api_handler.suffix = file_suffix # 日志文件的后缀为日期格式
|
||||
logger_http.addHandler(api_handler)
|
||||
|
||||
#所有sqlalchemy打印的日志
|
||||
logger_sql = logging.getLogger("sqlalchemy.engine.Engine")
|
||||
logger_sql.setLevel(logging.DEBUG)
|
||||
# 创建文件处理器并设置级别
|
||||
sql_log_file = os.path.join(log_dir, 'sql.log')
|
||||
sql_handler = TimedRotatingFileHandler(sql_log_file, when="midnight", interval=1, backupCount=30)
|
||||
sql_handler.setFormatter(formatter)
|
||||
sql_handler.suffix = file_suffix # 日志文件的后缀为日期格式
|
||||
logger_sql.addHandler(sql_handler)
|
||||
|
||||
|
4
app/common/redis_cli.py
Normal file
4
app/common/redis_cli.py
Normal file
@ -0,0 +1,4 @@
|
||||
import redis
|
||||
from app.config.config_reader import redis_db, redis_password, redis_port, redis_host
|
||||
|
||||
redis_conn = redis.Redis(host=redis_host, port=redis_port, db=redis_db, password=redis_password, decode_responses=True)
|
46
app/common/reponse_code.py
Normal file
46
app/common/reponse_code.py
Normal file
@ -0,0 +1,46 @@
|
||||
from fastapi.responses import JSONResponse, Response
|
||||
from fastapi import status
|
||||
from app.db.page_util import Pager
|
||||
|
||||
|
||||
def response_code_view(code: int,msg: str) -> Response:
|
||||
return JSONResponse(
|
||||
status_code=code,
|
||||
content={
|
||||
'code': code,
|
||||
'msg': msg
|
||||
}
|
||||
)
|
||||
|
||||
def response_success(msg: str = "查询成功", data: object = None):
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
content={
|
||||
'code': 200,
|
||||
'msg': msg,
|
||||
'data': data,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def response_success_pager(pager: Pager):
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
content={
|
||||
'code': 200,
|
||||
'msg': "查询成功",
|
||||
'data': pager.data,
|
||||
'total': pager.total
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def response_error(msg:str):
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
content={
|
||||
'code': 500,
|
||||
'msg': msg,
|
||||
'data': None,
|
||||
}
|
||||
)
|
11
app/config/application_config_dev.ini
Normal file
11
app/config/application_config_dev.ini
Normal file
@ -0,0 +1,11 @@
|
||||
[mysql]
|
||||
database_url = mysql+pymysql://root:root@localhost:3306/aicheckv2
|
||||
|
||||
[redis]
|
||||
host = localhost
|
||||
port = 6379
|
||||
db = 0
|
||||
password = sdust2020
|
||||
|
||||
[log]
|
||||
dir = D:\syg\workspace\logs
|
11
app/config/application_config_pro.ini
Normal file
11
app/config/application_config_pro.ini
Normal file
@ -0,0 +1,11 @@
|
||||
[mysql]
|
||||
database_url = mysql+pymysql://root:root@localhost:3306/sun
|
||||
|
||||
[redis]
|
||||
host = localhost
|
||||
port = 6379
|
||||
db = 0
|
||||
password = 123456
|
||||
|
||||
[log]
|
||||
dir = /Users/macbookpro/sunyg/workspace/logs
|
21
app/config/config_reader.py
Normal file
21
app/config/config_reader.py
Normal file
@ -0,0 +1,21 @@
|
||||
import configparser
|
||||
import os
|
||||
|
||||
env = "dev"
|
||||
|
||||
|
||||
script_directory = os.path.dirname(os.path.abspath(__file__))
|
||||
config_path = os.path.join(script_directory, f'application_config_{env}.ini')
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read(config_path)
|
||||
|
||||
|
||||
database_url = config['mysql']['database_url']
|
||||
|
||||
redis_host = config.get('redis', 'host')
|
||||
redis_port = config.get('redis', 'port')
|
||||
redis_db = config.get('redis', 'db')
|
||||
redis_password = config.get('redis', 'password')
|
||||
|
||||
log_dir = config.get('log', 'dir')
|
20
app/db/db_base.py
Normal file
20
app/db/db_base.py
Normal file
@ -0,0 +1,20 @@
|
||||
from sqlalchemy.ext.declarative import declarative_base, declared_attr
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
import datetime
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
|
||||
class DbCommon(Base):
|
||||
__abstract__ = True
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
create_time: Mapped[datetime.datetime] = mapped_column(default=datetime.datetime.utcnow())
|
||||
update_time: Mapped[datetime.datetime] = mapped_column(default=datetime.datetime.utcnow(), onupdate=datetime.datetime.utcnow())
|
||||
|
||||
def keys(self):
|
||||
return ["id", "create_time", "update_time"]
|
||||
|
||||
|
||||
@declared_attr
|
||||
def __tablename__(cls):
|
||||
return cls.__name__.lower()
|
9
app/db/db_engine.py
Normal file
9
app/db/db_engine.py
Normal file
@ -0,0 +1,9 @@
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker, scoped_session
|
||||
from app.config.config_reader import database_url
|
||||
|
||||
|
||||
db_engine = create_engine(database_url, echo=True, echo_pool=True)
|
||||
|
||||
db_session = sessionmaker(bind=db_engine, autoflush=False, autocommit=False, expire_on_commit=True)
|
||||
session = scoped_session(db_session)
|
9
app/db/db_session.py
Normal file
9
app/db/db_session.py
Normal file
@ -0,0 +1,9 @@
|
||||
from app.db.db_engine import db_session
|
||||
|
||||
|
||||
def get_db():
|
||||
session = db_session()
|
||||
try:
|
||||
yield session
|
||||
finally:
|
||||
session.close()
|
26
app/db/page_util.py
Normal file
26
app/db/page_util.py
Normal file
@ -0,0 +1,26 @@
|
||||
from sqlalchemy.orm.query import Query
|
||||
|
||||
|
||||
def get_pager(query: Query, pagerNum: int, pagerSize: int, ):
|
||||
total = query.count()
|
||||
data = query.limit(pagerSize).offset((pagerNum - 1) * pagerSize).all()
|
||||
pager = Pager(total, data)
|
||||
return pager
|
||||
|
||||
|
||||
class Pager:
|
||||
def __init__(self, total: int, data: object):
|
||||
self.total = total
|
||||
self.data = data
|
||||
|
||||
def keys(self):
|
||||
keys = ["total", "data"]
|
||||
return keys
|
||||
|
||||
def __getitem__(self, item):
|
||||
'''
|
||||
内置方法, 当使用obj['name']的形式的时候, 将调用这个方法, 这里返回的结果就是值
|
||||
:param item:
|
||||
:return:
|
||||
'''
|
||||
return getattr(self, item, None)
|
5
app/main.py
Normal file
5
app/main.py
Normal file
@ -0,0 +1,5 @@
|
||||
import uvicorn
|
||||
from app.application.app import my_app
|
||||
|
||||
if __name__ == '__main__':
|
||||
uvicorn.run("main:my_app", port=8080, reload=True)
|
67
app/model/crud/sys_user_crud.py
Normal file
67
app/model/crud/sys_user_crud.py
Normal file
@ -0,0 +1,67 @@
|
||||
from app.model.model import SysUser
|
||||
from app.model.schemas.sys_user_schemas import SysUserPager, SysUserOut
|
||||
from app.common.bcrypt_pw import hash_password
|
||||
from app.db.page_util import get_pager
|
||||
|
||||
from sqlalchemy import and_, desc
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
|
||||
def user_pager(user: SysUserPager, session: Session):
|
||||
query = session.query(SysUser).order_by(desc(SysUser.id))
|
||||
filters = []
|
||||
if user.username is not None:
|
||||
filters.append(SysUser.username.ilike(f"%{user.username}%"))
|
||||
if user.dept_id is not None:
|
||||
filters.append(SysUser.dept_id == user.dept_id)
|
||||
if len(filters) > 0:
|
||||
query.filter(and_(*filters))
|
||||
pager = get_pager(query, user.pagerNum, user.pagerSize)
|
||||
pager.data = [SysUserOut.from_orm(user) for user in pager.data]
|
||||
return pager
|
||||
|
||||
|
||||
def add_user(user: SysUser, session: Session):
|
||||
user.password = hash_password(user.password)
|
||||
session.add(user)
|
||||
session.commit()
|
||||
return user
|
||||
|
||||
|
||||
def get_user_by_id(id: int, session: Session):
|
||||
user = session.query(SysUser).filter(SysUser.id == id).first()
|
||||
return user
|
||||
|
||||
|
||||
def stop_user(user: SysUser, session: Session):
|
||||
user.user_status = "1"
|
||||
session.commit();
|
||||
return user
|
||||
|
||||
|
||||
def start_user(user: SysUser, session: Session):
|
||||
user.user_status = "0"
|
||||
session.commit();
|
||||
return user
|
||||
|
||||
|
||||
def get_user_by_username(username: str, session: Session):
|
||||
user = session.query(SysUser).filter(SysUser.username == username).first()
|
||||
return user
|
||||
|
||||
|
||||
# 验证username的唯一性
|
||||
def check_username(username: str, session: Session):
|
||||
count = session.query(SysUser).filter(SysUser.username == username).count()
|
||||
if count > 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
# 修改密码
|
||||
def update_pw(user: SysUser, session: Session):
|
||||
session.query(SysUser).filter_by(id=user.id).update({
|
||||
"password": user.password
|
||||
})
|
||||
session.commit()
|
29
app/model/model.py
Normal file
29
app/model/model.py
Normal file
@ -0,0 +1,29 @@
|
||||
from app.db.db_base import DbCommon
|
||||
from sqlalchemy import String,Integer
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
|
||||
class SysUser(DbCommon):
|
||||
|
||||
__tablename__ = "sys_user"
|
||||
username: Mapped[str] = mapped_column(String(50), unique=True, nullable=False)
|
||||
password: Mapped[str] = mapped_column(String(255))
|
||||
dept_id: Mapped[int] = mapped_column(Integer)
|
||||
login_name: Mapped[str] = mapped_column(String(255))
|
||||
avatar: Mapped[str] = mapped_column(String(255))
|
||||
user_status: Mapped[str] = mapped_column(String(10))
|
||||
|
||||
|
||||
def keys(self):
|
||||
keys = ["username", "password", "dept_id", "login_name", "avatar", "user_status"]
|
||||
keys.extend(super().keys())
|
||||
return keys
|
||||
|
||||
|
||||
def __getitem__(self, item):
|
||||
'''
|
||||
内置方法, 当使用obj['name']的形式的时候, 将调用这个方法, 这里返回的结果就是值
|
||||
:param item:
|
||||
:return:
|
||||
'''
|
||||
return getattr(self, item, None)
|
43
app/model/schemas/sys_user_schemas.py
Normal file
43
app/model/schemas/sys_user_schemas.py
Normal file
@ -0,0 +1,43 @@
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Optional
|
||||
|
||||
|
||||
# 用户相关的原型
|
||||
class SysUserIN(BaseModel):
|
||||
username: Optional[str] = Field(..., description="用户名", max_length=50)
|
||||
password: Optional[str] = Field(..., description="密码", max_length=30, min_length=6)
|
||||
dept_id: Optional[str] = Field(None, description="部门id")
|
||||
login_name: Optional[str] = Field(None, description="昵称", max_length=20)
|
||||
|
||||
|
||||
class SysUserLogin(BaseModel):
|
||||
username: Optional[str] = Field(..., description="用户名", max_length=50)
|
||||
password: Optional[str] = Field(..., description="密码", max_length=30, min_length=6)
|
||||
|
||||
|
||||
class SysUserOut(BaseModel):
|
||||
id: Optional[int] = Field(..., description="id")
|
||||
username: Optional[str] = Field(..., description="用户名")
|
||||
dept_id: Optional[str] = Field(None, description="部门id")
|
||||
dept_name: Optional[str] = Field(None, description="部门名称")
|
||||
login_name: Optional[str] = Field(None, description="昵称")
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
|
||||
|
||||
class SysUserUpdatePw(BaseModel):
|
||||
id: Optional[int] = Field(..., description="id")
|
||||
new_password: Optional[str] = Field(..., description="新密码", max_length=30, min_length=8)
|
||||
original_password: Optional[str] = Field(..., description="旧密码", max_length=30, min_length=8)
|
||||
|
||||
|
||||
class SysUserPager(BaseModel):
|
||||
username: Optional[str] = Field(None, description="用户名")
|
||||
dept_id: Optional[str] = Field(None, description="部门id")
|
||||
login_name: Optional[str] = Field(None, description="昵称")
|
||||
pagerNum: Optional[int] = Field(1, description="当前页码")
|
||||
pagerSize: Optional[int] = Field(10, description="每页数量")
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
Reference in New Issue
Block a user