fix(simulation): use current user for stored schemes
This commit is contained in:
@@ -72,6 +72,7 @@ def burst_analysis(
|
|||||||
modify_variable_pump_pattern: dict[str, list] = None,
|
modify_variable_pump_pattern: dict[str, list] = None,
|
||||||
modify_valve_opening: dict[str, float] = None,
|
modify_valve_opening: dict[str, float] = None,
|
||||||
scheme_name: str = None,
|
scheme_name: str = None,
|
||||||
|
username: str | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
爆管模拟
|
爆管模拟
|
||||||
@@ -86,6 +87,9 @@ def burst_analysis(
|
|||||||
:param scheme_name: 方案名称
|
:param scheme_name: 方案名称
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
if not username:
|
||||||
|
raise ValueError("username is required when storing burst analysis scheme")
|
||||||
|
|
||||||
scheme_detail: dict = {
|
scheme_detail: dict = {
|
||||||
"burst_ID": burst_ID,
|
"burst_ID": burst_ID,
|
||||||
"burst_size": burst_size,
|
"burst_size": burst_size,
|
||||||
@@ -211,7 +215,7 @@ def burst_analysis(
|
|||||||
name=name,
|
name=name,
|
||||||
scheme_name=scheme_name,
|
scheme_name=scheme_name,
|
||||||
scheme_type="burst_analysis",
|
scheme_type="burst_analysis",
|
||||||
username="admin",
|
username=username,
|
||||||
scheme_start_time=modify_pattern_start_time,
|
scheme_start_time=modify_pattern_start_time,
|
||||||
scheme_detail=scheme_detail,
|
scheme_detail=scheme_detail,
|
||||||
)
|
)
|
||||||
@@ -311,6 +315,7 @@ def flushing_analysis(
|
|||||||
drainage_node_ID: str = None,
|
drainage_node_ID: str = None,
|
||||||
flushing_flow: float = 0,
|
flushing_flow: float = 0,
|
||||||
scheme_name: str = None,
|
scheme_name: str = None,
|
||||||
|
username: str | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
管道冲洗模拟
|
管道冲洗模拟
|
||||||
@@ -323,6 +328,9 @@ def flushing_analysis(
|
|||||||
:param scheme_name: 方案名称
|
:param scheme_name: 方案名称
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
if not username:
|
||||||
|
raise ValueError("username is required when storing flushing analysis scheme")
|
||||||
|
|
||||||
scheme_detail: dict = {
|
scheme_detail: dict = {
|
||||||
"duration": modify_total_duration,
|
"duration": modify_total_duration,
|
||||||
"valve_opening": modify_valve_opening,
|
"valve_opening": modify_valve_opening,
|
||||||
@@ -455,7 +463,7 @@ def flushing_analysis(
|
|||||||
name=name,
|
name=name,
|
||||||
scheme_name=scheme_name,
|
scheme_name=scheme_name,
|
||||||
scheme_type="flushing_analysis",
|
scheme_type="flushing_analysis",
|
||||||
username="admin",
|
username=username,
|
||||||
scheme_start_time=modify_pattern_start_time,
|
scheme_start_time=modify_pattern_start_time,
|
||||||
scheme_detail=scheme_detail,
|
scheme_detail=scheme_detail,
|
||||||
)
|
)
|
||||||
@@ -473,6 +481,7 @@ def contaminant_simulation(
|
|||||||
concentration: float, # 污染源浓度,单位mg/L
|
concentration: float, # 污染源浓度,单位mg/L
|
||||||
scheme_name: str = None,
|
scheme_name: str = None,
|
||||||
source_pattern: str = None, # 污染源时间变化模式名称
|
source_pattern: str = None, # 污染源时间变化模式名称
|
||||||
|
username: str | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
污染模拟
|
污染模拟
|
||||||
@@ -486,6 +495,9 @@ def contaminant_simulation(
|
|||||||
:param scheme_name: 方案名称
|
:param scheme_name: 方案名称
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
if not username:
|
||||||
|
raise ValueError("username is required when storing contaminant analysis scheme")
|
||||||
|
|
||||||
scheme_detail: dict = {
|
scheme_detail: dict = {
|
||||||
"source": source,
|
"source": source,
|
||||||
"concentration": concentration,
|
"concentration": concentration,
|
||||||
@@ -608,7 +620,7 @@ def contaminant_simulation(
|
|||||||
name=name,
|
name=name,
|
||||||
scheme_name=scheme_name,
|
scheme_name=scheme_name,
|
||||||
scheme_type="contaminant_analysis",
|
scheme_type="contaminant_analysis",
|
||||||
username="admin",
|
username=username,
|
||||||
scheme_start_time=modify_pattern_start_time,
|
scheme_start_time=modify_pattern_start_time,
|
||||||
scheme_detail=scheme_detail,
|
scheme_detail=scheme_detail,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import json
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import threading
|
import threading
|
||||||
from fastapi import APIRouter, HTTPException, File, UploadFile, Query, Path, Body
|
from fastapi import APIRouter, Depends, HTTPException, File, UploadFile, Query, Path, Body
|
||||||
from fastapi.responses import PlainTextResponse
|
from fastapi.responses import PlainTextResponse
|
||||||
|
from app.auth.keycloak_dependencies import get_current_keycloak_username
|
||||||
import app.services.simulation as simulation
|
import app.services.simulation as simulation
|
||||||
import app.services.globals as globals
|
import app.services.globals as globals
|
||||||
from app.services.tjnetwork import (
|
from app.services.tjnetwork import (
|
||||||
@@ -209,6 +210,7 @@ async def fastapi_burst_analysis(
|
|||||||
burst_size: list[float] = Query(..., description="对应各爆管点的爆管流量大小列表(L/s)"),
|
burst_size: list[float] = Query(..., description="对应各爆管点的爆管流量大小列表(L/s)"),
|
||||||
modify_total_duration: int = Query(..., description="模拟总时长(秒)"),
|
modify_total_duration: int = Query(..., description="模拟总时长(秒)"),
|
||||||
scheme_name: str = Query(..., description="分析方案名称"),
|
scheme_name: str = Query(..., description="分析方案名称"),
|
||||||
|
username: str = Depends(get_current_keycloak_username),
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
爆管分析(高级版本)
|
爆管分析(高级版本)
|
||||||
@@ -229,6 +231,7 @@ async def fastapi_burst_analysis(
|
|||||||
burst_size=burst_size,
|
burst_size=burst_size,
|
||||||
modify_total_duration=modify_total_duration,
|
modify_total_duration=modify_total_duration,
|
||||||
scheme_name=scheme_name,
|
scheme_name=scheme_name,
|
||||||
|
username=username,
|
||||||
)
|
)
|
||||||
return "success"
|
return "success"
|
||||||
|
|
||||||
@@ -314,6 +317,7 @@ async def fastapi_flushing_analysis(
|
|||||||
flush_flow: float = Query(0, description="冲洗流量(L/s),0表示自动计算"),
|
flush_flow: float = Query(0, description="冲洗流量(L/s),0表示自动计算"),
|
||||||
duration: int | None = Query(None, description="模拟持续时间(秒),默认900秒"),
|
duration: int | None = Query(None, description="模拟持续时间(秒),默认900秒"),
|
||||||
scheme_name: str = Query(..., description="冲洗方案名称"),
|
scheme_name: str = Query(..., description="冲洗方案名称"),
|
||||||
|
username: str = Depends(get_current_keycloak_username),
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
冲洗分析(高级版本)
|
冲洗分析(高级版本)
|
||||||
@@ -340,6 +344,7 @@ async def fastapi_flushing_analysis(
|
|||||||
drainage_node_ID=drainage_node_ID,
|
drainage_node_ID=drainage_node_ID,
|
||||||
flushing_flow=flush_flow,
|
flushing_flow=flush_flow,
|
||||||
scheme_name=scheme_name,
|
scheme_name=scheme_name,
|
||||||
|
username=username,
|
||||||
)
|
)
|
||||||
return result or "success"
|
return result or "success"
|
||||||
|
|
||||||
@@ -354,6 +359,7 @@ async def fastapi_contaminant_simulation(
|
|||||||
duration: int = Query(..., description="模拟持续时间(秒)"),
|
duration: int = Query(..., description="模拟持续时间(秒)"),
|
||||||
scheme_name: str = Query(..., description="模拟方案名称"),
|
scheme_name: str = Query(..., description="模拟方案名称"),
|
||||||
pattern: str | None = Query(None, description="污染源模式ID(可选)"),
|
pattern: str | None = Query(None, description="污染源模式ID(可选)"),
|
||||||
|
username: str = Depends(get_current_keycloak_username),
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
污染物模拟
|
污染物模拟
|
||||||
@@ -376,6 +382,7 @@ async def fastapi_contaminant_simulation(
|
|||||||
source=source,
|
source=source,
|
||||||
concentration=concentration,
|
concentration=concentration,
|
||||||
source_pattern=pattern,
|
source_pattern=pattern,
|
||||||
|
username=username,
|
||||||
)
|
)
|
||||||
return result or "success"
|
return result or "success"
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,12 @@ def _load_simulation_module(monkeypatch):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_authenticated_client(module) -> TestClient:
|
||||||
|
app = build_test_app(module.router, "/api/v1")
|
||||||
|
app.dependency_overrides[module.get_current_keycloak_username] = lambda: "alice"
|
||||||
|
return TestClient(app)
|
||||||
|
|
||||||
|
|
||||||
def test_run_project_endpoint_returns_plain_text(monkeypatch):
|
def test_run_project_endpoint_returns_plain_text(monkeypatch):
|
||||||
module = _load_simulation_module(monkeypatch)
|
module = _load_simulation_module(monkeypatch)
|
||||||
monkeypatch.setattr(module, "run_project", lambda network: f"report::{network}")
|
monkeypatch.setattr(module, "run_project", lambda network: f"report::{network}")
|
||||||
@@ -339,6 +345,33 @@ def test_valve_close_endpoint_passes_scheme_name(monkeypatch):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_burst_endpoint_passes_current_username(monkeypatch):
|
||||||
|
module = _load_simulation_module(monkeypatch)
|
||||||
|
captured = {}
|
||||||
|
|
||||||
|
def fake_burst_analysis(**kwargs):
|
||||||
|
captured.update(kwargs)
|
||||||
|
|
||||||
|
monkeypatch.setattr(module, "burst_analysis", fake_burst_analysis)
|
||||||
|
client = _build_authenticated_client(module)
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
"/api/v1/burst_analysis/",
|
||||||
|
params={
|
||||||
|
"network": "demo",
|
||||||
|
"modify_pattern_start_time": "2025-01-02T03:04:05+08:00",
|
||||||
|
"burst_ID": ["P1"],
|
||||||
|
"burst_size": [10.0],
|
||||||
|
"modify_total_duration": 900,
|
||||||
|
"scheme_name": "burst_case_01",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.text == '"success"'
|
||||||
|
assert captured["username"] == "alice"
|
||||||
|
|
||||||
|
|
||||||
def test_flushing_endpoint_passes_required_scheme_name(monkeypatch):
|
def test_flushing_endpoint_passes_required_scheme_name(monkeypatch):
|
||||||
module = _load_simulation_module(monkeypatch)
|
module = _load_simulation_module(monkeypatch)
|
||||||
captured = {}
|
captured = {}
|
||||||
@@ -348,7 +381,7 @@ def test_flushing_endpoint_passes_required_scheme_name(monkeypatch):
|
|||||||
return "ok"
|
return "ok"
|
||||||
|
|
||||||
monkeypatch.setattr(module, "flushing_analysis", fake_flushing_analysis)
|
monkeypatch.setattr(module, "flushing_analysis", fake_flushing_analysis)
|
||||||
client = TestClient(build_test_app(module.router, "/api/v1"))
|
client = _build_authenticated_client(module)
|
||||||
|
|
||||||
response = client.get(
|
response = client.get(
|
||||||
"/api/v1/flushing_analysis/",
|
"/api/v1/flushing_analysis/",
|
||||||
@@ -374,12 +407,41 @@ def test_flushing_endpoint_passes_required_scheme_name(monkeypatch):
|
|||||||
"drainage_node_ID": "N1",
|
"drainage_node_ID": "N1",
|
||||||
"flushing_flow": 100.0,
|
"flushing_flow": 100.0,
|
||||||
"scheme_name": "flush_case_01",
|
"scheme_name": "flush_case_01",
|
||||||
|
"username": "alice",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_contaminant_endpoint_passes_current_username(monkeypatch):
|
||||||
|
module = _load_simulation_module(monkeypatch)
|
||||||
|
captured = {}
|
||||||
|
|
||||||
|
def fake_contaminant_simulation(**kwargs):
|
||||||
|
captured.update(kwargs)
|
||||||
|
return "ok"
|
||||||
|
|
||||||
|
monkeypatch.setattr(module, "contaminant_simulation", fake_contaminant_simulation)
|
||||||
|
client = _build_authenticated_client(module)
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
"/api/v1/contaminant_simulation/",
|
||||||
|
params={
|
||||||
|
"network": "demo",
|
||||||
|
"start_time": "2025-01-02T03:04:05+08:00",
|
||||||
|
"source": "N1",
|
||||||
|
"concentration": 10.0,
|
||||||
|
"duration": 900,
|
||||||
|
"scheme_name": "contaminant_case_01",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.text == "ok"
|
||||||
|
assert captured["username"] == "alice"
|
||||||
|
|
||||||
|
|
||||||
def test_contaminant_endpoint_requires_scheme_name(monkeypatch):
|
def test_contaminant_endpoint_requires_scheme_name(monkeypatch):
|
||||||
module = _load_simulation_module(monkeypatch)
|
module = _load_simulation_module(monkeypatch)
|
||||||
client = TestClient(build_test_app(module.router, "/api/v1"))
|
client = _build_authenticated_client(module)
|
||||||
|
|
||||||
response = client.get(
|
response = client.get(
|
||||||
"/api/v1/contaminant_simulation/",
|
"/api/v1/contaminant_simulation/",
|
||||||
|
|||||||
Reference in New Issue
Block a user