Merged in feature/local-pdp (pull request #208)

permit.io local pdp

* docs and testing

* build fix

* docs

* permit rights

* accept self signed certs

* fix eula error
This commit is contained in:
Jay Brown
2026-02-12 23:46:53 +00:00
parent 963ccc6553
commit d7f6c3700b
14 changed files with 1269 additions and 165 deletions
+37 -8
View File
@@ -5,6 +5,7 @@ package queryapi
import (
"context"
"errors"
"fmt"
"net/http"
"strings"
"time"
@@ -50,8 +51,12 @@ func (s *Controllers) ListEulaVersions(ctx echo.Context, params ListEulaVersions
PageSize: pageSize,
})
if err != nil {
s.cfg.GetAuthLogger().Error("ListEulaVersions: failed to list EULA versions",
"error", err,
"page", page,
"page_size", pageSize)
return ctx.JSON(http.StatusInternalServerError, ErrorMessage{
Message: "Failed to list EULA versions",
Message: fmt.Sprintf("Failed to list EULA versions: %v", err),
})
}
@@ -123,8 +128,12 @@ func (s *Controllers) CreateEulaVersion(ctx echo.Context) error {
Message: "EULA version already exists",
})
}
s.cfg.GetAuthLogger().Error("CreateEulaVersion: failed to create EULA version",
"error", err,
"version", req.Version,
"created_by", adminUser.Email)
return ctx.JSON(http.StatusInternalServerError, ErrorMessage{
Message: "Failed to create EULA version",
Message: fmt.Sprintf("Failed to create EULA version: %v", err),
})
}
@@ -157,8 +166,11 @@ func (s *Controllers) GetEulaVersion(ctx echo.Context, versionID EulaVersionID)
Message: "EULA version not found",
})
}
s.cfg.GetAuthLogger().Error("GetEulaVersion: failed to get EULA version",
"error", err,
"version_id", id)
return ctx.JSON(http.StatusInternalServerError, ErrorMessage{
Message: "Failed to get EULA version",
Message: fmt.Sprintf("Failed to get EULA version: %v", err),
})
}
@@ -210,8 +222,11 @@ func (s *Controllers) UpdateEulaVersion(ctx echo.Context, versionID EulaVersionI
Message: "EULA version not found",
})
}
s.cfg.GetAuthLogger().Error("UpdateEulaVersion: failed to update EULA version",
"error", err,
"version_id", id)
return ctx.JSON(http.StatusInternalServerError, ErrorMessage{
Message: "Failed to update EULA version",
Message: fmt.Sprintf("Failed to update EULA version: %v", err),
})
}
@@ -259,8 +274,12 @@ func (s *Controllers) ActivateEulaVersion(ctx echo.Context, versionID EulaVersio
Message: "Concurrent activation conflict - another version was activated. Please refresh and try again.",
})
}
s.cfg.GetAuthLogger().Error("ActivateEulaVersion: failed to activate EULA version",
"error", err,
"version_id", id,
"activated_by", adminUser.Email)
return ctx.JSON(http.StatusInternalServerError, ErrorMessage{
Message: "Failed to activate EULA version",
Message: fmt.Sprintf("Failed to activate EULA version: %v", err),
})
}
@@ -310,8 +329,12 @@ func (s *Controllers) ListEulaAgreements(ctx echo.Context, params ListEulaAgreem
result, err := s.svc.Eula.ListAgreements(ctx.Request().Context(), input)
if err != nil {
s.cfg.GetAuthLogger().Error("ListEulaAgreements: failed to list EULA agreements",
"error", err,
"page", page,
"page_size", pageSize)
return ctx.JSON(http.StatusInternalServerError, ErrorMessage{
Message: "Failed to list EULA agreements",
Message: fmt.Sprintf("Failed to list EULA agreements: %v", err),
})
}
@@ -355,8 +378,10 @@ func (s *Controllers) GetEulaCompliance(ctx echo.Context, params GetEulaComplian
// Initialize AWS config for Cognito
awsCfg, err := aws.GetAWSConfig(context.Background())
if err != nil {
s.cfg.GetAuthLogger().Error("GetEulaCompliance: failed to initialize AWS configuration",
"error", err)
return ctx.JSON(http.StatusInternalServerError, ErrorMessage{
Message: "Failed to initialize AWS configuration",
Message: fmt.Sprintf("Failed to initialize AWS configuration: %v", err),
})
}
@@ -399,12 +424,16 @@ func (s *Controllers) GetEulaCompliance(ctx echo.Context, params GetEulaComplian
}
// Check if it's a Cognito error
if strings.Contains(err.Error(), "Cognito") || strings.Contains(err.Error(), "cognito") {
s.cfg.GetAuthLogger().Error("GetEulaCompliance: Cognito error during compliance report",
"error", err)
return ctx.JSON(http.StatusBadGateway, ErrorMessage{
Message: "Failed to fetch users from Cognito: " + err.Error(),
})
}
s.cfg.GetAuthLogger().Error("GetEulaCompliance: failed to generate compliance report",
"error", err)
return ctx.JSON(http.StatusInternalServerError, ErrorMessage{
Message: "Failed to generate compliance report",
Message: fmt.Sprintf("Failed to generate compliance report: %v", err),
})
}
+27
View File
@@ -243,6 +243,33 @@ func TestAgreeToEula(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, http.StatusUnauthorized, rec.Code)
})
t.Run("succeeds with username fallback when email claim is missing", func(t *testing.T) {
// Simulate a Cognito access token that has 'sub' and 'cognito:username'
// but no 'email' claim. This is the default for Cognito 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"
// Set claims with sub but without email (mimics access token)
ctx.Set("user_claims", map[string]interface{}{
"sub": userSubject,
"cognito:username": "testuser",
})
ctx.Set("user_info", cognitoauth.UserInfo{
Username: "testuser",
Email: "", // empty - no email in access token
})
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) {
+33 -5
View File
@@ -4,6 +4,7 @@ package queryapi
import (
"errors"
"fmt"
"net/http"
"time"
@@ -32,8 +33,10 @@ func (s *Controllers) GetCurrentEula(ctx echo.Context) error {
Message: "No current EULA version configured",
})
}
s.cfg.GetAuthLogger().Error("GetCurrentEula: failed to get current EULA version",
"error", err)
return ctx.JSON(http.StatusInternalServerError, ErrorMessage{
Message: "Failed to get current EULA version",
Message: fmt.Sprintf("Failed to get current EULA version: %v", err),
})
}
@@ -79,8 +82,11 @@ func (s *Controllers) GetEulaStatus(ctx echo.Context) error {
Message: "No current EULA version configured",
})
}
s.cfg.GetAuthLogger().Error("GetEulaStatus: failed to get EULA status",
"error", err,
"user_subject", userSubject)
return ctx.JSON(http.StatusInternalServerError, ErrorMessage{
Message: "Failed to get EULA status",
Message: fmt.Sprintf("Failed to get EULA status: %v", err),
})
}
@@ -119,11 +125,25 @@ func (s *Controllers) AgreeToEula(ctx echo.Context) error {
userSubject, subjectOK := cognitoauth.GetUserSubject(ctx)
userInfo, infoOK := cognitoauth.GetUserInfo(ctx)
if !subjectOK || !infoOK {
s.cfg.GetAuthLogger().Error("AgreeToEula: authentication info missing from context",
"subject_ok", subjectOK,
"info_ok", infoOK)
return ctx.JSON(http.StatusUnauthorized, ErrorMessage{
Message: "Authentication required",
})
}
// Resolve the user identifier for the agreement record.
// Cognito access tokens do not include the email claim by default (only ID tokens do).
// Fall back to the username (cognito:username), which is always present in access tokens.
userIdentifier := userInfo.Email
if userIdentifier == "" {
userIdentifier = userInfo.Username
s.cfg.GetAuthLogger().Info("AgreeToEula: email claim missing from token, using username as fallback",
"user_subject", userSubject,
"username", userInfo.Username)
}
// Get current EULA version
currentVersion, err := s.svc.Eula.GetCurrentVersion(ctx.Request().Context())
if err != nil {
@@ -132,8 +152,11 @@ func (s *Controllers) AgreeToEula(ctx echo.Context) error {
Message: "No current EULA version configured",
})
}
s.cfg.GetAuthLogger().Error("AgreeToEula: failed to get current EULA version",
"error", err,
"user_subject", userSubject)
return ctx.JSON(http.StatusInternalServerError, ErrorMessage{
Message: "Failed to get current EULA version",
Message: fmt.Sprintf("Failed to get current EULA version: %v", err),
})
}
@@ -146,13 +169,18 @@ func (s *Controllers) AgreeToEula(ctx echo.Context) error {
// Record the agreement
result, err := s.svc.Eula.RecordAgreement(ctx.Request().Context(), &eula.RecordAgreementInput{
CognitoSubjectID: userSubject,
UserEmail: userInfo.Email,
UserEmail: userIdentifier,
EulaVersionID: currentVersion.ID,
IPAddress: ipAddress,
})
if err != nil {
s.cfg.GetAuthLogger().Error("AgreeToEula: failed to record EULA agreement",
"error", err,
"user_subject", userSubject,
"user_identifier", userIdentifier,
"eula_version_id", currentVersion.ID)
return ctx.JSON(http.StatusInternalServerError, ErrorMessage{
Message: "Failed to record EULA agreement",
Message: fmt.Sprintf("Failed to record EULA agreement: %v", err),
})
}