From 08c8e8c9a4d65677de6a493446a605d70efee631 Mon Sep 17 00:00:00 2001 From: zhaoqingang <zhaoqg0118@163.com> Date: 星期二, 10 十二月 2024 16:32:07 +0800 Subject: [PATCH] 12.10 16 --- app/service/v2/app_register.py | 0 alembic/versions/92ece82bc5a4_menu_table_update.py | 32 +++ app/service/group.py | 2 app/service/user.py | 141 ++++++++++--- app/service/auth.py | 33 +- app/service/v2/__init__.py | 0 app/task/fetch_agent.py | 12 + main.py | 8 app/models/group_model.py | 1 app/api/report.py | 4 app/api/v2/__init__.py | 0 env_conf/menu_conf.json | 104 ++++++++++ app/service/service_token.py | 15 app/api/chat.py | 6 app/models/menu_model.py | 39 +++ app/service/v2/api_token.py | 0 app/__init__.py | 0 app/api/agent.py | 8 app/api/user.py | 14 + alembic/versions/3845dc998475_menu_table_add.py | 53 +++++ app/api/auth.py | 15 app/models/__init__.py | 1 app/api/v2/public_api.py | 20 + alembic/versions/f49ae5b5f2c8_group_type_add.py | 30 +++ app/api/v2/conversation.py | 0 app/api/files.py | 6 app/service/v2/initialize_data.py | 36 +++ app/models/token_model.py | 9 28 files changed, 496 insertions(+), 93 deletions(-) diff --git a/alembic/versions/3845dc998475_menu_table_add.py b/alembic/versions/3845dc998475_menu_table_add.py new file mode 100644 index 0000000..570d716 --- /dev/null +++ b/alembic/versions/3845dc998475_menu_table_add.py @@ -0,0 +1,53 @@ +"""menu table add + +Revision ID: 3845dc998475 +Revises: abc6bb9129ed +Create Date: 2024-12-10 14:22:03.798597 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +# revision identifiers, used by Alembic. +revision: str = '3845dc998475' +down_revision: Union[str, None] = 'abc6bb9129ed' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('menu_capacity', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('menu_id', sa.Integer(), nullable=True), + sa.Column('capacity_id', sa.String(length=36), nullable=True), + sa.Column('capacity_type', sa.Integer(), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('menu_id', 'capacity_id', name='menu_capacity_id_ix') + ) + op.create_index(op.f('ix_menu_capacity_id'), 'menu_capacity', ['id'], unique=False) + op.create_table('web_menu', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('title', sa.String(length=128), nullable=True), + sa.Column('dialog', sa.String(length=1000), nullable=True), + sa.Column('desc', sa.String(length=1000), nullable=True), + sa.Column('icon', sa.String(length=16), nullable=True), + sa.Column('img', sa.String(length=255), nullable=True), + sa.PrimaryKeyConstraint('id') + ) + op.create_index(op.f('ix_web_menu_id'), 'web_menu', ['id'], unique=False) + op.drop_column('knowledgebase', 'count') + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('knowledgebase', sa.Column('count', mysql.VARCHAR(length=32), nullable=True)) + op.drop_index(op.f('ix_web_menu_id'), table_name='web_menu') + op.drop_table('web_menu') + op.drop_index(op.f('ix_menu_capacity_id'), table_name='menu_capacity') + op.drop_table('menu_capacity') + # ### end Alembic commands ### diff --git a/alembic/versions/92ece82bc5a4_menu_table_update.py b/alembic/versions/92ece82bc5a4_menu_table_update.py new file mode 100644 index 0000000..d33aab6 --- /dev/null +++ b/alembic/versions/92ece82bc5a4_menu_table_update.py @@ -0,0 +1,32 @@ +"""menu table update + +Revision ID: 92ece82bc5a4 +Revises: 3845dc998475 +Create Date: 2024-12-10 16:00:04.324833 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +# revision identifiers, used by Alembic. +revision: str = '92ece82bc5a4' +down_revision: Union[str, None] = '3845dc998475' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('web_menu', sa.Column('describe', sa.String(length=1000), nullable=True)) + op.drop_column('web_menu', 'dialog') + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('web_menu', sa.Column('dialog', mysql.VARCHAR(length=1000), nullable=True)) + op.drop_column('web_menu', 'describe') + # ### end Alembic commands ### diff --git a/alembic/versions/f49ae5b5f2c8_group_type_add.py b/alembic/versions/f49ae5b5f2c8_group_type_add.py new file mode 100644 index 0000000..c7ba5d9 --- /dev/null +++ b/alembic/versions/f49ae5b5f2c8_group_type_add.py @@ -0,0 +1,30 @@ +"""group type add + +Revision ID: f49ae5b5f2c8 +Revises: 92ece82bc5a4 +Create Date: 2024-12-10 16:26:34.371685 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'f49ae5b5f2c8' +down_revision: Union[str, None] = '92ece82bc5a4' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('group', sa.Column('group_type', sa.Integer(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('group', 'group_type') + # ### end Alembic commands ### diff --git a/app/service/common/__init__.py b/app/__init__.py similarity index 100% copy from app/service/common/__init__.py copy to app/__init__.py diff --git a/app/api/agent.py b/app/api/agent.py index 22ce8ef..2bde98c 100644 --- a/app/api/agent.py +++ b/app/api/agent.py @@ -42,7 +42,7 @@ if agent.agent_type == AgentType.RAGFLOW: ragflow_service = RagflowService(base_url=settings.fwr_base_url) try: - token = get_ragflow_token(db, current_user.id) + token = await get_ragflow_token(db, current_user.id) result = await ragflow_service.get_chat_sessions(token, agent_id) if not result: result = await get_session_history(db, current_user.id, agent_id) @@ -53,7 +53,7 @@ elif agent.agent_type == AgentType.BISHENG: bisheng_service = BishengService(base_url=settings.sgb_base_url) try: - token = get_bisheng_token(db, current_user.id) + token = await get_bisheng_token(db, current_user.id) result = await bisheng_service.get_chat_sessions(token, agent_id, page, limit) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @@ -84,7 +84,7 @@ if agent.agent_type == AgentType.RAGFLOW: ragflow_service = RagflowService(base_url=settings.fwr_base_url) try: - token = get_ragflow_token(db, current_user.id) + token = await get_ragflow_token(db, current_user.id) result = await ragflow_service.get_session_log(token, conversation_id) if 'session_log' in result and 'reference' in result: combined_logs = [] @@ -118,7 +118,7 @@ is_join = True bisheng_service = BishengService(base_url=settings.sgb_base_url) try: - token = get_bisheng_token(db, current_user.id) + token = await get_bisheng_token(db, current_user.id) result = await bisheng_service.get_session_log(token, agent_id, conversation_id) combined_logs = [] last_question = None diff --git a/app/api/auth.py b/app/api/auth.py index a4d96a3..f850882 100644 --- a/app/api/auth.py +++ b/app/api/auth.py @@ -18,7 +18,7 @@ from app.service.auth import authenticate_user, create_access_token, is_valid_password, save_register_user, \ update_user_token, UserAppDao from app.service.bisheng import BishengService -from app.service.common.app_register import AppRegisterDao +from app.service.v2.app_register import AppRegisterDao from app.service.difyService import DifyService from app.service.ragflow import RagflowService from sqlalchemy.future import select @@ -96,13 +96,10 @@ @router.get("/token", response_model=Response) async def token_api(db: Session = Depends(get_db), current_user: UserModel = Depends(get_current_user)): # 鏌ヨ鐜版湁璁板綍 - token = get_token(db, current_user.id) + token = await get_token(db, current_user.id) if token is None: return Response(code=400, msg="token not found") - return Response(code=200, msg="success", data={ - "ragflow_token": token.ragflow_token, - "bisheng_token": token.bisheng_token, - }) + return Response(code=200, msg="success", data=token) @router.post("/v2/login", response_model=Response) @@ -123,7 +120,7 @@ logger.error("鏈煡娉ㄥ唽搴旂敤---") continue try: - user_app = UserAppDao(db).get_data_by_id(user.id, app["id"]) + user_app = await UserAppDao(db).get_data_by_id(user.id, app["id"]) if user_app: name = user_app.username token = await service.login(name, login_data.password) @@ -134,7 +131,7 @@ # 鍒涘缓鏈湴token access_token = create_access_token(data={"sub": user.username, "user_id": user.id}) - await update_token(db, user.id, access_token, token_dict) + # await update_token(db, user.id, access_token, token_dict) await update_user_token(db, user.id, token_dict) result = await pdb.execute(select(AppToken).where(AppToken.id == user.id)) db_app_token = result.scalars().first() @@ -184,7 +181,7 @@ try: name = app["id"] + str(int(time.time())) register_info = await service.register(name, user.password) - print(register_info) + # print(register_info) register_dict[app['id']] = {"id":register_info.get("id"), "name": name, "email": register_info.get("email")} except Exception as e: return Response(code=500, msg=f"Failed to register with {app['id']}: {str(e)}") diff --git a/app/api/chat.py b/app/api/chat.py index 4344b62..cde74ff 100644 --- a/app/api/chat.py +++ b/app/api/chat.py @@ -14,7 +14,7 @@ from app.models.agent_model import AgentModel, AgentType from app.models.base_model import get_db from app.models.user_model import UserModel -from app.service.common.api_token import DfTokenDao +from app.service.v2.api_token import DfTokenDao from app.service.dialog import update_session_history from app.service.basic import BasicService from app.service.difyService import DifyService @@ -49,7 +49,7 @@ if agent_type == AgentType.RAGFLOW: ragflow_service = RagflowService(settings.fwr_base_url) - token = get_ragflow_token(db, current_user.id) + token = await get_ragflow_token(db, current_user.id) try: async def forward_to_ragflow(): while True: @@ -135,7 +135,7 @@ pass elif agent_type == AgentType.BISHENG: - token = get_bisheng_token(db, current_user.id) + token = await get_bisheng_token(db, current_user.id) service_uri = f"{settings.sgb_websocket_url}/api/v1/assistant/chat/{agent_id}?t=&chat_id={chat_id}" headers = {'cookie': f"access_token_cookie={token};"} diff --git a/app/api/files.py b/app/api/files.py index dca7d3c..25a45bf 100644 --- a/app/api/files.py +++ b/app/api/files.py @@ -15,7 +15,7 @@ from app.models.user_model import UserModel from app.service.basic import BasicService from app.service.bisheng import BishengService -from app.service.common.api_token import DfTokenDao +from app.service.v2.api_token import DfTokenDao from app.service.difyService import DifyService from app.service.ragflow import RagflowService from app.service.service_token import get_ragflow_token, get_bisheng_token @@ -50,7 +50,7 @@ return Response(code=400, msg=str(e)) if agent.agent_type == AgentType.RAGFLOW: - token = get_ragflow_token(db, current_user.id) + token = await get_ragflow_token(db, current_user.id) ragflow_service = RagflowService(base_url=settings.fwr_base_url) # 鏌ヨ浼氳瘽鏄惁瀛樺湪锛屼笉瀛樺湪鍏堝垱寤轰細璇� history = await ragflow_service.get_session_history(token, chat_id) @@ -65,7 +65,7 @@ elif agent.agent_type == AgentType.BISHENG: bisheng_service = BishengService(base_url=settings.sgb_base_url) try: - token = get_bisheng_token(db, current_user.id) + token = await get_bisheng_token(db, current_user.id) result = await bisheng_service.upload(token, file.filename, file_content) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) diff --git a/app/api/report.py b/app/api/report.py index 0d33194..fa64596 100644 --- a/app/api/report.py +++ b/app/api/report.py @@ -36,7 +36,7 @@ ret = {"message": "Agent error", "type": "close"} return websocket.send_json(ret) - token = get_bisheng_token(db, current_user.id) + token = await get_bisheng_token(db, current_user.id) service_uri = f"{settings.sgb_websocket_url}/api/v1/chat/{agent_id}?type=L1&t=&chat_id={chat_id}" headers = {'cookie': f"access_token_cookie={token};"} @@ -165,7 +165,7 @@ return ResponseList(code=404, msg="Agent not found") bisheng_service = BishengService(base_url=settings.sgb_base_url) try: - token = get_bisheng_token(db, current_user.id) + token = await get_bisheng_token(db, current_user.id) result = await bisheng_service.variable_list(token, agent_id) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) diff --git a/app/api/user.py b/app/api/user.py index 90a23cd..b5bd520 100644 --- a/app/api/user.py +++ b/app/api/user.py @@ -1,11 +1,11 @@ from fastapi import APIRouter, Depends -from app.api import Response, pwd_context, get_current_user +from app.api import Response, pwd_context, get_current_user, ResponseList from app.models.public_api_model import AppRegisterModel from app.models.base_model import get_db from app.models.user import PageParameter, UserStatus, UserInfo, LoginData from app.models.user_model import UserModel from app.service.user import get_user_list, edit_user_status, delete_user_data, create_user, edit_user_data, \ - edit_user_pwd, get_user_info, get_user_routers + edit_user_pwd, get_user_info, get_user_routers, get_user_menus user_router = APIRouter() @@ -95,4 +95,12 @@ routers = await get_user_routers(db, current_user.id) if not routers: return Response(code=500, msg="user get failure", data={}) - return Response(code=200, msg="successfully", data=routers) \ No newline at end of file + return Response(code=200, msg="successfully", data=routers) + + +@user_router.get("/menus", response_model=ResponseList) +async def user_menus(current_user: UserModel = Depends(get_current_user),db=Depends(get_db)): + menus = await get_user_menus(db, current_user.id) + # return Response(code=200, msg="successfully", data=menus) + # result = [item.to_dict() for item in agents] + return ResponseList(code=200, msg="successfully", data=menus) \ No newline at end of file diff --git a/app/service/common/__init__.py b/app/api/v2/__init__.py similarity index 100% copy from app/service/common/__init__.py copy to app/api/v2/__init__.py diff --git a/app/service/common/__init__.py b/app/api/v2/conversation.py similarity index 100% copy from app/service/common/__init__.py copy to app/api/v2/conversation.py diff --git a/app/api/public_api.py b/app/api/v2/public_api.py similarity index 77% rename from app/api/public_api.py rename to app/api/v2/public_api.py index 06a37dc..380daf5 100644 --- a/app/api/public_api.py +++ b/app/api/v2/public_api.py @@ -8,8 +8,9 @@ from app.config.const import IMAGE_TO_TEXT, DOCUMENT_TO_CLEANING, DOCUMENT_TO_REPORT, DIFY, BISHENG, RAGFLOW from app.models.base_model import get_db from app.models.public_api_model import DfToken, AppRegister -from app.service.common.api_token import DfTokenDao -from app.service.common.app_register import AppRegisterDao +from app.service.v2.api_token import DfTokenDao +from app.service.v2.app_register import AppRegisterDao +from app.service.v2.initialize_data import dialog_menu_sync from app.task.sync_resources import sync_knowledge, sync_dialog, sync_agent, sync_llm, sync_resource public_api = APIRouter() @@ -47,7 +48,7 @@ @public_api.get("/sync/resource", response_model=Response) -async def user_group_list(resource_type:int, db=Depends(get_db)): +async def sync_resource_data(resource_type:int, db=Depends(get_db)): if resource_type == 1: await sync_knowledge() elif resource_type == 2: @@ -59,4 +60,15 @@ else: await sync_resource() - return Response(code=200, msg="", data={}) \ No newline at end of file + return Response(code=200, msg="", data={}) + + +@public_api.get("/sync/dialog_menu", response_model=Response) +async def sync_dialog_menu(db=Depends(get_db)): + try: + await dialog_menu_sync(db) + except Exception as e: + logger.error(e) + return Response(code=500, msg="failed", data={}) + + return Response(code=200, msg="success", data={}) \ No newline at end of file diff --git a/app/models/__init__.py b/app/models/__init__.py index 97f96bd..c6370a9 100644 --- a/app/models/__init__.py +++ b/app/models/__init__.py @@ -14,6 +14,7 @@ from .token_model import * from .session_model import SessionModel from .public_api_model import * +from .menu_model import * # 鑾峰彇褰撳墠鏃跺尯鐨勬椂闂� diff --git a/app/models/group_model.py b/app/models/group_model.py index bb49da7..529db57 100644 --- a/app/models/group_model.py +++ b/app/models/group_model.py @@ -39,6 +39,7 @@ created_at = Column(DateTime, default=datetime.now()) updated_at = Column(DateTime, default=datetime.now(), onupdate=datetime.now()) creator = Column(Integer) + group_type = Column(Integer, default=1) knowledges = relationship('KnowledgeModel', diff --git a/app/models/menu_model.py b/app/models/menu_model.py new file mode 100644 index 0000000..77c00d9 --- /dev/null +++ b/app/models/menu_model.py @@ -0,0 +1,39 @@ +from datetime import datetime +from sqlalchemy import Column, Integer, String, DateTime, Table, ForeignKey, UniqueConstraint +from app.models.base_model import Base + + + +class WebMenuModel(Base): + __tablename__ = 'web_menu' + id = Column(Integer, primary_key=True, index=True) + title = Column(String(128)) + describe = Column(String(1000)) + desc = Column(String(1000)) + icon = Column(String(16)) + img = Column(String(255)) + + + def to_dict(self): + return { + 'id': self.id, + 'title': self.title, + 'icon': self.icon, + 'img': self.img, + 'desc': self.desc, + 'dialog': self.describe + } + + def __repr__(self): + return '<Role name:%r description:%r iconCls:%r seq:%r>\n' \ + % (self.NAME, self.DESCRIPTION, self.ICONCLS, self.SEQ) + + +class MenuCapacityModel(Base): + __tablename__ = 'menu_capacity' + __table_args__ = (UniqueConstraint('menu_id', 'capacity_id', name='menu_capacity_id_ix'),) + id = Column(Integer, primary_key=True, index=True) + menu_id = Column(Integer) + capacity_id = Column(String(36)) + capacity_type = Column(Integer) + diff --git a/app/models/token_model.py b/app/models/token_model.py index 2b50bfd..fad57e0 100644 --- a/app/models/token_model.py +++ b/app/models/token_model.py @@ -7,6 +7,7 @@ from Log import logger from app.config.const import RAGFLOW from app.models.base_model import Base +from app.service.auth import UserAppDao class TokenModel(Base): @@ -59,7 +60,7 @@ if not isinstance(user_id, int) or user_id <= 0: return db_token = None - print(token) + # print(token) try: # 鏌ヨ鐜版湁璁板綍 db_token = db.query(TokenModel).filter_by(user_id=user_id).first() @@ -88,5 +89,7 @@ db.rollback() # 鍥炴粴浜嬪姟 -def get_token(db: Session, user_id: int) -> Type[TokenModel] | None: - return db.query(TokenModel).filter_by(user_id=user_id).first() +async def get_token(db: Session, user_id: int): + # return db.query(TokenModel).filter_by(user_id=user_id).first() + + return {i.app_type.replace("app", "token"): i.access_token for i in await UserAppDao(db).get_user_datas(user_id)} diff --git a/app/service/auth.py b/app/service/auth.py index d843adb..d0436f8 100644 --- a/app/service/auth.py +++ b/app/service/auth.py @@ -77,7 +77,7 @@ db.refresh(db_user) user_id = db_user.id for k, v in register_dict.items(): - UserAppDao(db).update_and_insert_token(v.get("name"), pwd, v.get("email"), user_id, str(v.get("id")), k) + await UserAppDao(db).update_and_insert_data(v.get("name"), pwd, v.get("email"), user_id, str(v.get("id")), k) except Exception as e: logger.error(e) @@ -89,11 +89,10 @@ async def update_user_token(db, user_id, token_dict): - try: for k, v in token_dict.items(): - UserAppDao(db).update_user_app_data({"user_id": user_id, "app_type": k}, - {"access_token": v, "token_at": datetime.now()}) + await UserAppDao(db).update_user_app_data({"user_id": user_id, "app_type": k}, + {"access_token": v, "token_at": datetime.now()}) except Exception as e: logger.error(e) @@ -105,11 +104,11 @@ def __init__(self, db: Session): self.db = db - def get_data_by_id(self, user_id: int, app_type: int) -> Type[UserAppModel] | None: + async def get_data_by_id(self, user_id: int, app_type: int) -> Type[UserAppModel] | None: session = self.db.query(UserAppModel).filter_by(user_id=user_id, app_type=app_type).first() return session - def update_user_app_data(self, query: int, update_data: str): + async def update_user_app_data(self, query: dict, update_data: dict): logger.error("鏇存柊鏁版嵁df update_app_data---------------------------") try: @@ -120,7 +119,8 @@ self.db.rollback() raise Exception("鏇存柊澶辫触锛�") - def insert_user_app_data(self, username: str, password: str, email: str, user_id: int, app_id: str, app_type: int): + async def insert_user_app_data(self, username: str, password: str, email: str, user_id: int, app_id: str, + app_type: int): logger.error("鏂板鏁版嵁df insert_user_app_data---------------------------") new_session = UserAppModel( username=username, @@ -135,15 +135,18 @@ self.db.refresh(new_session) return new_session - def update_and_insert_token(self, username: str, password: str, email: str, user_id: int, app_id: str, - app_type: int): + async def update_and_insert_data(self, username: str, password: str, email: str, user_id: int, app_id: str, + app_type: int): logger.error("鏇存柊鎴栬�呮坊鍔犳暟鎹� update_and_insert_token---------------------------") - token_boj = self.get_data_by_id(user_id, app_type) + token_boj = await self.get_data_by_id(user_id, app_type) if token_boj: - self.update_user_app_data({"id": token_boj.id}, {"username": username, - "password": password, "email": email, "username": username, - "updated_at": datetime.now(), - }) + await self.update_user_app_data({"id": token_boj.id}, {"username": username, + "password": password, "email": email, + "updated_at": datetime.now(), + }) else: - self.insert_user_app_data(username, password, email, user_id, app_id, app_type) + await self.insert_user_app_data(username, password, email, user_id, app_id, app_type) + + async def get_user_datas(self, user_id: int): + return self.db.query(UserAppModel).filter_by(user_id=user_id).all() diff --git a/app/service/group.py b/app/service/group.py index af95c76..b142c84 100644 --- a/app/service/group.py +++ b/app/service/group.py @@ -81,7 +81,7 @@ UserModel.id.in_(user_list)).all()} print(user_dict) ragflow_service = RagflowService(settings.fwr_base_url) - token = get_ragflow_token(db, user_id) + token = await get_ragflow_token(db, user_id) try: for old_user in group_user_list: diff --git a/app/service/service_token.py b/app/service/service_token.py index 15ded3b..8fffc99 100644 --- a/app/service/service_token.py +++ b/app/service/service_token.py @@ -1,23 +1,26 @@ from Log import logger from app.config.config import settings +from app.config.const import BISHENG, RAGFLOW from app.models import UserModel from app.models.token_model import TokenModel +from app.service.auth import UserAppDao from app.service.bisheng import BishengService from app.service.ragflow import RagflowService -def get_bisheng_token(db, user_id: int): - token = db.query(TokenModel).filter(TokenModel.user_id == user_id).first() +async def get_bisheng_token(db, user_id: int): + # token = db.query(TokenModel).filter(TokenModel.user_id == user_id).first() + token = await UserAppDao.get_data_by_id(user_id, BISHENG) if not token: return None - return token.bisheng_token + return token.access_token -def get_ragflow_token(db, user_id: int): - token = db.query(TokenModel).filter(TokenModel.user_id == user_id).first() +async def get_ragflow_token(db, user_id: int): + token = await UserAppDao.get_data_by_id(user_id, RAGFLOW) if not token: return None - return token.ragflow_token + return token.access_token async def get_ragflow_new_token(db, user_id: int, app_type): diff --git a/app/service/user.py b/app/service/user.py index 9ceb047..21d2869 100644 --- a/app/service/user.py +++ b/app/service/user.py @@ -1,30 +1,35 @@ +import time from datetime import datetime from app.api import pwd_context from app.config.config import settings +from app.config.const import RAGFLOW, BISHENG, DIFY from app.models import RoleModel, GroupModel, AgentType, role_resource_table +from app.models.menu_model import WebMenuModel, MenuCapacityModel from app.models.user_model import UserModel from Log import logger +from app.service.auth import UserAppDao from app.service.bisheng import BishengService -from app.service.common.app_register import AppRegisterDao +from app.service.v2.app_register import AppRegisterDao +from app.service.difyService import DifyService from app.service.ragflow import RagflowService from app.service.service_token import get_ragflow_token, get_bisheng_token, get_ragflow_new_token -async def get_user_list(db, page_index: int, page_size: int, keyword: str, role_key:str, user_id): - query = db.query(UserModel).filter(UserModel.permission!="admin") +async def get_user_list(db, page_index: int, page_size: int, keyword: str, role_key: str, user_id): + query = db.query(UserModel).filter(UserModel.permission != "admin") # if role_key != "admin": # query.filter(UserModel.creator==user_id) if keyword: query = query.filter(UserModel.group_name.like('%{}%'.format(keyword))) users = query.order_by(UserModel.id.desc()).limit(page_size).offset( (page_index - 1) * page_size).all() - return {"total": query.count(), "rows": [user.to_json() for user in users]} + return {"total": query.count(), "rows": [user.to_json() for user in users]} async def edit_user_status(db, status: str, user_id: int): try: - db.query(UserModel).filter(UserModel.id == user_id).update({"status":status}) + db.query(UserModel).filter(UserModel.id == user_id).update({"status": status}) db.commit() except Exception as e: logger.error(e) @@ -35,7 +40,7 @@ async def delete_user_data(db, user_id: str): try: - db.query(UserModel).filter(UserModel.id == user_id, UserModel.permission!="admin").delete() + db.query(UserModel).filter(UserModel.id == user_id, UserModel.permission != "admin").delete() db.commit() except Exception as e: logger.error(e) @@ -46,38 +51,65 @@ async def create_user(db, user_name, email, phone, login_name, password, roles, groups, user_id): try: - bisheng_service = BishengService(settings.sgb_base_url) - ragflow_service = RagflowService(settings.fwr_base_url) - - # 娉ㄥ唽鍒版瘯鏄� - try: - bisheng_info = await bisheng_service.register(user_name, password) - except Exception as e: - logger.error(f"Failed to register with Bisheng: {str(e)}") - return False - - # 娉ㄥ唽鍒皉agflow - try: - ragflow_info = await ragflow_service.register(user_name, password) - except Exception as e: - logger.error(f"Failed to register with Ragflow: {str(e)}") - return False + # bisheng_service = BishengService(settings.sgb_base_url) + # ragflow_service = RagflowService(settings.fwr_base_url) + # + # # 娉ㄥ唽鍒版瘯鏄� + # try: + # bisheng_info = await bisheng_service.register(user_name, password) + # except Exception as e: + # logger.error(f"Failed to register with Bisheng: {str(e)}") + # return False + # + # # 娉ㄥ唽鍒皉agflow + # try: + # ragflow_info = await ragflow_service.register(user_name, password) + # except Exception as e: + # logger.error(f"Failed to register with Ragflow: {str(e)}") + # return False + app_register = AppRegisterDao(db).get_apps() + register_dict = {} + for app in app_register: + if app["id"] == RAGFLOW: + service = RagflowService(settings.fwr_base_url) + elif app["id"] == BISHENG: + service = BishengService(settings.sgb_base_url) + elif app["id"] == DIFY: + service = DifyService(settings.dify_base_url) + else: + logger.error("鏈煡娉ㄥ唽搴旂敤---") + continue + try: + name = app["id"] + str(int(time.time())) + register_info = await service.register(name, password) + # print(register_info) + register_dict[app['id']] = {"id": register_info.get("id"), "name": name, + "email": register_info.get("email")} + except Exception as e: + logger.error(e) + return False # 瀛樺偍鐢ㄦ埛淇℃伅 hashed_password = pwd_context.hash(password) - user_model = UserModel(username=user_name, hashed_password=hashed_password, email=email,ragflow_id=ragflow_info.get("id"),bisheng_id=bisheng_info.get("user_id"), - phone=phone,login_name=login_name) + user_model = UserModel(username=user_name, hashed_password=hashed_password, email=email, + ## ragflow_id=ragflow_info.get("id"),bisheng_id=bisheng_info.get("user_id"), + phone=phone, login_name=login_name) + pwd = user_model.encrypted_password(password) user_model.roles = [db.get(RoleModel, roleId) for roleId in roles] + user_model.password = pwd if groups: user_model.groups = [db.get(GroupModel, groupId) for groupId in groups] user_model.creator = user_id db.add(user_model) db.commit() db.refresh(user_model) + u_id = user_model.id + for k, v in register_dict.items(): + await UserAppDao(db).update_and_insert_data(v.get("name"), pwd, v.get("email"), u_id, str(v.get("id")), k) except Exception as e: logger.error(e) - db.rollback() + # db.rollback() return False return True @@ -100,21 +132,21 @@ return True -async def edit_user_pwd(db, user_id, current_user_id ,new_password="000000"): +async def edit_user_pwd(db, user_id, current_user_id, new_password="000000"): try: user = db.query(UserModel).filter(UserModel.id == user_id).first() pwd = user.decrypted_password() - for app_type in AppRegisterDao(db).get_app(): - if app_type == AgentType.RAGFLOW: - token = await get_ragflow_new_token(db, user_id, app_type) + for app in AppRegisterDao(db).get_apps(): + if app.get("id") == RAGFLOW: + token = await get_ragflow_new_token(db, user_id, 1) ragflow_service = RagflowService(settings.fwr_base_url) await ragflow_service.set_user_password(token, pwd, new_password) - elif app_type == AgentType.BISHENG: - token = get_bisheng_token(db, current_user_id) + elif app.get("id") == BISHENG: + token = await get_bisheng_token(db, current_user_id) bisheng_service = BishengService(settings.sgb_base_url) await bisheng_service.change_password_public(token, user.username, pwd, new_password) else: - logger.error("娉ㄥ唽鏈煡搴旂敤锛歿}".format(app_type)) + logger.error("娉ㄥ唽鏈煡搴旂敤锛歿}".format(app.get("id"))) # hashed_password = pwd_context.hash(password) hashed_password = user.encrypted_password(new_password) @@ -148,7 +180,7 @@ if user.permission == "admin": permissions = ["*:*:*"] - return {"permissions": list(permissions), "dept": dept , "roles": roles, "user": user.to_dict()} + return {"permissions": list(permissions), "dept": dept, "roles": roles, "user": user.to_dict()} async def role_resource(role_set, role_list, permissions, roles): @@ -167,6 +199,7 @@ dept_set = set() user = db.query(UserModel).filter_by(id=user_id).first() parent_id = "" + async def role_resource(role_set, permissions, roles): nonlocal parent_id for role in roles: @@ -192,14 +225,50 @@ parent_ogt = parent_ogt.parent tmp_dit = {} for permission in permissions.values(): - tmp_dit[permission["parentId"]] = tmp_dit.get(permission["parentId"], []) +[permission] + tmp_dit[permission["parentId"]] = tmp_dit.get(permission["parentId"], []) + [permission] + def get_child(parent_id): res = permissions[parent_id] res["children"] = [get_child(i["id"]) for i in tmp_dit.get(parent_id, [])] return res - print(parent_id) - print(tmp_dit) return {"routers": [get_child(i["id"]) for i in tmp_dit.get(parent_id, [])]} +async def get_user_menus(db, user_id): + dialog_list = [] + agent_list = [] + menu_dict = {} + res = [] + user = db.query(UserModel).filter_by(id=user_id).first() + for group in user.groups: + for dialog in group.dialogs: + dialog_list.append(dialog.id) + for agent in group.agents: + agent_list.append(agent.id) + menu_list = db.query(WebMenuModel.id, WebMenuModel.title, WebMenuModel.describe, WebMenuModel.icon, WebMenuModel.desc, + WebMenuModel.img, MenuCapacityModel.capacity_id, MenuCapacityModel.capacity_type).outerjoin( + MenuCapacityModel, WebMenuModel.id == MenuCapacityModel.menu_id).all() + + for menu in menu_list: + menu_dict[menu.id] = menu_dict.get(menu.id, []) + [menu] + # print(dialog_list) + for menus in menu_dict.values(): + + for m in menus: + if user.permission == "admin": + continue + elif not m.capacity_type or m.capacity_type == 1 and m.capacity_id not in dialog_list: + break + elif not m.capacity_type or m.capacity_type == 2 and m.capacity_id not in agent_list: + break + else: + res.append({ + 'id': menus[0].id, + 'title': menus[0].title, + 'icon': menus[0].icon, + 'img': menus[0].img, + 'desc': menus[0].desc, + 'dialog': menus[0].describe + }) + return res diff --git a/app/service/common/__init__.py b/app/service/v2/__init__.py similarity index 100% rename from app/service/common/__init__.py rename to app/service/v2/__init__.py diff --git a/app/service/common/api_token.py b/app/service/v2/api_token.py similarity index 100% rename from app/service/common/api_token.py rename to app/service/v2/api_token.py diff --git a/app/service/common/app_register.py b/app/service/v2/app_register.py similarity index 100% rename from app/service/common/app_register.py rename to app/service/v2/app_register.py diff --git a/app/service/v2/initialize_data.py b/app/service/v2/initialize_data.py new file mode 100644 index 0000000..bf05dcf --- /dev/null +++ b/app/service/v2/initialize_data.py @@ -0,0 +1,36 @@ +import json + +from Log import logger +from app.models import MenuCapacityModel, WebMenuModel, GroupModel + + +async def dialog_menu_sync(db): + menu_list = [] + with open("env_conf/menu_conf.json", 'r', encoding='utf-8') as file: + # 鍔犺浇JSON鏁版嵁 + data = json.load(file) + menu_list = data.get("data", []) + + db.query(WebMenuModel).delete() + db.query(MenuCapacityModel).delete() + db.commit() + + for menu in menu_list: + # print(menu) + agent = menu.pop("agent", []) + for i in agent: + capacity = MenuCapacityModel(menu_id=menu["id"], capacity_id=i, capacity_type=2) + db.add(capacity) + dialog = menu.pop("dialog", []) + for i in dialog: + capacity = MenuCapacityModel(menu_id=menu["id"], capacity_id=i, capacity_type=1) + db.add(capacity) + menu_obj = WebMenuModel(**menu) + db.add(menu_obj) + db.commit() + + +async def default_group_sync(db): + group = db.query(GroupModel).filter_by(group_type=2).first() + if not group: + logger.error("鏈垵濮嬪寲") \ No newline at end of file diff --git a/app/task/fetch_agent.py b/app/task/fetch_agent.py index 36b3c2e..42aa3e0 100644 --- a/app/task/fetch_agent.py +++ b/app/task/fetch_agent.py @@ -1,12 +1,14 @@ from typing import Dict, List, Tuple from sqlalchemy import create_engine, Column, String, Integer +from sqlalchemy.dialects.postgresql import array from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import sessionmaker from app.config.config import settings from app.models.agent_model import AgentModel from app.models.base_model import SessionLocal, Base +from app.service.v2.initialize_data import dialog_menu_sync # 鍒涘缓鏁版嵁搴撳紩鎿庡拰浼氳瘽宸ュ巶 engine_bisheng = create_engine(settings.sgb_db_url) @@ -147,3 +149,13 @@ print("Agents synchronized successfully") except Exception as e: print(f"Failed to sync agents: {str(e)}") + + +async def sync_web_menu(): + db = SessionLocal() + await dialog_menu_sync(db) + + +async def sync_default_group(): + db = SessionLocal() + await dialog_menu_sync(db) \ No newline at end of file diff --git a/env_conf/menu_conf.json b/env_conf/menu_conf.json new file mode 100644 index 0000000..8376abd --- /dev/null +++ b/env_conf/menu_conf.json @@ -0,0 +1,104 @@ +{ + "data": [ + { + "id": 10, + "title": "鎶ュ憡鐢熸垚", + "icon": "2", + "img": "/src/assets/index/2.png", + "desc": "鍩轰簬鎮ㄥ垱寤虹殑鎶ュ憡鏍煎紡鍜岀煡璇嗗簱涓殑鏂囨。鍐呭锛屽揩閫熺敓鎴愬畾鍒舵姤鍛婏紝骞舵敮鎸佷竴閿笅杞姐��", + "describe": "鍩轰簬鎮ㄥ垱寤虹殑鎶ュ憡鏍煎紡鍜岀煡璇嗗簱涓殑鏂囨。鍐呭锛屽揩閫熺敓鎴愬畾鍒舵姤鍛婏紝骞舵敮鎸佷竴閿笅杞姐��", + "agent" : [], + "dialog": ["1"] + }, + { + "id": 1, + "title": "鎶ヨ〃鍚堝苟", + "icon": "6", + "img": "/src/assets/index/6.png", + "desc": "鍩轰簬鎮ㄤ笂浼犵殑鎶ヨ〃杩涜鍚堝苟锛屽姪鎮ㄥ揩閫熷畬鎴愭姤琛ㄦ暣鍚堜笌鍒嗘瀽", + "describe": "鍩轰簬鎮ㄤ笂浼犵殑鎶ヨ〃杩涜鍚堝苟锛屽姪鎮ㄥ揩閫熷畬鎴愭姤琛ㄦ暣鍚堜笌鍒嗘瀽", + "agent" : [], + "dialog": ["2"] + }, + { + "id": 2, + "title": "鐭ヨ瘑闂瓟", + "icon": "5", + "img": "/src/assets/index/5.png", + "desc": "閬嶅巻宸插垱寤虹殑鏂囨。鐭ヨ瘑搴擄紝鐢熸垚瀹屾暣鍜屽噯纭殑绛旀锛屽悓鏃舵樉绀烘潵婧愭枃妗d緵鎮ㄥ弬鑰�", + "describe": "鍨傚煙鐭ヨ瘑鐨勯棶绛斿姪鎵嬶紝閽堝浣犵殑鎻愰棶锛屾垜浠皢閬嶅巻宸插垱寤虹殑鏂囨。鐭ヨ瘑搴擄紝鐢熸垚瀹屾暣鍜屽噯纭殑绛旀锛屽悓鏃舵樉绀烘潵婧愭枃妗d緵鎮ㄥ弬鑰冦��", + "agent" : [], + "dialog": [] + }, + { + "id": 3, + "title": "鏂囨。鏅鸿兘", + "icon": "7", + "img": "/src/assets/index/7.png", + "desc": "涓汉鐭ヨ瘑搴撶殑闂瓟鍔╂墜锛屽熀浜庢偍涓婁紶鐨勬枃妗h繘琛岄棶绛旓紝鏀寔澶氭枃妗�", + "describe": "涓汉鐭ヨ瘑搴撶殑闂瓟鍔╂墜锛屽熀浜庢偍涓婁紶鐨勬枃妗h繘琛岄棶绛旓紝鏀寔澶氭枃妗o紝澶у皬鍦�30M浠ュ唴銆�", + "agent" : [], + "dialog": ["3"] + }, + { + "id": 4, + "title": "鏅鸿兘闂瓟", + "icon": "1", + "img": "/src/assets/index/1.png", + "desc": "鑳藉鐞嗚В鍜屽涔犱汉绫荤殑璇█锛屽叿澶囧杞璇濈殑鑳藉姏", + "describe": "鎴戝彲浠ョ悊瑙e拰瀛︿範浜虹被鐨勮瑷�锛屽叿澶囧杞璇濈殑鑳藉姏锛岀幇鍦ㄥ拰鎴戝紑濮嬩氦娴佸惂锝�", + "agent" : [], + "dialog": [] + }, + { + "id": 5, + "title": "鏅鸿兘鏁版嵁", + "icon": "8", + "img": "/src/assets/index/8.png", + "desc": "鎮ㄥ彲浠ヤ笂浼犳枃妗f垨娣诲姞鏁版嵁搴撳湴鍧�锛屽皬鏁板彲閽堝浣犳枃妗g殑鏁版嵁杩涜鍒嗘瀽锛屽苟鐢熸垚鎸囧畾鐨勫浘琛�", + "describe": "鎮ㄥ彲浠ヤ笂浼犳枃妗f垨娣诲姞鏁版嵁搴撳湴鍧�锛屽皬鏁板彲閽堝浣犳枃妗g殑鏁版嵁杩涜鍒嗘瀽锛屽苟鐢熸垚鎸囧畾鐨勫浘琛�", + "agent" : ["3", "4"], + "dialog": [] + }, + { + "id": 6, + "title": "灏忔暟缁樺浘", + "icon": "7", + "img": "/src/assets/index/7.png", + "desc": "鍩轰簬鎮ㄤ笂浼犵殑鍥剧墖锛岀敓鎴愬搴旂殑鏂囧瓧鎻忚堪骞跺熀浜庡浘鐗囧唴瀹瑰疄鐜伴棶绛斻��", + "describe": "鍩轰簬鎮ㄤ笂浼犵殑鍥剧墖锛岀敓鎴愬搴旂殑鏂囧瓧鎻忚堪骞跺熀浜庡浘鐗囧唴瀹瑰疄鐜伴棶绛斻��", + "agent" : ["3"], + "dialog": [] + }, + { + "id": 7, + "title": "鏂囨。鍑哄嵎", + "icon": "6", + "img": "/src/assets/index/6.png", + "desc": "鎮ㄥ彲浠ヤ笂浼犳枃妗o紝灏忔暟鑳介拡瀵瑰崟鏂囨。鎴栧涓枃妗e唴瀹硅嚜鍔ㄥ嚭棰橈紝楂樻晥渚挎嵎鐨勫府鍔╀綘寤虹珛绉佷汉棰樺簱銆�", + "describe": "鎮ㄥ彲浠ヤ笂浼犳枃妗o紝灏忔暟鑳介拡瀵瑰崟鏂囨。鎴栧涓枃妗e唴瀹硅嚜鍔ㄥ嚭棰橈紝楂樻晥渚挎嵎鐨勫府鍔╀綘寤虹珛绉佷汉棰樺簱銆�", + "agent" : [], + "dialog": [] + }, + { + "id": 8, + "title": "鍑洪缁勫嵎", + "icon": "6", + "img": "/src/assets/index/6.png", + "desc": "鎮ㄥ彲浠ヤ笂浼犳枃妗o紝灏忔暟鑳介拡瀵瑰崟鏂囨。鎴栧涓枃妗e唴瀹硅嚜鍔ㄥ嚭棰橈紝楂樻晥渚挎嵎鐨勫府鍔╀綘寤虹珛绉佷汉棰樺簱銆�", + "describe": "鎮ㄥ彲浠ヤ笂浼犳枃妗o紝灏忔暟鑳介拡瀵瑰崟鏂囨。鎴栧涓枃妗e唴瀹硅嚜鍔ㄥ嚭棰橈紝楂樻晥渚挎嵎鐨勫府鍔╀綘寤虹珛绉佷汉棰樺簱銆�", + "agent" : ["4"], + "dialog": [] + }, + { + "id": 9, + "title": "鏂囨。鎶ュ憡", + "icon": "2", + "img": "/src/assets/index/2.png", + "desc": "鍩轰簬鎮ㄥ垱寤虹殑鎶ュ憡鏍煎紡鍜屼笂浼犵殑鏂囨。鍐呭锛屽揩閫熺敓鎴愬畾鍒舵姤鍛婏紝骞舵敮鎸佷竴閿笅杞姐��", + "describe": "鍩轰簬鎮ㄥ垱寤虹殑鎶ュ憡鏍煎紡鍜屼笂浼犵殑鏂囨。鍐呭锛屽揩閫熺敓鎴愬畾鍒舵姤鍛婏紝骞舵敮鎸佷竴閿笅杞姐��", + "agent" : [], + "dialog": [] + } + ] +} \ No newline at end of file diff --git a/main.py b/main.py index 8e41c56..f67d717 100644 --- a/main.py +++ b/main.py @@ -14,16 +14,14 @@ from app.api.knowledge import knowledge_router from app.api.llm import llm_router from app.api.organization import dept_router -from app.api.public_api import public_api +from app.api.v2.public_api import public_api from app.api.report import router as report_router from app.api.resource import menu_router # from app.api.sync_data import sync_router from app.api.user import user_router from app.api.group import group_router from app.api.role import role_router -from app.models.base_model import init_db -from app.task.fetch_agent import sync_agents, initialize_agents -from app.task.sync_resources import sync_resource +from app.task.fetch_agent import sync_agents, initialize_agents, sync_web_menu # 浣跨敤 Lifespan 浜嬩欢澶勭悊绋嬪簭 @@ -33,6 +31,8 @@ initialize_agents() # 鍦ㄥ簲鐢ㄥ惎鍔ㄦ椂鍚屾浠g悊 sync_agents() + await sync_default_group() + await sync_web_menu() yield # 鍦ㄥ簲鐢ㄥ叧闂椂鎵ц娓呯悊鎿嶄綔锛堝鏋滈渶瑕侊級 pass -- Gitblit v1.8.0