1
0
forked from baron/baron-sso

RP 생성 admin 관계 중복 부여 수정

This commit is contained in:
2026-04-29 14:12:37 +09:00
parent 68e7fb9ba2
commit 572ac39e60
2 changed files with 157 additions and 23 deletions

View File

@@ -752,6 +752,24 @@ func mapRelationTupleSummary(tuple service.RelationTuple, identity *service.Krat
return summary
}
func dedupeRelationTuples(tuples []service.RelationTuple) []service.RelationTuple {
if len(tuples) <= 1 {
return tuples
}
seen := make(map[string]struct{}, len(tuples))
deduped := make([]service.RelationTuple, 0, len(tuples))
for _, tuple := range tuples {
key := strings.TrimSpace(tuple.Relation) + "\x00" + strings.TrimSpace(tuple.SubjectID)
if _, exists := seen[key]; exists {
continue
}
seen[key] = struct{}{}
deduped = append(deduped, tuple)
}
return deduped
}
func (h *DevHandler) loadClientSummary(ctx context.Context, clientID string) (clientSummary, error) {
clientID = strings.TrimSpace(clientID)
if clientID == "" {
@@ -1210,6 +1228,7 @@ func (h *DevHandler) ListClientRelations(c *fiber.Ctx) error {
if err != nil {
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
}
tuples = dedupeRelationTuples(tuples)
for _, tuple := range tuples {
var identity *service.KratosIdentity
if tuple.SubjectID != "" && h.KratosAdmin != nil {
@@ -1722,23 +1741,11 @@ func (h *DevHandler) CreateClient(c *fiber.Ctx) error {
// [New] Automatically grant admin permission to the creator in Keto
if h.KetoOutbox != nil && profile != nil {
subject := "User:" + profile.ID
err := h.KetoOutbox.Create(c.Context(), &domain.KetoOutbox{
Namespace: "RelyingParty",
Object: created.ClientID,
Relation: "admins",
Subject: subject,
Action: domain.KetoOutboxActionCreate,
})
if err != nil {
if err := h.grantCreatorAdminRelation(c, created.ClientID, subject); err != nil {
slog.Warn("failed to grant automatic admin permission to creator", "clientID", created.ClientID, "userID", profile.ID, "error", err)
} else {
slog.Info("granted automatic admin permission to creator", "clientID", created.ClientID, "userID", profile.ID)
}
if h.Keto != nil {
if err := h.Keto.CreateRelation(c.Context(), "RelyingParty", created.ClientID, "admins", subject); err != nil {
slog.Warn("failed to grant immediate admin permission to creator", "clientID", created.ClientID, "userID", profile.ID, "error", err)
}
}
}
// Store secret in metadata for later retrieval
@@ -3314,6 +3321,41 @@ func (h *DevHandler) ensureDeveloperGrantRelation(c *fiber.Ctx, userID, tenantID
}
}
func (h *DevHandler) grantCreatorAdminRelation(c *fiber.Ctx, clientID string, subject string) error {
clientID = strings.TrimSpace(clientID)
subject = strings.TrimSpace(subject)
if clientID == "" || subject == "" {
return nil
}
if h.Keto != nil {
existing, err := h.Keto.ListRelations(c.Context(), "RelyingParty", clientID, "admins", subject)
if err == nil && len(existing) > 0 {
return nil
}
if err == nil {
if createErr := h.Keto.CreateRelation(c.Context(), "RelyingParty", clientID, "admins", subject); createErr == nil {
return nil
} else {
slog.Warn("failed to grant immediate admin permission to creator; falling back to outbox", "clientID", clientID, "subject", subject, "error", createErr)
}
} else {
slog.Warn("failed to check existing admin relation for creator; falling back to outbox", "clientID", clientID, "subject", subject, "error", err)
}
}
if h.KetoOutbox == nil {
return nil
}
return h.KetoOutbox.Create(c.Context(), &domain.KetoOutbox{
Namespace: "RelyingParty",
Object: clientID,
Relation: "admins",
Subject: subject,
Action: domain.KetoOutboxActionCreate,
})
}
func (h *DevHandler) revokeDeveloperGrantRelation(c *fiber.Ctx, userID, tenantID string) {
if h.KetoOutbox == nil || strings.TrimSpace(userID) == "" || strings.TrimSpace(tenantID) == "" {
return