Reorganize test files
This commit is contained in:
149
check.sh
149
check.sh
@@ -1,149 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Environment Variable Diagnostic Script
|
|
||||||
# This script helps identify where environment variables are getting lost
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "🔍 Environment Variable Diagnostic Script"
|
|
||||||
echo "=========================================="
|
|
||||||
|
|
||||||
# Check if .env file exists and contains JWT settings
|
|
||||||
echo "📋 Step 1: Checking .env file..."
|
|
||||||
if [ -f ".env" ]; then
|
|
||||||
echo "✅ .env file exists"
|
|
||||||
if grep -q "JWT_SECRET_KEY" .env; then
|
|
||||||
JWT_VALUE=$(grep "JWT_SECRET_KEY" .env | cut -d'=' -f2-)
|
|
||||||
echo "✅ JWT_SECRET_KEY found in .env: ${JWT_VALUE:0:30}..."
|
|
||||||
else
|
|
||||||
echo "❌ JWT_SECRET_KEY not found in .env"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "❌ .env file does not exist"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check docker-compose.yml configuration
|
|
||||||
echo "📋 Step 2: Checking docker-compose.yml..."
|
|
||||||
if grep -A 20 "auth-service:" docker-compose.yml | grep -q "JWT_SECRET_KEY"; then
|
|
||||||
echo "✅ auth-service has JWT_SECRET_KEY in docker-compose.yml"
|
|
||||||
else
|
|
||||||
echo "❌ auth-service missing JWT_SECRET_KEY in docker-compose.yml"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if services are running
|
|
||||||
echo "📋 Step 3: Checking running services..."
|
|
||||||
AUTH_RUNNING=$(docker-compose ps auth-service | grep -c "Up" || echo "0")
|
|
||||||
GATEWAY_RUNNING=$(docker-compose ps gateway | grep -c "Up" || echo "0")
|
|
||||||
|
|
||||||
echo "Auth Service Running: $AUTH_RUNNING"
|
|
||||||
echo "Gateway Running: $GATEWAY_RUNNING"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check environment at container startup
|
|
||||||
echo "📋 Step 4: Checking container environment at startup..."
|
|
||||||
echo "Starting fresh auth-service container..."
|
|
||||||
|
|
||||||
# Stop and start auth service
|
|
||||||
docker-compose stop auth-service
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
# Start auth service and immediately check environment
|
|
||||||
echo "Starting auth-service..."
|
|
||||||
docker-compose up -d auth-service
|
|
||||||
|
|
||||||
# Wait a moment for startup
|
|
||||||
sleep 3
|
|
||||||
|
|
||||||
echo "Checking environment immediately after startup..."
|
|
||||||
STARTUP_ENV=$(docker-compose exec -T auth-service env | grep JWT_SECRET_KEY || echo "NOT_SET")
|
|
||||||
echo "Startup Environment: $STARTUP_ENV"
|
|
||||||
|
|
||||||
# Wait a bit more and check again
|
|
||||||
sleep 5
|
|
||||||
echo "Checking environment after 5 seconds..."
|
|
||||||
AFTER_STARTUP=$(docker-compose exec -T auth-service env | grep JWT_SECRET_KEY || echo "NOT_SET")
|
|
||||||
echo "After Startup: $AFTER_STARTUP"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if the application is overriding environment variables
|
|
||||||
echo "📋 Step 5: Checking application configuration loading..."
|
|
||||||
|
|
||||||
# Create a temporary script to check Python environment loading
|
|
||||||
cat > /tmp/check_env.py << 'EOF'
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
sys.path.insert(0, '/app')
|
|
||||||
|
|
||||||
print("=== Python Environment Check ===")
|
|
||||||
print(f"JWT_SECRET_KEY from os.getenv: {os.getenv('JWT_SECRET_KEY', 'NOT_SET')}")
|
|
||||||
|
|
||||||
try:
|
|
||||||
from app.core.config import settings
|
|
||||||
print(f"JWT_SECRET_KEY from settings: {getattr(settings, 'JWT_SECRET_KEY', 'NOT_SET')}")
|
|
||||||
|
|
||||||
# Check if settings inherits from base
|
|
||||||
try:
|
|
||||||
from shared.config.base import BaseServiceSettings
|
|
||||||
base_settings = BaseServiceSettings()
|
|
||||||
print(f"JWT_SECRET_KEY from base settings: {getattr(base_settings, 'JWT_SECRET_KEY', 'NOT_SET')}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error loading base settings: {e}")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error loading auth settings: {e}")
|
|
||||||
|
|
||||||
print("=== Raw Environment Variables ===")
|
|
||||||
for key, value in sorted(os.environ.items()):
|
|
||||||
if 'JWT' in key or 'SECRET' in key:
|
|
||||||
print(f"{key}={value[:30]}..." if len(value) > 30 else f"{key}={value}")
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Copy the script into the container and run it
|
|
||||||
docker cp /tmp/check_env.py "$(docker-compose ps -q auth-service):/tmp/check_env.py"
|
|
||||||
echo "Running Python environment check..."
|
|
||||||
docker-compose exec -T auth-service python /tmp/check_env.py
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if there are any startup scripts or entrypoints modifying environment
|
|
||||||
echo "📋 Step 6: Checking container startup process..."
|
|
||||||
echo "Container entrypoint:"
|
|
||||||
docker-compose exec -T auth-service cat /usr/local/bin/docker-entrypoint.sh 2>/dev/null || echo "No entrypoint script found"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Docker image environment:"
|
|
||||||
docker-compose exec -T auth-service printenv | grep JWT || echo "No JWT variables in container environment"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check application logs for any environment variable issues
|
|
||||||
echo "📋 Step 7: Checking application logs for environment issues..."
|
|
||||||
echo "Recent auth-service logs:"
|
|
||||||
docker-compose logs --tail=20 auth-service | grep -i -E "(jwt|secret|env|config)" || echo "No relevant logs found"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Final diagnosis
|
|
||||||
echo "📋 Step 8: Diagnosis Summary"
|
|
||||||
echo "=============================="
|
|
||||||
|
|
||||||
if [ "$STARTUP_ENV" = "NOT_SET" ]; then
|
|
||||||
echo "❌ ISSUE: JWT_SECRET_KEY is not being passed to the container"
|
|
||||||
echo "🔧 SOLUTION: Fix docker-compose.yml environment variables"
|
|
||||||
elif [ "$STARTUP_ENV" != "NOT_SET" ] && [ "$AFTER_STARTUP" = "NOT_SET" ]; then
|
|
||||||
echo "❌ ISSUE: JWT_SECRET_KEY is present at startup but disappears"
|
|
||||||
echo "🔧 SOLUTION: Check application configuration loading"
|
|
||||||
else
|
|
||||||
echo "✅ Environment variables appear to be stable"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🏁 Diagnostic complete!"
|
|
||||||
|
|
||||||
# Cleanup
|
|
||||||
rm -f /tmp/check_env.py
|
|
||||||
@@ -1,230 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# JWT Debug and Verification Script
|
|
||||||
# This script helps debug JWT token issues between gateway and auth service
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Configuration
|
|
||||||
API_BASE="http://localhost:8000"
|
|
||||||
AUTH_BASE="http://localhost:8001"
|
|
||||||
EMAIL="test@bakery.com"
|
|
||||||
PASSWORD="TestPassword123!"
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
log_info() {
|
|
||||||
echo -e "${BLUE}ℹ️ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_success() {
|
|
||||||
echo -e "${GREEN}✅ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_warning() {
|
|
||||||
echo -e "${YELLOW}⚠️ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_error() {
|
|
||||||
echo -e "${RED}❌ $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_step() {
|
|
||||||
echo -e "${BLUE}🔄 $1${NC}"
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "🔍 JWT Token Debug and Verification Script"
|
|
||||||
echo "==========================================="
|
|
||||||
|
|
||||||
# Step 1: Check JWT Configuration
|
|
||||||
log_step "Step 1: Checking JWT Configuration Consistency"
|
|
||||||
|
|
||||||
log_info "Checking Gateway JWT Settings..."
|
|
||||||
GATEWAY_JWT_SECRET=$(docker-compose exec -T gateway env 2>/dev/null | grep JWT_SECRET_KEY || echo "NOT_SET")
|
|
||||||
GATEWAY_JWT_ALGO=$(docker-compose exec -T gateway env 2>/dev/null | grep JWT_ALGORITHM || echo "NOT_SET")
|
|
||||||
|
|
||||||
log_info "Checking Auth Service JWT Settings..."
|
|
||||||
AUTH_JWT_SECRET=$(docker-compose exec -T auth-service env 2>/dev/null | grep JWT_SECRET_KEY || echo "NOT_SET")
|
|
||||||
AUTH_JWT_ALGO=$(docker-compose exec -T auth-service env 2>/dev/null | grep JWT_ALGORITHM || echo "NOT_SET")
|
|
||||||
|
|
||||||
echo "Gateway JWT Secret: $GATEWAY_JWT_SECRET"
|
|
||||||
echo "Auth Service JWT Secret: $AUTH_JWT_SECRET"
|
|
||||||
echo "Gateway JWT Algorithm: $GATEWAY_JWT_ALGO"
|
|
||||||
echo "Auth Service JWT Algorithm: $AUTH_JWT_ALGO"
|
|
||||||
|
|
||||||
if [ "$GATEWAY_JWT_SECRET" = "$AUTH_JWT_SECRET" ]; then
|
|
||||||
log_success "JWT Secret Keys match!"
|
|
||||||
else
|
|
||||||
log_error "JWT Secret Keys DO NOT match!"
|
|
||||||
log_warning "This is likely the cause of the authentication issue"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Step 2: Test Direct Auth Service
|
|
||||||
log_step "Step 2: Testing Direct Auth Service"
|
|
||||||
|
|
||||||
# Login directly to auth service
|
|
||||||
log_info "Logging in directly to auth service..."
|
|
||||||
AUTH_LOGIN_RESPONSE=$(curl -s -X POST "$AUTH_BASE/api/v1/auth/login" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{
|
|
||||||
\"email\": \"$EMAIL\",
|
|
||||||
\"password\": \"$PASSWORD\"
|
|
||||||
}")
|
|
||||||
|
|
||||||
echo "Direct Auth Login Response:"
|
|
||||||
echo "$AUTH_LOGIN_RESPONSE" | jq '.' 2>/dev/null || echo "$AUTH_LOGIN_RESPONSE"
|
|
||||||
|
|
||||||
# Extract token
|
|
||||||
DIRECT_TOKEN=$(echo "$AUTH_LOGIN_RESPONSE" | jq -r '.access_token' 2>/dev/null)
|
|
||||||
|
|
||||||
if [ "$DIRECT_TOKEN" != "null" ] && [ "$DIRECT_TOKEN" != "" ]; then
|
|
||||||
log_success "Direct auth login successful!"
|
|
||||||
echo "Token: ${DIRECT_TOKEN:0:50}..."
|
|
||||||
|
|
||||||
# Test direct auth verification
|
|
||||||
log_info "Testing direct auth token verification..."
|
|
||||||
AUTH_VERIFY_RESPONSE=$(curl -s -X POST "$AUTH_BASE/api/v1/auth/verify" \
|
|
||||||
-H "Authorization: Bearer $DIRECT_TOKEN")
|
|
||||||
|
|
||||||
echo "Direct Auth Verify Response:"
|
|
||||||
echo "$AUTH_VERIFY_RESPONSE" | jq '.' 2>/dev/null || echo "$AUTH_VERIFY_RESPONSE"
|
|
||||||
|
|
||||||
# Test direct auth /users/me
|
|
||||||
log_info "Testing direct auth /users/me endpoint..."
|
|
||||||
AUTH_ME_RESPONSE=$(curl -s -X GET "$AUTH_BASE/api/v1/users/me" \
|
|
||||||
-H "Authorization: Bearer $DIRECT_TOKEN")
|
|
||||||
|
|
||||||
echo "Direct Auth /users/me Response:"
|
|
||||||
echo "$AUTH_ME_RESPONSE" | jq '.' 2>/dev/null || echo "$AUTH_ME_RESPONSE"
|
|
||||||
|
|
||||||
else
|
|
||||||
log_error "Direct auth login failed!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Step 3: Test Gateway Login
|
|
||||||
log_step "Step 3: Testing Gateway Login"
|
|
||||||
|
|
||||||
GATEWAY_LOGIN_RESPONSE=$(curl -s -X POST "$API_BASE/api/v1/auth/login" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{
|
|
||||||
\"email\": \"$EMAIL\",
|
|
||||||
\"password\": \"$PASSWORD\"
|
|
||||||
}")
|
|
||||||
|
|
||||||
echo "Gateway Login Response:"
|
|
||||||
echo "$GATEWAY_LOGIN_RESPONSE" | jq '.' 2>/dev/null || echo "$GATEWAY_LOGIN_RESPONSE"
|
|
||||||
|
|
||||||
GATEWAY_TOKEN=$(echo "$GATEWAY_LOGIN_RESPONSE" | jq -r '.access_token' 2>/dev/null)
|
|
||||||
|
|
||||||
if [ "$GATEWAY_TOKEN" != "null" ] && [ "$GATEWAY_TOKEN" != "" ]; then
|
|
||||||
log_success "Gateway login successful!"
|
|
||||||
echo "Token: ${GATEWAY_TOKEN:0:50}..."
|
|
||||||
else
|
|
||||||
log_error "Gateway login failed!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Step 4: Compare Tokens
|
|
||||||
log_step "Step 4: Comparing Tokens"
|
|
||||||
|
|
||||||
if [ "$DIRECT_TOKEN" = "$GATEWAY_TOKEN" ]; then
|
|
||||||
log_success "Tokens are identical (expected)"
|
|
||||||
else
|
|
||||||
log_warning "Tokens are different (unexpected if same login)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Decode tokens for comparison
|
|
||||||
log_info "Decoding direct auth token payload..."
|
|
||||||
DIRECT_PAYLOAD=$(echo "$DIRECT_TOKEN" | cut -d'.' -f2)
|
|
||||||
# Add padding if needed
|
|
||||||
while [ $((${#DIRECT_PAYLOAD} % 4)) -ne 0 ]; do
|
|
||||||
DIRECT_PAYLOAD="${DIRECT_PAYLOAD}="
|
|
||||||
done
|
|
||||||
echo "$DIRECT_PAYLOAD" | base64 -d 2>/dev/null | jq '.' || echo "Failed to decode"
|
|
||||||
|
|
||||||
log_info "Decoding gateway token payload..."
|
|
||||||
GATEWAY_PAYLOAD=$(echo "$GATEWAY_TOKEN" | cut -d'.' -f2)
|
|
||||||
# Add padding if needed
|
|
||||||
while [ $((${#GATEWAY_PAYLOAD} % 4)) -ne 0 ]; do
|
|
||||||
GATEWAY_PAYLOAD="${GATEWAY_PAYLOAD}="
|
|
||||||
done
|
|
||||||
echo "$GATEWAY_PAYLOAD" | base64 -d 2>/dev/null | jq '.' || echo "Failed to decode"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Step 5: Test Gateway Authentication
|
|
||||||
log_step "Step 5: Testing Gateway Authentication Middleware"
|
|
||||||
|
|
||||||
# Test gateway token verification
|
|
||||||
log_info "Testing gateway token verification..."
|
|
||||||
GATEWAY_VERIFY_RESPONSE=$(curl -s -X POST "$API_BASE/api/v1/auth/verify" \
|
|
||||||
-H "Authorization: Bearer $GATEWAY_TOKEN")
|
|
||||||
|
|
||||||
echo "Gateway Verify Response:"
|
|
||||||
echo "$GATEWAY_VERIFY_RESPONSE" | jq '.' 2>/dev/null || echo "$GATEWAY_VERIFY_RESPONSE"
|
|
||||||
|
|
||||||
# Test gateway /users/me (this is where the issue occurs)
|
|
||||||
log_info "Testing gateway /users/me endpoint (THE FAILING ENDPOINT)..."
|
|
||||||
GATEWAY_ME_RESPONSE=$(curl -s -w "\nHTTP_CODE:%{http_code}\n" -X GET "$API_BASE/api/v1/users/me" \
|
|
||||||
-H "Authorization: Bearer $GATEWAY_TOKEN")
|
|
||||||
|
|
||||||
echo "Gateway /users/me Response:"
|
|
||||||
echo "$GATEWAY_ME_RESPONSE"
|
|
||||||
|
|
||||||
# Check if successful
|
|
||||||
if echo "$GATEWAY_ME_RESPONSE" | grep -q "HTTP_CODE:200"; then
|
|
||||||
log_success "Gateway /users/me endpoint working!"
|
|
||||||
elif echo "$GATEWAY_ME_RESPONSE" | grep -q "HTTP_CODE:401"; then
|
|
||||||
log_error "Gateway /users/me endpoint returning 401 Unauthorized"
|
|
||||||
log_warning "This confirms the JWT middleware issue"
|
|
||||||
else
|
|
||||||
log_warning "Gateway /users/me endpoint returned unexpected response"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Step 6: Test with verbose curl to see middleware behavior
|
|
||||||
log_step "Step 6: Verbose Gateway Request Analysis"
|
|
||||||
|
|
||||||
log_info "Making verbose request to gateway /users/me..."
|
|
||||||
curl -v -X GET "$API_BASE/api/v1/users/me" \
|
|
||||||
-H "Authorization: Bearer $GATEWAY_TOKEN" 2>&1 | head -20
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Step 7: Recommendations
|
|
||||||
log_step "Step 7: Recommendations"
|
|
||||||
|
|
||||||
if [ "$GATEWAY_JWT_SECRET" != "$AUTH_JWT_SECRET" ]; then
|
|
||||||
log_error "CRITICAL: JWT secrets don't match between services"
|
|
||||||
echo "Fix: Update your .env file and restart services:"
|
|
||||||
echo "export JWT_SECRET_KEY='your-super-secret-jwt-key-change-in-production-min-32-characters-long'"
|
|
||||||
echo "docker-compose down && docker-compose up -d"
|
|
||||||
elif echo "$GATEWAY_ME_RESPONSE" | grep -q "HTTP_CODE:401"; then
|
|
||||||
log_warning "JWT secrets match but gateway middleware is still failing"
|
|
||||||
echo "Possible causes:"
|
|
||||||
echo "1. Gateway middleware token validation logic issue"
|
|
||||||
echo "2. Token payload structure mismatch"
|
|
||||||
echo "3. Gateway not using updated shared JWT handler"
|
|
||||||
echo ""
|
|
||||||
echo "Recommended fixes:"
|
|
||||||
echo "1. Apply the fixed gateway auth middleware"
|
|
||||||
echo "2. Apply the fixed shared JWT handler"
|
|
||||||
echo "3. Restart gateway service: docker-compose restart gateway"
|
|
||||||
else
|
|
||||||
log_success "All tests passed! JWT authentication is working correctly."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🏁 Debug script completed!"
|
|
||||||
235
test_new.sh
235
test_new.sh
@@ -1,235 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# Configuration
|
|
||||||
API_BASE="http://localhost:8000"
|
|
||||||
EMAIL="test4555@bakery.com"
|
|
||||||
PASSWORD="TestPassword123!"
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
echo "🧪 Testing New Tenant-Scoped API Architecture"
|
|
||||||
echo "=============================================="
|
|
||||||
|
|
||||||
# Function to check response status
|
|
||||||
check_response() {
|
|
||||||
local response="$1"
|
|
||||||
local step_name="$2"
|
|
||||||
|
|
||||||
if echo "$response" | grep -q '"detail"' && echo "$response" | grep -q '"error"'; then
|
|
||||||
echo -e "${RED}❌ $step_name FAILED${NC}"
|
|
||||||
echo "Error details: $response"
|
|
||||||
return 1
|
|
||||||
elif echo "$response" | grep -q '500 Internal Server Error'; then
|
|
||||||
echo -e "${RED}❌ $step_name FAILED - Server Error${NC}"
|
|
||||||
echo "Response: $response"
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
echo -e "${GREEN}✅ $step_name PASSED${NC}"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Step 1: Health Check
|
|
||||||
echo "1. Testing Gateway Health..."
|
|
||||||
HEALTH_RESPONSE=$(curl -s -X GET "$API_BASE/health")
|
|
||||||
echo "Health Response: $HEALTH_RESPONSE"
|
|
||||||
check_response "$HEALTH_RESPONSE" "Health Check"
|
|
||||||
|
|
||||||
# Step 2: Register User (or skip if already exists)
|
|
||||||
echo -e "\n2. Registering User..."
|
|
||||||
REGISTER_RESPONSE=$(curl -s -X POST "$API_BASE/api/v1/auth/register" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{
|
|
||||||
\"email\": \"$EMAIL\",
|
|
||||||
\"password\": \"$PASSWORD\",
|
|
||||||
\"full_name\": \"Test User\"
|
|
||||||
}")
|
|
||||||
|
|
||||||
echo "Registration Response: $REGISTER_RESPONSE"
|
|
||||||
|
|
||||||
# Check if user already exists
|
|
||||||
if echo "$REGISTER_RESPONSE" | grep -q "already exists"; then
|
|
||||||
echo -e "${YELLOW}⚠️ User already exists, proceeding to login${NC}"
|
|
||||||
elif check_response "$REGISTER_RESPONSE" "User Registration"; then
|
|
||||||
echo "New user registered successfully"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 3: Login
|
|
||||||
echo -e "\n3. Logging in..."
|
|
||||||
LOGIN_RESPONSE=$(curl -s -X POST "$API_BASE/api/v1/auth/login" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{
|
|
||||||
\"email\": \"$EMAIL\",
|
|
||||||
\"password\": \"$PASSWORD\"
|
|
||||||
}")
|
|
||||||
|
|
||||||
echo "Login Response: $LOGIN_RESPONSE"
|
|
||||||
|
|
||||||
# Extract token with better parsing
|
|
||||||
ACCESS_TOKEN=$(echo "$LOGIN_RESPONSE" | python3 -c "import json, sys; data=json.load(sys.stdin); print(data.get('access_token', ''))" 2>/dev/null)
|
|
||||||
|
|
||||||
if [ -z "$ACCESS_TOKEN" ]; then
|
|
||||||
# Fallback to grep method
|
|
||||||
ACCESS_TOKEN=$(echo "$LOGIN_RESPONSE" | grep -o '"access_token":"[^"]*"' | cut -d'"' -f4)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$ACCESS_TOKEN" ]; then
|
|
||||||
echo -e "${RED}❌ Failed to extract access token${NC}"
|
|
||||||
echo "Login response was: $LOGIN_RESPONSE"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Access Token: ${ACCESS_TOKEN:0:50}..."
|
|
||||||
check_response "$LOGIN_RESPONSE" "User Login"
|
|
||||||
|
|
||||||
# Step 3.5: Verify Token Works
|
|
||||||
echo -e "\n3.5. Verifying Access Token..."
|
|
||||||
TOKEN_TEST_RESPONSE=$(curl -s -X POST "$API_BASE/api/v1/auth/verify" \
|
|
||||||
-H "Authorization: Bearer $ACCESS_TOKEN")
|
|
||||||
|
|
||||||
echo "Token Verification Response: $TOKEN_TEST_RESPONSE"
|
|
||||||
|
|
||||||
if check_response "$TOKEN_TEST_RESPONSE" "Token Verification"; then
|
|
||||||
if echo "$TOKEN_TEST_RESPONSE" | grep -q '"user_id"'; then
|
|
||||||
echo -e "${GREEN}✅ Token contains user_id${NC}"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo -e "${RED}❌ Token verification failed, but continuing...${NC}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 3.6: Test Protected Endpoint (with error handling)
|
|
||||||
echo -e "\n3.6. Testing Protected Endpoint (User Profile)..."
|
|
||||||
USER_PROFILE_RESPONSE=$(curl -s -X GET "$API_BASE/api/v1/users/me" \
|
|
||||||
-H "Authorization: Bearer $ACCESS_TOKEN")
|
|
||||||
|
|
||||||
echo "User Profile Response: $USER_PROFILE_RESPONSE"
|
|
||||||
|
|
||||||
# This might fail due to the datetime serialization issue we identified
|
|
||||||
if echo "$USER_PROFILE_RESPONSE" | grep -q '"email"'; then
|
|
||||||
check_response "$USER_PROFILE_RESPONSE" "Protected Endpoint Access"
|
|
||||||
elif echo "$USER_PROFILE_RESPONSE" | grep -q "string_type"; then
|
|
||||||
echo -e "${YELLOW}⚠️ Known datetime serialization issue detected${NC}"
|
|
||||||
echo -e "${YELLOW} This is the Pydantic validation error we identified${NC}"
|
|
||||||
echo -e "${YELLOW} Continuing with tenant registration...${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${RED}❌ Protected endpoint access failed for unknown reason${NC}"
|
|
||||||
echo "Response was: $USER_PROFILE_RESPONSE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 4: Register Bakery
|
|
||||||
echo -e "\n4. Registering Bakery..."
|
|
||||||
echo "Using Token: ${ACCESS_TOKEN:0:50}..."
|
|
||||||
echo "Making request to: $API_BASE/api/v1/tenants/register"
|
|
||||||
|
|
||||||
BAKERY_RESPONSE=$(curl -s -w "\nHTTP_CODE:%{http_code}" -X POST "$API_BASE/api/v1/tenants/register" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
|
||||||
-d '{
|
|
||||||
"name": "Test Bakery API",
|
|
||||||
"business_type": "bakery",
|
|
||||||
"address": "Calle Test 123",
|
|
||||||
"city": "Madrid",
|
|
||||||
"postal_code": "28001",
|
|
||||||
"phone": "+34600123456"
|
|
||||||
}')
|
|
||||||
|
|
||||||
# Extract HTTP code and response
|
|
||||||
HTTP_CODE=$(echo "$BAKERY_RESPONSE" | grep "HTTP_CODE:" | cut -d: -f2)
|
|
||||||
BAKERY_RESPONSE=$(echo "$BAKERY_RESPONSE" | sed '/HTTP_CODE:/d')
|
|
||||||
|
|
||||||
echo "HTTP Status Code: $HTTP_CODE"
|
|
||||||
echo "Bakery Response: $BAKERY_RESPONSE"
|
|
||||||
|
|
||||||
# Extract tenant ID with better parsing
|
|
||||||
TENANT_ID=$(echo "$BAKERY_RESPONSE" | python3 -c "import json, sys; data=json.load(sys.stdin); print(data.get('id', ''))" 2>/dev/null)
|
|
||||||
|
|
||||||
if [ -z "$TENANT_ID" ]; then
|
|
||||||
# Fallback to grep method
|
|
||||||
TENANT_ID=$(echo "$BAKERY_RESPONSE" | grep -o '"id":"[^"]*"' | cut -d'"' -f4)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$TENANT_ID" ]; then
|
|
||||||
echo "Tenant ID: $TENANT_ID"
|
|
||||||
check_response "$BAKERY_RESPONSE" "Bakery Registration"
|
|
||||||
else
|
|
||||||
echo -e "${RED}❌ Failed to extract tenant ID${NC}"
|
|
||||||
echo "Cannot proceed with tenant-scoped tests"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 5: Test Tenant-Scoped Endpoint
|
|
||||||
if [ -n "$TENANT_ID" ]; then
|
|
||||||
echo -e "\n5. Testing Tenant Sales Endpoint..."
|
|
||||||
SALES_RESPONSE=$(curl -s -X GET "$API_BASE/api/v1/tenants/$TENANT_ID/sales" \
|
|
||||||
-H "Authorization: Bearer $ACCESS_TOKEN")
|
|
||||||
|
|
||||||
echo "Sales Response: $SALES_RESPONSE"
|
|
||||||
check_response "$SALES_RESPONSE" "Tenant Sales Endpoint"
|
|
||||||
|
|
||||||
# Step 6: Test Import Validation
|
|
||||||
echo -e "\n6. Testing Import Validation..."
|
|
||||||
VALIDATION_RESPONSE=$(curl -s -X POST "$API_BASE/api/v1/tenants/$TENANT_ID/sales/import/validate" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
|
||||||
-d '{
|
|
||||||
"data": "date,product,quantity,revenue\n2024-01-01,bread,10,25.50",
|
|
||||||
"data_format": "csv"
|
|
||||||
}')
|
|
||||||
|
|
||||||
echo "Validation Response: $VALIDATION_RESPONSE"
|
|
||||||
check_response "$VALIDATION_RESPONSE" "Import Validation"
|
|
||||||
|
|
||||||
# Step 6.5: Import Sample Sales Data
|
|
||||||
echo -e "\n6.5. Importing Sample Sales Data..."
|
|
||||||
IMPORT_RESPONSE=$(curl -s -X POST "$API_BASE/api/v1/tenants/$TENANT_ID/sales" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $ACCESS_TOKEN" \
|
|
||||||
-d '{
|
|
||||||
"product_name": "Pan Integral",
|
|
||||||
"quantity_sold": 25,
|
|
||||||
"revenue": 37.50,
|
|
||||||
"date": "2024-01-15T10:00:00Z"
|
|
||||||
}')
|
|
||||||
|
|
||||||
echo "Import Response: $IMPORT_RESPONSE"
|
|
||||||
check_response "$IMPORT_RESPONSE" "Sales Data Import"
|
|
||||||
|
|
||||||
# Now test sales endpoint again - should have data!
|
|
||||||
echo -e "\n6.6. Testing Sales Endpoint Again (Should Have Data)..."
|
|
||||||
SALES_RESPONSE_WITH_DATA=$(curl -s -X GET "$API_BASE/api/v1/tenants/$TENANT_ID/sales" \
|
|
||||||
-H "Authorization: Bearer $ACCESS_TOKEN")
|
|
||||||
|
|
||||||
echo "Sales Response with Data: $SALES_RESPONSE_WITH_DATA"
|
|
||||||
check_response "$SALES_RESPONSE_WITH_DATA" "Tenant Sales Endpoint with Data"
|
|
||||||
|
|
||||||
# Check if we actually got data
|
|
||||||
if echo "$SALES_RESPONSE_WITH_DATA" | grep -q "Pan Integral"; then
|
|
||||||
echo -e "${GREEN}✅ Successfully retrieved sales data!${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${YELLOW}⚠️ No sales data returned (might need different import endpoint)${NC}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Step 7: Additional Debug Information
|
|
||||||
echo -e "\n7. Debug Information..."
|
|
||||||
echo "Services Status:"
|
|
||||||
echo "- Auth Service: $(curl -s http://localhost:8001/health || echo 'Not responding')"
|
|
||||||
echo "- Tenant Service: $(curl -s http://localhost:8002/health || echo 'Not responding')"
|
|
||||||
echo "- Data Service: $(curl -s http://localhost:8003/health || echo 'Not responding')"
|
|
||||||
|
|
||||||
echo -e "\n${GREEN}✅ API Test Complete!${NC}"
|
|
||||||
echo "Summary:"
|
|
||||||
echo "- Gateway Health: ✓"
|
|
||||||
echo "- User Registration: ✓"
|
|
||||||
echo "- User Login: ✓"
|
|
||||||
echo "- Token Verification: ✓"
|
|
||||||
echo -e "- User Profile: ${YELLOW}⚠️ (Known datetime issue)${NC}"
|
|
||||||
echo "- Bakery Registration: ✓"
|
|
||||||
echo "- Tenant-scoped endpoints: ✓"
|
|
||||||
|
|
||||||
echo -e "\n${YELLOW}Note: If you see the datetime serialization error in step 3.6,"
|
|
||||||
echo -e "that's the Pydantic validation issue we identified earlier.${NC}"
|
|
||||||
echo -e "${YELLOW}Fix it by updating the UserResponse schema as discussed.${NC}"
|
|
||||||
@@ -1,235 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
# =================================================================
|
|
||||||
# Test Training Service Token Generation and Gateway Validation
|
|
||||||
# =================================================================
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Configuration
|
|
||||||
API_BASE="http://localhost:8000"
|
|
||||||
AUTH_BASE="http://localhost:8001"
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m'
|
|
||||||
|
|
||||||
log_info() { echo -e "${BLUE}ℹ️ $1${NC}"; }
|
|
||||||
log_success() { echo -e "${GREEN}✅ $1${NC}"; }
|
|
||||||
log_warning() { echo -e "${YELLOW}⚠️ $1${NC}"; }
|
|
||||||
log_error() { echo -e "${RED}❌ $1${NC}"; }
|
|
||||||
log_step() { echo -e "${BLUE}🔄 $1${NC}"; }
|
|
||||||
|
|
||||||
echo "🧪 Testing Training Service Token with Gateway Middleware"
|
|
||||||
echo "========================================================"
|
|
||||||
|
|
||||||
# Step 1: Create a service token like training service would
|
|
||||||
log_step "Step 1: Creating Service Token (Training Service Style)"
|
|
||||||
|
|
||||||
# Use Python to create the same token the training service would create
|
|
||||||
SERVICE_TOKEN=$(python3 -c "
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import os
|
|
||||||
sys.path.append('.')
|
|
||||||
|
|
||||||
# Import your shared JWT handler
|
|
||||||
from shared.auth.jwt_handler import JWTHandler
|
|
||||||
|
|
||||||
# Use same secret as gateway/auth service
|
|
||||||
JWT_SECRET = os.getenv('JWT_SECRET_KEY', 'your-super-secret-jwt-key-change-in-production-min-32-characters-long')
|
|
||||||
|
|
||||||
# Create JWT handler
|
|
||||||
jwt_handler = JWTHandler(JWT_SECRET)
|
|
||||||
|
|
||||||
# Create service payload (same as training service would)
|
|
||||||
service_payload = {
|
|
||||||
'sub': 'training-service',
|
|
||||||
'user_id': 'training-service',
|
|
||||||
'email': 'training-service@internal',
|
|
||||||
'service': 'training',
|
|
||||||
'type': 'access', # Important: must be 'access' type
|
|
||||||
'exp': int(time.time()) + 3600, # 1 hour
|
|
||||||
'iat': int(time.time()),
|
|
||||||
'iss': 'training-service',
|
|
||||||
'full_name': 'Training Service',
|
|
||||||
'is_verified': True,
|
|
||||||
'is_active': True
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create token
|
|
||||||
token = jwt_handler.create_access_token_from_payload(service_payload)
|
|
||||||
print(token)
|
|
||||||
")
|
|
||||||
|
|
||||||
if [ -z "$SERVICE_TOKEN" ]; then
|
|
||||||
log_error "Failed to create service token"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_success "Service token created successfully"
|
|
||||||
echo "Token: ${SERVICE_TOKEN:0:50}..."
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Step 2: Decode and inspect the token
|
|
||||||
log_step "Step 2: Decoding Service Token Payload"
|
|
||||||
|
|
||||||
# Decode the payload to see what's inside
|
|
||||||
PAYLOAD=$(echo "$SERVICE_TOKEN" | cut -d'.' -f2)
|
|
||||||
# Add padding if needed
|
|
||||||
while [ $((${#PAYLOAD} % 4)) -ne 0 ]; do
|
|
||||||
PAYLOAD="${PAYLOAD}="
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Service Token Payload:"
|
|
||||||
echo "$PAYLOAD" | base64 -d 2>/dev/null | jq '.' || echo "Failed to decode"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Step 3: Test token with gateway middleware
|
|
||||||
log_step "Step 3: Testing Service Token with Gateway Middleware"
|
|
||||||
|
|
||||||
# Test a tenant-scoped endpoint that training service would call
|
|
||||||
TENANT_ID="b2a268a0-904f-4182-8f81-ec25d0e6def7" # From your test
|
|
||||||
|
|
||||||
log_info "Testing GET /api/v1/tenants/$TENANT_ID/sales with service token..."
|
|
||||||
|
|
||||||
GATEWAY_RESPONSE=$(curl -s -w "\nHTTP_CODE:%{http_code}\n" -X GET \
|
|
||||||
"$API_BASE/api/v1/tenants/$TENANT_ID/sales" \
|
|
||||||
-H "Authorization: Bearer $SERVICE_TOKEN" \
|
|
||||||
-H "X-Tenant-ID: $TENANT_ID" \
|
|
||||||
-H "X-Service: training-service" \
|
|
||||||
-H "Content-Type: application/json")
|
|
||||||
|
|
||||||
echo "Gateway Response:"
|
|
||||||
echo "$GATEWAY_RESPONSE"
|
|
||||||
|
|
||||||
# Check the result
|
|
||||||
if echo "$GATEWAY_RESPONSE" | grep -q "HTTP_CODE:200"; then
|
|
||||||
log_success "✅ Service token ACCEPTED by gateway middleware!"
|
|
||||||
log_success "Training service authentication would work!"
|
|
||||||
elif echo "$GATEWAY_RESPONSE" | grep -q "HTTP_CODE:401"; then
|
|
||||||
log_error "❌ Service token REJECTED by gateway middleware (401 Unauthorized)"
|
|
||||||
log_warning "This explains why training service fails"
|
|
||||||
elif echo "$GATEWAY_RESPONSE" | grep -q "HTTP_CODE:404"; then
|
|
||||||
log_warning "⚠️ Endpoint not found (404) - but token was accepted by middleware"
|
|
||||||
log_success "Authentication passed, routing issue"
|
|
||||||
else
|
|
||||||
log_warning "Unexpected HTTP response code"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Step 4: Test with a known working user token for comparison
|
|
||||||
log_step "Step 4: Comparison Test with User Token"
|
|
||||||
|
|
||||||
# Get a real user token from the onboarding test
|
|
||||||
USER_TOKEN=""
|
|
||||||
if [ -f "/tmp/test_user_token.txt" ]; then
|
|
||||||
USER_TOKEN=$(cat /tmp/test_user_token.txt)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$USER_TOKEN" ]; then
|
|
||||||
log_info "Creating a user token for comparison..."
|
|
||||||
|
|
||||||
# Quick user login to get a token
|
|
||||||
USER_LOGIN_RESPONSE=$(curl -s -X POST "$API_BASE/api/v1/auth/login" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"email": "onboarding.test.1753606890@bakery.com",
|
|
||||||
"password": "TestPassword123!"
|
|
||||||
}')
|
|
||||||
|
|
||||||
USER_TOKEN=$(echo "$USER_LOGIN_RESPONSE" | jq -r '.access_token' 2>/dev/null)
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$USER_TOKEN" ] && [ "$USER_TOKEN" != "null" ]; then
|
|
||||||
log_info "Testing same endpoint with user token..."
|
|
||||||
|
|
||||||
USER_RESPONSE=$(curl -s -w "\nHTTP_CODE:%{http_code}\n" -X GET \
|
|
||||||
"$API_BASE/api/v1/tenants/$TENANT_ID/sales" \
|
|
||||||
-H "Authorization: Bearer $USER_TOKEN" \
|
|
||||||
-H "X-Tenant-ID: $TENANT_ID")
|
|
||||||
|
|
||||||
if echo "$USER_RESPONSE" | grep -q "HTTP_CODE:200"; then
|
|
||||||
log_success "User token works - gateway middleware is functioning"
|
|
||||||
elif echo "$USER_RESPONSE" | grep -q "HTTP_CODE:401"; then
|
|
||||||
log_warning "User token also fails - gateway middleware issue"
|
|
||||||
else
|
|
||||||
log_info "User token response: $(echo "$USER_RESPONSE" | tail -1)"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
log_warning "Could not get user token for comparison"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Step 5: Test gateway auth verification endpoint
|
|
||||||
log_step "Step 5: Testing Token with Gateway Auth Verification"
|
|
||||||
|
|
||||||
log_info "Testing service token with /api/v1/auth/verify..."
|
|
||||||
VERIFY_RESPONSE=$(curl -s -X POST "$API_BASE/api/v1/auth/verify" \
|
|
||||||
-H "Authorization: Bearer $SERVICE_TOKEN")
|
|
||||||
|
|
||||||
echo "Verification Response:"
|
|
||||||
echo "$VERIFY_RESPONSE" | jq '.' 2>/dev/null || echo "$VERIFY_RESPONSE"
|
|
||||||
|
|
||||||
if echo "$VERIFY_RESPONSE" | jq -e '.valid' > /dev/null 2>&1; then
|
|
||||||
if [ "$(echo "$VERIFY_RESPONSE" | jq -r '.valid')" = "true" ]; then
|
|
||||||
log_success "Service token is VALID according to auth service"
|
|
||||||
else
|
|
||||||
log_error "Service token is INVALID according to auth service"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
log_warning "Verification response doesn't contain 'valid' field"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Step 6: Diagnosis and recommendations
|
|
||||||
log_step "Step 6: Diagnosis and Recommendations"
|
|
||||||
|
|
||||||
# Check JWT secrets match
|
|
||||||
log_info "Checking JWT secret consistency..."
|
|
||||||
if docker-compose exec -T gateway env 2>/dev/null | grep -q JWT_SECRET_KEY; then
|
|
||||||
log_success "Gateway has JWT_SECRET_KEY configured"
|
|
||||||
else
|
|
||||||
log_error "Gateway missing JWT_SECRET_KEY configuration"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if docker-compose exec -T auth-service env 2>/dev/null | grep -q JWT_SECRET_KEY; then
|
|
||||||
log_success "Auth service has JWT_SECRET_KEY configured"
|
|
||||||
else
|
|
||||||
log_error "Auth service missing JWT_SECRET_KEY configuration"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🏁 Test Summary:"
|
|
||||||
echo "=================="
|
|
||||||
|
|
||||||
if echo "$GATEWAY_RESPONSE" | grep -q "HTTP_CODE:200"; then
|
|
||||||
echo "✅ Service token authentication: WORKING"
|
|
||||||
echo "✅ Training service should be able to fetch sales data"
|
|
||||||
echo ""
|
|
||||||
echo "🎯 Next Steps:"
|
|
||||||
echo "1. Update training service to use gateway URL: http://gateway:8000"
|
|
||||||
echo "2. Ensure training service creates tokens with same payload structure"
|
|
||||||
echo "3. Test with: docker-compose restart training-service"
|
|
||||||
elif echo "$GATEWAY_RESPONSE" | grep -q "HTTP_CODE:401"; then
|
|
||||||
echo "❌ Service token authentication: FAILING"
|
|
||||||
echo "❌ This explains why training service gets 401 errors"
|
|
||||||
echo ""
|
|
||||||
echo "🔧 Fixes needed:"
|
|
||||||
echo "1. Check JWT_SECRET_KEY matches across services"
|
|
||||||
echo "2. Update gateway middleware to accept service tokens"
|
|
||||||
echo "3. Verify token payload structure matches gateway expectations"
|
|
||||||
else
|
|
||||||
echo "⚠️ Inconclusive test results"
|
|
||||||
echo "Check the response details above"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "🧪 Test completed!"
|
|
||||||
@@ -1,488 +0,0 @@
|
|||||||
# ================================================================
|
|
||||||
# validate_data_service_fixed.py - FIXED VERSION
|
|
||||||
# ================================================================
|
|
||||||
|
|
||||||
import asyncio
|
|
||||||
import httpx
|
|
||||||
import json
|
|
||||||
import sys
|
|
||||||
import traceback
|
|
||||||
from datetime import datetime
|
|
||||||
from typing import Optional, Dict, Any
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
# Configuración
|
|
||||||
AUTH_URL = "http://localhost:8001"
|
|
||||||
DATA_URL = "http://localhost:8004"
|
|
||||||
GATEWAY_URL = "http://localhost:8000"
|
|
||||||
|
|
||||||
class DataServiceValidator:
|
|
||||||
"""Validador completo para el Data Service - FIXED VERSION"""
|
|
||||||
|
|
||||||
def __init__(self, use_gateway: bool = False):
|
|
||||||
self.auth_token: Optional[str] = None
|
|
||||||
self.use_gateway = use_gateway
|
|
||||||
self.base_url = GATEWAY_URL if use_gateway else DATA_URL
|
|
||||||
self.auth_base_url = GATEWAY_URL if use_gateway else AUTH_URL
|
|
||||||
self.user_data = None
|
|
||||||
|
|
||||||
async def test_service_health(self) -> bool:
|
|
||||||
"""Verificar que los servicios estén funcionando"""
|
|
||||||
print("🔍 Checking service health...")
|
|
||||||
|
|
||||||
try:
|
|
||||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
|
||||||
# Test auth service
|
|
||||||
auth_response = await client.get(f"{AUTH_URL}/health")
|
|
||||||
if auth_response.status_code == 200:
|
|
||||||
print("✅ Auth service is healthy")
|
|
||||||
else:
|
|
||||||
print(f"❌ Auth service unhealthy: {auth_response.status_code}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Test data service
|
|
||||||
data_response = await client.get(f"{DATA_URL}/health")
|
|
||||||
if data_response.status_code == 200:
|
|
||||||
print("✅ Data service is healthy")
|
|
||||||
else:
|
|
||||||
print(f"❌ Data service unhealthy: {data_response.status_code}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Test gateway if using it
|
|
||||||
if self.use_gateway:
|
|
||||||
gateway_response = await client.get(f"{GATEWAY_URL}/health")
|
|
||||||
if gateway_response.status_code == 200:
|
|
||||||
print("✅ Gateway is healthy")
|
|
||||||
else:
|
|
||||||
print(f"❌ Gateway unhealthy: {gateway_response.status_code}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
except httpx.ConnectError as e:
|
|
||||||
print(f"❌ Connection error: {e}")
|
|
||||||
print("💡 Make sure services are running with: docker-compose up -d")
|
|
||||||
return False
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ Health check failed: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
async def authenticate(self) -> bool:
|
|
||||||
"""Autenticar y obtener token"""
|
|
||||||
print("🔐 Authenticating...")
|
|
||||||
|
|
||||||
try:
|
|
||||||
async with httpx.AsyncClient(timeout=15.0) as client:
|
|
||||||
# Generar tenant_id único para esta prueba
|
|
||||||
tenant_id = str(uuid.uuid4())
|
|
||||||
|
|
||||||
# Datos de usuario de prueba con tenant_id
|
|
||||||
self.user_data = {
|
|
||||||
"email": "test@bakery.es",
|
|
||||||
"password": "TestPass123",
|
|
||||||
"full_name": "Test User",
|
|
||||||
"language": "es",
|
|
||||||
"tenant_id": tenant_id # ✅ AÑADIR TENANT_ID
|
|
||||||
}
|
|
||||||
|
|
||||||
# Intentar registrar usuario (puede fallar si ya existe)
|
|
||||||
register_endpoint = f"{self.auth_base_url}/api/v1/auth/register"
|
|
||||||
register_response = await client.post(register_endpoint, json=self.user_data)
|
|
||||||
|
|
||||||
if register_response.status_code == 200:
|
|
||||||
print("✅ User registered successfully")
|
|
||||||
elif register_response.status_code == 409:
|
|
||||||
print("ℹ️ User already exists, proceeding with login")
|
|
||||||
elif register_response.status_code == 400:
|
|
||||||
print("⚠️ Registration validation error, trying login")
|
|
||||||
else:
|
|
||||||
print(f"⚠️ Registration response: {register_response.status_code}")
|
|
||||||
print(f"Response body: {register_response.text}")
|
|
||||||
|
|
||||||
# Login con credenciales
|
|
||||||
login_data = {
|
|
||||||
"email": self.user_data["email"],
|
|
||||||
"password": self.user_data["password"]
|
|
||||||
}
|
|
||||||
|
|
||||||
login_endpoint = f"{self.auth_base_url}/api/v1/auth/login"
|
|
||||||
login_response = await client.post(login_endpoint, json=login_data)
|
|
||||||
|
|
||||||
if login_response.status_code == 200:
|
|
||||||
response_data = login_response.json()
|
|
||||||
self.auth_token = response_data["access_token"]
|
|
||||||
print("✅ Authentication successful")
|
|
||||||
|
|
||||||
# Verificar que el token tenga los campos necesarios
|
|
||||||
verify_endpoint = f"{self.auth_base_url}/api/v1/auth/verify"
|
|
||||||
verify_response = await client.post(
|
|
||||||
verify_endpoint,
|
|
||||||
headers={"Authorization": f"Bearer {self.auth_token}"}
|
|
||||||
)
|
|
||||||
|
|
||||||
if verify_response.status_code == 200:
|
|
||||||
token_data = verify_response.json()
|
|
||||||
print(f"🔍 Token contains: {list(token_data.keys())}")
|
|
||||||
|
|
||||||
# Verificar campos necesarios
|
|
||||||
required_fields = ["user_id", "email", "tenant_id"]
|
|
||||||
missing_fields = [field for field in required_fields if field not in token_data]
|
|
||||||
|
|
||||||
if missing_fields:
|
|
||||||
print(f"⚠️ Token missing fields: {missing_fields}")
|
|
||||||
else:
|
|
||||||
print("✅ Token has all required fields")
|
|
||||||
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
print(f"⚠️ Token verification failed: {verify_response.status_code}")
|
|
||||||
return True # Continuar de todas formas
|
|
||||||
else:
|
|
||||||
print(f"❌ Login failed: {login_response.status_code}")
|
|
||||||
print(f"Response: {login_response.text}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ Authentication failed: {e}")
|
|
||||||
traceback.print_exc()
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_headers(self) -> Dict[str, str]:
|
|
||||||
"""Obtener headers con token de autenticación"""
|
|
||||||
if not self.auth_token:
|
|
||||||
raise ValueError("No authentication token available")
|
|
||||||
return {"Authorization": f"Bearer {self.auth_token}"}
|
|
||||||
|
|
||||||
async def test_weather_endpoints(self) -> bool:
|
|
||||||
"""Probar endpoints de clima"""
|
|
||||||
print("🌤️ Testing weather endpoints...")
|
|
||||||
|
|
||||||
try:
|
|
||||||
headers = self.get_headers()
|
|
||||||
madrid_coords = {"latitude": 40.4168, "longitude": -3.7038}
|
|
||||||
|
|
||||||
async with httpx.AsyncClient(timeout=20.0) as client:
|
|
||||||
# Current weather - FIXED URL
|
|
||||||
if self.use_gateway:
|
|
||||||
current_endpoint = f"{self.base_url}/api/v1/data/weather/current"
|
|
||||||
else:
|
|
||||||
current_endpoint = f"{self.base_url}/api/v1/weather/current"
|
|
||||||
|
|
||||||
print(f"🔗 Requesting: {current_endpoint}")
|
|
||||||
current_response = await client.get(
|
|
||||||
current_endpoint,
|
|
||||||
params=madrid_coords,
|
|
||||||
headers=headers
|
|
||||||
)
|
|
||||||
|
|
||||||
if current_response.status_code == 200:
|
|
||||||
weather = current_response.json()
|
|
||||||
print(f"✅ Current weather: {weather.get('temperature')}°C, {weather.get('description')}")
|
|
||||||
else:
|
|
||||||
print(f"❌ Current weather failed: {current_response.status_code}")
|
|
||||||
print(f"Response: {current_response.text}")
|
|
||||||
|
|
||||||
# Si falla, intentar con mock data
|
|
||||||
if current_response.status_code == 503:
|
|
||||||
print("ℹ️ External API unavailable, this is expected in test environment")
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Weather forecast
|
|
||||||
if self.use_gateway:
|
|
||||||
forecast_endpoint = f"{self.base_url}/api/v1/data/weather/forecast"
|
|
||||||
else:
|
|
||||||
forecast_endpoint = f"{self.base_url}/api/v1/weather/forecast"
|
|
||||||
|
|
||||||
forecast_response = await client.get(
|
|
||||||
forecast_endpoint,
|
|
||||||
params={**madrid_coords, "days": 3},
|
|
||||||
headers=headers
|
|
||||||
)
|
|
||||||
|
|
||||||
if forecast_response.status_code == 200:
|
|
||||||
forecast = forecast_response.json()
|
|
||||||
print(f"✅ Weather forecast: {len(forecast)} days")
|
|
||||||
return True
|
|
||||||
elif forecast_response.status_code == 503:
|
|
||||||
print("ℹ️ Forecast API unavailable, this is expected in test environment")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
print(f"❌ Weather forecast failed: {forecast_response.status_code}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ Weather tests failed: {e}")
|
|
||||||
traceback.print_exc()
|
|
||||||
return False
|
|
||||||
|
|
||||||
async def test_traffic_endpoints(self) -> bool:
|
|
||||||
"""Probar endpoints de tráfico"""
|
|
||||||
print("🚦 Testing traffic endpoints...")
|
|
||||||
|
|
||||||
try:
|
|
||||||
headers = self.get_headers()
|
|
||||||
madrid_coords = {"latitude": 40.4168, "longitude": -3.7038}
|
|
||||||
|
|
||||||
async with httpx.AsyncClient(timeout=20.0) as client:
|
|
||||||
# Current traffic - FIXED URL
|
|
||||||
if self.use_gateway:
|
|
||||||
current_endpoint = f"{self.base_url}/api/v1/data/traffic/current"
|
|
||||||
else:
|
|
||||||
current_endpoint = f"{self.base_url}/api/v1/traffic/current"
|
|
||||||
|
|
||||||
print(f"🔗 Requesting: {current_endpoint}")
|
|
||||||
current_response = await client.get(
|
|
||||||
current_endpoint,
|
|
||||||
params=madrid_coords,
|
|
||||||
headers=headers
|
|
||||||
)
|
|
||||||
|
|
||||||
if current_response.status_code == 200:
|
|
||||||
traffic = current_response.json()
|
|
||||||
print(f"✅ Current traffic: {traffic.get('traffic_volume')} vehicles, {traffic.get('congestion_level')} congestion")
|
|
||||||
return True
|
|
||||||
elif current_response.status_code == 503:
|
|
||||||
print("ℹ️ Traffic API unavailable, this is expected in test environment")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
print(f"❌ Current traffic failed: {current_response.status_code}")
|
|
||||||
print(f"Response: {current_response.text}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ Traffic tests failed: {e}")
|
|
||||||
traceback.print_exc()
|
|
||||||
return False
|
|
||||||
|
|
||||||
async def test_sales_endpoints(self) -> bool:
|
|
||||||
"""Probar endpoints de ventas"""
|
|
||||||
print("📊 Testing sales endpoints...")
|
|
||||||
|
|
||||||
try:
|
|
||||||
headers = self.get_headers()
|
|
||||||
|
|
||||||
# Usar tenant_id del usuario autenticado
|
|
||||||
tenant_id = self.user_data.get("tenant_id", str(uuid.uuid4()))
|
|
||||||
|
|
||||||
# Datos de prueba
|
|
||||||
sales_data = {
|
|
||||||
"tenant_id": tenant_id,
|
|
||||||
"date": datetime.now().isoformat(),
|
|
||||||
"product_name": "Pan Integral Test",
|
|
||||||
"quantity_sold": 25,
|
|
||||||
"revenue": 37.50,
|
|
||||||
"location_id": "madrid_centro",
|
|
||||||
"source": "test"
|
|
||||||
}
|
|
||||||
|
|
||||||
async with httpx.AsyncClient(timeout=20.0) as client:
|
|
||||||
# Create sales record - FIXED URL
|
|
||||||
if self.use_gateway:
|
|
||||||
create_endpoint = f"{self.base_url}/api/v1/data/sales/"
|
|
||||||
else:
|
|
||||||
create_endpoint = f"{self.base_url}/api/v1/sales/"
|
|
||||||
|
|
||||||
print(f"🔗 Requesting: {create_endpoint}")
|
|
||||||
create_response = await client.post(
|
|
||||||
create_endpoint,
|
|
||||||
json=sales_data,
|
|
||||||
headers=headers
|
|
||||||
)
|
|
||||||
|
|
||||||
if create_response.status_code == 200:
|
|
||||||
record = create_response.json()
|
|
||||||
print(f"✅ Sales record created: ID {record.get('id')}")
|
|
||||||
else:
|
|
||||||
print(f"❌ Sales creation failed: {create_response.status_code}")
|
|
||||||
print(f"Response: {create_response.text}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Test import template
|
|
||||||
if self.use_gateway:
|
|
||||||
template_endpoint = f"{self.base_url}/api/v1/data/sales/import/template/csv"
|
|
||||||
else:
|
|
||||||
template_endpoint = f"{self.base_url}/api/v1/sales/import/template/csv"
|
|
||||||
|
|
||||||
template_response = await client.get(
|
|
||||||
template_endpoint,
|
|
||||||
headers=headers
|
|
||||||
)
|
|
||||||
|
|
||||||
if template_response.status_code == 200:
|
|
||||||
print("✅ Import template generated successfully")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
print(f"❌ Template generation failed: {template_response.status_code}")
|
|
||||||
print(f"Response: {template_response.text}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ Sales tests failed: {e}")
|
|
||||||
traceback.print_exc()
|
|
||||||
return False
|
|
||||||
|
|
||||||
async def test_import_functionality(self) -> bool:
|
|
||||||
"""Probar funcionalidad de importación"""
|
|
||||||
print("📄 Testing import functionality...")
|
|
||||||
|
|
||||||
try:
|
|
||||||
headers = self.get_headers()
|
|
||||||
|
|
||||||
# Usar tenant_id del usuario autenticado
|
|
||||||
tenant_id = self.user_data.get("tenant_id", str(uuid.uuid4()))
|
|
||||||
|
|
||||||
# Crear CSV de prueba
|
|
||||||
csv_content = """fecha,producto,cantidad,ingresos
|
|
||||||
15/01/2024,Pan Integral,25,37.50
|
|
||||||
15/01/2024,Croissant,15,22.50
|
|
||||||
15/01/2024,Café con Leche,10,20.00"""
|
|
||||||
|
|
||||||
# Test CSV import
|
|
||||||
import_data = {
|
|
||||||
"tenant_id": tenant_id,
|
|
||||||
"data_format": "csv",
|
|
||||||
"data": csv_content
|
|
||||||
}
|
|
||||||
|
|
||||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
|
||||||
if self.use_gateway:
|
|
||||||
import_endpoint = f"{self.base_url}/api/v1/data/sales/import/json"
|
|
||||||
else:
|
|
||||||
import_endpoint = f"{self.base_url}/api/v1/sales/import/json"
|
|
||||||
|
|
||||||
print(f"🔗 Requesting: {import_endpoint}")
|
|
||||||
import_response = await client.post(
|
|
||||||
import_endpoint,
|
|
||||||
json=import_data,
|
|
||||||
headers=headers
|
|
||||||
)
|
|
||||||
|
|
||||||
if import_response.status_code == 200:
|
|
||||||
result = import_response.json()
|
|
||||||
if result.get("success"):
|
|
||||||
print(f"✅ CSV import successful: {result.get('records_created')} records created")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
print(f"❌ CSV import failed: {result.get('error')}")
|
|
||||||
return False
|
|
||||||
elif import_response.status_code == 422:
|
|
||||||
print("ℹ️ Import validation error (expected in test environment)")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
print(f"❌ Import request failed: {import_response.status_code}")
|
|
||||||
print(f"Response: {import_response.text}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"❌ Import tests failed: {e}")
|
|
||||||
traceback.print_exc()
|
|
||||||
return False
|
|
||||||
|
|
||||||
async def main():
|
|
||||||
"""Función principal de validación"""
|
|
||||||
print("🚀 Starting Data Service Validation - FIXED VERSION")
|
|
||||||
print("=" * 60)
|
|
||||||
|
|
||||||
# Preguntar si usar gateway
|
|
||||||
use_gateway_input = input("Use API Gateway? (y/N): ").lower()
|
|
||||||
use_gateway = use_gateway_input == 'y'
|
|
||||||
|
|
||||||
if use_gateway:
|
|
||||||
print("📡 Testing via API Gateway")
|
|
||||||
else:
|
|
||||||
print("🔗 Testing direct service connections")
|
|
||||||
|
|
||||||
validator = DataServiceValidator(use_gateway=use_gateway)
|
|
||||||
|
|
||||||
try:
|
|
||||||
# 1. Health checks
|
|
||||||
print("\n" + "="*20 + " HEALTH CHECKS " + "="*20)
|
|
||||||
if not await validator.test_service_health():
|
|
||||||
print("\n❌ Health checks failed. Ensure services are running.")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 2. Authentication
|
|
||||||
print("\n" + "="*20 + " AUTHENTICATION " + "="*20)
|
|
||||||
if not await validator.authenticate():
|
|
||||||
print("\n❌ Authentication failed.")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 3. Weather tests
|
|
||||||
print("\n" + "="*20 + " WEATHER TESTS " + "="*20)
|
|
||||||
if not await validator.test_weather_endpoints():
|
|
||||||
print("\n❌ Weather endpoint tests failed.")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 4. Traffic tests
|
|
||||||
print("\n" + "="*20 + " TRAFFIC TESTS " + "="*20)
|
|
||||||
if not await validator.test_traffic_endpoints():
|
|
||||||
print("\n❌ Traffic endpoint tests failed.")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 5. Sales tests
|
|
||||||
print("\n" + "="*20 + " SALES TESTS " + "="*20)
|
|
||||||
if not await validator.test_sales_endpoints():
|
|
||||||
print("\n❌ Sales endpoint tests failed.")
|
|
||||||
return False
|
|
||||||
|
|
||||||
# 6. Import tests
|
|
||||||
print("\n" + "="*20 + " IMPORT TESTS " + "="*20)
|
|
||||||
if not await validator.test_import_functionality():
|
|
||||||
print("\n❌ Import functionality tests failed.")
|
|
||||||
return False
|
|
||||||
|
|
||||||
print("\n" + "=" * 60)
|
|
||||||
print("🎉 ALL TESTS PASSED! Data Service is working correctly!")
|
|
||||||
print("=" * 60)
|
|
||||||
return True
|
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
print("\n⚠️ Tests interrupted by user")
|
|
||||||
return False
|
|
||||||
except Exception as e:
|
|
||||||
print(f"\n❌ Unexpected error: {e}")
|
|
||||||
print("Traceback:")
|
|
||||||
traceback.print_exc()
|
|
||||||
return False
|
|
||||||
|
|
||||||
def check_dependencies():
|
|
||||||
"""Verificar que las dependencias estén instaladas"""
|
|
||||||
try:
|
|
||||||
import httpx
|
|
||||||
print("✅ httpx is available")
|
|
||||||
except ImportError:
|
|
||||||
print("❌ httpx not found. Install with: pip install httpx")
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print("🔧 Checking dependencies...")
|
|
||||||
|
|
||||||
if not check_dependencies():
|
|
||||||
print("\n💡 Install dependencies with:")
|
|
||||||
print("pip install httpx")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
print("✅ All dependencies available")
|
|
||||||
print()
|
|
||||||
|
|
||||||
# Ejecutar validación
|
|
||||||
success = asyncio.run(main())
|
|
||||||
|
|
||||||
if success:
|
|
||||||
print("\n🎯 Next steps:")
|
|
||||||
print("1. Check logs: docker-compose logs -f data-service")
|
|
||||||
print("2. Connect to DB: docker-compose exec data-db psql -U data_user -d data_db")
|
|
||||||
print("3. Test with real data imports")
|
|
||||||
print("4. Check monitoring: http://localhost:3002")
|
|
||||||
sys.exit(0)
|
|
||||||
else:
|
|
||||||
print("\n🔧 Troubleshooting:")
|
|
||||||
print("1. Check services: docker-compose ps")
|
|
||||||
print("2. Restart services: docker-compose restart")
|
|
||||||
print("3. Check logs: docker-compose logs data-service")
|
|
||||||
print("4. Check gateway logs: docker-compose logs gateway")
|
|
||||||
sys.exit(1)
|
|
||||||
Reference in New Issue
Block a user