Skip to content

Commit fb87ff5

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents f609dc2 + 692103d commit fb87ff5

File tree

5 files changed

+134
-18
lines changed

5 files changed

+134
-18
lines changed

backend/apps/chat/api/chat.py

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
from sqlalchemy import and_, select
1111
from starlette.responses import JSONResponse
1212

13-
from apps.chat.curd.chat import list_chats, get_chat_with_records, create_chat, rename_chat, \
13+
from apps.chat.curd.chat import delete_chat_with_user, get_chart_data_with_user, get_chat_predict_data_with_user, list_chats, get_chat_with_records, create_chat, rename_chat, \
1414
delete_chat, get_chat_chart_data, get_chat_predict_data, get_chat_with_records_with_data, get_chat_record_by_id, \
15-
format_json_data, format_json_list_data, get_chart_config, list_recent_questions,get_chat as get_chat_exec
15+
format_json_data, format_json_list_data, get_chart_config, list_recent_questions,get_chat as get_chat_exec, rename_chat_with_user
1616
from apps.chat.models.chat_model import CreateChat, ChatRecord, RenameChat, ChatQuestion, AxisObj, QuickCommand, \
1717
ChatInfo, Chat, ChatFinishStep
1818
from apps.chat.task.llm import LLMService
@@ -52,7 +52,7 @@ def inner():
5252
return await asyncio.to_thread(inner)
5353

5454

55-
@router.get("/record/{chat_record_id}/data", summary=f"{PLACEHOLDER_PREFIX}get_chart_data")
55+
""" @router.get("/record/{chat_record_id}/data", summary=f"{PLACEHOLDER_PREFIX}get_chart_data")
5656
async def chat_record_data(session: SessionDep, chat_record_id: int):
5757
def inner():
5858
data = get_chat_chart_data(chat_record_id=chat_record_id, session=session)
@@ -67,10 +67,27 @@ def inner():
6767
data = get_chat_predict_data(chat_record_id=chat_record_id, session=session)
6868
return format_json_list_data(data)
6969
70+
return await asyncio.to_thread(inner) """
71+
72+
@router.get("/record/{chat_record_id}/data", summary=f"{PLACEHOLDER_PREFIX}get_chart_data")
73+
async def chat_record_data(session: SessionDep, current_user: CurrentUser, chat_record_id: int):
74+
def inner():
75+
data = get_chart_data_with_user(chat_record_id=chat_record_id, session=session, current_user=current_user)
76+
return format_json_data(data)
77+
7078
return await asyncio.to_thread(inner)
7179

7280

73-
@router.post("/rename", response_model=str, summary=f"{PLACEHOLDER_PREFIX}rename_chat")
81+
@router.get("/record/{chat_record_id}/predict_data", summary=f"{PLACEHOLDER_PREFIX}get_chart_predict_data")
82+
async def chat_predict_data(session: SessionDep, current_user: CurrentUser, chat_record_id: int):
83+
def inner():
84+
data = get_chat_predict_data_with_user(chat_record_id=chat_record_id, session=session, current_user=current_user)
85+
return format_json_list_data(data)
86+
87+
return await asyncio.to_thread(inner)
88+
89+
90+
""" @router.post("/rename", response_model=str, summary=f"{PLACEHOLDER_PREFIX}rename_chat")
7491
@system_log(LogConfig(
7592
operation_type=OperationType.UPDATE,
7693
module=OperationModules.CHAT,
@@ -83,10 +100,24 @@ async def rename(session: SessionDep, chat: RenameChat):
83100
raise HTTPException(
84101
status_code=500,
85102
detail=str(e)
86-
)
103+
) """
87104

105+
@router.post("/rename", response_model=str, summary=f"{PLACEHOLDER_PREFIX}rename_chat")
106+
@system_log(LogConfig(
107+
operation_type=OperationType.UPDATE,
108+
module=OperationModules.CHAT,
109+
resource_id_expr="chat.id"
110+
))
111+
async def rename(session: SessionDep, current_user: CurrentUser, chat: RenameChat):
112+
try:
113+
return rename_chat_with_user(session=session, current_user=current_user, rename_object=chat)
114+
except Exception as e:
115+
raise HTTPException(
116+
status_code=500,
117+
detail=str(e)
118+
)
88119

89-
@router.delete("/{chart_id}/{brief}", response_model=str, summary=f"{PLACEHOLDER_PREFIX}delete_chat")
120+
""" @router.delete("/{chart_id}/{brief}", response_model=str, summary=f"{PLACEHOLDER_PREFIX}delete_chat")
90121
@system_log(LogConfig(
91122
operation_type=OperationType.DELETE,
92123
module=OperationModules.CHAT,
@@ -100,8 +131,23 @@ async def delete(session: SessionDep, chart_id: int, brief: str):
100131
raise HTTPException(
101132
status_code=500,
102133
detail=str(e)
103-
)
134+
) """
104135

