feat(server): add project RBAC and guarded workflows
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
import json
|
||||
from fastapi import APIRouter, Request, HTTPException, Query, Path, Body, Depends
|
||||
from fastapi import APIRouter, Request, HTTPException, Query, Path, Depends
|
||||
from fastapi.responses import PlainTextResponse
|
||||
from typing import Any, Dict, List
|
||||
from app.infra.db.metadb.repositories.metadata_repository import MetadataRepository
|
||||
from app.auth.project_dependencies import get_metadata_repository
|
||||
from app.auth.permissions import (
|
||||
ENVIRONMENT_MANAGE,
|
||||
require_permission,
|
||||
)
|
||||
from app.domain.schemas.metadata import ProjectMetaResponse
|
||||
import app.services.project_info as project_info
|
||||
from app.infra.db.postgresql.database import get_database_instance as get_pg_db
|
||||
@@ -18,7 +22,6 @@ from app.services.tjnetwork import (
|
||||
open_project,
|
||||
close_project,
|
||||
copy_project,
|
||||
import_inp,
|
||||
export_inp,
|
||||
read_inp,
|
||||
dump_inp,
|
||||
@@ -89,7 +92,8 @@ async def have_project_endpoint(
|
||||
|
||||
@router.post("/createproject/", summary="创建新项目", description="创建一个新的供水管网项目。如果项目已存在,可能会覆盖或报错(取决于底层实现)。")
|
||||
async def create_project_endpoint(
|
||||
network: str = Query(..., description="管网名称(或数据库名称)")
|
||||
network: str = Query(..., description="管网名称(或数据库名称)"),
|
||||
_=Depends(require_permission(ENVIRONMENT_MANAGE)),
|
||||
):
|
||||
"""
|
||||
创建新项目
|
||||
@@ -101,7 +105,8 @@ async def create_project_endpoint(
|
||||
|
||||
@router.post("/deleteproject/", summary="删除项目", description="永久删除指定的供水管网项目。此操作不可恢复。")
|
||||
async def delete_project_endpoint(
|
||||
network: str = Query(..., description="管网名称(或数据库名称)")
|
||||
network: str = Query(..., description="管网名称(或数据库名称)"),
|
||||
_=Depends(require_permission(ENVIRONMENT_MANAGE)),
|
||||
):
|
||||
"""
|
||||
删除项目
|
||||
@@ -172,7 +177,8 @@ async def close_project_endpoint(
|
||||
@router.post("/copyproject/", summary="复制项目", description="将现有项目复制为新项目。")
|
||||
async def copy_project_endpoint(
|
||||
source: str = Query(..., description="管网名称(或数据库名称)"),
|
||||
target: str = Query(..., description="管网名称(或数据库名称)")
|
||||
target: str = Query(..., description="管网名称(或数据库名称)"),
|
||||
_=Depends(require_permission(ENVIRONMENT_MANAGE)),
|
||||
):
|
||||
"""
|
||||
复制项目
|
||||
@@ -183,24 +189,6 @@ async def copy_project_endpoint(
|
||||
copy_project(source, target)
|
||||
return True
|
||||
|
||||
@router.post("/importinp/", summary="导入 INP 文件内容", description="将 INP 格式的文本内容导入到指定项目中。")
|
||||
async def import_inp_endpoint(
|
||||
req: Request,
|
||||
network: str = Query(..., description="管网名称(或数据库名称)")
|
||||
):
|
||||
"""
|
||||
导入 INP 文件内容
|
||||
|
||||
- **network**: 管网名称(或数据库名称)
|
||||
- **req**: 请求体,需包含 `{"inp": "..."}` 结构
|
||||
"""
|
||||
jo_root = await req.json()
|
||||
inp_text = jo_root["inp"]
|
||||
ps = {"inp": inp_text}
|
||||
ret = import_inp(network, ChangeSet(ps))
|
||||
print(ret)
|
||||
return ret
|
||||
|
||||
@router.get("/exportinp/", response_model=None, summary="导出项目为 ChangeSet", description="导出项目的变更集 (ChangeSet),包含顶点、SCADA 元素、DMA、SA、VD 等信息。")
|
||||
async def export_inp_endpoint(
|
||||
network: str = Query(..., description="管网名称(或数据库名称)"),
|
||||
@@ -331,26 +319,6 @@ def unlock_project_endpoint(
|
||||
|
||||
return False
|
||||
|
||||
# inp file operations
|
||||
@router.post("/uploadinp/", status_code=status.HTTP_200_OK, summary="上传 INP 文件", description="上传 INP 文件到服务器数据目录。")
|
||||
async def fastapi_upload_inp(
|
||||
afile: bytes = Body(..., description="文件二进制内容"),
|
||||
name: str = Query(..., description="保存的文件名")
|
||||
):
|
||||
"""
|
||||
上传 INP 文件
|
||||
|
||||
- **afile**: 文件内容
|
||||
- **name**: 文件名
|
||||
"""
|
||||
if not os.path.exists(inpDir):
|
||||
os.makedirs(inpDir, exist_ok=True)
|
||||
|
||||
filePath = inpDir + str(name)
|
||||
with open(filePath, "wb") as f:
|
||||
f.write(afile)
|
||||
return True
|
||||
|
||||
@router.get("/downloadinp/", status_code=status.HTTP_200_OK, summary="下载 INP 文件", description="从服务器数据目录下载指定的 INP 文件。")
|
||||
async def fastapi_download_inp(
|
||||
name: str = Query(..., description="文件名"),
|
||||
@@ -502,26 +470,6 @@ def unlock_project_endpoint(
|
||||
|
||||
return False
|
||||
|
||||
# inp file operations
|
||||
@router.post("/uploadinp/", status_code=status.HTTP_200_OK, summary="上传 INP 文件", description="上传 INP 文件到服务器数据目录。")
|
||||
async def fastapi_upload_inp(
|
||||
afile: bytes = Body(..., description="文件二进制内容"),
|
||||
name: str = Query(..., description="保存的文件名")
|
||||
):
|
||||
"""
|
||||
上传 INP 文件
|
||||
|
||||
- **afile**: 文件内容
|
||||
- **name**: 文件名
|
||||
"""
|
||||
if not os.path.exists(inpDir):
|
||||
os.makedirs(inpDir, exist_ok=True)
|
||||
|
||||
filePath = inpDir + str(name)
|
||||
with open(filePath, "wb") as f:
|
||||
f.write(afile)
|
||||
return True
|
||||
|
||||
@router.get("/downloadinp/", status_code=status.HTTP_200_OK, summary="下载 INP 文件", description="从服务器数据目录下载指定的 INP 文件。")
|
||||
async def fastapi_download_inp(
|
||||
name: str = Query(..., description="文件名"),
|
||||
|
||||
Reference in New Issue
Block a user