Files
query-orchestration/test/text_eula_all_integration_test.sh
Jay Brown 63c12a2f44 Merged in feature/eula.part1 (pull request #206)
eula support

* eula support

* docs
2026-01-22 18:17:27 +00:00

1339 lines
47 KiB
Bash
Executable File

#!/bin/bash
# =============================================================================
# text_eula_all_integration_test.sh
# =============================================================================
#
# DESCRIPTION:
# Comprehensive end-to-end integration test suite for EULA functionality.
# Combines admin and user EULA testing into a unified workflow that tests
# the complete EULA lifecycle including version management, user agreements,
# version upgrades, and compliance reporting.
#
# USAGE:
# ./text_eula_all_integration_test.sh <base_url>
#
# EXAMPLE:
# ./text_eula_all_integration_test.sh http://localhost:8080
#
# REQUIREMENTS:
# - bash 4.0+
# - curl
# - jq (for JSON parsing)
# - The target service must be running with DISABLE_AUTH=true
# - Run './run.compose.userauth.test.sh' or 'task compose:refresh' first
#
# HOW IT WORKS:
# Admin endpoints work normally (using system user) with DISABLE_AUTH=true.
# User endpoints use TestUserMiddleware which allows injecting user identity
# via headers:
# - X-Test-User-Subject: The user's subject ID (required for user endpoints)
# - X-Test-User-Email: The user's email (optional)
#
# API OPERATIONS PERFORMED (in order):
# +-----------------------------------------------------------------------+
# | PHASE 1: CREATE INITIAL EULA VERSION (Admin) |
# +-----------------------------------------------------------------------+
# | Step 1: POST /admin/eula Create new EULA version v1.0 |
# | Step 2: GET /admin/eula List all EULA versions |
# | Step 3: GET /admin/eula/{id} Get specific version by ID |
# +-----------------------------------------------------------------------+
# | PHASE 2: ACTIVATE EULA VERSION (Admin) |
# +-----------------------------------------------------------------------+
# | Step 4: POST /admin/eula/{id}/activate Activate v1.0 |
# | Step 5: GET /admin/eula Verify v1.0 is current |
# | Step 6: GET /eula Verify public endpoint |
# +-----------------------------------------------------------------------+
# | PHASE 3: USER AGREEMENT FLOW |
# +-----------------------------------------------------------------------+
# | Step 7: GET /eula/status Check user hasn't agreed |
# | Step 8: POST /eula/agree User agrees to EULA |
# | Step 9: GET /eula/status Verify user has agreed |
# | Step 10: POST /eula/agree Agree again (idempotent) |
# +-----------------------------------------------------------------------+
# | PHASE 4: MULTIPLE USERS |
# +-----------------------------------------------------------------------+
# | Step 11: POST /eula/agree Second user agrees |
# | Step 12: GET /eula/status Second user status |
# | Step 13: GET /admin/eula/agreements Verify both agreements |
# +-----------------------------------------------------------------------+
# | PHASE 5: CREATE AND ACTIVATE NEW VERSION (Admin) |
# +-----------------------------------------------------------------------+
# | Step 14: POST /admin/eula Create EULA version v2.0 |
# | Step 15: POST /admin/eula/{id}/activate Activate v2.0 |
# | Step 16: GET /admin/eula Verify v2.0 is current |
# +-----------------------------------------------------------------------+
# | PHASE 6: USER VERSION UPGRADE |
# +-----------------------------------------------------------------------+
# | Step 17: GET /eula/status Check user needs re-agreement |
# | Step 18: POST /eula/agree User agrees to v2.0 |
# | Step 19: GET /eula/status Verify user has agreed to v2.0 |
# +-----------------------------------------------------------------------+
# | PHASE 7: UPDATE EULA METADATA (Admin) |
# +-----------------------------------------------------------------------+
# | Step 20: PATCH /admin/eula/{id} Update version metadata |
# | Step 21: GET /admin/eula/{id} Verify update was applied |
# +-----------------------------------------------------------------------+
# | PHASE 8: COMPLIANCE REPORTING (Admin) |
# +-----------------------------------------------------------------------+
# | Step 22: GET /admin/eula/compliance Get compliance report |
# | Step 23: GET /admin/eula/agreements List all agreements |
# +-----------------------------------------------------------------------+
# | PHASE 9: ERROR HANDLING |
# +-----------------------------------------------------------------------+
# | Step 24: GET /eula/status No user header (expect 401) |
# +-----------------------------------------------------------------------+
#
# EXIT CODES:
# 0 - All tests passed
# 1 - Missing dependencies or invalid arguments
# 2 - API call failed
#
# =============================================================================
set -e # Exit on first error
# =============================================================================
# CONFIGURATION
# =============================================================================
# Colors for output (disable if not a terminal)
if [[ -t 1 ]]; then
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
else
RED=''
GREEN=''
YELLOW=''
BLUE=''
CYAN=''
NC=''
fi
# Generate unique identifiers for this test run
TIMESTAMP=$(date +%s)
EULA_VERSION_V1="test-v1.0-${TIMESTAMP}"
EULA_VERSION_V2="test-v2.0-${TIMESTAMP}"
# Test user identities
TEST_USER_1_SUB="test-user-1-${TIMESTAMP}"
TEST_USER_1_EMAIL="user1-${TIMESTAMP}@example.com"
TEST_USER_2_SUB="test-user-2-${TIMESTAMP}"
TEST_USER_2_EMAIL="user2-${TIMESTAMP}@example.com"
# Variables to store IDs across test steps
EULA_VERSION_ID_V1=""
EULA_VERSION_ID_V2=""
# Test counters
STEP_COUNT=0
PASS_COUNT=0
# =============================================================================
# HELPER FUNCTIONS
# =============================================================================
# print_header - Prints a formatted section header
# Parameters:
# $1 - Step number
# $2 - Description
print_header() {
local step="$1"
local desc="$2"
echo ""
echo -e "${BLUE}=== Step ${step}: ${desc} ===${NC}"
STEP_COUNT=$((STEP_COUNT + 1))
}
# print_success - Prints a success message
# Parameters:
# $1 - Message
print_success() {
echo -e "${GREEN}[PASS] $1${NC}"
PASS_COUNT=$((PASS_COUNT + 1))
}
# print_error - Prints an error message and exits
# Parameters:
# $1 - Message
print_error() {
echo -e "${RED}[FAIL] ERROR: $1${NC}"
exit 2
}
# print_warning - Prints a warning message
# Parameters:
# $1 - Message
print_warning() {
echo -e "${YELLOW}[WARN] WARNING: $1${NC}"
}
# print_info - Prints an informational message
# Parameters:
# $1 - Message
print_info() {
echo -e " $1"
}
# print_phase - Prints a phase header
# Parameters:
# $1 - Phase number
# $2 - Phase description
print_phase() {
local phase="$1"
local desc="$2"
echo ""
echo -e "${CYAN}========================================${NC}"
echo -e "${CYAN}PHASE ${phase}: ${desc}${NC}"
echo -e "${CYAN}========================================${NC}"
}
# check_response - Checks if the HTTP response code indicates success
# Parameters:
# $1 - Expected HTTP status code(s) (comma-separated, e.g., "200,201")
# $2 - Actual HTTP status code
# $3 - Response body (for error messages)
# $4 - Endpoint description
check_response() {
local expected="$1"
local actual="$2"
local body="$3"
local desc="$4"
# Check if actual code is in expected list
IFS=',' read -ra CODES <<< "$expected"
for code in "${CODES[@]}"; do
if [[ "$actual" == "$code" ]]; then
return 0
fi
done
echo -e "${RED}[FAIL] FAILED: $desc${NC}"
echo " Expected: $expected, Got: $actual"
echo " Response: $body"
exit 2
}
# api_call - Makes an API call and captures response (no user auth headers)
# Parameters:
# $1 - HTTP method (GET, POST, PATCH, DELETE)
# $2 - Endpoint path (e.g., "/admin/eula")
# $3 - Request body (optional, empty string for none)
# $4 - Content-Type header (optional, defaults to application/json)
# Returns:
# Sets global variables: HTTP_CODE, RESPONSE_BODY
api_call() {
local method="$1"
local endpoint="$2"
local body="$3"
local content_type="${4:-application/json}"
local url="${BASE_URL}${endpoint}"
local curl_opts=(-s -w "\n%{http_code}")
curl_opts+=(-X "$method")
if [[ -n "$body" ]]; then
curl_opts+=(-H "Content-Type: $content_type")
curl_opts+=(-d "$body")
fi
local response
local retries=3
local delay=1
# Retry loop for rate limiting (429 errors)
for ((i=1; i<=retries; i++)); do
response=$(curl "${curl_opts[@]}" "$url")
# Split response into body and status code
HTTP_CODE=$(echo "$response" | tail -n1)
RESPONSE_BODY=$(echo "$response" | sed '$d')
# If not rate limited, break out of retry loop
if [[ "$HTTP_CODE" != "429" ]]; then
break
fi
# Rate limited - wait and retry
if [[ $i -lt $retries ]]; then
print_info "Rate limited (429), waiting ${delay}s before retry $((i+1))/$retries..."
sleep "$delay"
delay=$((delay * 2)) # Exponential backoff
fi
done
# Small delay between all API calls to avoid rate limiting
sleep 0.1
}
# api_call_as_user - Makes an API call with test user headers
# Parameters:
# $1 - HTTP method (GET, POST, PATCH, DELETE)
# $2 - Endpoint path (e.g., "/eula/status")
# $3 - User subject ID
# $4 - User email
# $5 - Request body (optional, empty string for none)
# $6 - Content-Type header (optional, defaults to application/json)
# Returns:
# Sets global variables: HTTP_CODE, RESPONSE_BODY
api_call_as_user() {
local method="$1"
local endpoint="$2"
local user_subject="$3"
local user_email="$4"
local body="$5"
local content_type="${6:-application/json}"
local url="${BASE_URL}${endpoint}"
local curl_opts=(-s -w "\n%{http_code}")
curl_opts+=(-X "$method")
curl_opts+=(-H "X-Test-User-Subject: ${user_subject}")
curl_opts+=(-H "X-Test-User-Email: ${user_email}")
if [[ -n "$body" ]]; then
curl_opts+=(-H "Content-Type: $content_type")
curl_opts+=(-d "$body")
fi
local response
local retries=3
local delay=1
# Retry loop for rate limiting (429 errors)
for ((i=1; i<=retries; i++)); do
response=$(curl "${curl_opts[@]}" "$url")
# Split response into body and status code
HTTP_CODE=$(echo "$response" | tail -n1)
RESPONSE_BODY=$(echo "$response" | sed '$d')
# If not rate limited, break out of retry loop
if [[ "$HTTP_CODE" != "429" ]]; then
break
fi
# Rate limited - wait and retry
if [[ $i -lt $retries ]]; then
print_info "Rate limited (429), waiting ${delay}s before retry $((i+1))/$retries..."
sleep "$delay"
delay=$((delay * 2)) # Exponential backoff
fi
done
# Small delay between all API calls to avoid rate limiting
sleep 0.1
}
# =============================================================================
# VALIDATION
# =============================================================================
# Check for required tools
check_dependencies() {
local missing=()
if ! command -v curl &> /dev/null; then
missing+=("curl")
fi
if ! command -v jq &> /dev/null; then
missing+=("jq")
fi
if [[ ${#missing[@]} -gt 0 ]]; then
echo -e "${RED}ERROR: Missing required tools: ${missing[*]}${NC}"
echo "Please install the missing tools and try again."
exit 1
fi
}
# Validate command line arguments
validate_args() {
if [[ $# -lt 1 ]]; then
echo "Usage: $0 <base_url>"
echo ""
echo "Examples:"
echo " $0 http://localhost:8080"
echo ""
echo "Note: The service must be running with DISABLE_AUTH=true"
echo " Run './run.compose.userauth.test.sh' or 'task compose:refresh' first"
exit 1
fi
BASE_URL="${1%/}" # Remove trailing slash if present
echo -e "${CYAN}========================================${NC}"
echo -e "${CYAN}EULA Complete Integration Test Suite${NC}"
echo -e "${CYAN}========================================${NC}"
echo ""
echo "Base URL: ${BASE_URL}"
echo "Test Run ID: ${TIMESTAMP}"
echo ""
echo "EULA Versions:"
echo " v1: ${EULA_VERSION_V1}"
echo " v2: ${EULA_VERSION_V2}"
echo ""
echo "Test Users (via X-Test-User-Subject header):"
echo " User 1: ${TEST_USER_1_EMAIL} (sub: ${TEST_USER_1_SUB})"
echo " User 2: ${TEST_USER_2_EMAIL} (sub: ${TEST_USER_2_SUB})"
echo ""
}
# =============================================================================
# SAMPLE EULA CONTENT
# =============================================================================
# Generate sample EULA content v1
get_eula_content_v1() {
cat << 'EULA_V1'
# End User License Agreement
**Version 1.0**
## 1. Introduction
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
## 2. Definitions
- **Service**: The software platform and associated services provided by Acme Corporation.
- **User**: Any individual or entity that accesses or uses the Service.
- **Content**: All data, text, images, and other materials uploaded or generated through the Service.
## 3. License Grant
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
### 3.1 Permitted Uses
- Access and use the Service for lawful purposes
- Create, upload, and manage Content within the Service
- Share Content with authorized users
### 3.2 Restrictions
- You may not reverse engineer, decompile, or disassemble the Service
- You may not use the Service for any illegal or unauthorized purpose
- You may not interfere with or disrupt the Service
## 4. Privacy and Data Protection
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
## 5. Limitation of Liability
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
## 6. Governing Law
This Agreement shall be governed by and construed in accordance with the laws of the State of Delaware, without regard to its conflict of law provisions.
## 7. Contact Information
For questions about this Agreement, please contact: legal@acme-corp.example.com
EULA_V1
}
# Generate sample EULA content v2 (updated version)
get_eula_content_v2() {
cat << 'EULA_V2'
# End User License Agreement
**Version 2.0 - Updated Terms**
## 1. Introduction
Lorem ipsum dolor sit amet, consectetur adipiscing elit. This updated agreement includes new provisions for data protection and enhanced user rights. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
## 2. Definitions
- **Service**: The software platform and associated services provided by Acme Corporation.
- **User**: Any individual or entity that accesses or uses the Service.
- **Content**: All data, text, images, and other materials uploaded or generated through the Service.
- **Personal Data**: Any information relating to an identified or identifiable natural person.
## 3. License Grant
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident.
### 3.1 Permitted Uses
- Access and use the Service for lawful purposes
- Create, upload, and manage Content within the Service
- Share Content with authorized users
- Export your data at any time
### 3.2 Restrictions
- You may not reverse engineer, decompile, or disassemble the Service
- You may not use the Service for any illegal or unauthorized purpose
- You may not interfere with or disrupt the Service
- You may not use automated systems to access the Service without permission
## 4. Privacy and Data Protection
### 4.1 Data Collection
We collect and process personal data as described in our Privacy Policy. This includes:
- Account information (name, email, etc.)
- Usage data and analytics
- Content you create within the Service
### 4.2 Data Rights
You have the right to:
- Access your personal data
- Request correction of inaccurate data
- Request deletion of your data
- Export your data in a portable format
## 5. Limitation of Liability
IN NO EVENT SHALL ACME CORPORATION BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES ARISING OUT OF OR RELATED TO YOUR USE OF THE SERVICE.
## 6. Termination
We may terminate or suspend your access to the Service immediately, without prior notice or liability, for any reason.
## 7. Governing Law
This Agreement shall be governed by and construed in accordance with the laws of the State of Delaware, without regard to its conflict of law provisions.
## 8. Changes to This Agreement
We reserve the right to modify this Agreement at any time. We will notify you of any changes by posting the new Agreement on this page.
## 9. Contact Information
For questions about this Agreement, please contact: legal@acme-corp.example.com
EULA_V2
}
# =============================================================================
# PHASE 1: CREATE INITIAL EULA VERSION (Steps 1-3)
# =============================================================================
# Step 1: Create a new EULA version v1.0
step_01_create_eula_v1() {
print_header "1" "Create new EULA version v1.0 via POST /admin/eula"
local effective_date
effective_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
local content
content=$(get_eula_content_v1)
# Escape the content for JSON (handle newlines and special characters)
local escaped_content
escaped_content=$(echo "$content" | jq -Rs '.')
local body
body=$(cat << EOF
{
"version": "${EULA_VERSION_V1}",
"title": "Terms of Service v1.0 - Test ${TIMESTAMP}",
"content": ${escaped_content},
"effectiveDate": "${effective_date}"
}
EOF
)
print_info "Request: POST /admin/eula"
print_info "Version: ${EULA_VERSION_V1}"
api_call "POST" "/admin/eula" "$body"
check_response "201" "$HTTP_CODE" "$RESPONSE_BODY" "Create EULA version v1.0"
EULA_VERSION_ID_V1=$(echo "$RESPONSE_BODY" | jq -r '.id')
local created_version
created_version=$(echo "$RESPONSE_BODY" | jq -r '.version')
local is_current
is_current=$(echo "$RESPONSE_BODY" | jq -r '.isCurrent')
print_success "EULA version v1.0 created successfully"
print_info "Version ID: $EULA_VERSION_ID_V1"
print_info "Version: $created_version"
print_info "Is Current: $is_current"
}
# Step 2: List all EULA versions
step_02_list_eula_versions() {
print_header "2" "List all EULA versions via GET /admin/eula"
print_info "Request: GET /admin/eula"
api_call "GET" "/admin/eula" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "List EULA versions"
local total
total=$(echo "$RESPONSE_BODY" | jq -r '.total')
local versions_count
versions_count=$(echo "$RESPONSE_BODY" | jq '.versions | length')
print_success "EULA versions listed successfully"
print_info "Total versions: $total"
print_info "Versions in response: $versions_count"
# Verify our created version is in the list
local found
found=$(echo "$RESPONSE_BODY" | jq -r --arg id "$EULA_VERSION_ID_V1" '.versions[] | select(.id == $id) | .id')
if [[ "$found" == "$EULA_VERSION_ID_V1" ]]; then
print_success "Newly created EULA version found in list"
else
print_warning "Newly created EULA version not found in list"
fi
}
# Step 3: Get specific EULA version by ID
step_03_get_eula_version() {
print_header "3" "Get specific EULA version via GET /admin/eula/{id}"
print_info "Request: GET /admin/eula/${EULA_VERSION_ID_V1}"
api_call "GET" "/admin/eula/${EULA_VERSION_ID_V1}" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "Get EULA version"
local version
version=$(echo "$RESPONSE_BODY" | jq -r '.version')
local title
title=$(echo "$RESPONSE_BODY" | jq -r '.title')
local content_length
content_length=$(echo "$RESPONSE_BODY" | jq -r '.content | length')
local effective_date
effective_date=$(echo "$RESPONSE_BODY" | jq -r '.effectiveDate')
print_success "EULA version retrieved successfully"
print_info "Version: $version"
print_info "Title: $title"
print_info "Content length: $content_length characters"
print_info "Effective Date: $effective_date"
}
# =============================================================================
# PHASE 2: ACTIVATE EULA VERSION (Steps 4-6)
# =============================================================================
# Step 4: Activate EULA version v1.0
step_04_activate_eula_v1() {
print_header "4" "Activate EULA version v1.0 via POST /admin/eula/{id}/activate"
print_info "Request: POST /admin/eula/${EULA_VERSION_ID_V1}/activate"
api_call "POST" "/admin/eula/${EULA_VERSION_ID_V1}/activate" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "Activate EULA version v1.0"
local is_current
is_current=$(echo "$RESPONSE_BODY" | jq -r '.isCurrent')
local activated_at
activated_at=$(echo "$RESPONSE_BODY" | jq -r '.activatedAt')
if [[ "$is_current" == "true" ]]; then
print_success "EULA version v1.0 activated successfully"
else
print_error "EULA version v1.0 was not marked as current after activation"
fi
print_info "Is Current: $is_current"
print_info "Activated At: $activated_at"
}
# Step 5: Verify v1.0 is the current version
step_05_verify_v1_current() {
print_header "5" "Verify v1.0 is current via GET /admin/eula"
print_info "Request: GET /admin/eula"
api_call "GET" "/admin/eula" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "List EULA versions"
# Find the current version
local current_version_id
current_version_id=$(echo "$RESPONSE_BODY" | jq -r '.versions[] | select(.isCurrent == true) | .id')
local current_version
current_version=$(echo "$RESPONSE_BODY" | jq -r '.versions[] | select(.isCurrent == true) | .version')
if [[ "$current_version_id" == "$EULA_VERSION_ID_V1" ]]; then
print_success "Verified: v1.0 is the current active EULA version"
else
print_error "v1.0 is not the current version. Current: $current_version_id"
fi
print_info "Current version ID: $current_version_id"
print_info "Current version: $current_version"
}
# Step 6: Verify public EULA endpoint
step_06_verify_public_eula() {
print_header "6" "Verify public EULA endpoint via GET /eula"
print_info "Request: GET /eula (no auth required)"
api_call "GET" "/eula" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "Get public EULA"
local version
version=$(echo "$RESPONSE_BODY" | jq -r '.version')
local title
title=$(echo "$RESPONSE_BODY" | jq -r '.title')
if [[ "$version" == "$EULA_VERSION_V1" ]]; then
print_success "Public EULA endpoint returns correct version"
else
print_error "Public EULA endpoint returns wrong version. Expected: $EULA_VERSION_V1, Got: $version"
fi
print_info "Version: $version"
print_info "Title: $title"
}
# =============================================================================
# PHASE 3: USER AGREEMENT FLOW (Steps 7-10)
# =============================================================================
# Step 7: Check user hasn't agreed yet
step_07_check_status_before_agree() {
print_header "7" "Check user EULA status (before agreement) via GET /eula/status"
print_info "Request: GET /eula/status"
print_info "User: ${TEST_USER_1_EMAIL} (via X-Test-User-Subject header)"
api_call_as_user "GET" "/eula/status" "$TEST_USER_1_SUB" "$TEST_USER_1_EMAIL" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "Get EULA status (pre-agreement)"
local has_agreed
has_agreed=$(echo "$RESPONSE_BODY" | jq -r '.hasAgreed')
local current_version
current_version=$(echo "$RESPONSE_BODY" | jq -r '.currentVersion')
if [[ "$has_agreed" == "false" ]]; then
print_success "User has not agreed to EULA (as expected)"
else
print_error "User should not have agreed to EULA yet"
fi
if [[ "$current_version" == "$EULA_VERSION_V1" ]]; then
print_success "Current EULA version matches v1.0"
else
print_error "Current version mismatch. Expected: $EULA_VERSION_V1, Got: $current_version"
fi
print_info "Has Agreed: $has_agreed"
print_info "Current Version: $current_version"
}
# Step 8: User agrees to EULA
step_08_agree_to_eula() {
print_header "8" "User agrees to EULA via POST /eula/agree"
print_info "Request: POST /eula/agree"
print_info "User: ${TEST_USER_1_EMAIL}"
api_call_as_user "POST" "/eula/agree" "$TEST_USER_1_SUB" "$TEST_USER_1_EMAIL" ""
check_response "201" "$HTTP_CODE" "$RESPONSE_BODY" "Agree to EULA"
local agreement_id
agreement_id=$(echo "$RESPONSE_BODY" | jq -r '.id')
local eula_version
eula_version=$(echo "$RESPONSE_BODY" | jq -r '.eulaVersion')
local agreed_at
agreed_at=$(echo "$RESPONSE_BODY" | jq -r '.agreedAt')
print_success "User agreed to EULA successfully"
print_info "Agreement ID: $agreement_id"
print_info "EULA Version: $eula_version"
print_info "Agreed At: $agreed_at"
if [[ "$eula_version" == "$EULA_VERSION_V1" ]]; then
print_success "Agreement recorded for correct EULA version (v1.0)"
else
print_error "Agreement recorded for wrong version. Expected: $EULA_VERSION_V1, Got: $eula_version"
fi
}
# Step 9: Verify user status shows agreed
step_09_check_status_after_agree() {
print_header "9" "Verify user EULA status (after agreement) via GET /eula/status"
print_info "Request: GET /eula/status"
print_info "User: ${TEST_USER_1_EMAIL}"
api_call_as_user "GET" "/eula/status" "$TEST_USER_1_SUB" "$TEST_USER_1_EMAIL" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "Get EULA status (post-agreement)"
local has_agreed
has_agreed=$(echo "$RESPONSE_BODY" | jq -r '.hasAgreed')
local agreed_version
agreed_version=$(echo "$RESPONSE_BODY" | jq -r '.agreedVersion')
if [[ "$has_agreed" == "true" ]]; then
print_success "User has agreed to EULA (status updated correctly)"
else
print_error "User status should show hasAgreed=true after agreeing"
fi
if [[ "$agreed_version" == "$EULA_VERSION_V1" ]]; then
print_success "Agreed version matches v1.0"
else
print_error "Agreed version mismatch. Expected: $EULA_VERSION_V1, Got: $agreed_version"
fi
print_info "Has Agreed: $has_agreed"
print_info "Agreed Version: $agreed_version"
}
# Step 10: Agree again (should be idempotent, return 200)
step_10_agree_again_idempotent() {
print_header "10" "Test idempotency - User agrees again via POST /eula/agree"
print_info "Request: POST /eula/agree (second time)"
print_info "User: ${TEST_USER_1_EMAIL}"
api_call_as_user "POST" "/eula/agree" "$TEST_USER_1_SUB" "$TEST_USER_1_EMAIL" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "Agree to EULA (idempotent)"
if [[ "$HTTP_CODE" == "200" ]]; then
print_success "Idempotency confirmed: Second agreement returns 200 (already agreed)"
else
print_warning "Expected 200 for idempotent call, got $HTTP_CODE"
fi
print_info "Response: Same agreement returned"
}
# =============================================================================
# PHASE 4: MULTIPLE USERS (Steps 11-13)
# =============================================================================
# Step 11: Second user agrees
step_11_second_user_agrees() {
print_header "11" "Second user agrees to EULA via POST /eula/agree"
print_info "Request: POST /eula/agree"
print_info "User: ${TEST_USER_2_EMAIL}"
api_call_as_user "POST" "/eula/agree" "$TEST_USER_2_SUB" "$TEST_USER_2_EMAIL" ""
check_response "201" "$HTTP_CODE" "$RESPONSE_BODY" "Second user agrees to EULA"
local agreement_id
agreement_id=$(echo "$RESPONSE_BODY" | jq -r '.id')
local eula_version
eula_version=$(echo "$RESPONSE_BODY" | jq -r '.eulaVersion')
print_success "Second user agreed to EULA successfully"
print_info "Agreement ID: $agreement_id"
print_info "EULA Version: $eula_version"
}
# Step 12: Verify second user status
step_12_second_user_status() {
print_header "12" "Verify second user EULA status via GET /eula/status"
print_info "Request: GET /eula/status"
print_info "User: ${TEST_USER_2_EMAIL}"
api_call_as_user "GET" "/eula/status" "$TEST_USER_2_SUB" "$TEST_USER_2_EMAIL" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "Get second user EULA status"
local has_agreed
has_agreed=$(echo "$RESPONSE_BODY" | jq -r '.hasAgreed')
local agreed_version
agreed_version=$(echo "$RESPONSE_BODY" | jq -r '.agreedVersion')
if [[ "$has_agreed" == "true" ]]; then
print_success "Second user has agreed to EULA"
else
print_error "Second user status should show hasAgreed=true"
fi
print_info "Has Agreed: $has_agreed"
print_info "Agreed Version: $agreed_version"
}
# Step 13: Verify both agreements appear in admin list
step_13_verify_both_agreements() {
print_header "13" "Verify both agreements via GET /admin/eula/agreements"
print_info "Request: GET /admin/eula/agreements?version_id=${EULA_VERSION_ID_V1}"
api_call "GET" "/admin/eula/agreements?version_id=${EULA_VERSION_ID_V1}" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "List EULA agreements"
local total
total=$(echo "$RESPONSE_BODY" | jq -r '.total')
local agreements_count
agreements_count=$(echo "$RESPONSE_BODY" | jq '.agreements | length')
print_info "Total agreements for v1.0: $total"
print_info "Agreements in response: $agreements_count"
# Check for both users
local user1_found
user1_found=$(echo "$RESPONSE_BODY" | jq -r --arg email "$TEST_USER_1_EMAIL" '.agreements[] | select(.userEmail == $email) | .userEmail')
local user2_found
user2_found=$(echo "$RESPONSE_BODY" | jq -r --arg email "$TEST_USER_2_EMAIL" '.agreements[] | select(.userEmail == $email) | .userEmail')
if [[ "$user1_found" == "$TEST_USER_1_EMAIL" ]]; then
print_success "User 1 agreement found in list"
else
print_error "User 1 agreement not found in list"
fi
if [[ "$user2_found" == "$TEST_USER_2_EMAIL" ]]; then
print_success "User 2 agreement found in list"
else
print_error "User 2 agreement not found in list"
fi
}
# =============================================================================
# PHASE 5: CREATE AND ACTIVATE NEW VERSION (Steps 14-16)
# =============================================================================
# Step 14: Create EULA version v2.0
step_14_create_eula_v2() {
print_header "14" "Create new EULA version v2.0 via POST /admin/eula"
local effective_date
effective_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
local content
content=$(get_eula_content_v2)
# Escape the content for JSON
local escaped_content
escaped_content=$(echo "$content" | jq -Rs '.')
local body
body=$(cat << EOF
{
"version": "${EULA_VERSION_V2}",
"title": "Terms of Service v2.0 - Updated - Test ${TIMESTAMP}",
"content": ${escaped_content},
"effectiveDate": "${effective_date}"
}
EOF
)
print_info "Request: POST /admin/eula"
print_info "Version: ${EULA_VERSION_V2}"
api_call "POST" "/admin/eula" "$body"
check_response "201" "$HTTP_CODE" "$RESPONSE_BODY" "Create EULA version v2.0"
EULA_VERSION_ID_V2=$(echo "$RESPONSE_BODY" | jq -r '.id')
local created_version
created_version=$(echo "$RESPONSE_BODY" | jq -r '.version')
local is_current
is_current=$(echo "$RESPONSE_BODY" | jq -r '.isCurrent')
print_success "EULA version v2.0 created successfully"
print_info "Version ID: $EULA_VERSION_ID_V2"
print_info "Version: $created_version"
print_info "Is Current: $is_current (should be false, v1.0 is still active)"
}
# Step 15: Activate EULA version v2.0
step_15_activate_eula_v2() {
print_header "15" "Activate EULA version v2.0 via POST /admin/eula/{id}/activate"
print_info "Request: POST /admin/eula/${EULA_VERSION_ID_V2}/activate"
api_call "POST" "/admin/eula/${EULA_VERSION_ID_V2}/activate" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "Activate EULA version v2.0"
local is_current
is_current=$(echo "$RESPONSE_BODY" | jq -r '.isCurrent')
local activated_at
activated_at=$(echo "$RESPONSE_BODY" | jq -r '.activatedAt')
if [[ "$is_current" == "true" ]]; then
print_success "EULA version v2.0 activated successfully"
else
print_error "EULA version v2.0 was not marked as current after activation"
fi
print_info "Is Current: $is_current"
print_info "Activated At: $activated_at"
}
# Step 16: Verify v2.0 is now current and v1.0 is no longer current
step_16_verify_v2_current() {
print_header "16" "Verify v2.0 is current and v1.0 is not via GET /admin/eula"
print_info "Request: GET /admin/eula"
api_call "GET" "/admin/eula" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "List EULA versions"
# Find the current version
local current_version_id
current_version_id=$(echo "$RESPONSE_BODY" | jq -r '.versions[] | select(.isCurrent == true) | .id')
local current_version
current_version=$(echo "$RESPONSE_BODY" | jq -r '.versions[] | select(.isCurrent == true) | .version')
# Check v1.0 is no longer current
local v1_is_current
v1_is_current=$(echo "$RESPONSE_BODY" | jq -r --arg id "$EULA_VERSION_ID_V1" '.versions[] | select(.id == $id) | .isCurrent')
if [[ "$current_version_id" == "$EULA_VERSION_ID_V2" ]]; then
print_success "Verified: v2.0 is the current active EULA version"
else
print_error "v2.0 is not the current version. Current: $current_version_id"
fi
if [[ "$v1_is_current" == "false" ]]; then
print_success "Verified: v1.0 is no longer the current version"
else
print_warning "v1.0 still shows as current: $v1_is_current"
fi
print_info "Current version ID: $current_version_id"
print_info "Current version: $current_version"
}
# =============================================================================
# PHASE 6: USER VERSION UPGRADE (Steps 17-19)
# =============================================================================
# Step 17: Check user needs to re-agree for new version
step_17_check_needs_reagree() {
print_header "17" "Check user needs re-agreement for v2.0 via GET /eula/status"
print_info "Request: GET /eula/status"
print_info "User: ${TEST_USER_1_EMAIL}"
api_call_as_user "GET" "/eula/status" "$TEST_USER_1_SUB" "$TEST_USER_1_EMAIL" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "Get EULA status for version upgrade check"
local has_agreed
has_agreed=$(echo "$RESPONSE_BODY" | jq -r '.hasAgreed')
local current_version
current_version=$(echo "$RESPONSE_BODY" | jq -r '.currentVersion')
local agreed_version
agreed_version=$(echo "$RESPONSE_BODY" | jq -r '.agreedVersion')
# User agreed to v1.0, but current is now v2.0
# hasAgreed should be false (needs to re-agree)
if [[ "$has_agreed" == "false" ]]; then
print_success "User correctly shows as not agreed (needs to agree to new version)"
else
# Some implementations may keep hasAgreed=true if agreed to any version
print_warning "User shows hasAgreed=$has_agreed (implementation may vary)"
fi
if [[ "$current_version" == "$EULA_VERSION_V2" ]]; then
print_success "Current version is v2.0"
else
print_error "Current version mismatch. Expected: $EULA_VERSION_V2, Got: $current_version"
fi
print_info "Has Agreed: $has_agreed"
print_info "Current Version: $current_version"
print_info "Previously Agreed Version: $agreed_version"
}
# Step 18: User agrees to v2.0
step_18_agree_to_v2() {
print_header "18" "User agrees to v2.0 via POST /eula/agree"
print_info "Request: POST /eula/agree"
print_info "User: ${TEST_USER_1_EMAIL}"
api_call_as_user "POST" "/eula/agree" "$TEST_USER_1_SUB" "$TEST_USER_1_EMAIL" ""
check_response "201" "$HTTP_CODE" "$RESPONSE_BODY" "Agree to EULA v2.0"
local eula_version
eula_version=$(echo "$RESPONSE_BODY" | jq -r '.eulaVersion')
if [[ "$eula_version" == "$EULA_VERSION_V2" ]]; then
print_success "User agreed to v2.0 successfully"
else
print_error "Agreement should be for v2.0. Got: $eula_version"
fi
print_info "EULA Version: $eula_version"
}
# Step 19: Verify user status for v2.0
step_19_verify_v2_agreement() {
print_header "19" "Verify user agreed to v2.0 via GET /eula/status"
print_info "Request: GET /eula/status"
print_info "User: ${TEST_USER_1_EMAIL}"
api_call_as_user "GET" "/eula/status" "$TEST_USER_1_SUB" "$TEST_USER_1_EMAIL" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "Get EULA status after v2.0 agreement"
local has_agreed
has_agreed=$(echo "$RESPONSE_BODY" | jq -r '.hasAgreed')
local agreed_version
agreed_version=$(echo "$RESPONSE_BODY" | jq -r '.agreedVersion')
if [[ "$has_agreed" == "true" ]]; then
print_success "User has agreed to current EULA"
else
print_error "User status should show hasAgreed=true"
fi
if [[ "$agreed_version" == "$EULA_VERSION_V2" ]]; then
print_success "Agreed version is v2.0"
else
print_error "Agreed version mismatch. Expected: $EULA_VERSION_V2, Got: $agreed_version"
fi
print_info "Has Agreed: $has_agreed"
print_info "Agreed Version: $agreed_version"
}
# =============================================================================
# PHASE 7: UPDATE EULA METADATA (Steps 20-21)
# =============================================================================
# Step 20: Update EULA version metadata
step_20_update_eula_metadata() {
print_header "20" "Update EULA version metadata via PATCH /admin/eula/{id}"
local new_effective_date
new_effective_date=$(date -u -d "+30 days" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u -v+30d +"%Y-%m-%dT%H:%M:%SZ")
local body
body=$(cat << EOF
{
"title": "Terms of Service v2.0 - UPDATED TITLE - Test ${TIMESTAMP}",
"effectiveDate": "${new_effective_date}"
}
EOF
)
print_info "Request: PATCH /admin/eula/${EULA_VERSION_ID_V2}"
print_info "New Title: Terms of Service v2.0 - UPDATED TITLE - Test ${TIMESTAMP}"
api_call "PATCH" "/admin/eula/${EULA_VERSION_ID_V2}" "$body"
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "Update EULA version metadata"
local updated_title
updated_title=$(echo "$RESPONSE_BODY" | jq -r '.title')
print_success "EULA version metadata updated successfully"
print_info "Updated Title: $updated_title"
}
# Step 21: Verify the update was applied
step_21_verify_update() {
print_header "21" "Verify update was applied via GET /admin/eula/{id}"
print_info "Request: GET /admin/eula/${EULA_VERSION_ID_V2}"
api_call "GET" "/admin/eula/${EULA_VERSION_ID_V2}" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "Get updated EULA version"
local title
title=$(echo "$RESPONSE_BODY" | jq -r '.title')
if [[ "$title" == *"UPDATED TITLE"* ]]; then
print_success "Verified: Title was updated correctly"
else
print_error "Title was not updated correctly. Got: $title"
fi
print_info "Title: $title"
}
# =============================================================================
# PHASE 8: COMPLIANCE REPORTING (Steps 22-23)
# =============================================================================
# Step 22: Get EULA compliance report
step_22_get_compliance_report() {
print_header "22" "Get EULA compliance report via GET /admin/eula/compliance"
print_info "Request: GET /admin/eula/compliance"
api_call "GET" "/admin/eula/compliance" ""
# Compliance report may return:
# - 200: Success with compliance data
# - 502: Cognito unavailable or misconfigured (acceptable in test environments)
if [[ "$HTTP_CODE" == "200" ]]; then
local total_users
total_users=$(echo "$RESPONSE_BODY" | jq -r '.summary.totalUsers')
local agreed_count
agreed_count=$(echo "$RESPONSE_BODY" | jq -r '.summary.agreedCount')
local not_agreed_count
not_agreed_count=$(echo "$RESPONSE_BODY" | jq -r '.summary.notAgreedCount')
local compliance_pct
compliance_pct=$(echo "$RESPONSE_BODY" | jq -r '.summary.compliancePercentage')
local eula_version
eula_version=$(echo "$RESPONSE_BODY" | jq -r '.eulaVersion.version')
print_success "EULA compliance report retrieved successfully"
print_info "EULA Version: $eula_version"
print_info "Total Users: $total_users"
print_info "Agreed: $agreed_count"
print_info "Not Agreed: $not_agreed_count"
print_info "Compliance: ${compliance_pct}%"
elif [[ "$HTTP_CODE" == "502" ]]; then
print_warning "Compliance report returned 502 - Cognito unavailable or misconfigured"
print_info "This may happen in local testing if Cognito credentials are not configured."
else
check_response "200,502" "$HTTP_CODE" "$RESPONSE_BODY" "Get compliance report"
fi
}
# Step 23: List EULA agreements
step_23_list_all_agreements() {
print_header "23" "List all EULA agreements via GET /admin/eula/agreements"
print_info "Request: GET /admin/eula/agreements"
api_call "GET" "/admin/eula/agreements" ""
check_response "200" "$HTTP_CODE" "$RESPONSE_BODY" "List EULA agreements"
local total
total=$(echo "$RESPONSE_BODY" | jq -r '.total')
local agreements_count
agreements_count=$(echo "$RESPONSE_BODY" | jq '.agreements | length')
print_success "EULA agreements listed successfully"
print_info "Total agreements: $total"
print_info "Agreements in response: $agreements_count"
if [[ $agreements_count -gt 0 ]]; then
print_info "Agreements:"
echo "$RESPONSE_BODY" | jq -r '.agreements[] | " - User: \(.userEmail), Version: \(.eulaVersion), Agreed: \(.agreedAt)"'
fi
}
# =============================================================================
# PHASE 9: ERROR HANDLING (Step 24)
# =============================================================================
# Step 24: Test missing user header returns 401
step_24_test_no_user_header() {
print_header "24" "Test missing user header via GET /eula/status (expect 401)"
print_info "Request: GET /eula/status (no X-Test-User-Subject header)"
api_call "GET" "/eula/status" ""
if [[ "$HTTP_CODE" == "401" ]]; then
print_success "Missing user header correctly returns 401 Unauthorized"
else
print_error "Expected 401 for missing user header, got $HTTP_CODE"
fi
print_info "HTTP Code: $HTTP_CODE"
}
# =============================================================================
# MAIN EXECUTION
# =============================================================================
main() {
check_dependencies
validate_args "$@"
# Phase 1: Create Initial EULA Version
print_phase "1" "CREATE INITIAL EULA VERSION (Admin)"
step_01_create_eula_v1
step_02_list_eula_versions
step_03_get_eula_version
# Phase 2: Activate EULA Version
print_phase "2" "ACTIVATE EULA VERSION (Admin)"
step_04_activate_eula_v1
step_05_verify_v1_current
step_06_verify_public_eula
# Phase 3: User Agreement Flow
print_phase "3" "USER AGREEMENT FLOW"
step_07_check_status_before_agree
step_08_agree_to_eula
step_09_check_status_after_agree
step_10_agree_again_idempotent
# Phase 4: Multiple Users
print_phase "4" "MULTIPLE USERS"
step_11_second_user_agrees
step_12_second_user_status
step_13_verify_both_agreements
# Phase 5: Create and Activate New Version
print_phase "5" "CREATE AND ACTIVATE NEW VERSION (Admin)"
step_14_create_eula_v2
step_15_activate_eula_v2
step_16_verify_v2_current
# Phase 6: User Version Upgrade
print_phase "6" "USER VERSION UPGRADE"
step_17_check_needs_reagree
step_18_agree_to_v2
step_19_verify_v2_agreement
# Phase 7: Update EULA Metadata
print_phase "7" "UPDATE EULA METADATA (Admin)"
step_20_update_eula_metadata
step_21_verify_update
# Phase 8: Compliance Reporting
print_phase "8" "COMPLIANCE REPORTING (Admin)"
step_22_get_compliance_report
step_23_list_all_agreements
# Phase 9: Error Handling
print_phase "9" "ERROR HANDLING"
step_24_test_no_user_header
# Summary
echo ""
echo -e "${CYAN}========================================${NC}"
echo -e "${GREEN}All EULA integration tests completed!${NC}"
echo -e "${CYAN}========================================${NC}"
echo ""
echo "Summary:"
echo " Test Run ID: $TIMESTAMP"
echo " Total Steps: $STEP_COUNT"
echo " Passed Checks: $PASS_COUNT"
echo ""
echo "EULA Versions Created:"
echo " v1: ${EULA_VERSION_V1} (ID: ${EULA_VERSION_ID_V1})"
echo " v2: ${EULA_VERSION_V2} (ID: ${EULA_VERSION_ID_V2})"
echo " Current Active: v2.0"
echo ""
echo "Test Users:"
echo " User 1: ${TEST_USER_1_EMAIL}"
echo " - Subject: ${TEST_USER_1_SUB}"
echo " - Agreed to: v1.0, v2.0"
echo " User 2: ${TEST_USER_2_EMAIL}"
echo " - Subject: ${TEST_USER_2_SUB}"
echo " - Agreed to: v1.0"
echo ""
echo "Tests performed:"
echo " Admin:"
echo " - Created EULA versions v1.0 and v2.0"
echo " - Activated v1.0, then v2.0"
echo " - Updated v2.0 metadata"
echo " - Verified compliance report endpoint"
echo " - Verified agreements list endpoint"
echo " User:"
echo " - Verified public EULA endpoint"
echo " - Checked status before/after agreement"
echo " - Tested agreement idempotency"
echo " - Tested multiple users agreeing"
echo " - Tested version upgrade flow (v1->v2)"
echo " - Tested 401 for missing user header"
echo ""
}
# Run main function with all arguments
main "$@"