Files
asd-backend/scripts/expire-paid-user.sh

215 lines
6.4 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.
#!/bin/bash
# scripts/expire-paid-user.sh
# 通过 SSH 在服务器上执行 SQL使用户的付费时间过期仅修改 paid_expires_at
# 与 set-paid-user.sh --expires 的区别:此脚本专用于"过期"场景,
# 保持 is_paid=true用户仍标记为付费仅将 paid_expires_at 设到过去。
#
# 使用 config/development.toml 中的数据库配置
# 密码由服务器的 1panel/环境变量提供,无需手动传入
#
# 用法:
# ./scripts/expire-paid-user.sh <user_id>
# ./scripts/expire-paid-user.sh <user_id> --date YYYY-MM-DD
#
# 示例:
# ./scripts/expire-paid-user.sh 1 # 设为昨天到期(立即过期)
# ./scripts/expire-paid-user.sh 1 --date 2025-01-01 # 设为指定日期到期(已过期)
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
CONFIG_DIR="$PROJECT_ROOT/config"
ENV_FILE="$PROJECT_ROOT/.env"
get_ssh_host() {
grep '^SSH_SERVER=' "$ENV_FILE" 2>/dev/null | head -1 | cut -d'=' -f2- | tr -d '"' | tr -d "'" | xargs
}
usage() {
echo "用法: $0 <user_id> [--date YYYY-MM-DD]"
echo ""
echo " user_id 用户 ID必填"
echo " --date DATE 指定过期日期(默认: 昨天)"
echo ""
echo "说明:"
echo " 将用户 paid_expires_at 设到过去日期is_paid 保持 true"
echo " 用户的 is_paid_active 会变为 false"
echo ""
echo "数据源:"
echo " SSH 服务器: .env 中 SSH_SERVER"
echo " 数据库配置: config/development.toml (host/port/dbname)"
echo " 密码: 服务器上的环境变量/1panel 自动提供"
echo ""
echo "示例:"
echo " $0 1 # 设为昨天到期"
echo " $0 1 --date 2025-01-01 # 设为 2025-01-01"
exit 0
}
validate_date() {
local date="$1"
if [[ ! "$date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
echo "错误: 日期格式无效,请使用 YYYY-MM-DD"
exit 1
fi
}
# 解析 toml 文件中的 database_url
parse_toml_db_url() {
local file="$1"
grep '^database_url' "$file" 2>/dev/null | head -1 | sed 's/^database_url *= *["'"'"']//' | sed 's/["'"'"']*$//' | tr -d ' '
}
# 解析 postgres:// URL
parse_db_url() {
local db_url="$1"
local rest="${db_url#postgres://}"
DB_USER="${rest%%:*}"
local host_port="${rest##*@}"
host_port="${host_port%%/*}"
if [[ "$host_port" == *:* ]]; then
DB_HOST="${host_port%%:*}"
DB_PORT="${host_port##*:}"
else
DB_HOST="$host_port"
DB_PORT="5432"
fi
DB_NAME="${rest##*/}"
DB_NAME="${DB_NAME%%\?*}"
}
info() { echo "[INFO] $1"; }
warn() { echo "[WARN] $1"; }
error() { echo "[ERROR] $1" >&2; }
step() { echo ""; echo ">>> 第 $1 步: $2"; echo ""; }
# 在服务器上通过 docker exec 执行 SQL
exec_sql() {
local sql="$1"
ssh -o BatchMode=yes -o StrictHostKeyChecking=no -o ConnectTimeout=5 "$SSH_HOST" \
"cd /root/rust/rust_backend_dev 2>/dev/null || true; docker exec 1Panel-postgresql-FtMo psql -U ${DB_USER} -d ${DB_NAME} -c \"${sql}\"" 2>&1
}
main() {
if [[ $# -lt 1 ]]; then
usage
fi
USER_ID="$1"
shift
if [[ ! "$USER_ID" =~ ^[0-9]+$ ]]; then
error "user_id 必须是数字"
exit 1
fi
EXPIRES_DATE=""
while [[ $# -gt 0 ]]; do
case "$1" in
--date)
EXPIRES_DATE="$2"
validate_date "$EXPIRES_DATE"
shift 2
;;
-h|--help) usage ;;
*) error "未知参数: $1"; usage ;;
esac
done
# 默认过期日期:昨天
if [[ -z "$EXPIRES_DATE" ]]; then
if date --version 2>/dev/null | grep -q GNU; then
EXPIRES_DATE=$(date -d "yesterday" "+%Y-%m-%d")
else
EXPIRES_DATE=$(date -v -1d "+%Y-%m-%d")
fi
fi
# ===== Step 1: 读取配置 =====
step 1 "读取配置"
SSH_HOST="$(get_ssh_host)"
if [[ -z "$SSH_HOST" ]]; then
error "未找到 SSH_SERVER 配置,请检查 .env 文件"
exit 1
fi
info "SSH 服务器: $SSH_HOST"
CONFIG_FILE="$CONFIG_DIR/development.toml"
if [[ ! -f "$CONFIG_FILE" ]]; then
error "配置文件不存在: $CONFIG_FILE"
exit 1
fi
TOML_DB_URL="$(parse_toml_db_url "$CONFIG_FILE")"
if [[ -z "$TOML_DB_URL" ]]; then
error "development.toml 中未找到 database_url"
exit 1
fi
parse_db_url "$TOML_DB_URL"
info "数据库: ${DB_USER}@${DB_HOST}:${DB_PORT}/${DB_NAME}"
# ===== Step 2: 构造 SQL =====
step 2 "构造 SQL 语句"
SQL="UPDATE users SET is_paid = true, paid_expires_at = '${EXPIRES_DATE}'::date WHERE id = ${USER_ID};"
info "设置过期日期: $EXPIRES_DATE"
echo " SQL: $SQL"
# ===== Step 3: 执行 SQL =====
step 3 "通过 SSH 在服务器上执行 SQL"
info "连接 $SSH_HOST (超时 15s) ..."
SQL_RAW=$(exec_sql "$SQL")
SQL_EXIT=$?
if [[ $SQL_EXIT -ne 0 ]]; then
error "执行失败(退出码: $SQL_EXIT"
echo "$SQL_RAW" | sed 's/^/ /' >&2
exit 1
fi
echo "$SQL_RAW"
if echo "$SQL_RAW" | grep -q "UPDATE [01]"; then
ROWS=$(echo "$SQL_RAW" | grep "UPDATE" | grep -oP '\d+' | head -1)
if [[ "${ROWS:-0}" == "0" ]]; then
warn "未更新任何行(用户 ID $USER_ID 可能不存在)"
else
info "成功更新 ${ROWS}"
fi
else
warn "无法确认更新结果"
fi
# ===== Step 4: 验证结果 =====
step 4 "查询用户信息确认"
QUERY_SQL="SELECT id, name, phone, type, is_paid, is_admin, paid_expires_at FROM users WHERE id = ${USER_ID};"
info "SQL: $QUERY_SQL"
QUERY_RAW=$(exec_sql "$QUERY_SQL")
QUERY_EXIT=$?
if [[ $QUERY_EXIT -ne 0 ]]; then
warn "查询失败(退出码: $QUERY_EXIT),但数据更新已执行"
echo "$QUERY_RAW" | sed 's/^/ /'
else
echo "$QUERY_RAW"
fi
# ===== 总结 =====
echo ""
echo "============================================"
echo " 执行完成"
echo "============================================"
echo " 用户 ID: $USER_ID"
echo " 过期日期: $EXPIRES_DATE"
echo " 服务器: $SSH_HOST"
echo "============================================"
echo ""
echo "提示: is_paid 保持 trueis_paid_active 会变为 false付费已过期"
}
main "$@"