合并 agent-mvp 到 master #1

Merged
jiang merged 93 commits from agent-mvp into master 2026-08-18 17:56:43 +08:00
13 changed files with 17 additions and 558 deletions
Showing only changes of commit b6a6527bab - Show all commits
-36
View File
@@ -1,36 +0,0 @@
from fastapi import APIRouter, Request, Query
from typing import Any, List, Dict, Union
from app.services.tjnetwork import Any, get_all_users, get_user, get_user_schema
router = APIRouter()
###########################################################
# user 39
###########################################################
@router.get("/network-schemas/user", summary="获取用户模式", description="获取指定网络的用户模式定义")
async def fastapi_get_user_schema(network: str = Query(..., description="管网名称(或数据库名称)")) -> dict[str, dict[Any, Any]]:
"""
获取用户模式定义
返回指定网络的用户模式结构定义
"""
return get_user_schema(network)
@router.get("/users/detail", summary="获取单个用户", description="获取指定网络中的单个用户信息")
async def fastapi_get_user(network: str = Query(..., description="管网名称(或数据库名称)"), user_name: str = Query(..., description="用户名")) -> dict[Any, Any]:
"""
获取用户信息
返回指定网络中指定用户名的详细信息
"""
return get_user(network, user_name)
@router.get("/users", summary="获取所有用户", description="获取指定网络的所有用户列表")
async def fastapi_get_all_users(network: str = Query(..., description="管网名称(或数据库名称)")) -> list[dict[Any, Any]]:
"""
获取所有用户列表
返回指定网络中所有用户的信息
"""
return get_all_users(network)
-6
View File
@@ -22,7 +22,6 @@ from app.api.v1.endpoints import (
sensor_placement,
simulation,
snapshots,
users,
web_search,
)
from app.api.v1.endpoints.components import (
@@ -152,11 +151,6 @@ api_router.include_router(
tags=["Snapshots"],
dependencies=[simulation_access],
)
api_router.include_router(
users.router,
tags=["Users"],
dependencies=[webgis_view_access],
)
api_router.include_router(
schemes.router,
tags=["Schemes"],
-2
View File
@@ -460,8 +460,6 @@ from .s36_wda_cal import (
# -----------------------------------------------------------------------------
from .s38_scada_info import get_scada_info_schema, get_scada_info, get_all_scada_info
from .s39_user import get_user_schema, get_user, get_all_users
from .s40_schema import get_scheme_schema, get_scheme, get_all_schemes
from .s41_pipe_risk_probability import (
-37
View File
@@ -1,37 +0,0 @@
from .database import *
from .s0_base import *
class User(object):
def __init__(self, input: dict[str, Any]) -> None:
self.type = 'user'
self.id = str(input['user_id'])
self.name = str(input['username'])
self.password = str(input['password'])
def as_dict(self) -> dict[str, Any]:
return { 'type': self.type, 'id': self.id, 'name': self.name, 'password': self.password }
def as_id_dict(self) -> dict[str, Any]:
return { 'type': self.type, 'id': self.id }
def get_user_schema(name: str) -> dict[str, dict[Any, Any]]:
return { 'id' : {'type': 'str' , 'optional': False , 'readonly': True },
'name' : {'type': 'str' , 'optional': False , 'readonly': False},
'password' : {'type': 'str' , 'optional': False , 'readonly': False} }
def get_user(name: str, user_name: str) -> dict[Any, Any]:
t = try_read(name, f"select * from users where username = '{user_name}'")
if t == None:
return {}
d = {}
d['id'] = str(t['user_id'])
d['name'] = str(t['username'])
# d['password'] = str(t['password'])
return d
def get_all_users(name: str) -> list[dict[Any, Any]]:
return read_all(name, "select * from users")
+2 -49
View File
@@ -11,53 +11,6 @@ from app.core.config import get_pgconn_string
from app.services.time_api import parse_utc_time
# 2025/03/23
def create_user(name: str, username: str, password: str):
"""
创建用户
:param name: 数据库名称
:param username: 用户名
:param password: 密码
:return:
"""
try:
# 动态替换数据库名称
conn_string = get_pgconn_string(db_name=name)
# 连接到 PostgreSQL 数据库(这里是数据库 "bb"
with psycopg.connect(conn_string) as conn:
with conn.cursor() as cur:
cur.execute(
"INSERT INTO users (username, password) VALUES (%s, %s)",
(username, password),
)
# 提交事务
conn.commit()
print("新用户创建成功!")
except Exception as e:
print(f"创建用户出错:{e}")
# 2025/03/23
def delete_user(name: str, username: str):
"""
删除用户
:param name: 数据库名称
:param username: 用户名
:return:
"""
try:
# 动态替换数据库名称
conn_string = get_pgconn_string(db_name=name)
# 连接到 PostgreSQL 数据库(这里是数据库 "bb"
with psycopg.connect(conn_string) as conn:
with conn.cursor() as cur:
cur.execute("DELETE FROM users WHERE username = %s", (username,))
conn.commit()
print(f"用户 {username} 删除成功!")
except Exception as e:
print(f"删除用户出错:{e}")
# 2025/03/23
def scheme_name_exists(name: str, scheme_name: str) -> bool:
"""
@@ -98,8 +51,8 @@ def store_scheme_info(
:param name: 数据库名称
:param scheme_name: 方案名称
:param scheme_type: 方案类型
:param username: 用户名(需在 users 表中已存在)
:param scheme_start_time: 方案起始时间(字符串)
:param username: MetaDB 中的用户名快照
:param scheme_start_time: 带时区的方案起始时间;写入前统一转换为 UTC
:param scheme_detail: 方案详情(字典,会转换为 JSON)
:return:
"""
-13
View File
@@ -1290,19 +1290,6 @@ def get_scada_info(name: str, id: str) -> dict[str, Any]:
def get_all_scada_info(name: str) -> list[dict[str, Any]]:
return api.get_all_scada_info(name)
# DingZQ 2025-03-27
############################################################
# 39 users
############################################################
def get_user_schema(name: str) -> dict[str, dict[str, Any]]:
return api.get_user_schema(name)
def get_user(name: str, user_name: str) -> dict[str, Any]:
return api.get_user(name, user_name=user_name)
def get_all_users(name: str) -> list[dict[str, Any]]:
return api.get_all_users(name)
############################################################
# scheme 40
############################################################
-4
View File
@@ -305,7 +305,6 @@ GET /getjson/
app/api/v1/endpoints/snapshots.py
app/api/v1/endpoints/cache.py
app/api/v1/endpoints/audit.py
app/api/v1/endpoints/users.py
```
这些接口不纳入首批 Agent CLI。原因是它们更偏运维、审计或状态回滚,不属于 Agent 面向水务业务分析的核心调用范围。
@@ -335,9 +334,6 @@ POST /clearallredis/
GET /audit/logs
GET /audit/logs/my
GET /audit/logs/count
GET /getuserschema/
GET /getuser/
GET /getallusers/
```
## Help
+1 -1
View File
@@ -3,7 +3,7 @@
"contracts": {
"server": {
"file": "server-v1.openapi.json",
"sha256": "d80a968d281fdb2953364a5979c2d61fda5151a1e1759c01cc96780b11a6d56c"
"sha256": "3cb27b1a6f83ad0619e6b086b314303d15b4d23ce0c9ab318c9cbe720d974c40"
}
}
}
-333
View File
@@ -19425,108 +19425,6 @@
]
}
},
"/api/v1/network-schemas/user": {
"get": {
"description": "获取指定网络的用户模式定义",
"operationId": "get_network_schemas_user",
"parameters": [
{
"in": "header",
"name": "X-Project-Id",
"required": true,
"schema": {
"title": "X-Project-Id",
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"additionalProperties": {
"type": "object"
},
"title": "Response Get Network Schemas User",
"type": "object"
}
}
},
"description": "Successful Response"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Authentication required"
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Insufficient permission"
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Resource not found"
},
"409": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Resource conflict"
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Validation error"
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Dependency unavailable"
}
},
"security": [
{
"OAuth2PasswordBearer": []
}
],
"summary": "获取用户模式",
"tags": [
"Users"
]
}
},
"/api/v1/network-schemas/valve": {
"get": {
"description": "获取指定水网中所有阀门的架构和字段定义",
@@ -47552,237 +47450,6 @@
]
}
},
"/api/v1/users": {
"get": {
"description": "获取指定网络的所有用户列表",
"operationId": "get_users",
"parameters": [
{
"in": "query",
"name": "limit",
"required": false,
"schema": {
"default": 100,
"maximum": 1000,
"minimum": 1,
"title": "Limit",
"type": "integer"
}
},
{
"in": "query",
"name": "offset",
"required": false,
"schema": {
"default": 0,
"minimum": 0,
"title": "Offset",
"type": "integer"
}
},
{
"in": "header",
"name": "X-Project-Id",
"required": true,
"schema": {
"title": "X-Project-Id",
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Page_dict_Any__Any__"
}
}
},
"description": "Successful Response"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Authentication required"
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Insufficient permission"
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Resource not found"
},
"409": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Resource conflict"
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Validation error"
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Dependency unavailable"
}
},
"security": [
{
"OAuth2PasswordBearer": []
}
],
"summary": "获取所有用户",
"tags": [
"Users"
]
}
},
"/api/v1/users/detail": {
"get": {
"description": "获取指定网络中的单个用户信息",
"operationId": "get_users_detail",
"parameters": [
{
"description": "用户名",
"in": "query",
"name": "user_name",
"required": true,
"schema": {
"description": "用户名",
"title": "User Name",
"type": "string"
}
},
{
"in": "header",
"name": "X-Project-Id",
"required": true,
"schema": {
"title": "X-Project-Id",
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"title": "Response Get Users Detail",
"type": "object"
}
}
},
"description": "Successful Response"
},
"401": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Authentication required"
},
"403": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Insufficient permission"
},
"404": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Resource not found"
},
"409": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Resource conflict"
},
"422": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Validation error"
},
"503": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
},
"description": "Dependency unavailable"
}
},
"security": [
{
"OAuth2PasswordBearer": []
}
],
"summary": "获取单个用户",
"tags": [
"Users"
]
}
},
"/api/v1/valve-closure-analyses": {
"post": {
"description": "高级版本的阀门关闭分析,支持同时关闭多个阀门,并在指定持续时间内进行模拟。返回纯文本格式的分析结果。",
-21
View File
@@ -138,7 +138,6 @@ from app.services.tjnetwork import (
get_all_sensor_placements,
get_all_service_areas,
get_all_tanks,
get_all_users,
get_all_valves,
get_all_vertex_links,
get_all_vertices,
@@ -238,8 +237,6 @@ from app.services.tjnetwork import (
get_time_schema,
get_title,
get_title_schema,
get_user,
get_user_schema,
get_valve,
get_valve_schema,
get_vertex,
@@ -2910,24 +2907,6 @@ async def fastapi_get_all_scada_info(network: str) -> list[dict[str, float]]:
return get_all_scada_info(network)
###########################################################
# user 39
###########################################################
@app.get("/getuserschema/")
async def fastapi_get_user_schema(network: str) -> dict[str, dict[Any, Any]]:
return get_user_schema(network)
@app.get("/getuser/")
async def fastapi_get_user(network: str, user_name: str) -> dict[Any, Any]:
return get_user(network, user_name)
@app.get("/getallusers/")
async def fastapi_get_all_users(network: str) -> list[dict[Any, Any]]:
return get_all_users(network)
############################################################
# scheme 40
############################################################
-3
View File
@@ -327,9 +327,6 @@ Non-commented FastAPI routes defined in `scripts/main.py`.
- `GET /getscadainfoschema/`
- `GET /getscadainfo/`
- `GET /getallscadainfo/`
- `GET /getuserschema/`
- `GET /getuser/`
- `GET /getallusers/`
- `GET /getschemeschema/`
- `GET /getscheme/`
- `GET /getallschemes/`
-53
View File
@@ -1145,53 +1145,6 @@ def submit_scada_info(name: str, coord_id: str) -> None:
print(f"scada_info文件不存在。")
# 2025/03/23
def create_user(name: str, username: str, password: str):
"""
创建用户
:param name: 数据库名称
:param username: 用户名
:param password: 密码
:return:
"""
try:
# 动态替换数据库名称
conn_string = get_pgconn_string(db_name=name)
# 连接到 PostgreSQL 数据库(这里是数据库 "bb"
with psycopg.connect(conn_string) as conn:
with conn.cursor() as cur:
cur.execute(
"INSERT INTO users (username, password) VALUES (%s, %s)",
(username, password),
)
# 提交事务
conn.commit()
print("新用户创建成功!")
except Exception as e:
print(f"创建用户出错:{e}")
# 2025/03/23
def delete_user(name: str, username: str):
"""
删除用户
:param name: 数据库名称
:param username: 用户名
:return:
"""
try:
# 动态替换数据库名称
conn_string = get_pgconn_string(db_name=name)
# 连接到 PostgreSQL 数据库(这里是数据库 "bb"
with psycopg.connect(conn_string) as conn:
with conn.cursor() as cur:
cur.execute("DELETE FROM users WHERE username = %s", (username,))
conn.commit()
print(f"用户 {username} 删除成功!")
except Exception as e:
print(f"删除用户出错:{e}")
# 2025/03/23
def scheme_name_exists(name: str, scheme_name: str) -> bool:
"""
@@ -1572,12 +1525,6 @@ if __name__ == "__main__":
# burst_analysis(name='bb', modify_pattern_start_time='2025-04-17T00:00:00+08:00',
# burst_ID='GSD230112144241FA18292A84CB', burst_size=400, modify_total_duration=1800, scheme_name='GSD230112144241FA18292A84CB_400')
# 示例:create_user
# create_user(name=project_info.name, username='tjwater dev', password='123456')
# # 示例:delete_user
# delete_user(name=project_info.name, username='admin_test')
# # 示例:query_scheme_list
# result = query_scheme_list(name=project_info.name)
# print(result)
+14
View File
@@ -77,6 +77,20 @@ def test_handler_router_defines_only_the_public_rest_operations() -> None:
assert ("GET", "/getpipeproperties/") not in source_operations
def test_legacy_project_user_operations_are_not_exposed() -> None:
source_paths = {
route.path
for route in source_api_router.routes
if isinstance(route, APIRoute)
}
assert {
"/network-schemas/user",
"/users",
"/users/detail",
}.isdisjoint(source_paths)
def test_rest_openapi_satisfies_contract_invariants() -> None:
from fastapi import FastAPI