diff --git a/app/api/v1/endpoints/users.py b/app/api/v1/endpoints/users.py deleted file mode 100644 index 867a766..0000000 --- a/app/api/v1/endpoints/users.py +++ /dev/null @@ -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) \ No newline at end of file diff --git a/app/api/v1/router.py b/app/api/v1/router.py index b6f801c..b77b425 100644 --- a/app/api/v1/router.py +++ b/app/api/v1/router.py @@ -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"], diff --git a/app/native/wndb/__init__.py b/app/native/wndb/__init__.py index 4765495..35b9c20 100644 --- a/app/native/wndb/__init__.py +++ b/app/native/wndb/__init__.py @@ -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 ( diff --git a/app/native/wndb/s39_user.py b/app/native/wndb/s39_user.py deleted file mode 100644 index 3b4c37d..0000000 --- a/app/native/wndb/s39_user.py +++ /dev/null @@ -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") - diff --git a/app/services/scheme_management.py b/app/services/scheme_management.py index aaa5c04..1cab298 100644 --- a/app/services/scheme_management.py +++ b/app/services/scheme_management.py @@ -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: """ diff --git a/app/services/tjnetwork.py b/app/services/tjnetwork.py index fa36d76..2400e38 100644 --- a/app/services/tjnetwork.py +++ b/app/services/tjnetwork.py @@ -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 ############################################################ diff --git a/cli/tjwater_cli_endpoint_scope.md b/cli/tjwater_cli_endpoint_scope.md index 86da44a..bd6d36a 100644 --- a/cli/tjwater_cli_endpoint_scope.md +++ b/cli/tjwater_cli_endpoint_scope.md @@ -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 diff --git a/contracts/manifest.json b/contracts/manifest.json index 719a09e..22e0996 100644 --- a/contracts/manifest.json +++ b/contracts/manifest.json @@ -3,7 +3,7 @@ "contracts": { "server": { "file": "server-v1.openapi.json", - "sha256": "d80a968d281fdb2953364a5979c2d61fda5151a1e1759c01cc96780b11a6d56c" + "sha256": "3cb27b1a6f83ad0619e6b086b314303d15b4d23ce0c9ab318c9cbe720d974c40" } } } diff --git a/contracts/server-v1.openapi.json b/contracts/server-v1.openapi.json index 15f2abe..ddd1df1 100644 --- a/contracts/server-v1.openapi.json +++ b/contracts/server-v1.openapi.json @@ -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": "高级版本的阀门关闭分析,支持同时关闭多个阀门,并在指定持续时间内进行模拟。返回纯文本格式的分析结果。", diff --git a/scripts/main.py b/scripts/main.py index 7247e14..902f9ef 100644 --- a/scripts/main.py +++ b/scripts/main.py @@ -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 ############################################################ diff --git a/scripts/main_api_endpoints.md b/scripts/main_api_endpoints.md index 89e2132..aed26a8 100644 --- a/scripts/main_api_endpoints.md +++ b/scripts/main_api_endpoints.md @@ -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/` diff --git a/scripts/online_Analysis.py b/scripts/online_Analysis.py index e615ac0..72b2dba 100644 --- a/scripts/online_Analysis.py +++ b/scripts/online_Analysis.py @@ -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) diff --git a/tests/api/test_openapi_contract.py b/tests/api/test_openapi_contract.py index 3d2d169..c7542dd 100644 --- a/tests/api/test_openapi_contract.py +++ b/tests/api/test_openapi_contract.py @@ -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