From 48173ba60e01cabc870271ebba74cceeeb51872f Mon Sep 17 00:00:00 2001 From: chenxing Date: Tue, 11 Aug 2026 16:33:34 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9ci=E9=85=8D=E7=BD=AE=E6=B5=81?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/.env.example | 20 ---- deploy/_debug_run.sh | 6 -- deploy/_ps_chk.txt | 1 - deploy/_verify_remote.sh | 17 ---- deploy/build-push.sh | 36 ------- deploy/check_type_col.sh | 22 ----- deploy/deploy.sh | 40 -------- deploy/diag_caddy.sh | 23 ----- deploy/diag_deep.sh | 24 ----- deploy/docker-compose.userbase.yml | 74 -------------- deploy/find_db.sh | 8 -- deploy/fix_caddy.sh | 15 --- deploy/fix_restart.sh | 19 ---- deploy/fix_wildcard.sh | 33 ------- deploy/probe_nacos.sh | 19 ---- deploy/probe_net.sh | 10 -- deploy/redeploy_app.sh | 28 ------ deploy/remote_run.py | 35 ------- deploy/smoke.sh | 13 --- deploy/upload.py | 37 ------- deploy/userbase.nacos.yaml | 98 ------------------- deploy/verify_db.sh | 10 -- deploy/verify_final.sh | 19 ---- docker/application-prod.yml | 12 +-- .../java/com/bestsch/openapi/UserSysRole.java | 37 ------- .../java/com/bestsch/utils/DException.java | 22 ----- .../controller/api/AppSettingsController.java | 18 ---- .../com/yunhai/userbase/model/Operator.java | 29 ------ src/main/resources/bootstrap.yml | 4 +- 29 files changed, 7 insertions(+), 722 deletions(-) delete mode 100644 deploy/.env.example delete mode 100644 deploy/_debug_run.sh delete mode 100644 deploy/_ps_chk.txt delete mode 100644 deploy/_verify_remote.sh delete mode 100644 deploy/build-push.sh delete mode 100644 deploy/check_type_col.sh delete mode 100644 deploy/deploy.sh delete mode 100644 deploy/diag_caddy.sh delete mode 100644 deploy/diag_deep.sh delete mode 100644 deploy/docker-compose.userbase.yml delete mode 100644 deploy/find_db.sh delete mode 100644 deploy/fix_caddy.sh delete mode 100644 deploy/fix_restart.sh delete mode 100644 deploy/fix_wildcard.sh delete mode 100644 deploy/probe_nacos.sh delete mode 100644 deploy/probe_net.sh delete mode 100644 deploy/redeploy_app.sh delete mode 100644 deploy/remote_run.py delete mode 100644 deploy/smoke.sh delete mode 100644 deploy/upload.py delete mode 100644 deploy/userbase.nacos.yaml delete mode 100644 deploy/verify_db.sh delete mode 100644 deploy/verify_final.sh delete mode 100644 src/main/java/com/bestsch/openapi/UserSysRole.java delete mode 100644 src/main/java/com/bestsch/utils/DException.java delete mode 100644 src/main/java/com/yunhai/userbase/model/Operator.java diff --git a/deploy/.env.example b/deploy/.env.example deleted file mode 100644 index 6e7d395..0000000 --- a/deploy/.env.example +++ /dev/null @@ -1,20 +0,0 @@ -# 本地构建推送 / 远端部署 用的环境变量示例 -# 用法:复制为 .env 或直接 export 后执行脚本 - -# ---- ACR 阿里云镜像仓库 ---- -ACR_REGISTRY=registry.cn-hangzhou.aliyuncs.com -ACR_NAMESPACE=damaomi_docker -ACR_REPO=yunhai -ACR_USERNAME=your-acr-username -ACR_PASSWORD=your-acr-password - -# ---- 镜像 tag ---- -APP_VERSION=userbase-v1.0 -FRONT_VERSION=userbase-front-v1.0 - -# ---- 部署到远端 ---- -DEPLOY_HOST=192.168.10.157 -DEPLOY_PORT=22 -DEPLOY_USER=yunhai -REMOTE_DIR=/opt/docker/userbase -SSHPASS=your-ssh-password diff --git a/deploy/_debug_run.sh b/deploy/_debug_run.sh deleted file mode 100644 index 4f207bb..0000000 --- a/deploy/_debug_run.sh +++ /dev/null @@ -1,6 +0,0 @@ -docker run --rm --network infra-infra-net --entrypoint java registry.cn-hangzhou.aliyuncs.com/damaomi_docker/yunhai:userbase-v1.0 -jar /app/userbase.jar --spring.profiles.active=prod --debug > /tmp/ub_debug.log 2>&1 -echo "EXIT=$?" -echo "=== conditions / binding matches ===" -grep -nE "YhAuthAutoConfiguration|CasSsoConfiguration|Failed to bind|Binding to|YhSsoProperties|Exception starting filter|serverUrlPrefix|NoSuchBean" /tmp/ub_debug.log | head -60 -echo "=== tail (conditions report) ===" -tail -50 /tmp/ub_debug.log diff --git a/deploy/_ps_chk.txt b/deploy/_ps_chk.txt deleted file mode 100644 index 8500e20..0000000 --- a/deploy/_ps_chk.txt +++ /dev/null @@ -1 +0,0 @@ -EOF diff --git a/deploy/_verify_remote.sh b/deploy/_verify_remote.sh deleted file mode 100644 index dca455f..0000000 --- a/deploy/_verify_remote.sh +++ /dev/null @@ -1,17 +0,0 @@ -set -e -echo "== wait for health (up to 180s) ==" -for i in $(seq 1 36); do - st=$(docker inspect -f '{{.State.Health.Status}}' userbase-app 2>/dev/null || echo unknown) - echo " [$i] health=$st" - if [ "$st" = "healthy" ]; then break; fi - sleep 5 -done -echo "== container status ==" -docker ps --filter name=userbase --format "table {{.Names}}\t{{.Status}}" -echo "== nacos reachability (host) ==" -curl -s -m 5 -o /dev/null -w "host nacos http=%{http_code}\n" "http://nacos.yunhaixingtong.com:8848/nacos/v1/cs/configs?dataId=userbase.yaml&group=USERBASE&tenant=" || echo "host cannot reach nacos" -echo "== nacos reachability (container) ==" -docker exec userbase-app sh -c "curl -s -m 5 -o /dev/null -w 'container nacos http=%{http_code}\n' 'http://nacos.yunhaixingtong.com:8848/nacos/v1/cs/configs?dataId=userbase.yaml&group=USERBASE&tenant='" || echo "container cannot reach nacos" -echo "== app logs: nacos / config / errors (tail) ==" -docker logs --tail 200 userbase-app 2>&1 | grep -iE "Loading nacos data|userbase.yaml|locate Nacos|NacosConfig|get config from nacos|ERROR|Exception|connect.*refused|UnknownHost|403|401|拒绝|超时|Started " | tail -40 || true -echo "== done ==" diff --git a/deploy/build-push.sh b/deploy/build-push.sh deleted file mode 100644 index ace2b66..0000000 --- a/deploy/build-push.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash -# 本地构建 UserBase 前后端镜像并推送到阿里云 ACR -# 用法: ./build-push.sh [app_tag] [front_tag] -# 前置环境变量: ACR_NAMESPACE, ACR_USERNAME, ACR_PASSWORD -# 前置产物: service/target/userbase.jar、front/dist/prod/ -set -euo pipefail - -APP_VERSION="${1:-${APP_VERSION:-userbase-v1.0}}" -FRONT_VERSION="${2:-${FRONT_VERSION:-userbase-front-v1.0}}" -REGISTRY="${ACR_REGISTRY:-registry.cn-hangzhou.aliyuncs.com}" -NAMESPACE="${ACR_NAMESPACE:?请设置 ACR_NAMESPACE}" -REPO="${ACR_REPO:-yunhai}" - -APP_IMG="$REGISTRY/$NAMESPACE/$REPO:$APP_VERSION" -FRONT_IMG="$REGISTRY/$NAMESPACE/$REPO:$FRONT_VERSION" - -ROOT="$(cd "$(dirname "$0")/.." && pwd)" - -[ -f "$ROOT/service/target/userbase.jar" ] || { echo "缺少 service/target/userbase.jar,请先 mvn package"; exit 1; } -[ -f "$ROOT/front/dist/prod/index.html" ] || { echo "缺少 front/dist/prod,请先 npm run build:prod"; exit 1; } - -echo "== login $REGISTRY ==" -echo "${ACR_PASSWORD:?请设置 ACR_PASSWORD}" | docker login --username="${ACR_USERNAME:?请设置 ACR_USERNAME}" --password-stdin "$REGISTRY" - -echo "== build $APP_IMG ==" -docker build -f "$ROOT/service/docker/Dockerfile" -t "$APP_IMG" "$ROOT/service" - -echo "== build $FRONT_IMG ==" -docker build -f "$ROOT/front/docker/Dockerfile" -t "$FRONT_IMG" "$ROOT/front" - -echo "== push ==" -docker push "$APP_IMG" -docker push "$FRONT_IMG" - -echo "PUSHED $APP_IMG" -echo "PUSHED $FRONT_IMG" diff --git a/deploy/check_type_col.sh b/deploy/check_type_col.sh deleted file mode 100644 index dd8664d..0000000 --- a/deploy/check_type_col.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -set -e -MC=mysql8 -echo "MYSQL_CONTAINER=$MC" - -docker exec userbase-app cat /app/config/application-prod.yml > /tmp/cfg.yml -PW=$(awk '/username: root/{f=1} f&&/^ *password:/{sub(/^ *password: */,""); gsub(/\r/,""); print; exit}' /tmp/cfg.yml) -echo "PW_LEN=${#PW}" - -printf '[client]\nuser=root\npassword=%s\n' "$PW" > /tmp/my.cnf -docker cp /tmp/my.cnf "$MC":/tmp/my.cnf - -echo "== check sys_user.type column (via TCP 127.0.0.1) ==" -docker exec "$MC" sh -c "mysql --defaults-extra-file=/tmp/my.cnf -h 127.0.0.1 -N -e \"SELECT COLUMN_NAME, COLUMN_TYPE, COLUMN_DEFAULT, IS_NULLABLE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='bsch_userbase' AND TABLE_NAME='sys_user' AND COLUMN_NAME='type';\"" -echo "QUERY_EXIT=$?" - -echo "== also confirm DB reachable & table exists ==" -docker exec "$MC" sh -c "mysql --defaults-extra-file=/tmp/my.cnf -h 127.0.0.1 -N -e \"SHOW TABLES FROM bsch_userbase LIKE 'sys_user';\"" - -docker exec "$MC" rm -f /tmp/my.cnf -rm -f /tmp/my.cnf /tmp/cfg.yml -echo "CLEANED" diff --git a/deploy/deploy.sh b/deploy/deploy.sh deleted file mode 100644 index d1dabd8..0000000 --- a/deploy/deploy.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash -# 一键部署:上传编排文件 -> SSH 到服务器拉取镜像并启动 -# 用法: ./deploy.sh [app_tag] [front_tag] -# 前置环境变量: DEPLOY_HOST, SSHPASS(可选 ACR_NAMESPACE / DEPLOY_USER / REMOTE_DIR) -# 注:服务器需已 docker login registry.cn-hangzhou.aliyuncs.com -set -euo pipefail - -APP_VERSION="${1:-${APP_VERSION:-userbase-v1.0}}" -FRONT_VERSION="${2:-${FRONT_VERSION:-userbase-front-v1.0}}" -HOST="${DEPLOY_HOST:?请设置 DEPLOY_HOST}" -PORT="${DEPLOY_PORT:-22}" -USER="${DEPLOY_USER:-yunhai}" -REMOTE_DIR="${REMOTE_DIR:-/opt/docker/userbase}" -NAMESPACE="${ACR_NAMESPACE:-damaomi_docker}" -REGISTRY="${ACR_REGISTRY:-registry.cn-hangzhou.aliyuncs.com}" -PY="${PYTHON_BIN:-python3}" - -cd "$(dirname "$0")" - -echo "== 1/2 上传 compose 到 $HOST:$REMOTE_DIR ==" -"$PY" upload.py "$HOST" "$PORT" "$USER" \ - docker-compose.userbase.yml "$REMOTE_DIR/docker-compose.userbase.yml" - -echo "== 2/2 远端拉取镜像并启动 ==" -"$PY" remote_run.py "$HOST" "$PORT" "$USER" < .env < {{.Destination}}{{"\n"}}{{end}}' -echo -echo "===== 4. Running caddy admin config: does it contain 'userbase'? =====" -docker exec caddy curl -s localhost:2019/config/ | grep -i "userbase" | head -n 20 -echo "--- end grep ---" -echo -echo "===== 5. Caddy container status =====" -docker ps --filter name=caddy --format '{{.Names}} {{.Status}}' -echo -echo "===== 6. Direct test via 127.0.0.1 with Host header =====" -for p in /userbase/ /userbase/index.html /userbase/static/js/ /userbase/api/x; do - code=$(curl -s -o /tmp/ub_body -w "%{http_code}" -H "Host: www.yunhaixingtong.com" "http://127.0.0.1$p") - echo "$p -> $code | $(head -c 80 /tmp/ub_body | tr -d '\n')" -done diff --git a/deploy/diag_deep.sh b/deploy/diag_deep.sh deleted file mode 100644 index bd3797e..0000000 --- a/deploy/diag_deep.sh +++ /dev/null @@ -1,24 +0,0 @@ -set -u -echo "===== 1. In-container view of /etc/caddy/Caddyfile: userbase count =====" -docker exec caddy grep -c "userbase" /etc/caddy/Caddyfile -echo -echo "===== 2. Container start command =====" -docker inspect caddy --format 'CMD={{.Config.Cmd}} ENTRY={{.Config.Entrypoint}}' -echo -echo "===== 3. Admin API reachable? top-level keys =====" -docker exec caddy curl -s localhost:2019/ -echo -echo "===== 4. Running HTTP servers + route matchers in config =====" -docker exec caddy curl -s localhost:2019/config/ > /tmp/running.json -echo "bytes: $(wc -c < /tmp/running.json)" -echo "occurrences:" -for s in "userbase" "Welcome to Base Platform" "handle_path" "reverse_proxy" "www.yunhaixingtong.com"; do - echo " $s : $(grep -o "$s" /tmp/running.json | wc -l)" -done -echo -echo "===== 5. Do a manual POST /load from inside container and show result =====" -docker exec caddy caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile 2>&1 -echo "exit=$?" -sleep 1 -echo "--- after reload, recount ---" -docker exec caddy curl -s localhost:2019/config/ | grep -c "userbase" diff --git a/deploy/docker-compose.userbase.yml b/deploy/docker-compose.userbase.yml deleted file mode 100644 index ba61db6..0000000 --- a/deploy/docker-compose.userbase.yml +++ /dev/null @@ -1,74 +0,0 @@ -# UserBase 编排:后端(Spring Boot 8060) + 前端(nginx 80) -# 两者都挂在 infra-infra-net,由 caddy 按服务名反代到 www.yunhaixingtong.com/userbase -# 启动:cd /opt/docker/userbase && docker compose -f docker-compose.userbase.yml up -d -services: - userbase-app: - image: ${ACR_REGISTRY:-registry.cn-hangzhou.aliyuncs.com}/${ACR_NAMESPACE:-damaomi_docker}/yunhai:${APP_VERSION:-userbase-v1.0} - container_name: userbase-app - restart: unless-stopped - networks: - - infra-infra-net - # SSO 回调后容器内要做 CAS serviceValidate 回调 sso.yunhaixingtong.com, - # 该虚拟主机由宿主机 caddy 按 vhost 路由,但容器内无 DNS 记录会 UnknownHostException。 - # host-gateway 指向宿主机网关(caddy 监听 :80/:443 全接口),无需硬编码 IP; - # 旧版 Docker(<20.10)不支持 host-gateway,可改为宿主机桥接网关 IP,如 172.17.0.1。 - extra_hosts: - - "sso.yunhaixingtong.com:host-gateway" - environment: - TZ: Asia/Shanghai - # 配置中心:由 bootstrap.yml 中 spring.cloud.nacos.config 在 bootstrap 阶段自动拉取 - # 容器内通过 infra-infra-net 解析内网别名 nacos:8848(宿主机 shell 无法直接解析), - # 公网域名 nacos.yunhaixingtong.com 仅用于控制台管理,生产容器走内网。 - NACOS_ADDR: nacos:8848 - # Nacos 已开启鉴权,config 客户端需携带账号(与旧 run-app.sh 的 nacos/nacos 一致) - SPRING_CLOUD_NACOS_USERNAME: nacos - SPRING_CLOUD_NACOS_PASSWORD: nacos - SPRING_CLOUD_NACOS_CONFIG_USERNAME: nacos - SPRING_CLOUD_NACOS_CONFIG_PASSWORD: nacos - JAVA_OPTS: "-Xms512m -Xmx1024m" - volumes: - - ./upload-data:/data/upload - expose: - - "8060" - healthcheck: - # 只要能返回 HTTP 状态码就认为进程已起(业务接口普遍需要鉴权,不能用 -f) - test: ["CMD-SHELL", "curl -s -o /dev/null -w '%{http_code}' http://localhost:8060/userbase/ | grep -qE '^[234]'"] - interval: 30s - timeout: 10s - retries: 5 - start_period: 90s - deploy: - resources: - limits: - cpus: '1.5' - memory: 1536M - logging: - driver: "json-file" - options: - max-size: "10m" - max-file: "3" - - userbase-front: - image: ${ACR_REGISTRY:-registry.cn-hangzhou.aliyuncs.com}/${ACR_NAMESPACE:-damaomi_docker}/yunhai:${FRONT_VERSION:-userbase-front-v1.0} - container_name: userbase-front - restart: unless-stopped - networks: - - infra-infra-net - environment: - TZ: Asia/Shanghai - expose: - - "80" - deploy: - resources: - limits: - cpus: '0.5' - memory: 256M - logging: - driver: "json-file" - options: - max-size: "10m" - max-file: "3" - -networks: - infra-infra-net: - external: true diff --git a/deploy/find_db.sh b/deploy/find_db.sh deleted file mode 100644 index 073e482..0000000 --- a/deploy/find_db.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -set -e -echo "== all containers (name + image) ==" -docker ps -a --format '{{.Names}}\t{{.Image}}' -echo "== which containers are on infra-infra-net ==" -docker network inspect infra-infra-net --format '{{range .Containers}}{{.Name}} ({{.IPv4Address}}){{"\n"}}{{end}}' 2>/dev/null || echo "no such network" -echo "== resolve mysql8 from userbase-app ==" -docker exec userbase-app getent hosts mysql8 2>/dev/null || echo "getent failed" diff --git a/deploy/fix_caddy.sh b/deploy/fix_caddy.sh deleted file mode 100644 index 2ea602c..0000000 --- a/deploy/fix_caddy.sh +++ /dev/null @@ -1,15 +0,0 @@ -set -u -echo "===== A. Reload caddy from inside the container (reads mounted /etc/caddy/Caddyfile) =====" -docker exec caddy caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile -echo "reload exit: $?" -sleep 2 -echo -echo "===== B. Verify running config now contains userbase =====" -docker exec caddy curl -s localhost:2019/config/ | grep -c "userbase" -echo "(count above; 0 means still missing)" -echo -echo "===== C. Test routes via 127.0.0.1 with Host header =====" -for p in /userbase/ /userbase/index.html /userbase/static/js/ /userbase/api/x /userbase/login; do - code=$(curl -s -o /tmp/ub_body -w "%{http_code}" -H "Host: www.yunhaixingtong.com" "http://127.0.0.1$p") - echo "$p -> $code | $(head -c 90 /tmp/ub_body | tr -d '\n')" -done diff --git a/deploy/fix_restart.sh b/deploy/fix_restart.sh deleted file mode 100644 index d4b8568..0000000 --- a/deploy/fix_restart.sh +++ /dev/null @@ -1,19 +0,0 @@ -set -u -echo "===== host file (has userbase) =====" -grep -c "userbase" /opt/docker/infra/Caddyfile -echo "===== container file BEFORE restart (expect 0) =====" -docker exec caddy grep -c "userbase" /etc/caddy/Caddyfile -echo -echo "===== restart caddy to re-bind the edited file =====" -docker restart caddy -echo "restart exit: $?" -sleep 6 -echo -echo "===== container file AFTER restart (expect >0) =====" -docker exec caddy grep -c "userbase" /etc/caddy/Caddyfile -echo -echo "===== test routes =====" -for p in /userbase/ /userbase/index.html /userbase/static/js/ /userbase/api/x /userbase/login; do - code=$(curl -s -o /tmp/ub_body -w "%{http_code}" -H "Host: www.yunhaixingtong.com" "http://127.0.0.1$p") - echo "$p -> $code | $(head -c 100 /tmp/ub_body | tr -d '\n')" -done diff --git a/deploy/fix_wildcard.sh b/deploy/fix_wildcard.sh deleted file mode 100644 index b099adc..0000000 --- a/deploy/fix_wildcard.sh +++ /dev/null @@ -1,33 +0,0 @@ -set -u -CP=/opt/docker/infra/Caddyfile -echo "===== before: line 70 =====" -sed -n '70p' "$CP" -echo "===== apply wildcard matcher (inode will change; restart re-binds) =====" -sed -i 's#handle_path /userbase/ {#handle_path /userbase* {#' "$CP" -echo "after:"; sed -n '70p' "$CP" -echo -echo "===== restart caddy to re-bind edited file =====" -docker restart caddy -echo "restart exit: $?" -sleep 6 -echo "===== container sees fix? =====" -docker exec caddy grep -n "handle_path /userbase" /etc/caddy/Caddyfile -echo -echo "===== extract a real JS asset from SPA and test it =====" -html=$(curl -s -H "Host: www.yunhaixingtong.com" http://127.0.0.1/userbase/) -echo "$html" | grep -oE 'src="[^"]+\.js"' | head -3 -asset=$(echo "$html" | grep -oE '/[A-Za-z0-9_./-]+\.js' | head -1) -echo "first asset path: $asset" -if [ -n "$asset" ]; then - code=$(curl -s -o /dev/null -w "%{http_code}" -H "Host: www.yunhaixingtong.com" "http://127.0.0.1/userbase${asset}") - echo "/userbase${asset} -> $code" -fi -echo -echo "===== route tests =====" -for p in /userbase/ /userbase/index.html "/userbase${asset:-/static/js/}"; do - code=$(curl -s -o /tmp/b -w "%{http_code}" -H "Host: www.yunhaixingtong.com" "http://127.0.0.1$p") - echo "$p -> $code | $(head -c 70 /tmp/b|tr -d '\n')" -done -echo -echo "===== backend test =====" -curl -s -o /dev/null -w "/userbase/api/x -> %{http_code}\n" -H "Host: www.yunhaixingtong.com" http://127.0.0.1/userbase/api/x diff --git a/deploy/probe_nacos.sh b/deploy/probe_nacos.sh deleted file mode 100644 index 8152fa9..0000000 --- a/deploy/probe_nacos.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -# 探测内网 nacos:8848 是否可达、public 空间下 userbase.yaml 是否存在、是否需要鉴权 -echo "== resolve nacos ==" -getent hosts nacos || echo "cannot resolve nacos" -echo "== fetch userbase.yaml (public, no auth) ==" -curl -s -m 8 -o /tmp/nc.txt -w "http=%{http_code}\n" "http://nacos:8848/nacos/v1/cs/configs?dataId=userbase.yaml&group=USERBASE&tenant=" -echo "--- body (first 200 chars) ---" -head -c 200 /tmp/nc.txt; echo -if grep -q "unknown user" /tmp/nc.txt || grep -q "403" /tmp/nc.txt || [ "$(head -c 1 /tmp/nc.txt)" = "" ]; then - echo "== needs auth, try login nacos/nacos ==" - TOKEN=$(curl -s -m 8 -X POST "http://nacos:8848/nacos/v1/auth/login?username=nacos&password=nacos" | sed -n 's/.*"accessToken":"\([^"]*\)".*/\1/p') - echo "token_len=${#TOKEN}" - if [ -n "$TOKEN" ]; then - curl -s -m 8 -o /tmp/nc2.txt -w "http=%{http_code}\n" "http://nacos:8848/nacos/v1/cs/configs?dataId=userbase.yaml&group=USERBASE&tenant=&accessToken=$TOKEN" - echo "--- authed body (first 200 chars) ---" - head -c 200 /tmp/nc2.txt; echo - fi -fi -echo "== done ==" diff --git a/deploy/probe_net.sh b/deploy/probe_net.sh deleted file mode 100644 index 6e3bfcd..0000000 --- a/deploy/probe_net.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -echo "== containers on host ==" -docker ps --format '{{.Names}}\t{{.Networks}}' | head -40 -echo "== infra-infra-net members ==" -docker network inspect infra-infra-net --format '{{range .Containers}}{{.Name}} {{end}}' 2>/dev/null -echo "== resolve nacos from inside userbase-app ==" -docker exec userbase-app sh -c "getent hosts nacos || echo 'no nacos in container DNS'" -echo "== curl nacos:8848 from inside userbase-app (no auth) ==" -docker exec userbase-app sh -c "curl -s -m 8 -o /tmp/nc.txt -w 'http=%{http_code}\n' 'http://nacos:8848/nacos/v1/cs/configs?dataId=userbase.yaml&group=USERBASE&tenant=' ; head -c 200 /tmp/nc.txt; echo" || echo "curl failed" -echo "== done ==" diff --git a/deploy/redeploy_app.sh b/deploy/redeploy_app.sh deleted file mode 100644 index e0d5944..0000000 --- a/deploy/redeploy_app.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -# 重新部署 userbase-app:拉取新镜像、重建、等待健康,并核对是否真正从 Nacos 拉到了配置 -echo "== login ACR ==" -echo '59qtJRqlT7' | docker login --username=15121037482 --password-stdin registry.cn-hangzhou.aliyuncs.com - -cd /opt/docker/userbase -echo "== pull userbase-app ==" -docker compose -f docker-compose.userbase.yml pull userbase-app -echo "== up -d userbase-app ==" -docker compose -f docker-compose.userbase.yml up -d userbase-app - -echo "== wait for health (up to 150s) ==" -for i in $(seq 1 30); do - st=$(docker inspect -f '{{.State.Health.Status}}' userbase-app 2>/dev/null || echo unknown) - echo " [$i] health=$st" - if [ "$st" = "healthy" ]; then break; fi - sleep 5 -done - -echo "== nacos reachability (host) ==" -curl -s -m 5 -o /dev/null -w "host nacos http=%{http_code}\n" "http://nacos.yunhaixingtong.com:8848/nacos/v1/cs/configs?dataId=userbase.yaml&group=USERBASE&tenant=" || echo "host cannot reach nacos" - -echo "== nacos reachability (container) ==" -docker exec userbase-app sh -c "curl -s -m 5 -o /dev/null -w 'container nacos http=%{http_code}\n' 'http://nacos.yunhaixingtong.com:8848/nacos/v1/cs/configs?dataId=userbase.yaml&group=USERBASE&tenant='" || echo "container cannot reach nacos" - -echo "== app logs: nacos / config / errors ==" -docker logs --tail 150 userbase-app 2>&1 | grep -iE "Loading nacos data|userbase.yaml|locate Nacos|NacosConfig|get config from nacos|ERROR|Exception|connect.*refused|UnknownHost|403|401|拒绝|超时" | tail -50 || true -echo "== done ==" diff --git a/deploy/remote_run.py b/deploy/remote_run.py deleted file mode 100644 index b6e254e..0000000 --- a/deploy/remote_run.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 -# 通过 SSH 在远端以 sudo 执行脚本(从 stdin 读取) -# 用法: python3 remote_run.py < script.sh -# 依赖环境变量 SSHPASS -import os, sys, paramiko - - -def main(): - host = sys.argv[1] - port = int(sys.argv[2]) if len(sys.argv) > 2 else 22 - user = sys.argv[3] if len(sys.argv) > 3 else "root" - pw = os.environ.get("SSHPASS") - if not pw: - sys.stderr.write("ERROR: 请先设置环境变量 SSHPASS\n") - sys.exit(1) - script = sys.stdin.read() - c = paramiko.SSHClient() - c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - c.connect(host, port, user, password=pw, timeout=30) - stdin, stdout, stderr = c.exec_command("sudo -S bash -s", timeout=1800) - stdin.write(pw + "\n") - stdin.write(script) - stdin.flush() - stdin.channel.shutdown_write() - sys.stdout.write(stdout.read().decode(errors="replace")) - err = stderr.read().decode(errors="replace") - if err.strip(): - sys.stderr.write("STDERR:\n" + err) - code = stdout.channel.recv_exit_status() - c.close() - sys.exit(code) - - -if __name__ == "__main__": - main() diff --git a/deploy/smoke.sh b/deploy/smoke.sh deleted file mode 100644 index a911205..0000000 --- a/deploy/smoke.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -# 线上冒烟:经 Caddy 访问 UserBase,确认 Nacos 配置生效、前后端可达 -echo "== SPA 首页 ==" -curl -s -m 8 -o /dev/null -w "/userbase/ -> %{http_code}\n" -H "Host: www.yunhaixingtong.com" http://127.0.0.1/userbase/ -echo "== 前端静态资源 ==" -curl -s -m 8 -o /dev/null -w "/userbase/index.html -> %{http_code}\n" -H "Host: www.yunhaixingtong.com" http://127.0.0.1/userbase/index.html -echo "== 后端 API 可达性(CAS 重定向即代表到达后端) ==" -curl -s -m 8 -o /dev/null -w "/userbase/api/x -> %{http_code}\n" -H "Host: www.yunhaixingtong.com" http://127.0.0.1/userbase/api/x -echo "== 容器健康 ==" -docker inspect -f 'userbase-app health={{.State.Health.Status}}' userbase-app -echo "== 确认应用真正连的是 nacos 下发的 mysql8 数据源(日志里看 datasource url) ==" -docker logs --tail 200 userbase-app 2>&1 | grep -iE "jdbc:mysql://mysql8|HikariPool|Started UserBaseApplication" | tail -5 || true -echo "== done ==" diff --git a/deploy/upload.py b/deploy/upload.py deleted file mode 100644 index 80c0703..0000000 --- a/deploy/upload.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python3 -# 通过 SFTP 上传文件到远端(参数: host port user local remote [local remote ...]) -# 依赖环境变量 SSHPASS -import os, sys, paramiko - - -def main(): - host = sys.argv[1] - port = int(sys.argv[2]) if len(sys.argv) > 2 else 22 - user = sys.argv[3] if len(sys.argv) > 3 else "root" - pw = os.environ.get("SSHPASS") - if not pw: - sys.stderr.write("ERROR: 请先设置环境变量 SSHPASS\n") - sys.exit(1) - t = paramiko.Transport((host, port)) - t.connect(username=user, password=pw) - sftp = paramiko.SFTPClient.from_transport(t) - args = sys.argv[4:] - for i in range(0, len(args), 2): - local, remote = args[i], args[i + 1] - cur = "" - for p in [p for p in os.path.dirname(remote).split("/") if p]: - cur += "/" + p - try: - sftp.stat(cur) - except IOError: - try: - sftp.mkdir(cur) - except IOError: - pass - sftp.put(local, remote) - print(f"PUT {local} -> {remote}") - t.close() - - -if __name__ == "__main__": - main() diff --git a/deploy/userbase.nacos.yaml b/deploy/userbase.nacos.yaml deleted file mode 100644 index f217d6b..0000000 --- a/deploy/userbase.nacos.yaml +++ /dev/null @@ -1,98 +0,0 @@ -# ============================================================ -# 请在 Nacos 控制台新增此配置(public 命名空间) -# Data ID : userbase.yaml -# Group : USERBASE -# Format : YAML -# 说明: -# - 本文件即应用自身配置。Nacos 解析规则为 ${spring.application.name}.${file-extension}, -# 因 bootstrap.yml 中 name=userbase、file-extension=yaml,故 Data ID 必须是 userbase.yaml。 -# - public 空间下的 common.properties 会作为共享配置优先加载(低优先级), -# 本文件(高优先级)中的同名字段会覆盖 common.properties。 -# - 若 common.properties 已包含 datasource / redis 等公共项,下面这些行可按需删减; -# 保留也无害(应用配置优先级更高,仍以本文件为准)。 -# - 生产启动时 profile=prod,Nacos 还会额外尝试 userbase-prod.yaml(可选,不存在也无妨)。 -# ============================================================ - -server: - port: 8060 - servlet: - # 对外经 caddy 暴露为 http://www.yunhaixingtong.com/userbase - context-path: /userbase - -spring: - mvc: - date-format: yyyy-MM-dd HH:mm:ss - servlet: - multipart: - max-file-size: 50MB - max-request-size: 200MB - jackson: - time-zone: GMT+8 - date-format: yyyy-MM-dd HH:mm:ss - - redis: - host: redis-server - port: 6379 - database: 0 - password: 'wv&WcDYAmLtqTIGM' - timeout: 2000ms - data: - redis: - repositories: - enabled: false - - datasource: - url: jdbc:mysql://mysql8:3306/bsch_userbase?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true - username: root - password: 'CVf^x$sW*b6CGHxh' - driver-class-name: com.mysql.cj.jdbc.Driver - min-idle: 10 - max-active: 30 - - jpa: - database: MySQL - show-sql: false - hibernate: - ddl-auto: update - database-platform: org.hibernate.dialect.MySQL5InnoDBDialect - properties: - hibernate.order_by.default_null_ordering: last - hibernate: - dialect: org.hibernate.dialect.MySQL5InnoDBDialect - open-in-view: true - - rabbitmq: - host: rabbitmq - port: 5672 - username: admin - password: 'JdU29I#Q2E4yXoUl' - listener: - direct: - auto-startup: false - simple: - auto-startup: false - -# 单点登录 / 应用间签名鉴权(基础平台 yh-auth / yh-app-auth) -yh: - sso: - server-url-prefix: http://sso.yunhaixingtong.com - client-host-url: http://www.yunhaixingtong.com/userbase - allow-headers: all - allow-origins: all - url-pattern: /api/* - mobi-api-pattern: /mobiapi/* - app-auth: - enabled: true - -ADMIN_TAG_ID: 290 - -# 上传文件落容器卷,compose 里挂到宿主机 ./upload-data -FILE_PATH: /data/upload -FILE_WEB_PATH: http://www.yunhaixingtong.com/userbase/upload/ -ZIYUAN_WEB_PATH_HTTP: http://base.bestsch.com/ziyuanku/file/ -UPLOAD_WEB_PATH_HTTP: http://www.yunhaixingtong.com/userbase/upload/file/ -ORC_SERVICE_URL: http://oa.bestsch.com/OrcService/api/Ocr/Upload - -logging: - level: - root: INFO diff --git a/deploy/verify_db.sh b/deploy/verify_db.sh deleted file mode 100644 index 89711fa..0000000 --- a/deploy/verify_db.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -set -e -echo "== app startup DDL/schema hints ==" -docker logs userbase-app 2>&1 | grep -iE "alter table|update schema|create table|ddl|column|sys_user" | head -30 || echo "(no ddl lines captured)" - -echo "== datasource config from container ==" -docker exec userbase-app cat /app/config/application-prod.yml 2>/dev/null | grep -iE "url:|username:|password:|jdbc" | sed -E 's/(password:).*/\1 ****/' || echo "(no config)" - -echo "== mysql client available? ==" -which mysql || echo "NO_MYSQL_CLI" diff --git a/deploy/verify_final.sh b/deploy/verify_final.sh deleted file mode 100644 index 9d8bd40..0000000 --- a/deploy/verify_final.sh +++ /dev/null @@ -1,19 +0,0 @@ -set -u -echo "===== 1. Main app JS chunk from SPA =====" -html=$(curl -s -H "Host: www.yunhaixingtong.com" http://127.0.0.1/userbase/) -appjs=$(echo "$html" | grep -oE '/static/js/[A-Za-z0-9_./-]+\.js' | head -1) -echo "app js: $appjs" -curl -s -o /dev/null -w " /userbase${appjs} -> %{http_code}\n" -H "Host: www.yunhaixingtong.com" "http://127.0.0.1/userbase${appjs}" -echo -echo "===== 2. Ensure other sites not regressed (sso / b) =====" -curl -s -o /dev/null -w " sso host / -> %{http_code}\n" -H "Host: sso.yunhaixingtong.com" http://127.0.0.1/ -curl -s -o /dev/null -w " b host / -> %{http_code}\n" -H "Host: www.yunhaixingtong.com" http://127.0.0.1/b/ -echo -echo "===== 3. Caddy listening ports on host =====" -ss -ltnp 2>/dev/null | grep -E ':80 |:443 ' | head -echo -echo "===== 4. Containers status =====" -docker ps --format '{{.Names}} {{.Status}}' | grep -E 'caddy|userbase' -echo -echo "===== 5. userbase-front health (serve index directly) =====" -docker exec userbase-front wget -qO- http://localhost/ 2>/dev/null | head -c 60; echo diff --git a/docker/application-prod.yml b/docker/application-prod.yml index b88f43f..e1caeec 100644 --- a/docker/application-prod.yml +++ b/docker/application-prod.yml @@ -2,7 +2,7 @@ server: port: 8060 servlet: - # 对外经 caddy 暴露为 http://www.yunhaixingtong.com/userbase + # 对外经 caddy 暴露为 http://base.yunhaixingtong.com/userbase context-path: /userbase spring: @@ -61,8 +61,8 @@ spring: # 单点登录 / 应用间签名鉴权(基础平台 yh-auth / yh-app-auth) yh: sso: - server-url-prefix: http://sso.yunhaixingtong.com - client-host-url: http://www.yunhaixingtong.com/userbase + server-url-prefix: http://sso.yunhaixingtong.com/cas/ + client-host-url: http://base.yunhaixingtong.com/userbase allow-headers: all allow-origins: all url-pattern: /api/* @@ -74,10 +74,8 @@ ADMIN_TAG_ID: 290 # 上传文件落容器卷,compose 里挂到宿主机 ./upload-data FILE_PATH: /data/upload -FILE_WEB_PATH: http://www.yunhaixingtong.com/userbase/upload/ -ZIYUAN_WEB_PATH_HTTP: http://base.bestsch.com/ziyuanku/file/ -UPLOAD_WEB_PATH_HTTP: http://www.yunhaixingtong.com/userbase/upload/file/ -ORC_SERVICE_URL: http://oa.bestsch.com/OrcService/api/Ocr/Upload +FILE_WEB_PATH: http://base.yunhaixingtong.com/userbase/upload/ +UPLOAD_WEB_PATH_HTTP: http://base.yunhaixingtong.com/userbase/upload/file/ logging: level: diff --git a/src/main/java/com/bestsch/openapi/UserSysRole.java b/src/main/java/com/bestsch/openapi/UserSysRole.java deleted file mode 100644 index ff983b2..0000000 --- a/src/main/java/com/bestsch/openapi/UserSysRole.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.bestsch.openapi; - -/** - * 迁移兼容 shim:原 bestsch 开放接口的"当前角色"载体。 - * 仅保留 {@code Operator.of(...)} 所需的访问器,避免批量改动业务代码。 - * 后续可替换为 UserBase 自有角色模型。 - */ -public class UserSysRole { - - private Integer userId; - private Integer schId; - private Integer roleId; - - public Integer getUserId() { - return userId; - } - - public void setUserId(Integer userId) { - this.userId = userId; - } - - public Integer getSchId() { - return schId; - } - - public void setSchId(Integer schId) { - this.schId = schId; - } - - public Integer getRoleId() { - return roleId; - } - - public void setRoleId(Integer roleId) { - this.roleId = roleId; - } -} diff --git a/src/main/java/com/bestsch/utils/DException.java b/src/main/java/com/bestsch/utils/DException.java deleted file mode 100644 index a1ed5e9..0000000 --- a/src/main/java/com/bestsch/utils/DException.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.bestsch.utils; - -/** - * 迁移兼容 shim:原 bestsch 框架的业务异常类。 - * UserBase 大量业务代码依赖此异常,迁移到基础平台期间保留原包名与常用构造签名,避免批量改动。 - * 后续可统一替换为 UserBase 自有异常类型。 - */ -public class DException extends RuntimeException { - - public DException(String message) { - super(message); - } - - public DException(String message, Throwable cause) { - super(message, cause); - } - - /** 兼容历史调用方携带错误码的场景 */ - public DException(String message, int code) { - super(message); - } -} diff --git a/src/main/java/com/yunhai/userbase/controller/api/AppSettingsController.java b/src/main/java/com/yunhai/userbase/controller/api/AppSettingsController.java index bf43b57..4681960 100644 --- a/src/main/java/com/yunhai/userbase/controller/api/AppSettingsController.java +++ b/src/main/java/com/yunhai/userbase/controller/api/AppSettingsController.java @@ -2,15 +2,11 @@ package com.yunhai.userbase.controller.api; import com.bestsch.utils.DException; import com.yunhai.userbase.common.annotation.OperationLog; -import com.yunhai.userbase.common.context.UserContext; import com.yunhai.userbase.common.validation.ValidationGroups; import com.yunhai.userbase.config.Config; import com.yunhai.userbase.entity.ApplicationInfo; -import com.yunhai.userbase.enums.BookType; -import com.yunhai.userbase.model.BaseDict; import com.yunhai.userbase.model.BasePageQuery; import com.yunhai.userbase.model.BasePageResult; -import com.yunhai.userbase.model.Operator; import com.yunhai.userbase.model.appauthz.AppAuthzCategoryVo; import com.yunhai.userbase.model.appcategory.AppCategoryQuery; import com.yunhai.userbase.model.appcategory.AppCategoryRequest; @@ -26,27 +22,13 @@ import com.yunhai.userbase.service.IAppCategoryService; import com.yunhai.userbase.service.IApplicationInfoService; import com.yunhai.userbase.service.IAppModuleService; import com.yunhai.userbase.service.SignKeyCacheService; -import com.yunhai.userbase.utils.DicUtil; import com.yunhai.userbase.utils.PageUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.tomcat.util.http.fileupload.util.Streams; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Sort; import org.springframework.data.web.SortDefault; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; -import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.io.BufferedOutputStream; -import java.io.InputStream; -import java.net.URLEncoder; -import java.util.Enumeration; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; diff --git a/src/main/java/com/yunhai/userbase/model/Operator.java b/src/main/java/com/yunhai/userbase/model/Operator.java deleted file mode 100644 index 3f90288..0000000 --- a/src/main/java/com/yunhai/userbase/model/Operator.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.yunhai.userbase.model; - -import com.bestsch.openapi.UserSysRole; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.Date; - -/** - *功能描述 :操作人信息 - * @author chenx - * @date 2026/1/5 13:31 - * @description - */ -@AllArgsConstructor -@NoArgsConstructor -@Data -public class Operator { - private Integer userId; - private Integer schoolSid; - private Integer roleId; - private Date createTime=new Date(); - - public static Operator of(UserSysRole curRole){ - return new Operator(curRole.getUserId(),curRole.getSchId(),curRole.getRoleId(),new Date()); - } - -} diff --git a/src/main/resources/bootstrap.yml b/src/main/resources/bootstrap.yml index d5721ed..c1fd007 100644 --- a/src/main/resources/bootstrap.yml +++ b/src/main/resources/bootstrap.yml @@ -15,8 +15,8 @@ spring: # 默认指向 prod namespace UUID,避免本地误开时连到空的 dev 命名空间 # CI 用 SPRING_CLOUD_NACOS_CONFIG_NAMESPACE 覆盖(注意:NACOS_NAMESPACE 这个 env 名不生效,必须用 SPRING_CLOUD_NACOS_CONFIG_NAMESPACE) namespace: ${SPRING_CLOUD_NACOS_CONFIG_NAMESPACE:6196f0de-a28d-4894-8f10-e2982b57c6bc} - # 主配置 group:userbase.yaml / application-infra.yaml 同组 - group: DEFAULT_GROUP + # 主配置 group:userbase.yaml 在 USERBASE group(与下方 shared-configs 的 DEFAULT_GROUP 不同组,各自指定) + group: USERBASE # 配置文件格式;最终主配置 dataId = ${spring.application.name}.${file-extension} = userbase.yaml file-extension: yaml encode: UTF-8