Files
udmin/scripts/setup_demo.sh
2025-08-28 00:55:35 +08:00

443 lines
22 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
set -euo pipefail
API="http://127.0.0.1:8080/api"
extract_id() { sed -n -E 's/.*"id":([0-9]+).*/\1/p'; }
# 使用变量承载 JSON避免直接使用管道导致的 broken pipe
get_menu_id_by_parent_and_path(){
local parent_id="$1"; local path="$2"
local MENUS
MENUS=$(curl -s -X GET "$API/menus" -H "$H_AUTH")
echo "$MENUS" | P="$path" PID="$parent_id" python3 - <<'PY'
import json,sys,os
try:
data=json.load(sys.stdin)
except Exception:
sys.exit(0)
menus=data.get("data", [])
P=os.environ.get("P")
PID=os.environ.get("PID")
try:
pid_int=None if PID in (None, "", "null") else int(PID)
except Exception:
pid_int=None
for m in menus:
if m.get("path")==P and ((pid_int is None and m.get("parent_id") is None) or (pid_int is not None and m.get("parent_id")==pid_int)):
print(m.get("id"), end="")
break
PY
}
get_menu_id_by_parent_and_name(){
local parent_id="$1"; local name="$2"
local MENUS
MENUS=$(curl -s -X GET "$API/menus" -H "$H_AUTH")
echo "$MENUS" | N="$name" PID="$parent_id" python3 - <<'PY'
import json,sys,os
try:
data=json.load(sys.stdin)
except Exception:
sys.exit(0)
menus=data.get("data", [])
N=os.environ.get("N")
PID=os.environ.get("PID")
try:
pid_int=None if PID in (None, "", "null") else int(PID)
except Exception:
pid_int=None
for m in menus:
if m.get("name")==N and ((pid_int is None and m.get("parent_id") is None) or (pid_int is not None and m.get("parent_id")==pid_int)):
print(m.get("id"), end="")
break
PY
}
create_or_get_menu(){
# parent_id name type path component icon order_no [visible] [status] [keep_alive]
local parent_id="$1"; local name="$2"; local mtype="$3"; local path="$4"; local component="$5"; local icon="$6"; local order_no="$7"; local visible="${8:-true}"; local status="${9:-1}"; local keep_alive="${10:-true}"
local id=""
if [ -n "$path" ]; then id=$(get_menu_id_by_parent_and_path "$parent_id" "$path") || true; fi
if [ -z "$id" ]; then id=$(get_menu_id_by_parent_and_name "$parent_id" "$name") || true; fi
if [ -n "$id" ]; then echo "$id"; return 0; fi
# 规范化可选字段为 JSON 合法值
local j_parent j_path j_comp j_icon j_order
if [ -n "${parent_id:-}" ]; then j_parent="$parent_id"; else j_parent="null"; fi
if [ -n "${path:-}" ]; then j_path="\"$path\""; else j_path="null"; fi
if [ -n "${component:-}" ]; then j_comp="\"$component\""; else j_comp="null"; fi
if [ -n "${icon:-}" ]; then j_icon="\"$icon\""; else j_icon="null"; fi
j_order="${order_no:-0}"
local payload
payload=$(cat <<JSON
{"parent_id":$j_parent,"name":"$name","path":$j_path,"component":$j_comp,"type":$mtype,"icon":$j_icon,"order_no":$j_order,"visible":$visible,"status":$status,"keep_alive":$keep_alive}
JSON
)
local resp; resp=$(echo "$payload" | curl -s -X POST "$API/menus" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-)
id=$(echo "$resp" | extract_id)
echo "$id"
}
# 1) Admin login
LOGIN_JSON=$(printf '{"username":"admin","password":"Admin@123"}' | curl -s -X POST "$API/auth/login" -H "Content-Type: application/json" --data-binary @-)
TOKEN=$(echo "$LOGIN_JSON" | sed -n -E 's/.*"access_token":"([^"]*)".*/\1/p')
if [ -z "$TOKEN" ]; then echo "[ERROR] Admin 登录失败: $LOGIN_JSON"; exit 1; fi
H_AUTH="Authorization: Bearer $TOKEN"
echo "[OK] Admin 登录成功"
# 1b) 去重清理:仅保留最早创建的根菜单,删除其余重复的根及子树
cleanup_duplicate_roots(){
local ROOT_NAME="$1"; local ROOT_TYPE="$2"
local MENUS JSON
MENUS=$(curl -s -X GET "$API/menus" -H "$H_AUTH")
# 计算应保留的 root_id 与需要删除的 root_ids
JSON=$(echo "$MENUS" | NAME="$ROOT_NAME" RTYPE="$ROOT_TYPE" python3 - <<'PY'
import json,sys,os
try:
data=json.load(sys.stdin)
menus=data.get("data", [])
except Exception:
menus=[]
NAME=os.environ.get("NAME")
RTYPE=int(os.environ.get("RTYPE") or 0)
roots=[m for m in menus if m.get("name")==NAME and m.get("parent_id") is None and m.get("type")==RTYPE]
roots=sorted(roots, key=lambda m: m.get("id") or 1<<30)
keep_id=str(roots[0].get("id")) if roots else ""
duplicates=[str(m.get("id")) for m in roots[1:]]
# 构建子树映射
children={}
for m in menus:
pid=m.get("parent_id")
if pid is None: continue
children.setdefault(str(pid), []).append(str(m.get("id")))
# 计算每个重复根的删除顺序(自底向上)
orders={}
from collections import deque
for rid in duplicates:
order=[]
# BFS 收集所有节点
q=deque([rid])
seen=set()
while q:
x=q.popleft()
if x in seen: continue
seen.add(x)
for c in children.get(x, []):
q.append(c)
order.append(x)
# 逆序删除(叶 -> 根)
orders[rid]=list(reversed(order))
print(json.dumps({"keep": keep_id, "dups": duplicates, "orders": orders}))
PY
)
local KEEP_ID; KEEP_ID=$(echo "$JSON" | sed -n -E 's/.*"keep":"?([0-9]+)"?.*/\1/p')
local DUPS; DUPS=$(echo "$JSON" | sed -n -E 's/.*"dups":\[([^\]]*)\].*/\1/p' | tr -d '" ')
if [ -n "${DUPS:-}" ]; then
echo "[INFO] 发现重复根菜单: $ROOT_NAME (type=$ROOT_TYPE)保留ID=$KEEP_ID,待清理: [$DUPS]"
# 逐个根依次删除其子树
for rid in $(echo "$DUPS" | tr ',' ' '); do
local ORDER; ORDER=$(echo "$JSON" | RID="$rid" python3 - <<'PY'
import json,sys,os
obj=json.load(sys.stdin)
rid=os.environ.get("RID")
print(",".join(obj.get("orders", {}).get(rid, [])), end="")
PY
)
for id in $(echo "$ORDER" | tr ',' ' '); do
# 逐个删除(叶优先),失败重试一次
RES=$(curl -s -X DELETE "$API/menus/$id" -H "$H_AUTH" || true)
echo "$RES" | grep -q '"code":0' || {
sleep 0.2
RES=$(curl -s -X DELETE "$API/menus/$id" -H "$H_AUTH" || true)
echo "$RES" | grep -q '"code":0' || echo "[WARN] 删除菜单失败(id=$id): $RES"
}
done
done
echo "[OK] 已清理 $ROOT_NAME 重复根菜单"
fi
}
# 如数据库已存在相同根菜单,先做去重清理
cleanup_duplicate_roots "演示-系统管理" 0 || true
cleanup_duplicate_roots "系统管理" 1 || true
# 2) Create demo menus可通过环境变量 SKIP_DEMO=1 跳过)
if [ "${SKIP_DEMO:-0}" != "1" ]; then
# 幂等:优先查找已存在的“演示-系统管理”,否则创建(基于 Python 解析)
MENUS_JSON=$(curl -s -X GET "$API/menus" -H "$H_AUTH")
DEMO_ROOT_ID=$(echo "$MENUS_JSON" | python3 - <<'PY'
import json,sys
try:
data=json.load(sys.stdin)
menus=data.get("data", [])
except Exception:
menus=[]
for m in menus:
if m.get("name")=="演示-系统管理" and m.get("type")==0 and m.get("parent_id") is None:
print(m.get("id"), end="")
break
PY
)
if [ -z "${DEMO_ROOT_ID:-}" ]; then
DEMO_ROOT_JSON=$(printf '{"name":"演示-系统管理","type":0,"order_no":100,"visible":true,"status":1}' | curl -s -X POST "$API/menus" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-)
DEMO_ROOT_ID=$(echo "$DEMO_ROOT_JSON" | extract_id)
fi
if [ -z "${DEMO_ROOT_ID:-}" ]; then echo "[ERROR] 创建/获取 演示-系统管理 根菜单失败"; exit 1; fi
USERS_ID=$(create_or_get_menu "$DEMO_ROOT_ID" "演示-用户管理" 1 "/demo/users" "Users" "" 10)
ROLES_ID=$(create_or_get_menu "$DEMO_ROOT_ID" "演示-角色管理" 1 "/demo/roles" "Roles" "" 20)
MENUS_ID=$(create_or_get_menu "$DEMO_ROOT_ID" "演示-菜单管理" 1 "/demo/menus" "Menus" "" 30)
PERMS_ID=$(create_or_get_menu "$DEMO_ROOT_ID" "演示-权限管理" 1 "/demo/perms" "Permissions" "" 40)
DEPT_ID=$(create_or_get_menu "$DEMO_ROOT_ID" "演示-部门管理" 1 "/demo/departments" "Departments" "" 50)
POS_ID=$(create_or_get_menu "$DEMO_ROOT_ID" "演示-岗位管理" 1 "/demo/positions" "Positions" "" 60)
echo "[OK] 演示菜单准备完成: ROOT=$DEMO_ROOT_ID USERS=$USERS_ID ROLES=$ROLES_ID MENUS=$MENUS_ID PERMS=$PERMS_ID DEPT=$DEPT_ID POS=$POS_ID"
else
echo "[INFO] 已设置 SKIP_DEMO=1跳过演示菜单创建"
fi
# [INFO] 演示菜单已通过幂等逻辑创建/获取,避免重复
# 3) Create demo role
TS=$(date +%s)
ROLE_NAME="演示-经理-${TS}"
ROLE_CODE="demo_manager_${TS}"
ROLE_JSON=$(printf '{"name":"%s","code":"%s","status":1}' "$ROLE_NAME" "$ROLE_CODE" | curl -s -X POST "$API/roles" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-)
ROLE_ID=$(echo "$ROLE_JSON" | extract_id); if [ -z "$ROLE_ID" ]; then echo "[ERROR] 创建角色失败: $ROLE_JSON"; exit 1; fi
echo "[OK] 创建角色成功: $ROLE_NAME (id=$ROLE_ID)"
# 4) Bind menus to the role
IDS=""
for v in "${USERS_ID:-}" "${ROLES_ID:-}" "${MENUS_ID:-}" "${PERMS_ID:-}" "${DEPT_ID:-}" "${POS_ID:-}"; do
if [ -n "$v" ]; then
if [ -n "$IDS" ]; then IDS="$IDS,$v"; else IDS="$v"; fi
fi
done
if [ -n "$IDS" ]; then
BIND_MENU_JSON=$(printf '{"ids":[%s]}' "$IDS" | curl -s -X PUT "$API/roles/$ROLE_ID/menus" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-)
echo "$BIND_MENU_JSON" | grep -q '"code":0' || { echo "[ERROR] 绑定角色菜单失败: $BIND_MENU_JSON"; exit 1; }
echo "[OK] 绑定角色菜单成功"
else
echo "[WARN] 无可绑定的演示菜单,跳过绑定"
fi
# 5) Create a user and bind the role
USER_NAME="alice_${TS}"
USER_PASS="Password@123"
USER_JSON=$(printf '{"username":"%s","password":"%s","nickname":"Alice","status":1}' "$USER_NAME" "$USER_PASS" | curl -s -X POST "$API/users" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-)
USER_ID=$(echo "$USER_JSON" | extract_id); if [ -z "$USER_ID" ]; then echo "[ERROR] 创建用户失败: $USER_JSON"; exit 1; fi
echo "[OK] 创建用户成功: $USER_NAME (id=$USER_ID)"
BIND_ROLE_JSON=$(printf '{"ids":[%s]}' "$ROLE_ID" | curl -s -X PUT "$API/users/$USER_ID/roles" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-)
echo "$BIND_ROLE_JSON" | grep -q '"code":0' || { echo "[ERROR] 绑定用户角色失败: $BIND_ROLE_JSON"; exit 1; }
echo "[OK] 绑定用户角色成功"
# 5b) Bind demo role to admin and verify menus
ADMIN_JSON=$(curl -s -X GET "$API/users?page=1&page_size=50&keyword=admin" -H "$H_AUTH")
ADMIN_ID=$(echo "$ADMIN_JSON" | sed -n -E 's/.*"id":([0-9]+).*"username":"admin".*/\1/p')
if [ -z "$ADMIN_ID" ]; then
echo "[WARN] 未找到 admin 用户ID"
else
BIND_ADMIN_JSON=$(printf '{"ids":[%s]}' "$ROLE_ID" | curl -s -X PUT "$API/users/$ADMIN_ID/roles" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-)
echo "$BIND_ADMIN_JSON" | grep -q '"code":0' && echo "[OK] 已为 admin 绑定演示角色(id=$ROLE_ID)" || echo "[WARN] 为 admin 绑定角色可能失败: $BIND_ADMIN_JSON"
MENUS_ADMIN=$(curl -s -X GET "$API/auth/menus" -H "$H_AUTH")
echo "[RESULT] Admin 可见菜单响应: $MENUS_ADMIN"
fi
# 6) Login as new user and fetch menus
LOGIN2_JSON=$(printf '{"username":"%s","password":"%s"}' "$USER_NAME" "$USER_PASS" | curl -s -X POST "$API/auth/login" -H "Content-Type: application/json" --data-binary @-)
TOKEN2=$(echo "$LOGIN2_JSON" | sed -n -E 's/.*"access_token":"([^\"]*)".*/\1/p')
if [ -z "$TOKEN2" ]; then echo "[ERROR] 新用户登录失败: $LOGIN2_JSON"; exit 1; fi
MENUS2=$(curl -s -X GET "$API/auth/menus" -H "Authorization: Bearer $TOKEN2")
echo "[RESULT] 新用户可见菜单响应: $MENUS2"
# 7) Check permissions and seed defaults if empty
PERMS_LIST=$(curl -s -X GET "$API/permissions?page=1&page_size=100" -H "$H_AUTH") || true
PERMS_TOTAL=$(echo "$PERMS_LIST" | sed -n -E 's/.*"total":([0-9]+).*/\1/p') || true
[ -z "${PERMS_TOTAL:-}" ] && PERMS_TOTAL=0
echo "[RESULT] 当前权限总数: $PERMS_TOTAL"
if [ "$PERMS_TOTAL" = "0" ]; then
echo "[INFO] 权限为空,开始初始化默认权限"
curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"users:view","name":"用户查看","description":"查看用户"}' >/dev/null || true
curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"users:edit","name":"用户编辑","description":"编辑用户"}' >/dev/null || true
curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"roles:view","name":"角色查看","description":"查看角色"}' >/dev/null || true
curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"roles:edit","name":"角色编辑","description":"编辑角色"}' >/dev/null || true
curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"menus:view","name":"菜单查看","description":"查看菜单"}' >/dev/null || true
curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"menus:edit","name":"菜单编辑","description":"编辑菜单"}' >/dev/null || true
curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"permissions:view","name":"权限查看","description":"查看权限"}' >/dev/null || true
curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"permissions:edit","name":"权限编辑","description":"编辑权限"}' >/dev/null || true
curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"departments:view","name":"部门查看","description":"查看部门"}' >/dev/null || true
curl -s -X POST "$API/permissions" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary '{"code":"departments:edit","name":"部门编辑","description":"编辑部门"}' >/dev/null || true
PERMS_LIST=$(curl -s -X GET "$API/permissions?page=1&page_size=100" -H "$H_AUTH") || true
PERMS_TOTAL=$(echo "$PERMS_LIST" | sed -n -E 's/.*"total":([0-9]+).*/\1/p') || true
[ -z "${PERMS_TOTAL:-}" ] && PERMS_TOTAL=0
echo "[RESULT] 初始化后权限总数: $PERMS_TOTAL"
fi
echo "[SUMMARY] DEMO_ROOT=${DEMO_ROOT_ID:-} USERS=${USERS_ID:-} ROLES=${ROLES_ID:-} MENUS=${MENUS_ID:-} PERMS=${PERMS_ID:-} ROLE=$ROLE_ID USER=$USER_ID USERNAME=$USER_NAME"
# 8) Seed formal "系统管理" menus and Super Admin role
# 获取或创建 系统管理 根菜单:查找时不依赖字段顺序
MENUS_JSON=$(curl -s -X GET "$API/menus" -H "$H_AUTH")
SYS_ROOT_ID=$(echo "$MENUS_JSON" | python3 - <<'PY'
import json,sys
try:
data=json.load(sys.stdin)
menus=data.get("data", [])
except Exception:
menus=[]
for m in menus:
if m.get("name")=="系统管理" and m.get("type")==1 and m.get("parent_id") is None:
print(m.get("id"), end="")
break
PY
)
if [ -z "${SYS_ROOT_ID:-}" ]; then
SYS_ROOT_JSON=$(printf '{"name":"系统管理","type":1,"icon":"SettingOutlined","order_no":10,"visible":true,"status":1}' | curl -s -X POST "$API/menus" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-)
SYS_ROOT_ID=$(echo "$SYS_ROOT_JSON" | extract_id)
fi
if [ -z "${SYS_ROOT_ID:-}" ]; then echo "[ERROR] 创建/获取 系统管理 根菜单失败"; exit 1; fi
# helper to create child menu under 系统管理
create_menu_under_sys(){
local name="$1"; local path="$2"; local component="$3"; local icon="$4"; local order_no="$5"
local id
id=$(get_menu_id_by_parent_and_path "$SYS_ROOT_ID" "$path") || true
if [ -z "$id" ]; then id=$(get_menu_id_by_parent_and_name "$SYS_ROOT_ID" "$name") || true; fi
if [ -n "$id" ]; then echo "$id"; return 0; fi
id=$(create_or_get_menu "$SYS_ROOT_ID" "$name" 1 "$path" "$component" "$icon" "$order_no")
echo "$id"
}
USERS2_ID=$(create_menu_under_sys "用户管理" "/users" "Users" "UserOutlined" 20); [ -z "$USERS2_ID" ] && echo "[WARN] 用户管理 菜单ID获取失败"
ROLES2_ID=$(create_menu_under_sys "角色管理" "/roles" "Roles" "TeamOutlined" 30); [ -z "$ROLES2_ID" ] && echo "[WARN] 角色管理 菜单ID获取失败"
MENUS2_ID=$(create_menu_under_sys "菜单管理" "/menus" "Menus" "AppstoreOutlined" 40); [ -z "$MENUS2_ID" ] && echo "[WARN] 菜单管理 菜单ID获取失败"
PERMS2_ID=$(create_menu_under_sys "权限管理" "/permissions" "Permissions" "KeyOutlined" 50); [ -z "$PERMS2_ID" ] && echo "[WARN] 权限管理 菜单ID获取失败"
DEPTS2_ID=$(create_menu_under_sys "部门管理" "/departments" "Departments" "AppstoreOutlined" 60); [ -z "$DEPTS2_ID" ] && echo "[WARN] 部门管理 菜单ID获取失败"
POSITIONS2_ID=$(create_menu_under_sys "岗位管理" "/positions" "Positions" "IdcardOutlined" 65); [ -z "$POSITIONS2_ID" ] && echo "[WARN] 岗位管理 菜单ID获取失败"
echo "[OK] 正式系统菜单准备完成: ROOT=$SYS_ROOT_ID USERS=$USERS2_ID ROLES=$ROLES2_ID MENUS=$MENUS2_ID PERMS=$PERMS2_ID DEPTS=$DEPTS2_ID POSITIONS=$POSITIONS2_ID"
# 工具函数:根据 parent_id + perms 查找或创建按钮菜单(使用 Python 解析)
create_or_get_button(){
local parent_id="$1"; local name="$2"; local perms="$3"; local order_no="${4:-0}"
local id MENUS
MENUS=$(curl -s -X GET "$API/menus" -H "$H_AUTH")
id=$(echo "$MENUS" | PERM="$perms" PID="$parent_id" python3 - <<'PY'
import json,sys,os
try:
data=json.load(sys.stdin)
menus=data.get("data", [])
except Exception:
menus=[]
PERM=os.environ.get("PERM")
PID=os.environ.get("PID")
pid_int=None
try:
pid_int=int(PID)
except Exception:
pass
for m in menus:
if m.get("type")==3 and m.get("perms")==PERM and m.get("parent_id")==pid_int:
print(m.get("id"), end="")
break
PY
) || true
if [ -n "$id" ]; then echo "$id"; return 0; fi
local resp; resp=$(printf '{"parent_id":%s,"name":"%s","type":3,"order_no":%s,"visible":false,"status":1,"keep_alive":false,"perms":"%s"}' \
"$parent_id" "$name" "${order_no:-0}" "$perms" | curl -s -X POST "$API/menus" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-)
id=$(echo "$resp" | extract_id)
echo "$id"
}
# 为系统管理下添加按钮权限(幂等)
[ -n "${USERS2_ID:-}" ] && {
create_or_get_button "$USERS2_ID" "新增" "system:user:create" 10 >/dev/null || true
create_or_get_button "$USERS2_ID" "编辑" "system:user:update" 20 >/dev/null || true
create_or_get_button "$USERS2_ID" "重置密码" "system:user:reset" 30 >/dev/null || true
create_or_get_button "$USERS2_ID" "删除" "system:user:delete" 40 >/dev/null || true
create_or_get_button "$USERS2_ID" "分配岗位" "system:user:assignPosition" 50 >/dev/null || true
}
[ -n "${ROLES2_ID:-}" ] && {
create_or_get_button "$ROLES2_ID" "新增" "system:role:create" 10 >/dev/null || true
create_or_get_button "$ROLES2_ID" "编辑" "system:role:update" 20 >/dev/null || true
create_or_get_button "$ROLES2_ID" "分配菜单" "system:role:assign" 30 >/dev/null || true
create_or_get_button "$ROLES2_ID" "删除" "system:role:delete" 40 >/dev/null || true
}
[ -n "${MENUS2_ID:-}" ] && {
create_or_get_button "$MENUS2_ID" "新增" "system:menu:create" 10 >/dev/null || true
create_or_get_button "$MENUS2_ID" "编辑" "system:menu:update" 20 >/dev/null || true
create_or_get_button "$MENUS2_ID" "删除" "system:menu:delete" 30 >/dev/null || true
}
[ -n "${POSITIONS2_ID:-}" ] && {
create_or_get_button "$POSITIONS2_ID" "新增" "system:position:create" 10 >/dev/null || true
create_or_get_button "$POSITIONS2_ID" "编辑" "system:position:update" 20 >/dev/null || true
create_or_get_button "$POSITIONS2_ID" "删除" "system:position:delete" 30 >/dev/null || true
}
# 9) Create Super Admin role if not exists (code=super_admin)
SUPER_JSON=$(curl -s -X GET "$API/roles?page=1&page_size=100&keyword=super_admin" -H "$H_AUTH")
SUPER_ROLE_ID=$(echo "$SUPER_JSON" | sed -n -E 's/.*"id":([0-9]+).*"code":"super_admin".*/\1/p')
if [ -z "${SUPER_ROLE_ID:-}" ]; then
SUPER_CREATE_JSON=$(printf '{"name":"超级管理员","code":"super_admin","status":1}' | curl -s -X POST "$API/roles" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-)
SUPER_ROLE_ID=$(echo "$SUPER_CREATE_JSON" | extract_id)
fi
if [ -z "${SUPER_ROLE_ID:-}" ]; then echo "[ERROR] 创建/获取 超级管理员 角色失败"; exit 1; fi
echo "[OK] 超级管理员 角色ID=$SUPER_ROLE_ID"
# 10) Bind ALL menus to Super Admin (幂等)
ALL_MENU_IDS=$(curl -s -X GET "$API/menus" -H "$H_AUTH" | python3 - <<'PY'
import json,sys
try:
data=json.load(sys.stdin)
menus=data.get("data", [])
except Exception:
menus=[]
ids=[str(m.get("id")) for m in menus if isinstance(m.get("id"), int)]
print(",".join(ids), end="")
PY
)
BIND_SUPER_JSON=$(printf '{"ids":[%s]}' "$ALL_MENU_IDS" | curl -s -X PUT "$API/roles/$SUPER_ROLE_ID/menus" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-)
echo "$BIND_SUPER_JSON" | grep -q '"code":0' || { echo "[ERROR] 绑定全部菜单到 超级管理员 失败: $BIND_SUPER_JSON"; exit 1; }
echo "[OK] 已将全部菜单绑定到 超级管理员 角色"
# 11) Assign Super Admin role to admin (保留演示角色)
if [ -z "${ADMIN_ID:-}" ]; then
ADMIN_JSON=$(curl -s -X GET "$API/users?page=1&page_size=50&keyword=admin" -H "$H_AUTH")
ADMIN_ID=$(echo "$ADMIN_JSON" | sed -n -E 's/.*"id":([0-9]+).*"username":"admin".*/\1/p')
fi
if [ -n "${ADMIN_ID:-}" ]; then
CUR_ROLES_JSON=$(curl -s -X GET "$API/users/$ADMIN_ID/roles" -H "$H_AUTH")
NEW_ROLE_IDS=$(echo "$CUR_ROLES_JSON" | SUPER_ROLE_ID="$SUPER_ROLE_ID" python3 -c 'import json,sys,os
try:
data=json.load(sys.stdin)
except Exception:
data={}
ids=[]
for it in data.get("data", []):
try:
i=int(it.get("id"))
s=str(i)
if s not in ids:
ids.append(s)
except Exception:
pass
sid=os.environ.get("SUPER_ROLE_ID")
if sid and sid not in ids:
ids.append(sid)
print("".join([",".join(ids)]), end="")')
if [ -z "$NEW_ROLE_IDS" ]; then NEW_ROLE_IDS="$SUPER_ROLE_ID"; fi
ASSIGN_ADMIN_JSON=$(printf '{"ids":[%s]}' "$NEW_ROLE_IDS" | curl -s -X PUT "$API/users/$ADMIN_ID/roles" -H "$H_AUTH" -H "Content-Type: application/json" --data-binary @-)
echo "$ASSIGN_ADMIN_JSON" | grep -q '"code":0' && echo "[OK] 已为 admin 分配 超级管理员 角色(id=$SUPER_ROLE_ID) 合并现有角色: [$NEW_ROLE_IDS]" || echo "[WARN] 为 admin 分配 超级管理员 可能失败: $ASSIGN_ADMIN_JSON"
MENUS_ADMIN2=$(curl -s -X GET "$API/auth/menus" -H "$H_AUTH")
echo "[RESULT] Admin 可见菜单(包含正式菜单): $MENUS_ADMIN2"
else
echo "[WARN] 未能获取 admin 用户ID跳过角色分配"
fi
echo "[SUMMARY] DEMO_ROOT=${DEMO_ROOT_ID:-} USERS=${USERS_ID:-} ROLES=${ROLES_ID:-} MENUS=${MENUS_ID:-} PERMS=${PERMS_ID:-}"