1
0
forked from baron/baron-sso

개발자 권한 부여 페이지 추가

This commit is contained in:
2026-06-09 09:28:20 +09:00
parent 41e755b1c7
commit 0f11173739
11 changed files with 1050 additions and 3 deletions

View File

@@ -4049,7 +4049,7 @@ func (h *DevHandler) ListDeveloperRequests(c *fiber.Ctx) error {
userID = ""
}
requests, err := h.DeveloperSvc.ListRequests(c.Context(), userID, status)
requests, err := h.DeveloperSvc.ListRequests(c.Context(), userID, status, "")
if err != nil {
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
}
@@ -4057,6 +4057,159 @@ func (h *DevHandler) ListDeveloperRequests(c *fiber.Ctx) error {
return c.JSON(requests)
}
func (h *DevHandler) ListDeveloperGrants(c *fiber.Ctx) error {
profile := h.getCurrentProfile(c)
if profile == nil {
return errorJSON(c, fiber.StatusUnauthorized, "unauthorized")
}
if normalizeUserRole(profile.Role) != domain.RoleSuperAdmin {
return errorJSON(c, fiber.StatusForbidden, "forbidden: super_admin only")
}
tenantID := strings.TrimSpace(c.Query("tenantId"))
grants, err := h.DeveloperSvc.ListRequests(c.Context(), "", domain.DeveloperRequestStatusApproved, tenantID)
if err != nil {
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
}
return c.JSON(grants)
}
func (h *DevHandler) CreateDeveloperGrant(c *fiber.Ctx) error {
profile := h.getCurrentProfile(c)
if profile == nil {
return errorJSON(c, fiber.StatusUnauthorized, "unauthorized")
}
if normalizeUserRole(profile.Role) != domain.RoleSuperAdmin {
return errorJSON(c, fiber.StatusForbidden, "forbidden: super_admin only")
}
var reqBody struct {
UserID string `json:"userId"`
TenantID string `json:"tenantId"`
Reason string `json:"reason"`
AdminNotes string `json:"adminNotes"`
}
if err := c.BodyParser(&reqBody); err != nil {
return errorJSON(c, fiber.StatusBadRequest, "invalid request body")
}
userID := strings.TrimSpace(reqBody.UserID)
tenantID := strings.TrimSpace(reqBody.TenantID)
if userID == "" || tenantID == "" {
return errorJSON(c, fiber.StatusBadRequest, "userId and tenantId are required")
}
if h.KratosAdmin == nil || h.TenantSvc == nil {
return errorJSON(c, fiber.StatusServiceUnavailable, "required services are unavailable")
}
identity, err := h.KratosAdmin.GetIdentity(c.Context(), userID)
if err != nil || identity == nil {
return errorJSON(c, fiber.StatusNotFound, "user not found")
}
tenant, err := h.TenantSvc.GetTenant(c.Context(), tenantID)
if err != nil || tenant == nil {
return errorJSON(c, fiber.StatusNotFound, "tenant not found")
}
name := strings.TrimSpace(extractTraitString(identity.Traits, "name"))
if name == "" {
name = userID
}
organization := strings.TrimSpace(tenant.Name)
if organization == "" {
organization = tenantID
}
email := strings.TrimSpace(extractTraitString(identity.Traits, "email"))
phone := strings.TrimSpace(extractTraitString(identity.Traits, "phone"))
role := normalizeUserRole(extractTraitString(identity.Traits, "role"))
if role == "" {
role = domain.RoleUser
}
reason := strings.TrimSpace(reqBody.Reason)
if reason == "" {
reason = "직접 부여"
}
existing, err := h.DeveloperSvc.GetRequestStatus(c.Context(), userID, tenantID)
if err != nil {
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
}
if existing != nil {
switch existing.Status {
case domain.DeveloperRequestStatusApproved:
h.ensureDeveloperGrantRelation(c, userID, tenantID)
return c.JSON(existing)
case domain.DeveloperRequestStatusPending:
if err := h.DeveloperSvc.ApproveRequest(c.Context(), existing.ID, reqBody.AdminNotes); err != nil {
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
}
h.ensureDeveloperGrantRelation(c, userID, tenantID)
existing.Status = domain.DeveloperRequestStatusApproved
existing.AdminNotes = reqBody.AdminNotes
return c.JSON(existing)
}
}
grant := domain.DeveloperRequest{
UserID: userID,
TenantID: tenantID,
Name: name,
Organization: organization,
Email: email,
Phone: phone,
Role: role,
Reason: reason,
Status: domain.DeveloperRequestStatusApproved,
AdminNotes: strings.TrimSpace(reqBody.AdminNotes),
}
if err := h.DeveloperSvc.CreateGrant(c.Context(), grant); err != nil {
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
}
h.ensureDeveloperGrantRelation(c, userID, tenantID)
return c.Status(fiber.StatusCreated).JSON(grant)
}
func (h *DevHandler) RevokeDeveloperGrant(c *fiber.Ctx) error {
profile := h.getCurrentProfile(c)
if profile == nil {
return errorJSON(c, fiber.StatusUnauthorized, "unauthorized")
}
if normalizeUserRole(profile.Role) != domain.RoleSuperAdmin {
return errorJSON(c, fiber.StatusForbidden, "forbidden: super_admin only")
}
idStr := c.Params("id")
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil {
return errorJSON(c, fiber.StatusBadRequest, "invalid grant id")
}
var reqBody struct {
AdminNotes string `json:"adminNotes"`
}
if err := c.BodyParser(&reqBody); err != nil {
return errorJSON(c, fiber.StatusBadRequest, "invalid request body")
}
devReq, err := h.DeveloperSvc.GetRequestByID(c.Context(), uint(id))
if err != nil {
return errorJSON(c, fiber.StatusInternalServerError, "failed to fetch grant details")
}
if devReq.Status != domain.DeveloperRequestStatusApproved {
return errorJSON(c, fiber.StatusBadRequest, "only approved grants can be revoked")
}
if err := h.DeveloperSvc.CancelApprovedRequest(c.Context(), uint(id), reqBody.AdminNotes); err != nil {
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
}
h.revokeDeveloperGrantRelation(c, devReq.UserID, devReq.TenantID)
return c.JSON(fiber.Map{"status": "ok"})
}
func (h *DevHandler) ApproveDeveloperRequest(c *fiber.Ctx) error {
profile := h.getCurrentProfile(c)
if profile == nil {