|
@ -24,6 +24,7 @@ class CustomOAuth2PasswordRequestForm(OAuth2PasswordRequestForm): |
|
|
""" |
|
|
""" |
|
|
自定义OAuth2PasswordRequestForm类,增加验证码及会话编号参数 |
|
|
自定义OAuth2PasswordRequestForm类,增加验证码及会话编号参数 |
|
|
""" |
|
|
""" |
|
|
|
|
|
|
|
|
def __init__( |
|
|
def __init__( |
|
|
self, |
|
|
self, |
|
|
grant_type: str = Form(default=None, regex="password"), |
|
|
grant_type: str = Form(default=None, regex="password"), |
|
@ -47,6 +48,7 @@ class LoginService: |
|
|
""" |
|
|
""" |
|
|
登录模块服务层 |
|
|
登录模块服务层 |
|
|
""" |
|
|
""" |
|
|
|
|
|
|
|
|
@classmethod |
|
|
@classmethod |
|
|
async def authenticate_user(cls, request: Request, query_db: AsyncSession, login_user: UserLogin): |
|
|
async def authenticate_user(cls, request: Request, query_db: AsyncSession, login_user: UserLogin): |
|
|
""" |
|
|
""" |
|
@ -231,57 +233,95 @@ class LoginService: |
|
|
""" |
|
|
""" |
|
|
query_user = await UserDao.get_user_by_id(query_db, user_id=user_id) |
|
|
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 ['M', 'C']], 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 ['M', 'C']], key=lambda x: x.order_num) |
|
|
user_router = cls.__generate_user_router_menu(0, user_router_menu) |
|
|
menus = cls.__generate_menus(0, user_router_menu) |
|
|
return user_router |
|
|
user_router = cls.__generate_user_router_menu(menus) |
|
|
|
|
|
return [router.model_dump(exclude_unset=True, by_alias=True) for router in user_router] |
|
|
|
|
|
|
|
|
@classmethod |
|
|
@classmethod |
|
|
def __generate_user_router_menu(cls, pid: int, permission_list): |
|
|
def __generate_menus(cls, pid: int, permission_list: List[SysMenu]): |
|
|
""" |
|
|
""" |
|
|
工具方法:根据菜单信息生成路由信息树形嵌套数据 |
|
|
工具方法:根据菜单信息生成菜单信息树形嵌套数据 |
|
|
:param pid: 菜单id |
|
|
:param pid: 菜单id |
|
|
:param permission_list: 菜单列表信息 |
|
|
:param permission_list: 菜单列表信息 |
|
|
:return: 路由信息树形嵌套数据 |
|
|
:return: 菜单信息树形嵌套数据 |
|
|
""" |
|
|
""" |
|
|
router_list = [] |
|
|
menu_list: List[MenuTreeModel] = [] |
|
|
for permission in permission_list: |
|
|
for permission in permission_list: |
|
|
if permission.parent_id == pid: |
|
|
if permission.parent_id == pid: |
|
|
children = cls.__generate_user_router_menu(permission.menu_id, permission_list) |
|
|
children = cls.__generate_menus(permission.menu_id, permission_list) |
|
|
router_list_data = {} |
|
|
menu_list_data = MenuTreeModel(**CamelCaseUtil.transform_result(permission)) |
|
|
if permission.menu_type == 'M': |
|
|
if children: |
|
|
router_list_data['name'] = permission.path.capitalize() |
|
|
menu_list_data.children = children |
|
|
router_list_data['hidden'] = False if permission.visible == '0' else True |
|
|
menu_list.append(menu_list_data) |
|
|
if permission.parent_id == 0: |
|
|
|
|
|
router_list_data['component'] = 'Layout' |
|
|
return menu_list |
|
|
router_list_data['path'] = f'/{permission.path}' |
|
|
|
|
|
else: |
|
|
@classmethod |
|
|
router_list_data['component'] = 'ParentView' |
|
|
def __generate_user_router_menu(cls, permission_list: List[MenuTreeModel]): |
|
|
router_list_data['path'] = permission.path |
|
|
""" |
|
|
if permission.is_frame == 1: |
|
|
工具方法:根据菜单树信息生成路由信息树形嵌套数据 |
|
|
router_list_data['redirect'] = 'noRedirect' |
|
|
:param permission_list: 菜单树列表信息 |
|
|
else: |
|
|
:return: 路由信息树形嵌套数据 |
|
|
router_list_data['path'] = permission.path |
|
|
""" |
|
|
if children: |
|
|
router_list: List[RouterModel] = [] |
|
|
router_list_data['alwaysShow'] = True |
|
|
for permission in permission_list: |
|
|
router_list_data['children'] = children |
|
|
router = RouterModel( |
|
|
router_list_data['meta'] = { |
|
|
hidden=True if permission.visible == '1' else False, |
|
|
'title': permission.menu_name, |
|
|
name=RouterUtil.get_router_name(permission), |
|
|
'icon': permission.icon, |
|
|
path=RouterUtil.get_router_path(permission), |
|
|
'noCache': False if permission.is_cache == '0' else True, |
|
|
component=RouterUtil.get_component(permission), |
|
|
'link': permission.path if permission.is_frame == 0 else None |
|
|
query=permission.query, |
|
|
} |
|
|
meta=MetaModel( |
|
|
elif permission.menu_type == 'C': |
|
|
title=permission.menu_name, |
|
|
router_list_data['name'] = permission.path.capitalize() |
|
|
icon=permission.icon, |
|
|
router_list_data['path'] = permission.path |
|
|
noCache=True if permission.is_cache == 1 else False, |
|
|
router_list_data['query'] = permission.query |
|
|
link=permission.path if RouterUtil.is_http(permission.path) else None |
|
|
router_list_data['hidden'] = False if permission.visible == '0' else True |
|
|
) |
|
|
router_list_data['component'] = permission.component |
|
|
) |
|
|
router_list_data['meta'] = { |
|
|
c_menus = permission.children |
|
|
'title': permission.menu_name, |
|
|
if c_menus and permission.menu_type == 'M': |
|
|
'icon': permission.icon, |
|
|
router.always_show = True |
|
|
'noCache': False if permission.is_cache == '0' else True, |
|
|
router.redirect = 'noRedirect' |
|
|
'link': permission.path if permission.is_frame == 0 else None |
|
|
router.children = cls.__generate_user_router_menu(c_menus) |
|
|
} |
|
|
elif RouterUtil.is_menu_frame(permission): |
|
|
router_list.append(router_list_data) |
|
|
router.meta = None |
|
|
|
|
|
children_list: List[RouterModel] = [] |
|
|
|
|
|
children = RouterModel( |
|
|
|
|
|
path=permission.path, |
|
|
|
|
|
component=permission.component, |
|
|
|
|
|
name=permission.path.capitalize(), |
|
|
|
|
|
meta=MetaModel( |
|
|
|
|
|
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 |
|
|
|
|
|
), |
|
|
|
|
|
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.path = '/' |
|
|
|
|
|
children_list: List[RouterModel] = [] |
|
|
|
|
|
router_path = RouterUtil.inner_link_replace_each(permission.path) |
|
|
|
|
|
children = RouterModel( |
|
|
|
|
|
path=router_path, |
|
|
|
|
|
component='InnerLink', |
|
|
|
|
|
name=router_path.capitalize(), |
|
|
|
|
|
meta=MetaModel( |
|
|
|
|
|
title=permission.menu_name, |
|
|
|
|
|
icon=permission.icon, |
|
|
|
|
|
link=permission.path if RouterUtil.is_http(permission.path) else None |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
children_list.append(children) |
|
|
|
|
|
router.children = children_list |
|
|
|
|
|
|
|
|
|
|
|
router_list.append(router) |
|
|
|
|
|
|
|
|
return router_list |
|
|
return router_list |
|
|
|
|
|
|
|
@ -386,3 +426,106 @@ class LoginService: |
|
|
# await request.app.state.redis.delete(f'{current_user.user.user_id}_session_id') |
|
|
# await request.app.state.redis.delete(f'{current_user.user.user_id}_session_id') |
|
|
|
|
|
|
|
|
return True |
|
|
return True |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class RouterUtil: |
|
|
|
|
|
""" |
|
|
|
|
|
路由处理工具类 |
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
@classmethod |
|
|
|
|
|
def get_router_name(cls, menu: MenuTreeModel): |
|
|
|
|
|
""" |
|
|
|
|
|
获取路由名称 |
|
|
|
|
|
:param menu: 菜单数对象 |
|
|
|
|
|
:return: 路由名称 |
|
|
|
|
|
""" |
|
|
|
|
|
router_name = menu.path.capitalize() |
|
|
|
|
|
if cls.is_menu_frame(menu): |
|
|
|
|
|
router_name = '' |
|
|
|
|
|
|
|
|
|
|
|
return router_name |
|
|
|
|
|
|
|
|
|
|
|
@classmethod |
|
|
|
|
|
def get_router_path(cls, menu: MenuTreeModel): |
|
|
|
|
|
""" |
|
|
|
|
|
获取路由地址 |
|
|
|
|
|
:param menu: 菜单数对象 |
|
|
|
|
|
:return: 路由地址 |
|
|
|
|
|
""" |
|
|
|
|
|
# 内链打开外网方式 |
|
|
|
|
|
router_path = menu.path |
|
|
|
|
|
if menu.parent_id != 0 and cls.is_inner_link(menu): |
|
|
|
|
|
router_path = cls.inner_link_replace_each(router_path) |
|
|
|
|
|
# 非外链并且是一级目录(类型为目录) |
|
|
|
|
|
if menu.parent_id == 0 and menu.menu_type == 'M' and menu.is_frame == 1: |
|
|
|
|
|
router_path = f'/{menu.path}' |
|
|
|
|
|
# 非外链并且是一级目录(类型为菜单) |
|
|
|
|
|
elif cls.is_menu_frame(menu): |
|
|
|
|
|
router_path = '/' |
|
|
|
|
|
return router_path |
|
|
|
|
|
|
|
|
|
|
|
@classmethod |
|
|
|
|
|
def get_component(cls, menu: MenuTreeModel): |
|
|
|
|
|
""" |
|
|
|
|
|
获取组件信息 |
|
|
|
|
|
:param menu: 菜单数对象 |
|
|
|
|
|
:return: 组件信息 |
|
|
|
|
|
""" |
|
|
|
|
|
component = 'Layout' |
|
|
|
|
|
if menu.component and not cls.is_menu_frame(menu): |
|
|
|
|
|
component = menu.component |
|
|
|
|
|
elif menu.component and menu.parent_id != 0 and cls.is_inner_link(menu): |
|
|
|
|
|
component = 'InnerLink' |
|
|
|
|
|
elif menu.component and cls.is_parent_view(menu): |
|
|
|
|
|
component = 'ParentView' |
|
|
|
|
|
return component |
|
|
|
|
|
|
|
|
|
|
|
@classmethod |
|
|
|
|
|
def is_menu_frame(cls, menu: MenuTreeModel): |
|
|
|
|
|
""" |
|
|
|
|
|
判断是否为菜单内部跳转 |
|
|
|
|
|
:param menu: 菜单数对象 |
|
|
|
|
|
:return: 是否为菜单内部跳转 |
|
|
|
|
|
""" |
|
|
|
|
|
return menu.parent_id == 0 and menu.menu_type == 'C' and menu.is_frame == 1 |
|
|
|
|
|
|
|
|
|
|
|
@classmethod |
|
|
|
|
|
def is_inner_link(cls, menu: MenuTreeModel): |
|
|
|
|
|
""" |
|
|
|
|
|
判断是否为内链组件 |
|
|
|
|
|
:param menu: 菜单数对象 |
|
|
|
|
|
:return: 是否为内链组件 |
|
|
|
|
|
""" |
|
|
|
|
|
return menu.is_frame == 1 and cls.is_http(menu.path) |
|
|
|
|
|
|
|
|
|
|
|
@classmethod |
|
|
|
|
|
def is_parent_view(cls, menu: MenuTreeModel): |
|
|
|
|
|
""" |
|
|
|
|
|
判断是否为parent_view组件 |
|
|
|
|
|
:param menu: 菜单数对象 |
|
|
|
|
|
:return: 是否为parent_view组件 |
|
|
|
|
|
""" |
|
|
|
|
|
return menu.parent_id != 0 and menu.menu_type == 'M' |
|
|
|
|
|
|
|
|
|
|
|
@classmethod |
|
|
|
|
|
def is_http(cls, link: str): |
|
|
|
|
|
""" |
|
|
|
|
|
判断是否为http(s)://开头 |
|
|
|
|
|
:param link: 链接 |
|
|
|
|
|
:return: 是否为http(s)://开头 |
|
|
|
|
|
""" |
|
|
|
|
|
return link.startswith('http://') or link.startswith('https://') |
|
|
|
|
|
|
|
|
|
|
|
@classmethod |
|
|
|
|
|
def inner_link_replace_each(cls, path: str): |
|
|
|
|
|
""" |
|
|
|
|
|
内链域名特殊字符替换 |
|
|
|
|
|
:param path: 内链域名 |
|
|
|
|
|
:return: 替换后的内链域名 |
|
|
|
|
|
""" |
|
|
|
|
|
old_values = ["http://", "https://", "www.", ".", ":"] |
|
|
|
|
|
new_values = ["", "", "", "/", "/"] |
|
|
|
|
|
for old, new in zip(old_values, new_values): |
|
|
|
|
|
path = path.replace(old, new) |
|
|
|
|
|
return path |
|
|