#!/bin/bash # 权限码一致性校验脚本 # 校验后端/数据库/前端/canonical基线四维权限码差异 # 支持多段权限码(如 approval.index.batch.transfer.ALL)和连字符(如 system.api-key.create.ALL) set -e echo "=== 权限码一致性校验 ===" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" BACKEND_PERMS="$SCRIPT_DIR/.permission_check_backend.txt" FRONTEND_PERMS="$SCRIPT_DIR/.permission_check_frontend.txt" DB_PERMS="$SCRIPT_DIR/.permission_check_db.txt" CANONICAL_PERMS="$SCRIPT_DIR/.permission_check_canonical.txt" DIFF_REPORT="$SCRIPT_DIR/permission_diff_report.md" # 清理旧文件 rm -f "$BACKEND_PERMS" "$FRONTEND_PERMS" "$DB_PERMS" "$CANONICAL_PERMS" "$DIFF_REPORT" echo "0. 加载Canonical 90基线..." CANONICAL_FILE="$PROJECT_DIR/src/test/resources/permission/canonical-permissions-90.txt" if [ -f "$CANONICAL_FILE" ]; then grep -v '^#' "$CANONICAL_FILE" | grep -v '^$' | sort -u > "$CANONICAL_PERMS" || true fi CANONICAL_COUNT=$(wc -l < "$CANONICAL_PERMS") echo " Canonical基线权限码数量: $CANONICAL_COUNT" echo "1. 提取前端权限码..." # 提取前端权限码(从roles.ts) # 支持多段格式: module.resource[.subresource].operation[.suboperation].dataScope # 例如: approval.index.batch.transfer.ALL (5段), dashboard.chart.realtime.ALL (4段) grep -oE "'[a-z]+(-[a-z]+)*\.[a-z]+(-[a-z]+)*(\.[a-z]+(-[a-z]+)*)*\.[A-Z]+'" "$PROJECT_DIR/frontend/admin/src/auth/roles.ts" 2>/dev/null | \ sed "s/'//g" | sort -u > "$FRONTEND_PERMS" || true # 也支持双引号 grep -oE '"[a-z]+(-[a-z]+)*\.[a-z]+(-[a-z]+)*(\.[a-z]+(-[a-z]+)*)*\.[A-Z]+"' "$PROJECT_DIR/frontend/admin/src/auth/roles.ts" 2>/dev/null | \ sed 's/"//g' >> "$FRONTEND_PERMS" || true sort -u "$FRONTEND_PERMS" -o "$FRONTEND_PERMS" FRONTEND_COUNT=$(wc -l < "$FRONTEND_PERMS") echo " 前端权限码数量: $FRONTEND_COUNT" echo "2. 提取数据库权限码..." # 提取数据库权限码(从SQL迁移脚本) # 支持多段格式: module.resource[.subresource].operation[.suboperation].dataScope grep -oE "'[a-z]+(-[a-z]+)*\.[a-z]+(-[a-z]+)*(\.[a-z]+(-[a-z]+)*)*\.[A-Z]+'" "$PROJECT_DIR/src/main/resources/db/migration/V26__Seed_roles_permissions.sql" 2>/dev/null | \ sed "s/'//g" > "$DB_PERMS" || true # 从其他迁移脚本补充 for sql in "$PROJECT_DIR/src/main/resources/db/migration"/V*.sql; do grep -oE "'[a-z]+(-[a-z]+)*\.[a-z]+(-[a-z]+)*(\.[a-z]+(-[a-z]+)*)*\.[A-Z]+'" "$sql" 2>/dev/null | sed "s/'//g" >> "$DB_PERMS" || true done sort -u "$DB_PERMS" -o "$DB_PERMS" DB_COUNT=$(wc -l < "$DB_PERMS") echo " 数据库权限码总数: $DB_COUNT" echo "3. 提取后端权限码..." # 提取后端权限码(从RequirePermission注解) # 支持直接字符串: @RequirePermission("approval.index.view.ALL") # 支持多段格式: module.resource[.subresource].operation[.suboperation].dataScope grep -r "RequirePermission" "$PROJECT_DIR/src/main/java" --include="*.java" 2>/dev/null | \ grep -oE '"[a-z]+(-[a-z]+)*\.[a-z]+(-[a-z]+)*(\.[a-z]+(-[a-z]+)*)*\.[A-Z]+"' | sed 's/"//g' >> "$BACKEND_PERMS" || true # 支持常量引用: @RequirePermission(PERM_XXX) - 需要进一步处理常量定义 # 找出所有常量定义 grep -r "private static final String PERM_" "$PROJECT_DIR/src/main/java" --include="*.java" 2>/dev/null | \ grep -oE 'PERM_[A-Z_]+ = "[a-z]+(-[a-z]+)*\.[a-z]+(-[a-z]+)*(\.[a-z]+(-[a-z]+)*)*\.[A-Z]+"' | \ sed 's/.*= *"/"/g' | sed 's/"//g' >> "$BACKEND_PERMS" || true sort -u "$BACKEND_PERMS" -o "$BACKEND_PERMS" BACKEND_COUNT=$(wc -l < "$BACKEND_PERMS") echo " 后端权限码数量: $BACKEND_COUNT" echo "" echo "4. 生成差异报告..." # 计算差异 comm -23 "$FRONTEND_PERMS" "$CANONICAL_PERMS" > "$SCRIPT_DIR/.frontend_only.txt" || true comm -23 "$DB_PERMS" "$CANONICAL_PERMS" > "$SCRIPT_DIR/.db_only.txt" || true comm -23 "$BACKEND_PERMS" "$CANONICAL_PERMS" > "$SCRIPT_DIR/.backend_only.txt" || true comm -23 "$CANONICAL_PERMS" "$FRONTEND_PERMS" > "$SCRIPT_DIR/.canonical_not_in_frontend.txt" || true comm -23 "$CANONICAL_PERMS" "$DB_PERMS" > "$SCRIPT_DIR/.canonical_not_in_db.txt" || true comm -23 "$CANONICAL_PERMS" "$BACKEND_PERMS" > "$SCRIPT_DIR/.canonical_not_in_backend.txt" || true FRONTEND_ONLY=$(wc -l < "$SCRIPT_DIR/.frontend_only.txt") DB_ONLY=$(wc -l < "$SCRIPT_DIR/.db_only.txt") BACKEND_ONLY=$(wc -l < "$SCRIPT_DIR/.backend_only.txt") CANONICAL_NOT_IN_FRONTEND=$(wc -l < "$SCRIPT_DIR/.canonical_not_in_frontend.txt") CANONICAL_NOT_IN_DB=$(wc -l < "$SCRIPT_DIR/.canonical_not_in_db.txt") CANONICAL_NOT_IN_BACKEND=$(wc -l < "$SCRIPT_DIR/.canonical_not_in_backend.txt") # 写入报告 cat > "$DIFF_REPORT" << EOF # 权限码一致性校验报告 生成时间: $(date '+%Y-%m-%d %H:%M:%S') ## 四维统计 | 来源 | 权限码数量 | |------|------------| | Canonical基线 | $CANONICAL_COUNT | | 前端 | $FRONTEND_COUNT | | 数据库 | $DB_COUNT | | 后端 | $BACKEND_COUNT | ## Canonical基线覆盖率 | 维度 | 缺失数量 | 说明 | |------|----------|------| | 前端缺失 | $CANONICAL_NOT_IN_FRONTEND | Canonical基线在前端未定义 | | 数据库缺失 | $CANONICAL_NOT_IN_DB | Canonical基线在数据库未导入 | | 后端缺失 | $CANONICAL_NOT_IN_BACKEND | Canonical基线在后端未使用 | ## 额外权限码分析(不在Canonical基线中) ### 前端独有权限码 (不在Canonical基线中): $FRONTEND_ONLY EOF if [ $FRONTEND_ONLY -gt 0 ]; then echo "" >> "$DIFF_REPORT" cat "$SCRIPT_DIR/.frontend_only.txt" >> "$DIFF_REPORT" echo "" >> "$DIFF_REPORT" fi cat >> "$DIFF_REPORT" << EOF ### 数据库独有权限码 (不在Canonical基线中): $DB_ONLY EOF if [ $DB_ONLY -gt 0 ]; then echo "" >> "$DIFF_REPORT" cat "$SCRIPT_DIR/.db_only.txt" >> "$DIFF_REPORT" echo "" >> "$DIFF_REPORT" fi cat >> "$DIFF_REPORT" << EOF ### 后端独有权限码 (不在Canonical基线中): $BACKEND_ONLY EOF if [ $BACKEND_ONLY -gt 0 ]; then echo "" >> "$DIFF_REPORT" cat "$SCRIPT_DIR/.backend_only.txt" >> "$DIFF_REPORT" echo "" >> "$DIFF_REPORT" fi cat >> "$DIFF_REPORT" << EOF ## Canonical基线缺失项 ### 前端未覆盖Canonical基线 ($CANONICAL_NOT_IN_FRONTEND) EOF if [ $CANONICAL_NOT_IN_FRONTEND -gt 0 ]; then echo "" >> "$DIFF_REPORT" cat "$SCRIPT_DIR/.canonical_not_in_frontend.txt" >> "$DIFF_REPORT" echo "" >> "$DIFF_REPORT" fi cat >> "$DIFF_REPORT" << EOF ### 数据库未导入Canonical基线 ($CANONICAL_NOT_IN_DB) EOF if [ $CANONICAL_NOT_IN_DB -gt 0 ]; then echo "" >> "$DIFF_REPORT" cat "$SCRIPT_DIR/.canonical_not_in_db.txt" >> "$DIFF_REPORT" echo "" >> "$DIFF_REPORT" fi cat >> "$DIFF_REPORT" << EOF ### 后端未实现Canonical基线 ($CANONICAL_NOT_IN_BACKEND) EOF if [ $CANONICAL_NOT_IN_BACKEND -gt 0 ]; then echo "" >> "$DIFF_REPORT" cat "$SCRIPT_DIR/.canonical_not_in_backend.txt" >> "$DIFF_REPORT" echo "" >> "$DIFF_REPORT" fi # 判断是否通过 - 以Canonical基线为基准 if [ $CANONICAL_NOT_IN_FRONTEND -eq 0 ] && [ $CANONICAL_NOT_IN_DB -eq 0 ] && [ $CANONICAL_NOT_IN_BACKEND -eq 0 ]; then echo "" echo "✅ 权限码一致性校验通过!Canonical基线已完整覆盖。" RESULT=0 else echo "" echo "❌ 权限码一致性校验未通过,请查看差异报告: $DIFF_REPORT" echo " Canonical基线缺失 - 前端: $CANONICAL_NOT_IN_FRONTEND" echo " Canonical基线缺失 - 数据库: $CANONICAL_NOT_IN_DB" echo " Canonical基线缺失 - 后端: $CANONICAL_NOT_IN_BACKEND" RESULT=1 fi # 清理临时文件 rm -f "$SCRIPT_DIR/.frontend_only.txt" "$SCRIPT_DIR/.db_only.txt" "$SCRIPT_DIR/.backend_only.txt" rm -f "$SCRIPT_DIR/.canonical_not_in_frontend.txt" "$SCRIPT_DIR/.canonical_not_in_db.txt" "$SCRIPT_DIR/.canonical_not_in_backend.txt" exit $RESULT