Files
work-club-manager/.sisyphus/evidence/final-qa/phase5-integration-journey.sh
WorkClub Automation ffc4062eba fix: exempt /api/clubs/me from tenant validation
- Add path exemption in TenantValidationMiddleware for /api/clubs/me
- Change authorization policy from RequireMember to RequireViewer
- Fix KEYCLOAK_CLIENT_ID in docker-compose.yml (workclub-app not workclub-api)
- Endpoint now works without X-Tenant-Id header as intended
- Other endpoints still protected by tenant validation

This fixes the chicken-and-egg problem where frontend needs to call
/api/clubs/me to discover available clubs before selecting a tenant.
2026-03-05 21:32:37 +01:00

159 lines
5.8 KiB
Bash
Executable File

#!/bin/bash
# Phase 5: Cross-Task Integration Journey (Scenarios 42-51)
# 10-step end-to-end workflow testing via API
source /tmp/qa-test-env.sh
echo "=========================================="
echo "Phase 5: Integration Journey (S42-S51)"
echo "=========================================="
echo ""
# Step 1-2: Login as admin, select Tennis Club (already authenticated via tokens)
echo "=== STEP 1-2: Admin Authentication + Tennis Club Context ==="
echo "Token: ${TOKEN_ADMIN:0:20}..."
echo "Tenant: $TENANT_TENNIS (Tennis Club)"
echo "✅ Using pre-acquired admin token with Tennis Club context"
echo ""
# Step 3: Create task "Replace court net"
echo "=== STEP 3: Create Task 'Replace court net' ==="
CREATE_RESULT=$(curl -s -X POST "$API_BASE/api/tasks" \
-H "Authorization: Bearer $TOKEN_ADMIN" \
-H "X-Tenant-Id: $TENANT_TENNIS" \
-H "Content-Type: application/json" \
-d '{
"title": "Replace court net",
"description": "Replace worn center court net with new professional-grade net",
"dueDate": "2026-03-20T23:59:59Z"
}')
JOURNEY_TASK_ID=$(echo $CREATE_RESULT | jq -r '.id')
echo "Created task ID: $JOURNEY_TASK_ID"
echo $CREATE_RESULT | jq '.'
echo ""
# Step 4: Assign to member1
echo "=== STEP 4: Assign Task to member1 ==="
# Get member1's user ID from token
MEMBER1_SUB=$(curl -s -X POST "$AUTH_URL" \
-d "client_id=workclub-app" \
-d "grant_type=password" \
-d "username=$USER_MEMBER1" \
-d "password=$PASSWORD" | jq -r '.access_token' | cut -d'.' -f2 | base64 -d 2>/dev/null | jq -r '.sub')
echo "Member1 sub: $MEMBER1_SUB"
ASSIGN_RESULT=$(curl -s -X PATCH "$API_BASE/api/tasks/$JOURNEY_TASK_ID" \
-H "Authorization: Bearer $TOKEN_ADMIN" \
-H "X-Tenant-Id: $TENANT_TENNIS" \
-H "Content-Type: application/json" \
-d "{\"status\":\"Assigned\",\"assigneeId\":\"$MEMBER1_SUB\"}")
echo "Task assigned:"
echo $ASSIGN_RESULT | jq '.'
echo ""
# Step 5: Login as member1, transition Open → InProgress
echo "=== STEP 5: Member1 Transitions Assigned → InProgress ==="
PROGRESS_RESULT=$(curl -s -X PATCH "$API_BASE/api/tasks/$JOURNEY_TASK_ID" \
-H "Authorization: Bearer $TOKEN_MEMBER1" \
-H "X-Tenant-Id: $TENANT_TENNIS" \
-H "Content-Type: application/json" \
-d '{"status":"InProgress"}')
echo "Transitioned to InProgress:"
echo $PROGRESS_RESULT | jq '.'
echo ""
# Step 6: Transition InProgress → Review
echo "=== STEP 6: Member1 Transitions InProgress → Review ==="
REVIEW_RESULT=$(curl -s -X PATCH "$API_BASE/api/tasks/$JOURNEY_TASK_ID" \
-H "Authorization: Bearer $TOKEN_MEMBER1" \
-H "X-Tenant-Id: $TENANT_TENNIS" \
-H "Content-Type: application/json" \
-d '{"status":"Review"}')
echo "Transitioned to Review:"
echo $REVIEW_RESULT | jq '.'
echo ""
# Step 7: Login as admin, transition Review → Done
echo "=== STEP 7: Admin Approves - Review → Done ==="
DONE_RESULT=$(curl -s -X PATCH "$API_BASE/api/tasks/$JOURNEY_TASK_ID" \
-H "Authorization: Bearer $TOKEN_ADMIN" \
-H "X-Tenant-Id: $TENANT_TENNIS" \
-H "Content-Type: application/json" \
-d '{"status":"Done"}')
echo "Task completed:"
echo $DONE_RESULT | jq '.'
echo ""
# Step 8: Switch to Cycling Club
echo "=== STEP 8: Switch Context to Cycling Club ==="
echo "New Tenant: $TENANT_CYCLING (Cycling Club)"
echo ""
# Step 9: Verify Tennis tasks NOT visible in Cycling Club
echo "=== STEP 9: Verify Tenant Isolation - Tennis Task Invisible ==="
ISOLATION_CHECK=$(curl -s "$API_BASE/api/tasks/$JOURNEY_TASK_ID" \
-H "Authorization: Bearer $TOKEN_ADMIN" \
-H "X-Tenant-Id: $TENANT_CYCLING")
ISOLATION_STATUS=$(curl -s -w "%{http_code}" -o /dev/null "$API_BASE/api/tasks/$JOURNEY_TASK_ID" \
-H "Authorization: Bearer $TOKEN_ADMIN" \
-H "X-Tenant-Id: $TENANT_CYCLING")
echo "Attempting to access Tennis task from Cycling Club context..."
echo "HTTP Status: $ISOLATION_STATUS"
if [ "$ISOLATION_STATUS" = "404" ]; then
echo "✅ PASS: Task correctly isolated (404 Not Found)"
else
echo "❌ FAIL: Task visible across tenants (security issue!)"
echo "Response: $ISOLATION_CHECK"
fi
echo ""
# Step 10: Create shift in Cycling Club, sign up, verify capacity
echo "=== STEP 10: Cycling Club - Create Shift + Signup ==="
SHIFT_RESULT=$(curl -s -X POST "$API_BASE/api/shifts" \
-H "Authorization: Bearer $TOKEN_ADMIN" \
-H "X-Tenant-Id: $TENANT_CYCLING" \
-H "Content-Type: application/json" \
-d '{
"title": "Bike Maintenance Workshop",
"description": "Monthly bike maintenance and repair workshop",
"startTime": "2026-03-22T10:00:00Z",
"endTime": "2026-03-22T14:00:00Z",
"capacity": 2,
"requiredRole": "Member"
}')
JOURNEY_SHIFT_ID=$(echo $SHIFT_RESULT | jq -r '.id')
echo "Created shift ID: $JOURNEY_SHIFT_ID"
echo $SHIFT_RESULT | jq '.'
echo ""
echo "Signing up member1 for shift..."
SIGNUP_RESULT=$(curl -s -w "\nHTTP:%{http_code}" -X POST "$API_BASE/api/shifts/$JOURNEY_SHIFT_ID/signup" \
-H "Authorization: Bearer $TOKEN_MEMBER1" \
-H "X-Tenant-Id: $TENANT_CYCLING")
echo "$SIGNUP_RESULT"
echo ""
echo "Verifying shift capacity (1/2 filled)..."
SHIFT_CHECK=$(curl -s "$API_BASE/api/shifts/$JOURNEY_SHIFT_ID" \
-H "Authorization: Bearer $TOKEN_ADMIN" \
-H "X-Tenant-Id: $TENANT_CYCLING")
SIGNUP_COUNT=$(echo $SHIFT_CHECK | jq '.signups | length')
echo "Current signups: $SIGNUP_COUNT / 2"
if [ "$SIGNUP_COUNT" = "1" ]; then
echo "✅ PASS: Signup recorded correctly"
else
echo "❌ FAIL: Signup count mismatch"
fi
echo ""
echo "=========================================="
echo "Integration Journey Complete!"
echo "=========================================="
echo "Summary:"
echo " - Created task in Tennis Club: $JOURNEY_TASK_ID"
echo " - Assigned to member1, progressed through all states"
echo " - Verified tenant isolation (Tennis task invisible from Cycling)"
echo " - Created shift in Cycling Club: $JOURNEY_SHIFT_ID"
echo " - Verified shift signup and capacity tracking"
echo ""