#!/bin/bash # Test configuration file # Source this file in test scripts to get consistent configuration # API Configuration export TEST_API_BASE="${TEST_API_BASE:-http://localhost:7130/api}" # Root admin credentials - can be overridden by environment variables export TEST_ADMIN_USERNAME="${TEST_ADMIN_USERNAME:-${ROOT_ADMIN_USERNAME:-admin}}" export TEST_ADMIN_PASSWORD="${TEST_ADMIN_PASSWORD:-${ROOT_ADMIN_PASSWORD:-change-this-password}}" # User test credentials export TEST_USER_EMAIL_PREFIX="${TEST_USER_EMAIL_PREFIX:-testuser_}" # Colors for output export RED='\033[0;31m' export GREEN='\033[0;32m' export YELLOW='\033[1;33m' export BLUE='\033[0;34m' export NC='\033[0m' # No Color # Utility functions print_success() { echo -e "${GREEN}โœ… $1${NC}" } print_fail() { echo -e "${RED}โŒ $1${NC}" track_test_failure } print_info() { echo -e "${YELLOW}$1${NC}" } print_blue() { echo -e "${BLUE}$1${NC}" } # Build admin login JSON without trusting shell string interpolation. build_admin_login_payload() { if command -v jq &> /dev/null; then jq -cn \ --arg username "$1" \ --arg password "$2" \ '{username: $username, password: $password}' else node -e 'process.stdout.write(JSON.stringify({ username: process.argv[1] ?? "", password: process.argv[2] ?? "" }))' "$1" "$2" fi } # Function to login as admin and get token get_admin_token() { # Use JWT admin endpoint local payload payload=$(build_admin_login_payload "$TEST_ADMIN_USERNAME" "$TEST_ADMIN_PASSWORD") local response response=$(curl -s -X POST "$TEST_API_BASE/auth/admin/sessions" \ -H "Content-Type: application/json" \ -d "$payload") if echo "$response" | grep -q '"accessToken"'; then echo "$response" | grep -o '"accessToken":"[^"]*"' | cut -d'"' -f4 else echo "" fi } # Function to get admin API key get_admin_api_key() { # Only use ACCESS_API_KEY environment variable if [ -n "$ACCESS_API_KEY" ]; then echo "$ACCESS_API_KEY" else echo "" fi } # Check if required tools are installed check_requirements() { if ! command -v curl &> /dev/null; then print_fail "curl is required but not installed" exit 1 fi if ! command -v jq &> /dev/null; then print_info "jq is recommended for JSON parsing" fi } # Array to track test tables created declare -a TEST_TABLES_CREATED=() # Array to track test users created declare -a TEST_USERS_CREATED=() # Array to track test buckets created declare -a TEST_BUCKETS_CREATED=() # Function to register a table for cleanup register_test_table() { local table_name=$1 TEST_TABLES_CREATED+=("$table_name") } # Function to register a user for cleanup register_test_user() { local user_email=$1 TEST_USERS_CREATED+=("$user_email") } # Function to register a bucket for cleanup register_test_bucket() { local bucket_name=$1 TEST_BUCKETS_CREATED+=("$bucket_name") } # Function to get the public anon key from the metadata endpoint (requires admin auth) get_anon_key() { local admin_token admin_token=$(get_admin_token) if [ -z "$admin_token" ]; then echo "" return 1 fi local response response=$(curl -s "$TEST_API_BASE/metadata/anon-key" \ -H "Authorization: Bearer $admin_token") echo "$response" | grep -o '"anonKey":"[^"]*"' | cut -d'"' -f4 } # Function to register a user with Better Auth register_user() { local email=$1 local password=$2 local name=${3:-"Test User"} local anon_key="${4:-${ACCESS_ANON_KEY:-$(get_anon_key)}}" # Use JWT registration (requires anon key in Authorization header) curl -s -X POST "$TEST_API_BASE/auth/users" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $anon_key" \ -d "{\"email\":\"$email\",\"password\":\"$password\",\"name\":\"$name\"}" } # Function to login a user with Better Auth login_user() { local email=$1 local password=$2 # Use JWT login curl -s -X POST "$TEST_API_BASE/auth/sessions" \ -H "Content-Type: application/json" \ -d "{\"email\":\"$email\",\"password\":\"$password\"}" } # Function to get user profile with auth token get_user_profile() { local token=$1 # Use JWT profile endpoint curl -s -X GET "$TEST_API_BASE/auth/sessions/current" \ -H "Authorization: Bearer $token" } # Function to delete a table delete_table() { local table_name=$1 local token=$2 curl -s -X DELETE "$TEST_API_BASE/database/tables/$table_name" \ -H "Authorization: Bearer $token" \ -H "Content-Type: application/json" > /dev/null 2>&1 } # Function to cleanup all test data cleanup_test_data() { # Always attempt cleanup, even if some parts fail print_info "๐Ÿงน Cleaning up test data..." local cleanup_failed=0 # Try to get root admin credentials - but continue cleanup even if they fail local admin_token=$(get_admin_token 2>/dev/null || echo "") local api_key=$(get_admin_api_key 2>/dev/null || echo "") if [ -z "$admin_token" ]; then print_info "No admin token available - some cleanup may be limited" fi if [ -z "$api_key" ]; then print_info "No API key available - bucket cleanup may be limited" fi # 1. Delete all registered test tables if [ ${#TEST_TABLES_CREATED[@]} -gt 0 ]; then if [ -n "$admin_token" ]; then print_info "Deleting test tables..." for table in "${TEST_TABLES_CREATED[@]}"; do print_info " - Deleting table: $table" if ! delete_table "$table" "$admin_token"; then echo " โœ— Failed to delete" cleanup_failed=1 else echo " โœ“ Deleted" fi done else print_fail "Cannot delete tables without admin token" print_info "Tables to delete manually:" for table in "${TEST_TABLES_CREATED[@]}"; do echo " - $table" done cleanup_failed=1 fi fi # 2. Delete all test users if [ ${#TEST_USERS_CREATED[@]} -gt 0 ] && [ -n "$admin_token" ]; then print_info "Deleting test users..." # Get all users to find IDs of test users local users_response=$(curl -s -X GET "$TEST_API_BASE/auth/users?limit=100" \ -H "Authorization: Bearer $admin_token" \ -H "Content-Type: application/json" 2>/dev/null || echo "") if [ -n "$users_response" ] && echo "$users_response" | grep -q '"data"'; then local user_ids=() # Extract data array from response (new format uses "data" instead of "users") local users_json=$(echo "$users_response" | grep -o '"data":\[[^]]*\]' | sed 's/"data"://') # Find IDs of test users by email for test_email in "${TEST_USERS_CREATED[@]}"; do local user_id=$(echo "$users_json" | grep -B2 -A2 "\"email\":\"$test_email\"" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4) if [ -n "$user_id" ]; then user_ids+=("$user_id") print_info " - Found test user: $test_email (ID: $user_id)" fi done # Bulk delete test users if [ ${#user_ids[@]} -gt 0 ]; then local delete_response=$(curl -s -X DELETE "$TEST_API_BASE/auth/users" \ -H "Authorization: Bearer $admin_token" \ -H "Content-Type: application/json" \ -d "{\"userIds\": [$(printf '"%s",' "${user_ids[@]}" | sed 's/,$//' )]}") if ! echo "$delete_response" | grep -q '"error"'; then print_success " Deleted ${#user_ids[@]} test users" else print_fail " Failed to delete test users" echo " Response: $delete_response" fi fi else print_fail " Could not list users for cleanup" fi fi # 3. Delete all test buckets if [ ${#TEST_BUCKETS_CREATED[@]} -gt 0 ]; then if [ -n "$api_key" ]; then print_info "Deleting test buckets..." for bucket in "${TEST_BUCKETS_CREATED[@]}"; do print_info " - Deleting bucket: $bucket" delete_response=$(curl -s -w "\n%{http_code}" -X DELETE "$TEST_API_BASE/storage/buckets/$bucket" \ -H "Authorization: Bearer $api_key" 2>/dev/null || echo "500") status=$(echo "$delete_response" | tail -n 1) if [ "$status" -ge 200 ] && [ "$status" -lt 300 ]; then echo " โœ“ Deleted" else echo " โœ— Failed (status: $status)" cleanup_failed=1 fi done else print_fail "Cannot delete buckets without API key" print_info "Buckets to delete manually:" for bucket in "${TEST_BUCKETS_CREATED[@]}"; do echo " - $bucket" done cleanup_failed=1 fi fi if [ $cleanup_failed -eq 1 ]; then print_fail "Cleanup completed with errors - some resources may need manual cleanup" else print_success "Cleanup completed successfully" fi } # Test failure tracking TEST_FAILED=0 # Function to track test failures track_test_failure() { TEST_FAILED=1 } # Function to exit with proper code exit_with_status() { if [ $TEST_FAILED -eq 1 ]; then exit 1 else exit 0 fi } # Set error handling set -E # Inherit ERR trap in functions # Function to handle script termination handle_exit() { local exit_code=$? # Run cleanup cleanup_test_data # Exit with the original exit code or our tracked failure status if [ $TEST_FAILED -eq 1 ] || [ $exit_code -ne 0 ]; then exit 1 else exit 0 fi } # Trap to ensure cleanup runs on any exit condition trap handle_exit EXIT trap handle_exit ERR trap handle_exit INT trap handle_exit TERM