136+
@router.delete("/{chart_id}/{brief}", response_model=str, summary=f"{PLACEHOLDER_PREFIX}delete_chat")
137+
@system_log(LogConfig(
138+
operation_type=OperationType.DELETE,
139+
module=OperationModules.CHAT,
140+
resource_id_expr="chart_id",
141+
remark_expr="brief"
142+
))
143+
async def delete(session: SessionDep, current_user: CurrentUser, chart_id: int, brief: str):
144+
try:
145+
return delete_chat_with_user(session=session, current_user=current_user, chart_id=chart_id)
146+
except Exception as e:
147+
raise HTTPException(
148+
status_code=500,
149+
detail=str(e)
150+
)
105151

106152
@router.post("/start", response_model=ChatInfo, summary=f"{PLACEHOLDER_PREFIX}start_chat")
107153
@require_permissions(permission=SqlbotPermission(type='ds', keyExpression="create_chat_obj.datasource"))
@@ -391,14 +437,18 @@ def _err(_e: Exception):
391437

392438

393439
@router.get("/record/{chat_record_id}/excel/export", summary=f"{PLACEHOLDER_PREFIX}export_chart_data")
394-
async def export_excel(session: SessionDep, chat_record_id: int, trans: Trans):
440+
async def export_excel(session: SessionDep, current_user: CurrentUser, chat_record_id: int, trans: Trans):
395441
chat_record = session.get(ChatRecord, chat_record_id)
396442
if not chat_record:
397443
raise HTTPException(
398444
status_code=500,
399445
detail=f"ChatRecord with id {chat_record_id} not found"
400446
)
401-
447+
if chat_record.create_by != current_user.id:
448+
raise HTTPException(
449+
status_code=500,
450+
detail=f"ChatRecord with id {chat_record_id} not Owned by the current user"
451+
)
402452
is_predict_data = chat_record.predict_record_id is not None
403453

404454
_origin_data = format_json_data(get_chat_chart_data(chat_record_id=chat_record_id, session=session))

backend/apps/chat/curd/chat.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,21 @@ def list_recent_questions(session: SessionDep, current_user: CurrentUser, dataso
5959
)
6060
return [record[0] for record in chat_records] if chat_records else []
6161

62+
def rename_chat_with_user(session: SessionDep, current_user: CurrentUser, rename_object: RenameChat) -> str:
63+
chat = session.get(Chat, rename_object.id)
64+
if not chat:
65+
raise Exception(f"Chat with id {rename_object.id} not found")
66+
if chat.create_by != current_user.id:
67+
raise Exception(f"Chat with id {rename_object.id} not Owned by the current user")
68+
chat.brief = rename_object.brief.strip()[:20]
69+
chat.brief_generate = rename_object.brief_generate
70+
session.add(chat)
71+
session.flush()
72+
session.refresh(chat)
73+
74+
brief = chat.brief
75+
session.commit()
76+
return brief
6277

6378
def rename_chat(session: SessionDep, rename_object: RenameChat) -> str:
6479
chat = session.get(Chat, rename_object.id)
@@ -86,6 +101,17 @@ def delete_chat(session, chart_id) -> str:
86101

87102
return f'Chat with id {chart_id} has been deleted'
88103

104+
def delete_chat_with_user(session, current_user: CurrentUser, chart_id) -> str:
105+
chat = session.query(Chat).filter(Chat.id == chart_id).first()
106+
if not chat:
107+
return f'Chat with id {chart_id} has been deleted'
108+
if chat.create_by != current_user.id:
109+
raise Exception(f"Chat with id {chart_id} not Owned by the current user")
110+
session.delete(chat)
111+
session.commit()
112+
113+
return f'Chat with id {chart_id} has been deleted'
114+
89115

90116
def get_chart_config(session: SessionDep, chart_record_id: int):
91117
stmt = select(ChatRecord.chart).where(and_(ChatRecord.id == chart_record_id))
@@ -173,6 +199,15 @@ def get_chat_chart_config(session: SessionDep, chat_record_id: int):
173199
pass
174200
return {}
175201

202+
def get_chart_data_with_user(session: SessionDep, current_user: CurrentUser, chat_record_id: int):
203+
stmt = select(ChatRecord.data).where(and_(ChatRecord.id == chat_record_id, ChatRecord.create_by == current_user.id))
204+
res = session.execute(stmt)
205+
for row in res:
206+
try:
207+
return orjson.loads(row.data)
208+
except Exception:
209+
pass
210+
return {}
176211

