forked from baron/baron-sso
Consent 승인 및 해지 이벤트 감사 로그 기록
This commit is contained in:
@@ -3342,6 +3342,24 @@ func (h *AuthHandler) RevokeLinkedRp(c *fiber.Ctx) error {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to revoke link")
|
||||
}
|
||||
|
||||
if h.AuditRepo != nil {
|
||||
detailsMap := map[string]interface{}{
|
||||
"client_id": clientID,
|
||||
}
|
||||
detailsBytes, _ := json.Marshal(detailsMap)
|
||||
|
||||
_ = h.AuditRepo.Create(&domain.AuditLog{
|
||||
EventID: GenerateSecureToken(16),
|
||||
Timestamp: time.Now(),
|
||||
UserID: subject,
|
||||
EventType: "consent.revoked",
|
||||
Status: "success",
|
||||
IPAddress: c.IP(),
|
||||
UserAgent: string(c.Request().Header.UserAgent()),
|
||||
Details: string(detailsBytes),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(fiber.Map{
|
||||
"status": "success",
|
||||
"message": "Link revoked successfully",
|
||||
@@ -3467,6 +3485,26 @@ func (h *AuthHandler) AcceptConsentRequest(c *fiber.Ctx) error {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to accept consent request")
|
||||
}
|
||||
|
||||
if h.AuditRepo != nil {
|
||||
detailsMap := map[string]interface{}{
|
||||
"client_id": consentRequest.Client.ClientID,
|
||||
"scopes": consentRequest.RequestedScope,
|
||||
"client_name": consentRequest.Client.ClientName,
|
||||
}
|
||||
detailsBytes, _ := json.Marshal(detailsMap)
|
||||
|
||||
_ = h.AuditRepo.Create(&domain.AuditLog{
|
||||
EventID: GenerateSecureToken(16),
|
||||
Timestamp: time.Now(),
|
||||
UserID: consentRequest.Subject,
|
||||
EventType: "consent.granted",
|
||||
Status: "success",
|
||||
IPAddress: c.IP(),
|
||||
UserAgent: string(c.Request().Header.UserAgent()),
|
||||
Details: string(detailsBytes),
|
||||
})
|
||||
}
|
||||
|
||||
return c.JSON(acceptResp)
|
||||
}
|
||||
|
||||
@@ -4998,3 +5036,100 @@ func mergeScopes(current []string, next []string) []string {
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
type rpHistoryItem struct {
|
||||
ClientID string `json:"client_id"`
|
||||
ClientName string `json:"client_name"`
|
||||
Scopes []string `json:"scopes"`
|
||||
LastApprovedAt *time.Time `json:"last_approved_at"`
|
||||
LastRevokedAt *time.Time `json:"last_revoked_at"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
func (h *AuthHandler) ListRpHistory(c *fiber.Ctx) error {
|
||||
subject, err := h.resolveConsentSubject(c)
|
||||
if err != nil || subject == "" {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Invalid session"})
|
||||
}
|
||||
|
||||
if h.AuditRepo == nil {
|
||||
return c.Status(fiber.StatusServiceUnavailable).JSON(fiber.Map{"error": "Audit service unavailable"})
|
||||
}
|
||||
|
||||
logs, err := h.AuditRepo.FindByUserAndEvents(c.Context(), subject, []string{"consent.granted", "consent.revoked"}, 100)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to fetch history"})
|
||||
}
|
||||
|
||||
historyMap := make(map[string]*rpHistoryItem)
|
||||
|
||||
// Logs are DESC (newest first). Iterate in reverse (oldest first) to build state.
|
||||
for i := len(logs) - 1; i >= 0; i-- {
|
||||
log := logs[i]
|
||||
details, _ := parseAuditDetails(log.Details)
|
||||
clientID, _ := details["client_id"].(string)
|
||||
if clientID == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
item, ok := historyMap[clientID]
|
||||
if !ok {
|
||||
item = &rpHistoryItem{
|
||||
ClientID: clientID,
|
||||
Status: "unknown",
|
||||
}
|
||||
historyMap[clientID] = item
|
||||
}
|
||||
|
||||
if name, ok := details["client_name"].(string); ok && name != "" {
|
||||
item.ClientName = name
|
||||
}
|
||||
|
||||
if log.EventType == "consent.granted" {
|
||||
item.Status = "active"
|
||||
ts := log.Timestamp
|
||||
item.LastApprovedAt = &ts
|
||||
|
||||
if scopesRaw, ok := details["scopes"].([]interface{}); ok {
|
||||
scopes := make([]string, 0, len(scopesRaw))
|
||||
for _, s := range scopesRaw {
|
||||
if str, ok := s.(string); ok {
|
||||
scopes = append(scopes, str)
|
||||
}
|
||||
}
|
||||
item.Scopes = scopes
|
||||
}
|
||||
} else if log.EventType == "consent.revoked" {
|
||||
item.Status = "revoked"
|
||||
ts := log.Timestamp
|
||||
item.LastRevokedAt = &ts
|
||||
}
|
||||
}
|
||||
|
||||
items := make([]rpHistoryItem, 0, len(historyMap))
|
||||
for _, item := range historyMap {
|
||||
items = append(items, *item)
|
||||
}
|
||||
|
||||
sort.Slice(items, func(i, j int) bool {
|
||||
t1 := time.Time{}
|
||||
if items[i].LastApprovedAt != nil {
|
||||
t1 = *items[i].LastApprovedAt
|
||||
}
|
||||
if items[i].LastRevokedAt != nil && items[i].LastRevokedAt.After(t1) {
|
||||
t1 = *items[i].LastRevokedAt
|
||||
}
|
||||
|
||||
t2 := time.Time{}
|
||||
if items[j].LastApprovedAt != nil {
|
||||
t2 = *items[j].LastApprovedAt
|
||||
}
|
||||
if items[j].LastRevokedAt != nil && items[j].LastRevokedAt.After(t2) {
|
||||
t2 = *items[j].LastRevokedAt
|
||||
}
|
||||
|
||||
return t1.After(t2)
|
||||
})
|
||||
|
||||
return c.JSON(fiber.Map{"items": items})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user