#!/bin/bash # RBAC E2E 测试脚本 # 测试:超级管理员登录、角色字段持久化、权限策略执行 BASE_URL="http://localhost:8888/api/v1" TIMESTAMP=$(date +%s) PASS=0 FAIL=0 log_step() { echo -e "\n\033[36m--- Step $1: $2 ---\033[0m" } log_success() { echo -e "\033[32m[PASS]\033[0m $1" PASS=$((PASS + 1)) } log_error() { echo -e "\033[31m[FAIL]\033[0m $1" FAIL=$((FAIL + 1)) } extract_value() { echo "$1" | grep -o "\"$2\":\"[^\"]*\"" | head -1 | sed 's/"'"$2"'"://' | sed 's/^"//' | sed 's/"$//' } extract_int() { echo "$1" | grep -o "\"$2\":[^,}]*" | head -1 | sed 's/"'"$2"'"://' | tr -d ' ' } # ============================ # Part 1: 超级管理员登录 # ============================ log_step "1" "Super admin login (admin@system.local / admin123)" LOGIN_RESULT=$(curl -s -X POST ${BASE_URL}/login \ -H "Content-Type: application/json" \ -d '{"email":"admin@system.local","password":"admin123"}') ADMIN_TOKEN=$(extract_value "$LOGIN_RESULT" "token") LOGIN_CODE=$(extract_int "$LOGIN_RESULT" "code") if [ "$LOGIN_CODE" = "200" ] && [ -n "$ADMIN_TOKEN" ]; then log_success "Super admin login success" else log_error "Super admin login failed: $LOGIN_RESULT" echo "=== RESULT: $PASS passed, $FAIL failed ===" exit 1 fi # ============================ # Part 2: 验证 JWT 包含 role claim # ============================ log_step "2" "Verify JWT contains role claim" JWT_PAYLOAD=$(echo "$ADMIN_TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null) JWT_ROLE=$(echo "$JWT_PAYLOAD" | grep -o '"role":"[^"]*"' | head -1 | sed 's/"role":"//' | sed 's/"$//') if [ "$JWT_ROLE" = "super_admin" ]; then log_success "JWT role claim = super_admin" else log_error "JWT role claim expected 'super_admin', got '$JWT_ROLE'" fi # ============================ # Part 3: 创建带角色的用户(admin 管理员用户) # ============================ log_step "3" "Create user with role=admin via super_admin" CREATE_ADMIN_RESULT=$(curl -s -X POST ${BASE_URL}/user \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${ADMIN_TOKEN}" \ -d "{\"username\":\"rbac_admin_${TIMESTAMP}\",\"email\":\"rbac_admin_${TIMESTAMP}@test.com\",\"password\":\"password123\",\"role\":\"admin\",\"remark\":\"RBAC test admin\"}") ADMIN_USER_ID=$(extract_int "$CREATE_ADMIN_RESULT" "id") CREATED_ROLE=$(extract_value "$CREATE_ADMIN_RESULT" "role") CREATED_SOURCE=$(extract_value "$CREATE_ADMIN_RESULT" "source") CREATED_REMARK=$(extract_value "$CREATE_ADMIN_RESULT" "remark") if [ -n "$ADMIN_USER_ID" ] && [ "$CREATED_ROLE" = "admin" ]; then log_success "Created admin user (id=$ADMIN_USER_ID, role=$CREATED_ROLE)" else log_error "Create admin user failed: $CREATE_ADMIN_RESULT" fi if [ "$CREATED_SOURCE" = "manual" ]; then log_success "Source = manual (correct for admin-created user)" else log_error "Source expected 'manual', got '$CREATED_SOURCE'" fi if [ "$CREATED_REMARK" = "RBAC test admin" ]; then log_success "Remark preserved correctly" else log_error "Remark expected 'RBAC test admin', got '$CREATED_REMARK'" fi # ============================ # Part 4: 创建普通用户 # ============================ log_step "4" "Create user with default role (user)" CREATE_USER_RESULT=$(curl -s -X POST ${BASE_URL}/user \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${ADMIN_TOKEN}" \ -d "{\"username\":\"rbac_user_${TIMESTAMP}\",\"email\":\"rbac_user_${TIMESTAMP}@test.com\",\"password\":\"password123\"}") NORMAL_USER_ID=$(extract_int "$CREATE_USER_RESULT" "id") NORMAL_ROLE=$(extract_value "$CREATE_USER_RESULT" "role") if [ -n "$NORMAL_USER_ID" ] && [ "$NORMAL_ROLE" = "user" ]; then log_success "Created normal user (id=$NORMAL_USER_ID, role=user)" else log_error "Create normal user failed: $CREATE_USER_RESULT" fi # ============================ # Part 5: 注册用户验证默认 role 和 source # ============================ log_step "5" "Register new user — verify role=user, source=register" REGISTER_RESULT=$(curl -s -X POST ${BASE_URL}/register \ -H "Content-Type: application/json" \ -d "{\"username\":\"rbac_reg_${TIMESTAMP}\",\"email\":\"rbac_reg_${TIMESTAMP}@test.com\",\"password\":\"password123\"}") REG_ROLE=$(extract_value "$REGISTER_RESULT" "role") REG_SOURCE=$(extract_value "$REGISTER_RESULT" "source") if [ "$REG_ROLE" = "user" ]; then log_success "Registered user role = user" else log_error "Registered user role expected 'user', got '$REG_ROLE'" fi if [ "$REG_SOURCE" = "register" ]; then log_success "Registered user source = register" else log_error "Registered user source expected 'register', got '$REG_SOURCE'" fi # ============================ # Part 6: 普通用户登录 — 验证受限访问 # ============================ log_step "6" "Normal user login" NORMAL_LOGIN=$(curl -s -X POST ${BASE_URL}/login \ -H "Content-Type: application/json" \ -d "{\"email\":\"rbac_user_${TIMESTAMP}@test.com\",\"password\":\"password123\"}") USER_TOKEN=$(extract_value "$NORMAL_LOGIN" "token") NORMAL_LOGIN_CODE=$(extract_int "$NORMAL_LOGIN" "code") if [ "$NORMAL_LOGIN_CODE" = "200" ] && [ -n "$USER_TOKEN" ]; then log_success "Normal user login success" else log_error "Normal user login failed: $NORMAL_LOGIN" fi # ============================ # Part 7: 普通用户 GET /users — 应该 403 # ============================ log_step "7" "Normal user GET /users — expect 403" USER_LIST_RESULT=$(curl -s -o /dev/null -w "%{http_code}" -X GET "${BASE_URL}/users?page=1&pageSize=10" \ -H "Authorization: Bearer ${USER_TOKEN}") if [ "$USER_LIST_RESULT" = "403" ]; then log_success "GET /users returned 403 for role=user" else log_error "GET /users expected 403, got $USER_LIST_RESULT" fi # ============================ # Part 8: 普通用户 POST /user — 应该 403 # ============================ log_step "8" "Normal user POST /user — expect 403" USER_CREATE_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST ${BASE_URL}/user \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${USER_TOKEN}" \ -d '{"username":"hacker","email":"hacker@test.com","password":"password123"}') if [ "$USER_CREATE_CODE" = "403" ]; then log_success "POST /user returned 403 for role=user" else log_error "POST /user expected 403, got $USER_CREATE_CODE" fi # ============================ # Part 9: 普通用户 DELETE /user/:id — 应该 403 # ============================ log_step "9" "Normal user DELETE /user/:id — expect 403" USER_DELETE_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE "${BASE_URL}/user/${NORMAL_USER_ID}" \ -H "Authorization: Bearer ${USER_TOKEN}") if [ "$USER_DELETE_CODE" = "403" ]; then log_success "DELETE /user/:id returned 403 for role=user" else log_error "DELETE /user/:id expected 403, got $USER_DELETE_CODE" fi # ============================ # Part 10: 普通用户 GET /profile/me — 应该 200 # ============================ log_step "10" "Normal user GET /profile/me — expect 200" PROFILE_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X GET "${BASE_URL}/profile/me" \ -H "Authorization: Bearer ${USER_TOKEN}") if [ "$PROFILE_CODE" = "200" ]; then log_success "GET /profile/me returned 200 for role=user" else log_error "GET /profile/me expected 200, got $PROFILE_CODE" fi # ============================ # Part 11: 普通用户 GET /dashboard/stats — 应该 200 # ============================ log_step "11" "Normal user GET /dashboard/stats — expect 200" DASHBOARD_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X GET "${BASE_URL}/dashboard/stats" \ -H "Authorization: Bearer ${USER_TOKEN}") if [ "$DASHBOARD_CODE" = "200" ]; then log_success "GET /dashboard/stats returned 200 for role=user (inherits guest)" else log_error "GET /dashboard/stats expected 200, got $DASHBOARD_CODE" fi # ============================ # Part 12: admin 用户登录 — 验证管理权限 # ============================ log_step "12" "Admin user login" ADMIN_USER_LOGIN=$(curl -s -X POST ${BASE_URL}/login \ -H "Content-Type: application/json" \ -d "{\"email\":\"rbac_admin_${TIMESTAMP}@test.com\",\"password\":\"password123\"}") ADMIN_USER_TOKEN=$(extract_value "$ADMIN_USER_LOGIN" "token") if [ -n "$ADMIN_USER_TOKEN" ]; then log_success "Admin user login success" else log_error "Admin user login failed" fi # ============================ # Part 13: admin 用户 GET /users — 应该 200 # ============================ log_step "13" "Admin user GET /users — expect 200" ADMIN_LIST_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X GET "${BASE_URL}/users?page=1&pageSize=10" \ -H "Authorization: Bearer ${ADMIN_USER_TOKEN}") if [ "$ADMIN_LIST_CODE" = "200" ]; then log_success "GET /users returned 200 for role=admin" else log_error "GET /users expected 200, got $ADMIN_LIST_CODE" fi # ============================ # Part 14: admin 用户 DELETE /user/:id — 应该 403 (仅 super_admin 可删除) # ============================ log_step "14" "Admin user DELETE /user/:id — expect 403" ADMIN_DELETE_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE "${BASE_URL}/user/${NORMAL_USER_ID}" \ -H "Authorization: Bearer ${ADMIN_USER_TOKEN}") if [ "$ADMIN_DELETE_CODE" = "403" ]; then log_success "DELETE /user/:id returned 403 for role=admin" else log_error "DELETE /user/:id expected 403, got $ADMIN_DELETE_CODE" fi # ============================ # Part 15: 更新用户角色 (super_admin 修改 role) # ============================ log_step "15" "Super admin update user role" UPDATE_ROLE_RESULT=$(curl -s -X PUT "${BASE_URL}/user/${NORMAL_USER_ID}" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${ADMIN_TOKEN}" \ -d '{"role":"admin","remark":"promoted to admin"}') UPDATED_ROLE=$(extract_value "$UPDATE_ROLE_RESULT" "role") UPDATED_REMARK=$(extract_value "$UPDATE_ROLE_RESULT" "remark") if [ "$UPDATED_ROLE" = "admin" ]; then log_success "User role updated to admin" else log_error "User role update failed, expected 'admin', got '$UPDATED_ROLE'" fi if [ "$UPDATED_REMARK" = "promoted to admin" ]; then log_success "Remark updated correctly" else log_error "Remark expected 'promoted to admin', got '$UPDATED_REMARK'" fi # ============================ # Part 16: super_admin 用户列表包含 role/source 字段 # ============================ log_step "16" "Verify user list returns role/source fields" LIST_RESULT=$(curl -s -X GET "${BASE_URL}/users?page=1&pageSize=100" \ -H "Authorization: Bearer ${ADMIN_TOKEN}") if echo "$LIST_RESULT" | grep -q '"role"'; then log_success "User list contains 'role' field" else log_error "User list missing 'role' field" fi if echo "$LIST_RESULT" | grep -q '"source"'; then log_success "User list contains 'source' field" else log_error "User list missing 'source' field" fi if echo "$LIST_RESULT" | grep -q '"remark"'; then log_success "User list contains 'remark' field" else log_error "User list missing 'remark' field" fi # ============================ # Part 17: super_admin DELETE — 应该 200 # ============================ log_step "17" "Super admin DELETE /user/:id — expect 200" SA_DELETE_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE "${BASE_URL}/user/${NORMAL_USER_ID}" \ -H "Authorization: Bearer ${ADMIN_TOKEN}") if [ "$SA_DELETE_CODE" = "200" ]; then log_success "DELETE /user/:id returned 200 for super_admin" else log_error "DELETE /user/:id expected 200 for super_admin, got $SA_DELETE_CODE" fi # ============================ # Cleanup: 删除测试创建的 admin 用户 # ============================ log_step "18" "Cleanup — delete test admin user" curl -s -o /dev/null -X DELETE "${BASE_URL}/user/${ADMIN_USER_ID}" \ -H "Authorization: Bearer ${ADMIN_TOKEN}" log_success "Cleanup complete" # 删除注册的测试用户 REG_USER=$(curl -s -X GET "${BASE_URL}/users?page=1&pageSize=100&keyword=rbac_reg_${TIMESTAMP}" \ -H "Authorization: Bearer ${ADMIN_TOKEN}") REG_USER_ID=$(extract_int "$REG_USER" "id") if [ -n "$REG_USER_ID" ]; then curl -s -o /dev/null -X DELETE "${BASE_URL}/user/${REG_USER_ID}" \ -H "Authorization: Bearer ${ADMIN_TOKEN}" fi # ============================ # 结果汇总 # ============================ echo "" echo "=========================================" echo -e " RBAC E2E Test Results" echo -e " \033[32mPassed: $PASS\033[0m | \033[31mFailed: $FAIL\033[0m" echo "=========================================" if [ "$FAIL" -gt 0 ]; then exit 1 fi