From bd242c95f737d0c7fe08d6347face91bd320bfc2 Mon Sep 17 00:00:00 2001 From: insistence <3055204202@qq.com> Date: Fri, 12 Jul 2024 09:35:26 +0800 Subject: [PATCH] =?UTF-8?q?style:=20=E4=BD=BF=E7=94=A8ruff=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96=E7=99=BB=E5=BD=95=E6=A8=A1=E5=9D=97=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/login_controller.py | 99 ++++--- .../module_admin/dao/login_dao.py | 18 +- .../module_admin/entity/vo/login_vo.py | 14 +- .../module_admin/service/login_service.py | 257 +++++++++++------- 4 files changed, 241 insertions(+), 147 deletions(-) diff --git a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py index 7c769a1..b8b3133 100644 --- a/ruoyi-fastapi-backend/module_admin/controller/login_controller.py +++ b/ruoyi-fastapi-backend/module_admin/controller/login_controller.py @@ -1,79 +1,104 @@ -from fastapi import APIRouter -from module_admin.service.login_service import * -from module_admin.entity.vo.login_vo import * -from module_admin.dao.login_dao import * -from module_admin.annotation.log_annotation import log_decorator -from config.env import JwtConfig, RedisInitKeyConfig +import uuid +from datetime import datetime, timedelta +from fastapi import APIRouter, Depends, Request +from jose import jwt +from sqlalchemy.ext.asyncio import AsyncSession +from typing import Optional from config.enums import BusinessType +from config.env import AppConfig, JwtConfig, RedisInitKeyConfig +from config.get_db import get_db +from module_admin.annotation.log_annotation import log_decorator +from module_admin.entity.vo.common_vo import CrudResponseModel +from module_admin.entity.vo.login_vo import UserLogin, UserRegister, Token +from module_admin.entity.vo.user_vo import CurrentUserModel, EditUserModel +from module_admin.service.login_service import CustomOAuth2PasswordRequestForm, LoginService, oauth2_scheme +from module_admin.service.user_service import UserService +from utils.log_util import logger from utils.response_util import ResponseUtil -from utils.log_util import * -from datetime import timedelta loginController = APIRouter() -@loginController.post("/login", response_model=Token) +@loginController.post('/login', response_model=Token) @log_decorator(title='用户登录', business_type=BusinessType.OTHER, log_type='login') -async def login(request: Request, form_data: CustomOAuth2PasswordRequestForm = Depends(), query_db: AsyncSession = Depends(get_db)): - captcha_enabled = True if await request.app.state.redis.get(f"{RedisInitKeyConfig.SYS_CONFIG.get('key')}:sys.account.captchaEnabled") == 'true' else False +async def login( + request: Request, form_data: CustomOAuth2PasswordRequestForm = Depends(), query_db: AsyncSession = Depends(get_db) +): + captcha_enabled = ( + True + if await request.app.state.redis.get(f"{RedisInitKeyConfig.SYS_CONFIG.get('key')}:sys.account.captchaEnabled") + == 'true' + else False + ) user = UserLogin( userName=form_data.username, password=form_data.password, code=form_data.code, uuid=form_data.uuid, loginInfo=form_data.login_info, - captchaEnabled=captcha_enabled + captchaEnabled=captcha_enabled, ) result = await LoginService.authenticate_user(request, query_db, user) access_token_expires = timedelta(minutes=JwtConfig.jwt_expire_minutes) session_id = str(uuid.uuid4()) access_token = await LoginService.create_access_token( data={ - "user_id": str(result[0].user_id), - "user_name": result[0].user_name, - "dept_name": result[1].dept_name if result[1] else None, - "session_id": session_id, - "login_info": user.login_info + 'user_id': str(result[0].user_id), + 'user_name': result[0].user_name, + 'dept_name': result[1].dept_name if result[1] else None, + 'session_id': session_id, + 'login_info': user.login_info, }, - expires_delta=access_token_expires + expires_delta=access_token_expires, ) if AppConfig.app_same_time_login: - await request.app.state.redis.set(f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{session_id}", access_token, - ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes)) + await request.app.state.redis.set( + f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{session_id}", + access_token, + ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes), + ) else: # 此方法可实现同一账号同一时间只能登录一次 - await request.app.state.redis.set(f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{result[0].user_id}", access_token, - ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes)) - await UserService.edit_user_services(query_db, EditUserModel(userId=result[0].user_id, loginDate=datetime.now(), type='status')) + await request.app.state.redis.set( + f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{result[0].user_id}", + access_token, + ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes), + ) + await UserService.edit_user_services( + query_db, EditUserModel(userId=result[0].user_id, loginDate=datetime.now(), type='status') + ) logger.info('登录成功') # 判断请求是否来自于api文档,如果是返回指定格式的结果,用于修复api文档认证成功后token显示undefined的bug request_from_swagger = request.headers.get('referer').endswith('docs') if request.headers.get('referer') else False request_from_redoc = request.headers.get('referer').endswith('redoc') if request.headers.get('referer') else False if request_from_swagger or request_from_redoc: return {'access_token': access_token, 'token_type': 'Bearer'} - return ResponseUtil.success( - msg='登录成功', - dict_content={'token': access_token} - ) + return ResponseUtil.success(msg='登录成功', dict_content={'token': access_token}) -@loginController.get("/getInfo", response_model=CurrentUserModel) -async def get_login_user_info(request: Request, current_user: CurrentUserModel = Depends(LoginService.get_current_user)): +@loginController.get('/getInfo', response_model=CurrentUserModel) +async def get_login_user_info( + request: Request, current_user: CurrentUserModel = Depends(LoginService.get_current_user) +): logger.info('获取成功') return ResponseUtil.success(model_content=current_user) -@loginController.get("/getRouters") -async def get_login_user_routers(request: Request, current_user: CurrentUserModel = Depends(LoginService.get_current_user), query_db: AsyncSession = Depends(get_db)): +@loginController.get('/getRouters') +async def get_login_user_routers( + request: Request, + current_user: CurrentUserModel = Depends(LoginService.get_current_user), + query_db: AsyncSession = Depends(get_db), +): logger.info('获取成功') user_routers = await LoginService.get_current_user_routers(current_user.user.user_id, query_db) return ResponseUtil.success(data=user_routers) -@loginController.post("/register", response_model=CrudResponseModel) +@loginController.post('/register', response_model=CrudResponseModel) async def register_user(request: Request, user_register: UserRegister, query_db: AsyncSession = Depends(get_db)): user_register_result = await LoginService.register_user_services(request, query_db, user_register) logger.info(user_register_result.message) @@ -111,11 +136,13 @@ async def register_user(request: Request, user_register: UserRegister, query_db: # return ResponseUtil.error(msg=str(e)) -@loginController.post("/logout") +@loginController.post('/logout') async def logout(request: Request, token: Optional[str] = Depends(oauth2_scheme)): - payload = jwt.decode(token, JwtConfig.jwt_secret_key, algorithms=[JwtConfig.jwt_algorithm], options={'verify_exp': False}) - session_id: str = payload.get("session_id") + payload = jwt.decode( + token, JwtConfig.jwt_secret_key, algorithms=[JwtConfig.jwt_algorithm], options={'verify_exp': False} + ) + session_id: str = payload.get('session_id') await LoginService.logout_services(request, session_id) logger.info('退出成功') - return ResponseUtil.success(msg="退出成功") + return ResponseUtil.success(msg='退出成功') diff --git a/ruoyi-fastapi-backend/module_admin/dao/login_dao.py b/ruoyi-fastapi-backend/module_admin/dao/login_dao.py index baa77ab..9bafa65 100644 --- a/ruoyi-fastapi-backend/module_admin/dao/login_dao.py +++ b/ruoyi-fastapi-backend/module_admin/dao/login_dao.py @@ -1,7 +1,7 @@ -from sqlalchemy import select, and_ +from sqlalchemy import and_, select from sqlalchemy.ext.asyncio import AsyncSession -from module_admin.entity.do.user_do import SysUser from module_admin.entity.do.dept_do import SysDept +from module_admin.entity.do.user_do import SysUser async def login_by_account(db: AsyncSession, user_name: str): @@ -11,11 +11,17 @@ async def login_by_account(db: AsyncSession, user_name: str): :param user_name: 用户名 :return: 用户对象 """ - user = (await db.execute( - select(SysUser, SysDept) + user = ( + await db.execute( + select(SysUser, SysDept) .where(SysUser.user_name == user_name, SysUser.del_flag == '0') - .join(SysDept, and_(SysUser.dept_id == SysDept.dept_id, SysDept.status == '0', SysDept.del_flag == '0'), isouter=True) + .join( + SysDept, + and_(SysUser.dept_id == SysDept.dept_id, SysDept.status == '0', SysDept.del_flag == '0'), + isouter=True, + ) .distinct() - )).first() + ) + ).first() return user diff --git a/ruoyi-fastapi-backend/module_admin/entity/vo/login_vo.py b/ruoyi-fastapi-backend/module_admin/entity/vo/login_vo.py index c3ee684..fbd6e07 100644 --- a/ruoyi-fastapi-backend/module_admin/entity/vo/login_vo.py +++ b/ruoyi-fastapi-backend/module_admin/entity/vo/login_vo.py @@ -1,7 +1,7 @@ import re from pydantic import BaseModel, ConfigDict, Field, model_validator from pydantic.alias_generators import to_camel -from typing import Optional, List, Union +from typing import List, Optional, Union from exceptions.exception import ModelValidatorException from module_admin.entity.vo.menu_vo import MenuModel @@ -28,11 +28,11 @@ class UserRegister(BaseModel): @model_validator(mode='after') def check_password(self) -> 'UserRegister': - pattern = r'''^[^<>"'|\\]+$''' + pattern = r"""^[^<>"'|\\]+$""" if self.password is None or re.match(pattern, self.password): return self else: - raise ModelValidatorException(message="密码不能包含非法字符:< > \" ' \\ |") + raise ModelValidatorException(message='密码不能包含非法字符:< > " \' \\ |') class Token(BaseModel): @@ -75,9 +75,13 @@ class RouterModel(BaseModel): name: Optional[str] = Field(default=None, description='路由名称') path: Optional[str] = Field(default=None, description='路由地址') hidden: Optional[bool] = Field(default=None, description='是否隐藏路由,当设置 true 的时候该路由不会再侧边栏出现') - redirect: Optional[str] = Field(default=None, description='重定向地址,当设置 noRedirect 的时候该路由在面包屑导航中不可被点击') + redirect: Optional[str] = Field( + default=None, description='重定向地址,当设置 noRedirect 的时候该路由在面包屑导航中不可被点击' + ) component: Optional[str] = Field(default=None, description='组件地址') query: Optional[str] = Field(default=None, description='路由参数:如 {"id": 1, "name": "ry"}') - always_show: Optional[bool] = Field(default=None, description='当你一个路由下面的children声明的路由大于1个时,自动会变成嵌套的模式--如组件页面') + always_show: Optional[bool] = Field( + default=None, description='当你一个路由下面的children声明的路由大于1个时,自动会变成嵌套的模式--如组件页面' + ) meta: Optional[MetaModel] = Field(default=None, description='其他元素') children: Optional[Union[List['RouterModel'], None]] = Field(default=None, description='子路由') diff --git a/ruoyi-fastapi-backend/module_admin/service/login_service.py b/ruoyi-fastapi-backend/module_admin/service/login_service.py index f4a96b3..ddf792a 100644 --- a/ruoyi-fastapi-backend/module_admin/service/login_service.py +++ b/ruoyi-fastapi-backend/module_admin/service/login_service.py @@ -1,24 +1,28 @@ -from fastapi import Request, Form -from fastapi import Depends -from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm -from jose import JWTError, jwt import random import uuid -from datetime import timedelta -from module_admin.service.user_service import * -from module_admin.entity.vo.login_vo import * -from module_admin.entity.vo.common_vo import CrudResponseModel -from module_admin.dao.login_dao import * -from exceptions.exception import LoginException, AuthException, ServiceException +from datetime import datetime, timedelta +from fastapi import Depends, Form, Request +from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm +from jose import JWTError, jwt +from sqlalchemy.ext.asyncio import AsyncSession +from typing import Dict, List, Optional, Union from config.constant import CommonConstant, MenuConstant from config.env import AppConfig, JwtConfig, RedisInitKeyConfig from config.get_db import get_db +from exceptions.exception import LoginException, AuthException, ServiceException +from module_admin.dao.login_dao import login_by_account +from module_admin.dao.user_dao import UserDao +from module_admin.entity.do.menu_do import SysMenu +from module_admin.entity.vo.common_vo import CrudResponseModel +from module_admin.entity.vo.login_vo import MenuTreeModel, MetaModel, RouterModel, SmsCode, UserLogin, UserRegister +from module_admin.entity.vo.user_vo import AddUserModel, CurrentUserModel, ResetUserModel, TokenData, UserInfoModel +from module_admin.service.user_service import UserService from utils.common_util import CamelCaseUtil -from utils.pwd_util import * -from utils.response_util import * -from utils.message_util import * +from utils.log_util import logger +from utils.message_util import message_service +from utils.pwd_util import PwdUtil -oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login") +oauth2_scheme = OAuth2PasswordBearer(tokenUrl='login') class CustomOAuth2PasswordRequestForm(OAuth2PasswordRequestForm): @@ -27,19 +31,25 @@ class CustomOAuth2PasswordRequestForm(OAuth2PasswordRequestForm): """ def __init__( - self, - grant_type: str = Form(default=None, regex="password"), - username: str = Form(), - password: str = Form(), - scope: str = Form(default=""), - client_id: Optional[str] = Form(default=None), - client_secret: Optional[str] = Form(default=None), - code: Optional[str] = Form(default=""), - uuid: Optional[str] = Form(default=""), - login_info: Optional[Dict[str, str]] = Form(default=None) + self, + grant_type: str = Form(default=None, regex='password'), + username: str = Form(), + password: str = Form(), + scope: str = Form(default=''), + client_id: Optional[str] = Form(default=None), + client_secret: Optional[str] = Form(default=None), + code: Optional[str] = Form(default=''), + uuid: Optional[str] = Form(default=''), + login_info: Optional[Dict[str, str]] = Form(default=None), ): - super().__init__(grant_type=grant_type, username=username, password=password, - scope=scope, client_id=client_id, client_secret=client_secret) + super().__init__( + grant_type=grant_type, + username=username, + password=password, + scope=scope, + client_id=client_id, + client_secret=client_secret, + ) self.code = code self.uuid = uuid self.login_info = login_info @@ -61,47 +71,61 @@ class LoginService: """ await cls.__check_login_ip(request) account_lock = await request.app.state.redis.get( - f"{RedisInitKeyConfig.ACCOUNT_LOCK.get('key')}:{login_user.user_name}") + f"{RedisInitKeyConfig.ACCOUNT_LOCK.get('key')}:{login_user.user_name}" + ) if login_user.user_name == account_lock: - logger.warning("账号已锁定,请稍后再试") - raise LoginException(data="", message="账号已锁定,请稍后再试") + logger.warning('账号已锁定,请稍后再试') + raise LoginException(data='', message='账号已锁定,请稍后再试') # 判断请求是否来自于api文档,如果是返回指定格式的结果,用于修复api文档认证成功后token显示undefined的bug - request_from_swagger = request.headers.get('referer').endswith('docs') if request.headers.get('referer') else False - request_from_redoc = request.headers.get('referer').endswith('redoc') if request.headers.get('referer') else False + request_from_swagger = ( + request.headers.get('referer').endswith('docs') if request.headers.get('referer') else False + ) + request_from_redoc = ( + request.headers.get('referer').endswith('redoc') if request.headers.get('referer') else False + ) # 判断是否开启验证码,开启则验证,否则不验证(dev模式下来自API文档的登录请求不检验) - if not login_user.captcha_enabled or ((request_from_swagger or request_from_redoc) and AppConfig.app_env == 'dev'): + if not login_user.captcha_enabled or ( + (request_from_swagger or request_from_redoc) and AppConfig.app_env == 'dev' + ): pass else: await cls.__check_login_captcha(request, login_user) user = await login_by_account(query_db, login_user.user_name) if not user: - logger.warning("用户不存在") - raise LoginException(data="", message="用户不存在") + logger.warning('用户不存在') + raise LoginException(data='', message='用户不存在') if not PwdUtil.verify_password(login_user.password, user[0].password): cache_password_error_count = await request.app.state.redis.get( - f"{RedisInitKeyConfig.PASSWORD_ERROR_COUNT.get('key')}:{login_user.user_name}") + f"{RedisInitKeyConfig.PASSWORD_ERROR_COUNT.get('key')}:{login_user.user_name}" + ) password_error_counted = 0 if cache_password_error_count: password_error_counted = cache_password_error_count password_error_count = int(password_error_counted) + 1 await request.app.state.redis.set( - f"{RedisInitKeyConfig.PASSWORD_ERROR_COUNT.get('key')}:{login_user.user_name}", password_error_count, - ex=timedelta(minutes=10)) + f"{RedisInitKeyConfig.PASSWORD_ERROR_COUNT.get('key')}:{login_user.user_name}", + password_error_count, + ex=timedelta(minutes=10), + ) if password_error_count > 5: await request.app.state.redis.delete( - f"{RedisInitKeyConfig.PASSWORD_ERROR_COUNT.get('key')}:{login_user.user_name}") + f"{RedisInitKeyConfig.PASSWORD_ERROR_COUNT.get('key')}:{login_user.user_name}" + ) await request.app.state.redis.set( - f"{RedisInitKeyConfig.ACCOUNT_LOCK.get('key')}:{login_user.user_name}", login_user.user_name, - ex=timedelta(minutes=10)) - logger.warning("10分钟内密码已输错超过5次,账号已锁定,请10分钟后再试") - raise LoginException(data="", message="10分钟内密码已输错超过5次,账号已锁定,请10分钟后再试") - logger.warning("密码错误") - raise LoginException(data="", message="密码错误") + f"{RedisInitKeyConfig.ACCOUNT_LOCK.get('key')}:{login_user.user_name}", + login_user.user_name, + ex=timedelta(minutes=10), + ) + logger.warning('10分钟内密码已输错超过5次,账号已锁定,请10分钟后再试') + raise LoginException(data='', message='10分钟内密码已输错超过5次,账号已锁定,请10分钟后再试') + logger.warning('密码错误') + raise LoginException(data='', message='密码错误') if user[0].status == '1': - logger.warning("用户已停用") - raise LoginException(data="", message="用户已停用") + logger.warning('用户已停用') + raise LoginException(data='', message='用户已停用') await request.app.state.redis.delete( - f"{RedisInitKeyConfig.PASSWORD_ERROR_COUNT.get('key')}:{login_user.user_name}") + f"{RedisInitKeyConfig.PASSWORD_ERROR_COUNT.get('key')}:{login_user.user_name}" + ) return user @classmethod @@ -112,11 +136,12 @@ class LoginService: :return: 校验结果 """ black_ip_value = await request.app.state.redis.get( - f"{RedisInitKeyConfig.SYS_CONFIG.get('key')}:sys.login.blackIPList") + f"{RedisInitKeyConfig.SYS_CONFIG.get('key')}:sys.login.blackIPList" + ) black_ip_list = black_ip_value.split(',') if black_ip_value else [] if request.headers.get('X-Forwarded-For') in black_ip_list: - logger.warning("当前IP禁止登录") - raise LoginException(data="", message="当前IP禁止登录") + logger.warning('当前IP禁止登录') + raise LoginException(data='', message='当前IP禁止登录') return True @classmethod @@ -128,13 +153,14 @@ class LoginService: :return: 校验结果 """ captcha_value = await request.app.state.redis.get( - f"{RedisInitKeyConfig.CAPTCHA_CODES.get('key')}:{login_user.uuid}") + f"{RedisInitKeyConfig.CAPTCHA_CODES.get('key')}:{login_user.uuid}" + ) if not captcha_value: - logger.warning("验证码已失效") - raise LoginException(data="", message="验证码已失效") + logger.warning('验证码已失效') + raise LoginException(data='', message='验证码已失效') if login_user.code != str(captcha_value): - logger.warning("验证码错误") - raise LoginException(data="", message="验证码错误") + logger.warning('验证码错误') + raise LoginException(data='', message='验证码错误') return True @classmethod @@ -150,13 +176,14 @@ class LoginService: expire = datetime.utcnow() + expires_delta else: expire = datetime.utcnow() + timedelta(minutes=30) - to_encode.update({"exp": expire}) + to_encode.update({'exp': expire}) encoded_jwt = jwt.encode(to_encode, JwtConfig.jwt_secret_key, algorithm=JwtConfig.jwt_algorithm) return encoded_jwt @classmethod - async def get_current_user(cls, request: Request = Request, token: str = Depends(oauth2_scheme), - query_db: AsyncSession = Depends(get_db)): + async def get_current_user( + cls, request: Request = Request, token: str = Depends(oauth2_scheme), query_db: AsyncSession = Depends(get_db) + ): """ 根据token获取当前用户信息 :param request: Request对象 @@ -172,31 +199,41 @@ class LoginService: if token.startswith('Bearer'): token = token.split(' ')[1] payload = jwt.decode(token, JwtConfig.jwt_secret_key, algorithms=[JwtConfig.jwt_algorithm]) - user_id: str = payload.get("user_id") - session_id: str = payload.get("session_id") + user_id: str = payload.get('user_id') + session_id: str = payload.get('session_id') if user_id is None: - logger.warning("用户token不合法") - raise AuthException(data="", message="用户token不合法") + logger.warning('用户token不合法') + raise AuthException(data='', message='用户token不合法') token_data = TokenData(user_id=int(user_id)) except JWTError: - logger.warning("用户token已失效,请重新登录") - raise AuthException(data="", message="用户token已失效,请重新登录") + logger.warning('用户token已失效,请重新登录') + raise AuthException(data='', message='用户token已失效,请重新登录') query_user = await UserDao.get_user_by_id(query_db, user_id=token_data.user_id) if query_user.get('user_basic_info') is None: - logger.warning("用户token不合法") - raise AuthException(data="", message="用户token不合法") + logger.warning('用户token不合法') + raise AuthException(data='', message='用户token不合法') if AppConfig.app_same_time_login: - redis_token = await request.app.state.redis.get(f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{session_id}") + redis_token = await request.app.state.redis.get( + f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{session_id}" + ) else: # 此方法可实现同一账号同一时间只能登录一次 - redis_token = await request.app.state.redis.get(f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{query_user.get('user_basic_info').user_id}") + redis_token = await request.app.state.redis.get( + f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{query_user.get('user_basic_info').user_id}" + ) if token == redis_token: if AppConfig.app_same_time_login: - await request.app.state.redis.set(f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{session_id}", redis_token, - ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes)) + await request.app.state.redis.set( + f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{session_id}", + redis_token, + ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes), + ) else: - await request.app.state.redis.set(f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{query_user.get('user_basic_info').user_id}", redis_token, - ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes)) + await request.app.state.redis.set( + f"{RedisInitKeyConfig.ACCESS_TOKEN.get('key')}:{query_user.get('user_basic_info').user_id}", + redis_token, + ex=timedelta(minutes=JwtConfig.jwt_redis_expire_minutes), + ) role_id_list = [item.role_id for item in query_user.get('user_role_info')] if 1 in role_id_list: @@ -215,13 +252,13 @@ class LoginService: postIds=post_ids, roleIds=role_ids, dept=CamelCaseUtil.transform_result(query_user.get('user_dept_info')), - role=CamelCaseUtil.transform_result(query_user.get('user_role_info')) - ) + role=CamelCaseUtil.transform_result(query_user.get('user_role_info')), + ), ) return current_user else: - logger.warning("用户token已失效,请重新登录") - raise AuthException(data="", message="用户token已失效,请重新登录") + logger.warning('用户token已失效,请重新登录') + raise AuthException(data='', message='用户token已失效,请重新登录') @classmethod async def get_current_user_routers(cls, user_id: int, query_db: AsyncSession): @@ -232,7 +269,14 @@ class LoginService: :return: 当前用户路由信息对象 """ query_user = await UserDao.get_user_by_id(query_db, user_id=user_id) - user_router_menu = sorted([row for row in query_user.get('user_menu_info') if row.menu_type in [MenuConstant.TYPE_DIR, MenuConstant.TYPE_MENU]], key=lambda x: x.order_num) + user_router_menu = sorted( + [ + row + for row in query_user.get('user_menu_info') + if row.menu_type in [MenuConstant.TYPE_DIR, MenuConstant.TYPE_MENU] + ], + key=lambda x: x.order_num, + ) menus = cls.__generate_menus(0, user_router_menu) user_router = cls.__generate_user_router_menu(menus) return [router.model_dump(exclude_unset=True, by_alias=True) for router in user_router] @@ -275,8 +319,8 @@ class LoginService: title=permission.menu_name, icon=permission.icon, noCache=True if permission.is_cache == 1 else False, - link=permission.path if RouterUtil.is_http(permission.path) else None - ) + link=permission.path if RouterUtil.is_http(permission.path) else None, + ), ) c_menus = permission.children if c_menus and permission.menu_type == MenuConstant.TYPE_DIR: @@ -294,17 +338,14 @@ class LoginService: title=permission.menu_name, icon=permission.icon, noCache=True if permission.is_cache == 1 else False, - link=permission.path if RouterUtil.is_http(permission.path) else None + link=permission.path if RouterUtil.is_http(permission.path) else None, ), - query=permission.query + query=permission.query, ) children_list.append(children) router.children = children_list elif permission.parent_id == 0 and RouterUtil.is_inner_link(permission): - router.meta = MetaModel( - title=permission.menu_name, - icon=permission.icon - ) + router.meta = MetaModel(title=permission.menu_name, icon=permission.icon) router.path = '/' children_list: List[RouterModel] = [] router_path = RouterUtil.inner_link_replace_each(permission.path) @@ -315,8 +356,8 @@ class LoginService: meta=MetaModel( title=permission.menu_name, icon=permission.icon, - link=permission.path if RouterUtil.is_http(permission.path) else None - ) + link=permission.path if RouterUtil.is_http(permission.path) else None, + ), ) children_list.append(children) router.children = children_list @@ -334,15 +375,26 @@ class LoginService: :param user_register: 注册用户对象 :return: 注册结果 """ - register_enabled = True if await request.app.state.redis.get( - f"{RedisInitKeyConfig.SYS_CONFIG.get('key')}:sys.account.registerUser") == 'true' else False - captcha_enabled = True if await request.app.state.redis.get( - f"{RedisInitKeyConfig.SYS_CONFIG.get('key')}:sys.account.captchaEnabled") == 'true' else False + register_enabled = ( + True + if await request.app.state.redis.get(f"{RedisInitKeyConfig.SYS_CONFIG.get('key')}:sys.account.registerUser") + == 'true' + else False + ) + captcha_enabled = ( + True + if await request.app.state.redis.get( + f"{RedisInitKeyConfig.SYS_CONFIG.get('key')}:sys.account.captchaEnabled" + ) + == 'true' + else False + ) if user_register.password == user_register.confirm_password: if register_enabled: if captcha_enabled: captcha_value = await request.app.state.redis.get( - f"{RedisInitKeyConfig.CAPTCHA_CODES.get('key')}:{user_register.uuid}") + f"{RedisInitKeyConfig.CAPTCHA_CODES.get('key')}:{user_register.uuid}" + ) if not captcha_value: raise ServiceException(message='验证码已失效') elif user_register.code != str(captcha_value): @@ -350,7 +402,7 @@ class LoginService: add_user = AddUserModel( userName=user_register.username, nickName=user_register.username, - password=PwdUtil.get_password_hash(user_register.password) + password=PwdUtil.get_password_hash(user_register.password), ) result = await UserService.add_user_services(query_db, add_user) return result @@ -369,15 +421,17 @@ class LoginService: :return: 短信验证码对象 """ redis_sms_result = await request.app.state.redis.get( - f"{RedisInitKeyConfig.SMS_CODE.get('key')}:{user.session_id}") + f"{RedisInitKeyConfig.SMS_CODE.get('key')}:{user.session_id}" + ) if redis_sms_result: return SmsCode(**dict(is_success=False, sms_code='', session_id='', message='短信验证码仍在有效期内')) is_user = await UserDao.get_user_by_name(query_db, user.user_name) if is_user: sms_code = str(random.randint(100000, 999999)) session_id = str(uuid.uuid4()) - await request.app.state.redis.set(f"{RedisInitKeyConfig.SMS_CODE.get('key')}:{session_id}", sms_code, - ex=timedelta(minutes=2)) + await request.app.state.redis.set( + f"{RedisInitKeyConfig.SMS_CODE.get('key')}:{session_id}", sms_code, ex=timedelta(minutes=2) + ) # 此处模拟调用短信服务 message_service(sms_code) @@ -395,7 +449,8 @@ class LoginService: :return: 重置结果 """ redis_sms_result = await request.app.state.redis.get( - f"{RedisInitKeyConfig.SMS_CODE.get('key')}:{forget_user.session_id}") + f"{RedisInitKeyConfig.SMS_CODE.get('key')}:{forget_user.session_id}" + ) if forget_user.sms_code == redis_sms_result: forget_user.password = PwdUtil.get_password_hash(forget_user.password) forget_user.user_id = (await UserDao.get_user_by_name(query_db, forget_user.user_name)).user_id @@ -484,7 +539,9 @@ class RouterUtil: :param menu: 菜单数对象 :return: 是否为菜单内部跳转 """ - return menu.parent_id == 0 and menu.menu_type == MenuConstant.TYPE_MENU and menu.is_frame == MenuConstant.NO_FRAME + return ( + menu.parent_id == 0 and menu.menu_type == MenuConstant.TYPE_MENU and menu.is_frame == MenuConstant.NO_FRAME + ) @classmethod def is_inner_link(cls, menu: MenuTreeModel): @@ -520,8 +577,8 @@ class RouterUtil: :param path: 内链域名 :return: 替换后的内链域名 """ - old_values = [CommonConstant.HTTP, CommonConstant.HTTPS, CommonConstant.WWW, ".", ":"] - new_values = ["", "", "", "/", "/"] + old_values = [CommonConstant.HTTP, CommonConstant.HTTPS, CommonConstant.WWW, '.', ':'] + new_values = ['', '', '', '/', '/'] for old, new in zip(old_values, new_values): path = path.replace(old, new) return path