1
0
forked from baron/baron-sso

e2e 구조변경

This commit is contained in:
Lectom C Han
2026-02-24 15:23:36 +09:00
parent 3fdcaa5832
commit 4ffe5110dd
46 changed files with 2735 additions and 393 deletions

View File

@@ -125,7 +125,7 @@ func (h *UserHandler) ListUsers(c *fiber.Ctx) error {
// Fetch from UserRepo
users, total, err := h.UserRepo.List(c.Context(), offset, limit, search)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to fetch users from both kratos and local db"})
return errorJSON(c, fiber.StatusInternalServerError, "failed to fetch users from both kratos and local db")
}
items := make([]userSummary, 0, len(users))
@@ -154,20 +154,20 @@ func (h *UserHandler) ListUsers(c *fiber.Ctx) error {
func (h *UserHandler) GetUser(c *fiber.Ctx) error {
if h.KratosAdmin == nil {
return c.Status(fiber.StatusServiceUnavailable).JSON(fiber.Map{"error": "identity provider not available"})
return errorJSON(c, fiber.StatusServiceUnavailable, "identity provider not available")
}
userID := strings.TrimSpace(c.Params("id"))
if userID == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "user id is required"})
return errorJSON(c, fiber.StatusBadRequest, "user id is required")
}
identity, err := h.KratosAdmin.GetIdentity(c.Context(), userID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
}
if identity == nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "user not found"})
return errorJSON(c, fiber.StatusNotFound, "user not found")
}
// [New] Check access scope
@@ -175,7 +175,7 @@ func (h *UserHandler) GetUser(c *fiber.Ctx) error {
if requester != nil && requester.Role == domain.RoleTenantAdmin {
compCode := extractTraitString(identity.Traits, "companyCode")
if requester.CompanyCode == "" || compCode != requester.CompanyCode {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "forbidden: access to user in another tenant denied"})
return errorJSON(c, fiber.StatusForbidden, "forbidden: access to user in another tenant denied")
}
}
@@ -184,7 +184,7 @@ func (h *UserHandler) GetUser(c *fiber.Ctx) error {
func (h *UserHandler) CreateUser(c *fiber.Ctx) error {
if h.OryProvider == nil || h.KratosAdmin == nil {
return c.Status(fiber.StatusServiceUnavailable).JSON(fiber.Map{"error": "identity provider not available"})
return errorJSON(c, fiber.StatusServiceUnavailable, "identity provider not available")
}
var req struct {
@@ -198,19 +198,19 @@ func (h *UserHandler) CreateUser(c *fiber.Ctx) error {
Metadata map[string]any `json:"metadata"`
}
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid request body"})
return errorJSON(c, fiber.StatusBadRequest, "invalid request body")
}
email := strings.TrimSpace(req.Email)
if email == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "email is required"})
return errorJSON(c, fiber.StatusBadRequest, "email is required")
}
if !strings.Contains(email, "@") || !strings.Contains(email, ".") {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid email format"})
return errorJSON(c, fiber.StatusBadRequest, "invalid email format")
}
name := strings.TrimSpace(req.Name)
if name == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "name is required"})
return errorJSON(c, fiber.StatusBadRequest, "name is required")
}
password := strings.TrimSpace(req.Password)
@@ -230,13 +230,13 @@ func (h *UserHandler) CreateUser(c *fiber.Ctx) error {
if password == "" {
generated, genErr := utils.GeneratePasswordWithPolicy(policy)
if genErr != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to generate password"})
return errorJSON(c, fiber.StatusInternalServerError, "failed to generate password")
}
password = generated
generatedPassword = generated
} else {
if err := utils.ValidatePasswordWithPolicy(policy, password); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
return errorJSON(c, fiber.StatusBadRequest, err.Error())
}
}
@@ -282,9 +282,9 @@ func (h *UserHandler) CreateUser(c *fiber.Ctx) error {
identityID, err := h.OryProvider.CreateUser(brokerUser, password)
if err != nil {
if strings.Contains(err.Error(), "already exists") {
return c.Status(fiber.StatusConflict).JSON(fiber.Map{"error": "email already exists"})
return errorJSON(c, fiber.StatusConflict, "email already exists")
}
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
}
// [New] Local DB Sync
@@ -334,7 +334,7 @@ func (h *UserHandler) CreateUser(c *fiber.Ctx) error {
identity, err := h.KratosAdmin.GetIdentity(c.Context(), identityID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
}
if identity == nil {
return c.Status(fiber.StatusCreated).JSON(fiber.Map{"id": identityID, "initialPassword": generatedPassword})
@@ -349,20 +349,20 @@ func (h *UserHandler) CreateUser(c *fiber.Ctx) error {
func (h *UserHandler) UpdateUser(c *fiber.Ctx) error {
if h.KratosAdmin == nil {
return c.Status(fiber.StatusServiceUnavailable).JSON(fiber.Map{"error": "identity provider not available"})
return errorJSON(c, fiber.StatusServiceUnavailable, "identity provider not available")
}
userID := strings.TrimSpace(c.Params("id"))
if userID == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "user id is required"})
return errorJSON(c, fiber.StatusBadRequest, "user id is required")
}
identity, err := h.KratosAdmin.GetIdentity(c.Context(), userID)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
}
if identity == nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "user not found"})
return errorJSON(c, fiber.StatusNotFound, "user not found")
}
// [New] Check access scope
@@ -370,7 +370,7 @@ func (h *UserHandler) UpdateUser(c *fiber.Ctx) error {
if requester != nil && requester.Role == domain.RoleTenantAdmin {
compCode := extractTraitString(identity.Traits, "companyCode")
if requester.CompanyCode == "" || compCode != requester.CompanyCode {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "forbidden: cannot update user in another tenant"})
return errorJSON(c, fiber.StatusForbidden, "forbidden: cannot update user in another tenant")
}
}
@@ -385,13 +385,13 @@ func (h *UserHandler) UpdateUser(c *fiber.Ctx) error {
Metadata map[string]any `json:"metadata"`
}
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid request body"})
return errorJSON(c, fiber.StatusBadRequest, "invalid request body")
}
// [New] Tenant Admin restriction: Cannot change companyCode
if requester != nil && requester.Role == domain.RoleTenantAdmin {
if req.CompanyCode != nil && *req.CompanyCode != requester.CompanyCode {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "forbidden: tenant admins cannot change user's tenant"})
return errorJSON(c, fiber.StatusForbidden, "forbidden: tenant admins cannot change user's tenant")
}
}
@@ -451,7 +451,7 @@ func (h *UserHandler) UpdateUser(c *fiber.Ctx) error {
state := normalizeKratosState(req.Status)
updated, err := h.KratosAdmin.UpdateIdentity(c.Context(), userID, traits, state)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
}
// [New] Local DB Sync
@@ -519,7 +519,7 @@ func (h *UserHandler) UpdateUser(c *fiber.Ctx) error {
if req.Password != nil && *req.Password != "" {
if err := h.KratosAdmin.UpdateIdentityPassword(c.Context(), userID, *req.Password); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
}
}
@@ -528,12 +528,12 @@ func (h *UserHandler) UpdateUser(c *fiber.Ctx) error {
func (h *UserHandler) DeleteUser(c *fiber.Ctx) error {
if h.KratosAdmin == nil {
return c.Status(fiber.StatusServiceUnavailable).JSON(fiber.Map{"error": "identity provider not available"})
return errorJSON(c, fiber.StatusServiceUnavailable, "identity provider not available")
}
userID := strings.TrimSpace(c.Params("id"))
if userID == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "user id is required"})
return errorJSON(c, fiber.StatusBadRequest, "user id is required")
}
// [New] Check access scope before deletion
@@ -543,13 +543,13 @@ func (h *UserHandler) DeleteUser(c *fiber.Ctx) error {
if err == nil && identity != nil {
compCode := extractTraitString(identity.Traits, "companyCode")
if requester.CompanyCode == "" || compCode != requester.CompanyCode {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "forbidden: cannot delete user in another tenant"})
return errorJSON(c, fiber.StatusForbidden, "forbidden: cannot delete user in another tenant")
}
}
}
if err := h.KratosAdmin.DeleteIdentity(c.Context(), userID); err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
}
// [Keto] Cleanup relations (Best effort)