ktianc ebcdac7796 版本升级
1. 新增(kinit-api):防止密码破解,新增输入5次错误密码,账号锁定,使用过期时间为1天
2. 新增(kinit-api):新增 OpenAuth 开放认证方式
3. 新增(kinit-api,kinit-uni):创建用户时,如果没有头像,则添加默认头像链接
4. 优化(kinit-api):登录接口优化
5. 新增(kinit-api):新增Count计数类
6. 更新(kinit-admin):前端升级到vue-element-plus-admin最新版本1.9.4
2023-03-05 22:55:24 +08:00

151 lines
4.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
# @version : 1.0
# @Creaet Time : 2021/10/24 16:44
# @File : current.py
# @IDE : PyCharm
# @desc : 获取认证后的信息工具
from typing import List, Optional
from jose import jwt, JWTError
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import joinedload
from apps.vadmin.auth.crud import UserDal
from apps.vadmin.auth.models import VadminUser
from core.exception import CustomException
from utils import status
from .validation import AuthValidation
from fastapi import Request, Depends
from application import settings
from core.database import db_getter
from .validation.auth import Auth
def get_user_permissions(user: VadminUser) -> set:
"""
获取员工用户所有权限列表
"""
if any([role.is_admin for role in user.roles]):
return {'*.*.*'}
permissions = set()
for role_obj in user.roles:
for menu in role_obj.menus:
if menu.perms and not menu.disabled:
permissions.add(menu.perms)
return permissions
class OpenAuth(AuthValidation):
"""
开放认证,无认证也可以访问
认证了以后可以获取到用户信息,无认证则获取不到
"""
@classmethod
def validate_token(cls, token: str | None, db: AsyncSession) -> str | None:
"""
验证用户 token没有则返回 None
"""
if not token:
return None
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=[settings.ALGORITHM])
telephone: str = payload.get("sub")
if telephone is None:
return None
except JWTError:
return None
return telephone
@classmethod
async def validate_user(cls, request: Request, user: VadminUser, db: AsyncSession) -> Auth:
"""
验证用户信息
"""
if user is None:
return Auth(db=db)
elif not user.is_active:
return Auth(db=db)
request.scope["telephone"] = user.telephone
try:
request.scope["body"] = await request.body()
except RuntimeError:
request.scope["body"] = "获取失败"
return Auth(user=user, db=db)
async def __call__(
self,
request: Request,
token: str = Depends(settings.oauth2_scheme),
db: AsyncSession = Depends(db_getter)
):
"""
每次调用依赖此类的接口会执行该方法
"""
telephone = self.validate_token(token, db)
if telephone:
user = await UserDal(db).get_data(telephone=telephone, v_return_none=True)
return await self.validate_user(request, user, db)
return Auth(db=db)
class AllUserAuth(AuthValidation):
"""
支持所有用户认证
获取用户基本信息
"""
async def __call__(
self,
request: Request,
token: str = Depends(settings.oauth2_scheme),
db: AsyncSession = Depends(db_getter)
):
"""
每次调用依赖此类的接口会执行该方法
"""
telephone = self.validate_token(token, db)
if isinstance(telephone, Auth):
return telephone
user = await UserDal(db).get_data(telephone=telephone, v_return_none=True)
return await self.validate_user(request, user, db)
class FullAdminAuth(AuthValidation):
"""
只支持员工用户认证
获取员工用户完整信息
如果有权限,那么会验证该用户是否包括权限列表中的其中一个权限
"""
def __init__(self, permissions: Optional[List[str]] = None):
if permissions:
self.permissions = set(permissions)
else:
self.permissions = None
async def __call__(
self,
request: Request,
token: str = Depends(settings.oauth2_scheme),
db: AsyncSession = Depends(db_getter)
) -> Auth:
"""
每次调用依赖此类的接口会执行该方法
"""
telephone = self.validate_token(token, db)
if isinstance(telephone, Auth):
return telephone
options = [joinedload(VadminUser.roles), joinedload("roles.menus")]
user = await UserDal(db).get_data(telephone=telephone, v_return_none=True, v_options=options, is_staff=True)
result = await self.validate_user(request, user, db)
permissions = get_user_permissions(user)
if permissions != {'*.*.*'} and self.permissions:
if not (self.permissions & permissions):
raise CustomException(msg="无权限操作", code=status.HTTP_403_FORBIDDEN)
return result