177212
def get_chat_chart_data(session: SessionDep, chat_record_id: int):
178213
stmt = select(ChatRecord.data).where(and_(ChatRecord.id == chat_record_id))
@@ -184,6 +219,15 @@ def get_chat_chart_data(session: SessionDep, chat_record_id: int):
184219
pass
185220
return {}
186221

222+
def get_chat_predict_data_with_user(session: SessionDep, current_user: CurrentUser, chat_record_id: int):
223+
stmt = select(ChatRecord.predict_data).where(and_(ChatRecord.id == chat_record_id, ChatRecord.create_by == current_user.id))
224+
res = session.execute(stmt)
225+
for row in res:
226+
try:
227+
return orjson.loads(row.predict_data)
228+
except Exception:
229+
pass
230+
return {}
187231

188232
def get_chat_predict_data(session: SessionDep, chat_record_id: int):
189233
stmt = select(ChatRecord.predict_data).where(and_(ChatRecord.id == chat_record_id))
@@ -210,7 +254,8 @@ def get_chat_with_records(session: SessionDep, chart_id: int, current_user: Curr
210254
chat = session.get(Chat, chart_id)
211255
if not chat:
212256
raise Exception(f"Chat with id {chart_id} not found")
213-
257+
if chat.create_by != current_user.id:
258+
raise Exception(f"Chat with id {chart_id} not Owned by the current user")
214259
chat_info = ChatInfo(**chat.model_dump())
215260

216261
if current_assistant and current_assistant.type in dynamic_ds_types:

backend/apps/dashboard/api/dashboard_api.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,15 @@ async def list_resource_api(session: SessionDep, dashboard: QueryDashboard, curr
1919

2020

2121
@router.post("/load_resource", summary=f"{PLACEHOLDER_PREFIX}load_resource_api")
22-
async def load_resource_api(session: SessionDep, dashboard: QueryDashboard):
23-
return load_resource(session=session, dashboard=dashboard)
22+
async def load_resource_api(session: SessionDep, current_user: CurrentUser, dashboard: QueryDashboard):
23+
resource_dict = load_resource(session=session, dashboard=dashboard)
24+
if resource_dict and resource_dict.get("create_by") != str(current_user.id):
25+
raise HTTPException(
26+
status_code=403,
27+
detail="You do not have permission to access this resource"
28+
)
29+
30+
return resource_dict
2431

2532

2633
@router.post("/create_resource", response_model=BaseDashboard, summary=f"{PLACEHOLDER_PREFIX}create_resource_api")
@@ -45,8 +52,8 @@ async def update_resource_api(session: SessionDep, user: CurrentUser, dashboard:
4552
resource_id_expr="resource_id",
4653
remark_expr="name"
4754
))
48-
async def delete_resource_api(session: SessionDep, resource_id: str, name: str):
49-
return delete_resource(session, resource_id)
55+
async def delete_resource_api(session: SessionDep, current_user: CurrentUser, resource_id: str, name: str):
56+
return delete_resource(session, current_user, resource_id)
5057

5158

5259
@router.post("/create_canvas", response_model=BaseDashboard, summary=f"{PLACEHOLDER_PREFIX}create_canvas_api")

backend/apps/dashboard/crud/dashboard_service.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def list_resource(session: SessionDep, dashboard: QueryDashboard, current_user:
2727
nodes = [DashboardBaseResponse(**row) for row in result.mappings()]
2828
tree = build_tree_generic(nodes, root_pid="root")
2929
return tree
30-
30+
3131

3232
def load_resource(session: SessionDep, dashboard: QueryDashboard):
3333
sql = text("""
@@ -130,7 +130,12 @@ def validate_name(session: SessionDep,user: CurrentUser, dashboard: QueryDashbo
130130
return not session.query(query.exists()).scalar()
131131

132132

133-
def delete_resource(session: SessionDep, resource_id: str):
133+
def delete_resource(session: SessionDep, current_user: CurrentUser, resource_id: str):
134+
coreDashboard = session.get(CoreDashboard, resource_id)
135+
if not coreDashboard:
136+
raise ValueError(f"Resource with id {resource_id} does not exist")
137+
if coreDashboard.create_by != str(current_user.id):
138+
raise ValueError(f"Resource with id {resource_id} not owned by the current user")
134139
sql = text("DELETE FROM core_dashboard WHERE id = :resource_id")
135140
result = session.execute(sql, {"resource_id": resource_id})
136141
session.commit()

backend/apps/datasource/api/datasource.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ def inner():
8383

8484

8585
@router.post("/chooseTables/{id}", response_model=None, summary=f"{PLACEHOLDER_PREFIX}ds_choose_tables")
86+
@require_permissions(permission=SqlbotPermission(role=['ws_admin'], permission=SqlbotPermission(type='ds', keyExpression="id")))
8687
async def choose_tables(session: SessionDep, trans: Trans, tables: List[CoreTable],
8788
id: int = Path(..., description=f"{PLACEHOLDER_PREFIX}ds_id")):
8889
def inner():
@@ -117,6 +118,7 @@ async def get_tables(session: SessionDep, id: int = Path(..., description=f"{PLA
117118

118119

119120
@router.post("/getTablesByConf", response_model=List[TableSchemaResponse], summary=f"{PLACEHOLDER_PREFIX}ds_get_tables")
121+
@require_permissions(permission=SqlbotPermission(role=['ws_admin']))
120122
async def get_tables_by_conf(session: SessionDep, trans: Trans, ds: CoreDatasource):
121123
try:
122124
def inner():
@@ -135,6 +137,7 @@ def inner():
135137

136138

137139
@router.post("/getSchemaByConf", response_model=List[str], summary=f"{PLACEHOLDER_PREFIX}ds_get_schema")
140+
@require_permissions(permission=SqlbotPermission(role=['ws_admin']))
138141
async def get_schema_by_conf(session: SessionDep, trans: Trans, ds: CoreDatasource):
139142
try:
140143
def inner():
@@ -154,6 +157,7 @@ def inner():
154157

155158
@router.post("/getFields/{id}/{table_name}", response_model=List[ColumnSchemaResponse],
156159
summary=f"{PLACEHOLDER_PREFIX}ds_get_fields")
160+
@require_permissions(permission=SqlbotPermission(role=['ws_admin'], type='ds', keyExpression="id"))
157161
async def get_fields(session: SessionDep,
158162
id: int = Path(..., description=f"{PLACEHOLDER_PREFIX}ds_id"),
159163
table_name: str = Path(..., description=f"{PLACEHOLDER_PREFIX}ds_table_name")):
@@ -174,7 +178,7 @@ class TestObj(BaseModel):
174178

175179

176180
# not used, just do test
177-
@router.post("/execSql/{id}", include_in_schema=False)
181+
""" @router.post("/execSql/{id}", include_in_schema=False)
178182
async def exec_sql(session: SessionDep, id: int, obj: TestObj):
179183
def inner():
180184
data = execSql(session, id, obj.sql)
@@ -187,31 +191,36 @@ def inner():
187191
188192
return data
189193
190-
return await asyncio.to_thread(inner)
194+
return await asyncio.to_thread(inner) """
191195

192196

193197
@router.post("/tableList/{id}", response_model=List[CoreTable], summary=f"{PLACEHOLDER_PREFIX}ds_table_list")
198+
@require_permissions(permission=SqlbotPermission(role=['ws_admin'], type='ds', keyExpression="id"))
194199
async def table_list(session: SessionDep, id: int = Path(..., description=f"{PLACEHOLDER_PREFIX}ds_id")):
195200
return get_tables_by_ds_id(session, id)
196201

197202

198203
@router.post("/fieldList/{id}", response_model=List[CoreField], summary=f"{PLACEHOLDER_PREFIX}ds_field_list")
204+
@require_permissions(permission=SqlbotPermission(role=['ws_admin']))
199205
async def field_list(session: SessionDep, field: FieldObj,
200206
id: int = Path(..., description=f"{PLACEHOLDER_PREFIX}ds_table_id")):
201207
return get_fields_by_table_id(session, id, field)
202208

203209

204210
@router.post("/editLocalComment", include_in_schema=False)
211+
@require_permissions(permission=SqlbotPermission(role=['ws_admin']))
205212
async def edit_local(session: SessionDep, data: TableObj):
206213
update_table_and_fields(session, data)
207214

208215

209216
@router.post("/editTable", response_model=None, summary=f"{PLACEHOLDER_PREFIX}ds_edit_table")
217+
@require_permissions(permission=SqlbotPermission(role=['ws_admin']))
210218
async def edit_table(session: SessionDep, table: CoreTable):
211219
updateTable(session, table)
212220

213221

214222
@router.post("/editField", response_model=None, summary=f"{PLACEHOLDER_PREFIX}ds_edit_field")
223+
@require_permissions(permission=SqlbotPermission(role=['ws_admin']))
215224
async def edit_field(session: SessionDep, field: CoreField):
216225
updateField(session, field)
217226

0 commit comments

Comments
 (0)