Reorganize test files

This commit is contained in:
Urtzi Alfaro
2025-07-27 16:36:56 +02:00
parent e63a99b818
commit 280d356a51
6 changed files with 0 additions and 1337 deletions

149
check.sh
View File

@@ -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

View File

@@ -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!"

View File

@@ -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}"

View File

@@ -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!"

View File

@@ -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)