feat(server): add project RBAC and guarded workflows
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
||||
from app.main import app
|
||||
|
||||
|
||||
HTTP_METHODS = ("get", "post", "put", "patch", "delete", "options", "head")
|
||||
|
||||
|
||||
def _parameter_line(parameter: dict) -> str:
|
||||
required = "必填" if parameter.get("required") else "可选"
|
||||
description = parameter.get("description")
|
||||
suffix = f" {description}" if description else ""
|
||||
return (
|
||||
f" - `{parameter.get('name', '-')}` "
|
||||
f"({parameter.get('in', '-')}, {required}){suffix}"
|
||||
)
|
||||
|
||||
|
||||
def build_markdown() -> str:
|
||||
schema = app.openapi()
|
||||
info = schema.get("info", {})
|
||||
lines = [
|
||||
"# TJWater Server API 文档",
|
||||
"",
|
||||
"本文档根据后端服务 OpenAPI 配置生成,用于查看接口路径、方法和用途。",
|
||||
"",
|
||||
"## 基本信息",
|
||||
"",
|
||||
f"- 标题:{info.get('title', '')}",
|
||||
f"- 版本:{info.get('version', '')}",
|
||||
f"- 描述:{info.get('description', '')}",
|
||||
"",
|
||||
"## 接口列表",
|
||||
"",
|
||||
]
|
||||
|
||||
for path in sorted(schema.get("paths", {})):
|
||||
path_item = schema["paths"][path]
|
||||
for method in HTTP_METHODS:
|
||||
operation = path_item.get(method)
|
||||
if not operation:
|
||||
continue
|
||||
lines.extend(
|
||||
[
|
||||
f"### `{method.upper()} {path}`",
|
||||
"",
|
||||
f"- 分组:{', '.join(operation.get('tags', [])) or '-'}",
|
||||
f"- 说明:{operation.get('summary', '')}",
|
||||
]
|
||||
)
|
||||
if operation.get("description"):
|
||||
lines.append(f"- 详情:{operation['description'].strip()}")
|
||||
parameters = operation.get("parameters", [])
|
||||
if parameters:
|
||||
lines.append("- 参数:")
|
||||
lines.extend(_parameter_line(parameter) for parameter in parameters)
|
||||
if operation.get("requestBody"):
|
||||
lines.append("- 请求体:需要")
|
||||
response_codes = ", ".join(operation.get("responses", {}).keys())
|
||||
lines.extend([f"- 响应状态:{response_codes}", ""])
|
||||
|
||||
return "\n".join(lines).rstrip() + "\n"
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("outputs", nargs="+", type=Path)
|
||||
args = parser.parse_args()
|
||||
content = build_markdown()
|
||||
for output in args.outputs:
|
||||
output.parent.mkdir(parents=True, exist_ok=True)
|
||||
output.write_text(content, encoding="utf-8")
|
||||
print(output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user