Files
query-orchestration/api/queryAPI/eulaHandlers_test.go
T
Jay Brown 62b5de5722 Merged in bug/eula-email (pull request #212)
fix eula issue when email not present in jwt

* bug fix
2026-02-26 21:46:00 +00:00

826 lines
27 KiB
Go

package queryapi_test
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"
queryapi "queryorchestration/api/queryAPI"
"queryorchestration/internal/cognitoauth"
"queryorchestration/internal/eula"
"queryorchestration/internal/test"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
"github.com/oapi-codegen/nullable"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// ptrTime is a helper to create a pointer to a time.Time value.
func ptrTime(t time.Time) *time.Time {
return &t
}
// setupEulaTestContext creates an echo context with the specified path and method.
func setupEulaTestContext(method, path string, body interface{}) (echo.Context, *httptest.ResponseRecorder) {
e := echo.New()
var req *http.Request
if body != nil {
jsonBody, _ := json.Marshal(body)
req = httptest.NewRequest(method, path, bytes.NewReader(jsonBody))
req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON)
} else {
req = httptest.NewRequest(method, path, nil)
}
rec := httptest.NewRecorder()
ctx := e.NewContext(req, rec)
return ctx, rec
}
// setupEulaTestContextWithUser creates an echo context with user info set.
func setupEulaTestContextWithUser(method, path string, body interface{}, userSubject, userEmail string) (echo.Context, *httptest.ResponseRecorder) {
ctx, rec := setupEulaTestContext(method, path, body)
// Set up user info in context (simulating authenticated user)
// Note: GetUserSubject expects map[string]interface{} with "sub" key
// Note: GetUserInfo expects cognitoauth.UserInfo (not pointer)
ctx.Set("user_claims", map[string]interface{}{
"sub": userSubject,
"email": userEmail,
})
ctx.Set("user_info", cognitoauth.UserInfo{
Email: userEmail,
})
return ctx, rec
}
// createTestEulaVersion creates a test EULA version in the database.
func createTestEulaVersion(t *testing.T, svc *eula.Service, version, title string, activate bool) *uuid.UUID {
ctx := t.Context()
input := &eula.CreateVersionInput{
Version: version,
Title: title,
Content: "# Test EULA\n\nThis is test content.",
EffectiveDate: ptrTime(time.Now()),
CreatedBy: "admin@test.com",
}
created, err := svc.CreateVersion(ctx, input)
require.NoError(t, err)
if activate {
_, err = svc.ActivateVersion(ctx, created.ID, "admin@test.com")
require.NoError(t, err)
}
return &created.ID
}
func TestGetCurrentEula(t *testing.T) {
cfg := &ControllerConfig{}
test.CreateDB(t, cfg)
initializeTestConfig(t, cfg)
svc := createControllerServices(cfg)
cons := queryapi.NewControllers(svc, cfg)
t.Run("returns current EULA version", func(t *testing.T) {
// Create and activate a version
versionStr := "1.0.0-test-" + uuid.New().String()[:8]
createTestEulaVersion(t, svc.Eula, versionStr, "Test EULA", true)
ctx, rec := setupEulaTestContext(http.MethodGet, "/eula", nil)
err := cons.GetCurrentEula(ctx)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
var response queryapi.EulaPublicResponse
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
assert.Equal(t, versionStr, response.Version)
})
t.Run("returns 404 when no current version", func(t *testing.T) {
// Create a new config without any EULA versions activated
cfg2 := &ControllerConfig{}
test.CreateDB(t, cfg2)
initializeTestConfig(t, cfg2)
svc2 := createControllerServices(cfg2)
cons2 := queryapi.NewControllers(svc2, cfg2)
ctx, rec := setupEulaTestContext(http.MethodGet, "/eula", nil)
err := cons2.GetCurrentEula(ctx)
require.NoError(t, err)
assert.Equal(t, http.StatusNotFound, rec.Code)
})
}
func TestGetEulaStatus(t *testing.T) {
cfg := &ControllerConfig{}
test.CreateDB(t, cfg)
initializeTestConfig(t, cfg)
svc := createControllerServices(cfg)
cons := queryapi.NewControllers(svc, cfg)
// Create and activate a version
versionStr := "status-test-" + uuid.New().String()[:8]
versionID := createTestEulaVersion(t, svc.Eula, versionStr, "Status Test EULA", true)
t.Run("returns status for unagreed user", func(t *testing.T) {
userSubject := "user-" + uuid.New().String()[:8]
ctx, rec := setupEulaTestContextWithUser(http.MethodGet, "/eula/status", nil, userSubject, "user@test.com")
err := cons.GetEulaStatus(ctx)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
var response queryapi.EulaStatusResponse
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
assert.False(t, response.HasAgreed)
assert.Equal(t, versionStr, response.CurrentVersion)
})
t.Run("returns status for agreed user", func(t *testing.T) {
userSubject := "agreed-user-" + uuid.New().String()[:8]
userEmail := "agreed@test.com"
// Record agreement
_, err := svc.Eula.RecordAgreement(t.Context(), &eula.RecordAgreementInput{
CognitoSubjectID: userSubject,
UserEmail: userEmail,
EulaVersionID: *versionID,
IPAddress: "192.168.1.1",
})
require.NoError(t, err)
ctx, rec := setupEulaTestContextWithUser(http.MethodGet, "/eula/status", nil, userSubject, userEmail)
err = cons.GetEulaStatus(ctx)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
var response queryapi.EulaStatusResponse
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
assert.True(t, response.HasAgreed)
})
t.Run("returns 401 for unauthenticated user", func(t *testing.T) {
ctx, rec := setupEulaTestContext(http.MethodGet, "/eula/status", nil)
// Don't set user info
err := cons.GetEulaStatus(ctx)
require.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, rec.Code)
})
}
func TestAgreeToEula(t *testing.T) {
cfg := &ControllerConfig{}
test.CreateDB(t, cfg)
initializeTestConfig(t, cfg)
svc := createControllerServices(cfg)
cons := queryapi.NewControllers(svc, cfg)
// Create and activate a version
versionStr := "agree-test-" + uuid.New().String()[:8]
createTestEulaVersion(t, svc.Eula, versionStr, "Agree Test EULA", true)
t.Run("records new agreement", func(t *testing.T) {
userSubject := "agree-user-" + uuid.New().String()[:8]
userEmail := "agreeuser@test.com"
ctx, rec := setupEulaTestContextWithUser(http.MethodPost, "/eula/agree", nil, userSubject, userEmail)
ctx.Request().RemoteAddr = "192.168.1.100:12345"
err := cons.AgreeToEula(ctx)
require.NoError(t, err)
assert.Equal(t, http.StatusCreated, rec.Code)
var response queryapi.EulaAgreementResponse
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
assert.Equal(t, versionStr, response.EulaVersion)
})
t.Run("idempotent - returns 200 for existing agreement", func(t *testing.T) {
userSubject := "idempotent-user-" + uuid.New().String()[:8]
userEmail := "idempotent@test.com"
// First call
ctx1, rec1 := setupEulaTestContextWithUser(http.MethodPost, "/eula/agree", nil, userSubject, userEmail)
ctx1.Request().RemoteAddr = "192.168.1.100:12345"
err := cons.AgreeToEula(ctx1)
require.NoError(t, err)
assert.Equal(t, http.StatusCreated, rec1.Code)
// Second call (same user)
ctx2, rec2 := setupEulaTestContextWithUser(http.MethodPost, "/eula/agree", nil, userSubject, userEmail)
ctx2.Request().RemoteAddr = "192.168.1.100:12345"
err = cons.AgreeToEula(ctx2)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec2.Code)
})
t.Run("returns 401 for unauthenticated user", func(t *testing.T) {
ctx, rec := setupEulaTestContext(http.MethodPost, "/eula/agree", nil)
err := cons.AgreeToEula(ctx)
require.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, rec.Code)
})
t.Run("succeeds with username fallback when email is missing (access token)", func(t *testing.T) {
// Simulate a real Cognito access token: has 'sub' and 'username' (not
// 'cognito:username') and no 'email'. This is the default for access tokens.
userSubject := "no-email-user-" + uuid.New().String()[:8]
ctx, rec := setupEulaTestContext(http.MethodPost, "/eula/agree", nil)
ctx.Request().RemoteAddr = "192.168.1.100:12345"
// Mimic what the middleware produces from a real access token:
// ExtractUserInfo sees "username" (not "cognito:username") and no "email".
claims := map[string]interface{}{
"sub": userSubject,
"username": "accessuser",
"token_use": "access",
}
ctx.Set("user_claims", claims)
ctx.Set("user_info", cognitoauth.ExtractUserInfo(claims))
err := cons.AgreeToEula(ctx)
require.NoError(t, err)
assert.Equal(t, http.StatusCreated, rec.Code)
var response queryapi.EulaAgreementResponse
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
assert.Equal(t, versionStr, response.EulaVersion)
})
t.Run("succeeds with subject ID fallback when email and username are both missing", func(t *testing.T) {
// Edge case: token has sub but neither email nor any username claim.
userSubject := "bare-token-user-" + uuid.New().String()[:8]
ctx, rec := setupEulaTestContext(http.MethodPost, "/eula/agree", nil)
ctx.Request().RemoteAddr = "192.168.1.100:12345"
claims := map[string]interface{}{
"sub": userSubject,
"token_use": "access",
}
ctx.Set("user_claims", claims)
ctx.Set("user_info", cognitoauth.ExtractUserInfo(claims))
err := cons.AgreeToEula(ctx)
require.NoError(t, err)
assert.Equal(t, http.StatusCreated, rec.Code)
var response queryapi.EulaAgreementResponse
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
assert.Equal(t, versionStr, response.EulaVersion)
})
}
func TestListEulaVersions(t *testing.T) {
cfg := &ControllerConfig{}
test.CreateDB(t, cfg)
initializeTestConfig(t, cfg)
svc := createControllerServices(cfg)
cons := queryapi.NewControllers(svc, cfg)
// Create multiple versions
for i := 0; i < 5; i++ {
createTestEulaVersion(t, svc.Eula, "list-v"+uuid.New().String()[:8], "List EULA", false)
}
t.Run("lists all versions with pagination", func(t *testing.T) {
ctx, rec := setupEulaTestContext(http.MethodGet, "/admin/eula?page=1&page_size=3", nil)
page := int32(1)
pageSize := int32(3)
params := queryapi.ListEulaVersionsParams{
Page: &page,
PageSize: &pageSize,
}
err := cons.ListEulaVersions(ctx, params)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
var response queryapi.EulaVersionList
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
assert.LessOrEqual(t, len(response.Versions), 3)
assert.GreaterOrEqual(t, response.Total, int32(5))
})
}
func TestCreateEulaVersion(t *testing.T) {
cfg := &ControllerConfig{}
test.CreateDB(t, cfg)
initializeTestConfig(t, cfg)
svc := createControllerServices(cfg)
cons := queryapi.NewControllers(svc, cfg)
t.Run("creates new EULA version", func(t *testing.T) {
versionStr := "create-test-" + uuid.New().String()[:8]
body := queryapi.EulaVersionCreate{
Version: versionStr,
Title: "Created EULA",
Content: "# Created EULA Content\n\nTest content here.",
EffectiveDate: nullable.NewNullableWithValue(time.Now().Add(24 * time.Hour)),
}
ctx, rec := setupEulaTestContextWithUser(http.MethodPost, "/admin/eula", body, "admin-subject", "admin@test.com")
err := cons.CreateEulaVersion(ctx)
require.NoError(t, err)
assert.Equal(t, http.StatusCreated, rec.Code)
var response queryapi.EulaVersion
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
assert.Equal(t, versionStr, response.Version)
assert.Equal(t, "Created EULA", response.Title)
})
t.Run("returns 409 for duplicate version", func(t *testing.T) {
versionStr := "dup-test-" + uuid.New().String()[:8]
body := queryapi.EulaVersionCreate{
Version: versionStr,
Title: "First EULA",
Content: "Content",
EffectiveDate: nullable.NewNullableWithValue(time.Now()),
}
// First creation
ctx1, _ := setupEulaTestContextWithUser(http.MethodPost, "/admin/eula", body, "admin-subject", "admin@test.com")
err := cons.CreateEulaVersion(ctx1)
require.NoError(t, err)
// Second creation (same version)
ctx2, rec2 := setupEulaTestContextWithUser(http.MethodPost, "/admin/eula", body, "admin-subject", "admin@test.com")
err = cons.CreateEulaVersion(ctx2)
require.NoError(t, err)
assert.Equal(t, http.StatusConflict, rec2.Code)
})
}
func TestGetEulaVersion(t *testing.T) {
cfg := &ControllerConfig{}
test.CreateDB(t, cfg)
initializeTestConfig(t, cfg)
svc := createControllerServices(cfg)
cons := queryapi.NewControllers(svc, cfg)
t.Run("gets existing version by ID", func(t *testing.T) {
versionStr := "get-test-" + uuid.New().String()[:8]
versionID := createTestEulaVersion(t, svc.Eula, versionStr, "Get Test EULA", false)
ctx, rec := setupEulaTestContext(http.MethodGet, "/admin/eula/"+versionID.String(), nil)
err := cons.GetEulaVersion(ctx, *versionID)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
var response queryapi.EulaVersion
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
assert.Equal(t, versionStr, response.Version)
})
t.Run("returns 404 for non-existent version", func(t *testing.T) {
nonExistentID := uuid.New()
ctx, rec := setupEulaTestContext(http.MethodGet, "/admin/eula/"+nonExistentID.String(), nil)
err := cons.GetEulaVersion(ctx, nonExistentID)
require.NoError(t, err)
assert.Equal(t, http.StatusNotFound, rec.Code)
})
}
func TestUpdateEulaVersion(t *testing.T) {
cfg := &ControllerConfig{}
test.CreateDB(t, cfg)
initializeTestConfig(t, cfg)
svc := createControllerServices(cfg)
cons := queryapi.NewControllers(svc, cfg)
t.Run("updates version title", func(t *testing.T) {
versionStr := "update-test-" + uuid.New().String()[:8]
versionID := createTestEulaVersion(t, svc.Eula, versionStr, "Original Title", false)
newTitle := "Updated Title"
body := queryapi.EulaVersionUpdate{
Title: &newTitle,
}
ctx, rec := setupEulaTestContext(http.MethodPatch, "/admin/eula/"+versionID.String(), body)
err := cons.UpdateEulaVersion(ctx, *versionID)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
var response queryapi.EulaVersion
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
assert.Equal(t, newTitle, response.Title)
})
}
func TestActivateEulaVersion(t *testing.T) {
cfg := &ControllerConfig{}
test.CreateDB(t, cfg)
initializeTestConfig(t, cfg)
svc := createControllerServices(cfg)
cons := queryapi.NewControllers(svc, cfg)
t.Run("activates version", func(t *testing.T) {
versionStr := "activate-test-" + uuid.New().String()[:8]
versionID := createTestEulaVersion(t, svc.Eula, versionStr, "Activate Test EULA", false)
ctx, rec := setupEulaTestContextWithUser(http.MethodPost, "/admin/eula/"+versionID.String()+"/activate", nil, "admin-subject", "admin@test.com")
err := cons.ActivateEulaVersion(ctx, *versionID)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
var response queryapi.EulaVersion
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
assert.True(t, response.IsCurrent)
})
t.Run("returns 404 for non-existent version", func(t *testing.T) {
nonExistentID := uuid.New()
ctx, rec := setupEulaTestContextWithUser(http.MethodPost, "/admin/eula/"+nonExistentID.String()+"/activate", nil, "admin-subject", "admin@test.com")
err := cons.ActivateEulaVersion(ctx, nonExistentID)
require.NoError(t, err)
assert.Equal(t, http.StatusNotFound, rec.Code)
})
}
func TestListEulaAgreements(t *testing.T) {
cfg := &ControllerConfig{}
test.CreateDB(t, cfg)
initializeTestConfig(t, cfg)
svc := createControllerServices(cfg)
cons := queryapi.NewControllers(svc, cfg)
// Create version and some agreements
versionID := createTestEulaVersion(t, svc.Eula, "agreements-test-"+uuid.New().String()[:8], "Agreements Test", true)
for i := 0; i < 3; i++ {
_, err := svc.Eula.RecordAgreement(t.Context(), &eula.RecordAgreementInput{
CognitoSubjectID: "user-" + uuid.New().String()[:8],
UserEmail: "user" + uuid.New().String()[:4] + "@test.com",
EulaVersionID: *versionID,
IPAddress: "192.168.1.1",
})
require.NoError(t, err)
}
t.Run("lists agreements", func(t *testing.T) {
ctx, rec := setupEulaTestContext(http.MethodGet, "/admin/eula/agreements", nil)
page := int32(1)
pageSize := int32(10)
params := queryapi.ListEulaAgreementsParams{
Page: &page,
PageSize: &pageSize,
}
err := cons.ListEulaAgreements(ctx, params)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
var response queryapi.EulaAgreementList
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
assert.GreaterOrEqual(t, len(response.Agreements), 3)
})
}
// TestListEulaAgreements_NonEmailIdentifier verifies that GET /admin/eula/agreements
// returns 200 (not 500) when agreements contain non-email user identifiers.
// Reproduces the bug where username/subject ID fallback values in userEmail caused
// JSON serialization failure via openapi_types.Email strict validation.
func TestListEulaAgreements_NonEmailIdentifier(t *testing.T) {
cfg := &ControllerConfig{}
test.CreateDB(t, cfg)
initializeTestConfig(t, cfg)
svc := createControllerServices(cfg)
cons := queryapi.NewControllers(svc, cfg)
versionID := createTestEulaVersion(t, svc.Eula, "nonemail-agree-"+uuid.New().String()[:8], "Non-Email Test", true)
// Record agreements with non-email identifiers (simulating username/subject fallback)
nonEmailIdentifiers := []string{"accessuser", "bare-subject-id-12345", "admin_username"}
for _, identifier := range nonEmailIdentifiers {
_, err := svc.Eula.RecordAgreement(t.Context(), &eula.RecordAgreementInput{
CognitoSubjectID: "user-" + uuid.New().String()[:8],
UserEmail: identifier,
EulaVersionID: *versionID,
IPAddress: "192.168.1.1",
})
require.NoError(t, err)
}
t.Run("returns 200 with non-email userEmail values", func(t *testing.T) {
ctx, rec := setupEulaTestContext(http.MethodGet, "/admin/eula/agreements", nil)
page := int32(1)
pageSize := int32(50)
params := queryapi.ListEulaAgreementsParams{
Page: &page,
PageSize: &pageSize,
}
err := cons.ListEulaAgreements(ctx, params)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code, "expected 200 OK, got %d: %s", rec.Code, rec.Body.String())
var response queryapi.EulaAgreementList
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
// Verify non-email identifiers are present in the response
foundIdentifiers := make(map[string]bool)
for _, a := range response.Agreements {
foundIdentifiers[string(a.UserEmail)] = true
}
for _, id := range nonEmailIdentifiers {
assert.True(t, foundIdentifiers[id], "expected to find non-email identifier %q in response", id)
}
})
}
// TestListEulaVersions_NonEmailCreatedBy verifies that GET /admin/eula
// returns 200 (not 500) when versions have non-email createdBy/activatedBy values.
func TestListEulaVersions_NonEmailCreatedBy(t *testing.T) {
cfg := &ControllerConfig{}
test.CreateDB(t, cfg)
initializeTestConfig(t, cfg)
svc := createControllerServices(cfg)
cons := queryapi.NewControllers(svc, cfg)
// Create a version with a non-email createdBy (simulating username fallback)
versionStr := "nonemail-ver-" + uuid.New().String()[:8]
_, err := svc.Eula.CreateVersion(t.Context(), &eula.CreateVersionInput{
Version: versionStr,
Title: "Non-Email CreatedBy Test",
Content: "# Test EULA\n\nContent.",
CreatedBy: "adminuser", // non-email identifier
})
require.NoError(t, err)
t.Run("returns 200 with non-email createdBy", func(t *testing.T) {
ctx, rec := setupEulaTestContext(http.MethodGet, "/admin/eula", nil)
page := int32(1)
pageSize := int32(50)
params := queryapi.ListEulaVersionsParams{
Page: &page,
PageSize: &pageSize,
}
err := cons.ListEulaVersions(ctx, params)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code, "expected 200 OK, got %d: %s", rec.Code, rec.Body.String())
var response queryapi.EulaVersionList
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
// Find our version and verify the non-email createdBy is present
found := false
for _, v := range response.Versions {
if v.Version == versionStr {
assert.Equal(t, "adminuser", string(v.CreatedBy))
found = true
break
}
}
assert.True(t, found, "expected to find version %q in response", versionStr)
})
}
// TestActivateEulaVersion_NonEmailActivatedBy verifies that activating a version
// with a non-email admin identifier doesn't cause serialization errors when
// the version is later retrieved.
func TestActivateEulaVersion_NonEmailActivatedBy(t *testing.T) {
cfg := &ControllerConfig{}
test.CreateDB(t, cfg)
initializeTestConfig(t, cfg)
svc := createControllerServices(cfg)
cons := queryapi.NewControllers(svc, cfg)
// Create version with non-email createdBy
versionStr := "nonemail-act-" + uuid.New().String()[:8]
created, err := svc.Eula.CreateVersion(t.Context(), &eula.CreateVersionInput{
Version: versionStr,
Title: "Non-Email ActivatedBy Test",
Content: "# Test EULA\n\nContent.",
CreatedBy: "sysadmin",
})
require.NoError(t, err)
// Activate with non-email identifier
_, err = svc.Eula.ActivateVersion(t.Context(), created.ID, "opsadmin")
require.NoError(t, err)
t.Run("returns 200 listing version with non-email activatedBy", func(t *testing.T) {
ctx, rec := setupEulaTestContext(http.MethodGet, "/admin/eula", nil)
page := int32(1)
pageSize := int32(50)
params := queryapi.ListEulaVersionsParams{
Page: &page,
PageSize: &pageSize,
}
err := cons.ListEulaVersions(ctx, params)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code, "expected 200 OK, got %d: %s", rec.Code, rec.Body.String())
var response queryapi.EulaVersionList
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
// Find our version and verify the non-email activatedBy is present
found := false
for _, v := range response.Versions {
if v.Version == versionStr {
assert.Equal(t, "sysadmin", string(v.CreatedBy))
assert.True(t, v.ActivatedBy.IsSpecified(), "activatedBy should be set")
val, err := v.ActivatedBy.Get()
require.NoError(t, err)
assert.Equal(t, "opsadmin", string(val))
found = true
break
}
}
assert.True(t, found, "expected to find version %q in response", versionStr)
})
}
func TestGetEulaCompliance(t *testing.T) {
// This test requires real Cognito access - opt-in via env var
if os.Getenv("ENABLE_COGNITO_INTEGRATION_TESTS") != "true" {
t.Skip("Skipping Cognito integration test: set ENABLE_COGNITO_INTEGRATION_TESTS=true to run")
}
userPoolID := os.Getenv("COGNITO_USER_POOL_ID")
awsRegion := os.Getenv("AWS_REGION")
if awsRegion == "" {
awsRegion = os.Getenv("AUTH_REGION")
}
if userPoolID == "" || awsRegion == "" {
t.Skip("Skipping compliance handler test: COGNITO_USER_POOL_ID and AWS_REGION/AUTH_REGION must be set")
}
cfg := &ControllerConfig{}
test.CreateDB(t, cfg)
initializeTestConfig(t, cfg)
svc := createControllerServices(cfg)
cons := queryapi.NewControllers(svc, cfg)
// Create and activate a version for testing
versionStr := "compliance-handler-" + uuid.New().String()[:8]
createTestEulaVersion(t, svc.Eula, versionStr, "Compliance Handler Test EULA", true)
t.Run("returns_compliance_report", func(t *testing.T) {
ctx, rec := setupEulaTestContext(http.MethodGet, "/admin/eula/compliance", nil)
params := queryapi.GetEulaComplianceParams{}
err := cons.GetEulaCompliance(ctx, params)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
var response queryapi.EulaComplianceReport
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
// Verify structure
assert.NotEmpty(t, response.EulaVersion.Id)
assert.NotEmpty(t, response.EulaVersion.Version)
assert.GreaterOrEqual(t, response.Summary.TotalUsers, int32(0))
assert.Equal(t, response.Summary.TotalUsers, response.Summary.AgreedCount+response.Summary.NotAgreedCount)
})
t.Run("returns_404_for_nonexistent_version", func(t *testing.T) {
ctx, rec := setupEulaTestContext(http.MethodGet, "/admin/eula/compliance?version_id=00000000-0000-0000-0000-000000000000", nil)
nonExistentID := uuid.MustParse("00000000-0000-0000-0000-000000000000")
params := queryapi.GetEulaComplianceParams{
VersionId: (*queryapi.EulaVersionID)(&nonExistentID),
}
err := cons.GetEulaCompliance(ctx, params)
require.NoError(t, err)
assert.Equal(t, http.StatusNotFound, rec.Code)
})
t.Run("filters_by_agreed_status", func(t *testing.T) {
ctx, rec := setupEulaTestContext(http.MethodGet, "/admin/eula/compliance?agreed=false", nil)
agreed := false
params := queryapi.GetEulaComplianceParams{
Agreed: &agreed,
}
err := cons.GetEulaCompliance(ctx, params)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
var response queryapi.EulaComplianceReport
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
// All users in the result should have agreed=false
for _, user := range response.Users {
assert.False(t, user.Agreed)
}
})
t.Run("pagination_params_work", func(t *testing.T) {
ctx, rec := setupEulaTestContext(http.MethodGet, "/admin/eula/compliance?page=1&page_size=5", nil)
page := int32(1)
pageSize := int32(5)
params := queryapi.GetEulaComplianceParams{
Page: &page,
PageSize: &pageSize,
}
err := cons.GetEulaCompliance(ctx, params)
require.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
var response queryapi.EulaComplianceReport
err = json.Unmarshal(rec.Body.Bytes(), &response)
require.NoError(t, err)
assert.Equal(t, int32(1), response.Pagination.Page)
assert.Equal(t, int32(5), response.Pagination.PageSize)
assert.LessOrEqual(t, len(response.Users), 5)
})
}
func TestGetEulaComplianceNoCurrentVersion(t *testing.T) {
// This test requires real Cognito access - opt-in via env var
if os.Getenv("ENABLE_COGNITO_INTEGRATION_TESTS") != "true" {
t.Skip("Skipping Cognito integration test: set ENABLE_COGNITO_INTEGRATION_TESTS=true to run")
}
userPoolID := os.Getenv("COGNITO_USER_POOL_ID")
awsRegion := os.Getenv("AWS_REGION")
if awsRegion == "" {
awsRegion = os.Getenv("AUTH_REGION")
}
if userPoolID == "" || awsRegion == "" {
t.Skip("Skipping compliance handler test: COGNITO_USER_POOL_ID and AWS_REGION/AUTH_REGION must be set")
}
// Fresh database with no EULA versions
cfg := &ControllerConfig{}
test.CreateDB(t, cfg)
initializeTestConfig(t, cfg)
svc := createControllerServices(cfg)
cons := queryapi.NewControllers(svc, cfg)
t.Run("returns_404_no_current_eula", func(t *testing.T) {
ctx, rec := setupEulaTestContext(http.MethodGet, "/admin/eula/compliance", nil)
params := queryapi.GetEulaComplianceParams{}
err := cons.GetEulaCompliance(ctx, params)
require.NoError(t, err)
assert.Equal(t, http.StatusNotFound, rec.Code)
})
}