forked from baron/baron-sso
169 lines
5.1 KiB
Go
169 lines
5.1 KiB
Go
package handler
|
|
|
|
import (
|
|
"baron-sso-backend/internal/domain"
|
|
"baron-sso-backend/internal/service"
|
|
"log/slog"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
type RelyingPartyHandler struct {
|
|
Service service.RelyingPartyService
|
|
UserSvc *service.KratosAdminService
|
|
}
|
|
|
|
func NewRelyingPartyHandler(s service.RelyingPartyService, userSvc *service.KratosAdminService) *RelyingPartyHandler {
|
|
return &RelyingPartyHandler{Service: s, UserSvc: userSvc}
|
|
}
|
|
|
|
func (h *RelyingPartyHandler) Create(c *fiber.Ctx) error {
|
|
tenantID := c.Params("tenantId")
|
|
if tenantID == "" {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "tenantId is required"})
|
|
}
|
|
|
|
var req domain.HydraClient
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid request body"})
|
|
}
|
|
|
|
rp, err := h.Service.Create(c.Context(), tenantID, req)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
|
|
return c.Status(fiber.StatusCreated).JSON(rp)
|
|
}
|
|
|
|
func (h *RelyingPartyHandler) ListAll(c *fiber.Ctx) error {
|
|
profile, ok := c.Locals("user_profile").(*domain.UserProfileResponse)
|
|
if !ok {
|
|
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "unauthorized: user profile not found in context"})
|
|
}
|
|
|
|
var rps []domain.RelyingParty
|
|
var err error
|
|
|
|
if profile.Role == domain.RoleSuperAdmin {
|
|
rps, err = h.Service.ListAll(c.Context())
|
|
} else if profile.Role == domain.RoleTenantAdmin && profile.TenantID != nil {
|
|
rps, err = h.Service.List(c.Context(), *profile.TenantID)
|
|
} else {
|
|
slog.Warn("Forbidden access to all applications", "userID", profile.ID, "role", profile.Role)
|
|
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "forbidden: insufficient role to list all applications"})
|
|
}
|
|
|
|
if err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
|
|
return c.JSON(rps)
|
|
}
|
|
|
|
func (h *RelyingPartyHandler) List(c *fiber.Ctx) error {
|
|
tenantID := c.Params("tenantId")
|
|
if tenantID == "" {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "tenantId is required"})
|
|
}
|
|
|
|
rps, err := h.Service.List(c.Context(), tenantID)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
|
|
return c.JSON(rps)
|
|
}
|
|
|
|
func (h *RelyingPartyHandler) Get(c *fiber.Ctx) error {
|
|
id := c.Params("id")
|
|
rp, hydraClient, err := h.Service.Get(c.Context(), id)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "relying party not found"})
|
|
}
|
|
|
|
return c.JSON(fiber.Map{
|
|
"relyingParty": rp,
|
|
"oauth2Config": hydraClient,
|
|
})
|
|
}
|
|
|
|
func (h *RelyingPartyHandler) Update(c *fiber.Ctx) error {
|
|
id := c.Params("id")
|
|
var req domain.HydraClient
|
|
if err := c.BodyParser(&req); err != nil {
|
|
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid request body"})
|
|
}
|
|
|
|
rp, err := h.Service.Update(c.Context(), id, req)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
|
|
return c.JSON(rp)
|
|
}
|
|
|
|
func (h *RelyingPartyHandler) Delete(c *fiber.Ctx) error {
|
|
id := c.Params("id")
|
|
if err := h.Service.Delete(c.Context(), id); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
|
|
return c.SendStatus(fiber.StatusNoContent)
|
|
}
|
|
|
|
func (h *RelyingPartyHandler) ListOwners(c *fiber.Ctx) error {
|
|
clientID := c.Params("id")
|
|
subjects, err := h.Service.ListOwners(c.Context(), clientID)
|
|
if err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
|
|
type ownerInfo struct {
|
|
Subject string `json:"subject"`
|
|
Name string `json:"name,omitempty"`
|
|
Email string `json:"email,omitempty"`
|
|
Type string `json:"type"` // "user" or "group"
|
|
}
|
|
|
|
owners := make([]ownerInfo, 0, len(subjects))
|
|
for _, s := range subjects {
|
|
info := ownerInfo{Subject: s, Type: "unknown"}
|
|
if len(s) > 5 && s[:5] == "User:" {
|
|
info.Type = "user"
|
|
userID := s[5:]
|
|
identity, err := h.UserSvc.GetIdentity(c.Context(), userID)
|
|
if err == nil && identity != nil {
|
|
info.Name, _ = identity.Traits["name"].(string)
|
|
info.Email, _ = identity.Traits["email"].(string)
|
|
}
|
|
} else if len(s) > 10 && s[:10] == "UserGroup:" {
|
|
info.Type = "group"
|
|
// Group name enrichment could be added if we have a GroupService here
|
|
}
|
|
owners = append(owners, info)
|
|
}
|
|
|
|
return c.JSON(owners)
|
|
}
|
|
|
|
func (h *RelyingPartyHandler) AddOwner(c *fiber.Ctx) error {
|
|
clientID := c.Params("id")
|
|
subject := c.Params("subject") // e.g. "User:uuid"
|
|
|
|
if err := h.Service.AddOwner(c.Context(), clientID, subject); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
return c.JSON(fiber.Map{"message": "owner added"})
|
|
}
|
|
|
|
func (h *RelyingPartyHandler) RemoveOwner(c *fiber.Ctx) error {
|
|
clientID := c.Params("id")
|
|
subject := c.Params("subject")
|
|
|
|
if err := h.Service.RemoveOwner(c.Context(), clientID, subject); err != nil {
|
|
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
return c.JSON(fiber.Map{"message": "owner removed"})
|
|
}
|