forked from baron/baron-sso
106 lines
2.8 KiB
Go
106 lines
2.8 KiB
Go
package handler
|
|
|
|
import (
|
|
"baron-sso-backend/internal/domain"
|
|
"baron-sso-backend/internal/service"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestRevokeLinkedRp_Success(t *testing.T) {
|
|
// Mock Hydra transport for revocation
|
|
transport := roundTripFunc(func(r *http.Request) (*http.Response, error) {
|
|
// 1. Kratos whoami
|
|
if r.URL.Path == "/sessions/whoami" {
|
|
return httpJSONAny(r, http.StatusOK, map[string]interface{}{
|
|
"identity": map[string]interface{}{"id": "user-123"},
|
|
}), nil
|
|
}
|
|
// 2. Hydra Revoke
|
|
if r.Method == http.MethodDelete && r.URL.Path == "/oauth2/auth/sessions/consent" {
|
|
return httpResponse(r, http.StatusNoContent, ""), nil
|
|
}
|
|
return httpResponse(r, http.StatusNotFound, "not found"), nil
|
|
})
|
|
|
|
client := &http.Client{Transport: transport}
|
|
origDefault := http.DefaultClient
|
|
http.DefaultClient = client
|
|
defer func() { http.DefaultClient = origDefault }()
|
|
|
|
auditRepo := &mockAuditRepo{}
|
|
h := &AuthHandler{
|
|
Hydra: &service.HydraAdminService{
|
|
AdminURL: "http://hydra.test",
|
|
HTTPClient: client,
|
|
},
|
|
AuditRepo: auditRepo,
|
|
}
|
|
app := fiber.New()
|
|
app.Delete("/api/v1/user/rp/linked/:id", h.RevokeLinkedRp)
|
|
|
|
req := httptest.NewRequest(http.MethodDelete, "/api/v1/user/rp/linked/app-1", nil)
|
|
req.Header.Set("Cookie", "valid")
|
|
|
|
resp, _ := app.Test(req, -1)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
assert.Equal(t, 1, len(auditRepo.logs))
|
|
}
|
|
|
|
func TestListRpHistory_Aggregation(t *testing.T) {
|
|
now := time.Now()
|
|
auditRepo := &mockAuditRepo{
|
|
logs: []domain.AuditLog{
|
|
{
|
|
UserID: "user-123",
|
|
EventType: "consent.revoked", // Newest
|
|
Timestamp: now,
|
|
Details: `{"client_id":"app-1"}`,
|
|
},
|
|
{
|
|
UserID: "user-123",
|
|
EventType: "consent.granted", // Oldest
|
|
Timestamp: now.Add(-1 * time.Hour),
|
|
Details: `{"client_id":"app-1", "client_name":"App One"}`,
|
|
},
|
|
},
|
|
}
|
|
|
|
h := &AuthHandler{
|
|
AuditRepo: auditRepo,
|
|
}
|
|
app := fiber.New()
|
|
app.Get("/api/v1/user/rp/history", h.ListRpHistory)
|
|
|
|
transport := roundTripFunc(func(r *http.Request) (*http.Response, error) {
|
|
return httpJSONAny(r, http.StatusOK, map[string]interface{}{
|
|
"identity": map[string]interface{}{"id": "user-123"},
|
|
}), nil
|
|
})
|
|
http.DefaultClient = &http.Client{Transport: transport}
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/user/rp/history", nil)
|
|
req.Header.Set("Cookie", "valid")
|
|
|
|
resp, _ := app.Test(req, -1)
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
|
|
var res struct {
|
|
Items []struct {
|
|
ClientID string `json:"client_id"`
|
|
Status string `json:"status"`
|
|
} `json:"items"`
|
|
}
|
|
json.NewDecoder(resp.Body).Decode(&res)
|
|
|
|
assert.Equal(t, 1, len(res.Items))
|
|
assert.Equal(t, "app-1", res.Items[0].ClientID)
|
|
// Newest event (revoked) should win
|
|
assert.Equal(t, "revoked", res.Items[0].Status)
|
|
} |