1
0
forked from baron/baron-sso

테넌트 등록 방식을 결정

This commit is contained in:
2026-02-02 14:05:50 +09:00
parent 9e9c622600
commit 5dd425050c
21 changed files with 613 additions and 84 deletions

View File

@@ -2,6 +2,7 @@ package handler
import (
"baron-sso-backend/internal/domain"
"baron-sso-backend/internal/service"
"errors"
"strings"
"time"
@@ -11,21 +12,23 @@ import (
)
type TenantHandler struct {
DB *gorm.DB
DB *gorm.DB
Service service.TenantService
}
func NewTenantHandler(db *gorm.DB) *TenantHandler {
return &TenantHandler{DB: db}
func NewTenantHandler(db *gorm.DB, svc service.TenantService) *TenantHandler {
return &TenantHandler{DB: db, Service: svc}
}
type tenantSummary struct {
ID string `json:"id"`
Name string `json:"name"`
Slug string `json:"slug"`
Description string `json:"description"`
Status string `json:"status"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
ID string `json:"id"`
Name string `json:"name"`
Slug string `json:"slug"`
Description string `json:"description"`
Status string `json:"status"`
Domains []string `json:"domains,omitempty"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
type tenantListResponse struct {
@@ -55,7 +58,7 @@ func (h *TenantHandler) ListTenants(c *fiber.Ctx) error {
}
var tenants []domain.Tenant
if err := h.DB.Order("created_at desc").Limit(limit).Offset(offset).Find(&tenants).Error; err != nil {
if err := h.DB.Order("created_at desc").Limit(limit).Offset(offset).Preload("Domains").Find(&tenants).Error; err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
@@ -78,7 +81,7 @@ func (h *TenantHandler) GetTenant(c *fiber.Ctx) error {
}
var tenant domain.Tenant
if err := h.DB.First(&tenant, "id = ?", tenantID).Error; err != nil {
if err := h.DB.Preload("Domains").First(&tenant, "id = ?", tenantID).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "tenant not found"})
}
@@ -94,10 +97,11 @@ func (h *TenantHandler) CreateTenant(c *fiber.Ctx) error {
}
var req struct {
Name string `json:"name"`
Slug string `json:"slug"`
Description string `json:"description"`
Status string `json:"status"`
Name string `json:"name"`
Slug string `json:"slug"`
Description string `json:"description"`
Status string `json:"status"`
Domains []string `json:"domains"`
}
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid request body"})
@@ -121,25 +125,16 @@ func (h *TenantHandler) CreateTenant(c *fiber.Ctx) error {
status = "active"
}
var exists domain.Tenant
if err := h.DB.Unscoped().Where("slug = ?", slug).First(&exists).Error; err == nil {
return c.Status(fiber.StatusConflict).JSON(fiber.Map{"error": "slug already exists"})
} else if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
// Use Service
tenant, err := h.Service.RegisterTenant(c.Context(), name, slug, req.Description, req.Domains)
if err != nil {
if strings.Contains(err.Error(), "already exists") {
return c.Status(fiber.StatusConflict).JSON(fiber.Map{"error": err.Error()})
}
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
tenant := domain.Tenant{
Name: name,
Slug: slug,
Description: strings.TrimSpace(req.Description),
Status: status,
}
if err := h.DB.Create(&tenant).Error; err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
return c.Status(fiber.StatusCreated).JSON(mapTenantSummary(tenant))
return c.Status(fiber.StatusCreated).JSON(mapTenantSummary(*tenant))
}
func (h *TenantHandler) UpdateTenant(c *fiber.Ctx) error {
@@ -161,10 +156,11 @@ func (h *TenantHandler) UpdateTenant(c *fiber.Ctx) error {
}
var req struct {
Name *string `json:"name"`
Slug *string `json:"slug"`
Description *string `json:"description"`
Status *string `json:"status"`
Name *string `json:"name"`
Slug *string `json:"slug"`
Description *string `json:"description"`
Status *string `json:"status"`
Domains []string `json:"domains"`
}
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid request body"})
@@ -207,6 +203,32 @@ func (h *TenantHandler) UpdateTenant(c *fiber.Ctx) error {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
}
// Update domains if provided
if req.Domains != nil {
// Simple approach: Delete existing and recreate
if err := h.DB.Delete(&domain.TenantDomain{}, "tenant_id = ?", tenant.ID).Error; err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to clear old domains"})
}
for _, d := range req.Domains {
if strings.TrimSpace(d) == "" {
continue
}
td := domain.TenantDomain{
TenantID: tenant.ID,
Domain: strings.TrimSpace(d),
Verified: true,
}
if err := h.DB.Create(&td).Error; err != nil {
// Log and continue or return error?
// For now return error to be safe.
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to add domain: " + d})
}
}
}
// Refetch to get updated relations
h.DB.Preload("Domains").First(&tenant, "id = ?", tenant.ID)
return c.JSON(mapTenantSummary(tenant))
}
@@ -228,12 +250,18 @@ func (h *TenantHandler) DeleteTenant(c *fiber.Ctx) error {
}
func mapTenantSummary(t domain.Tenant) tenantSummary {
domains := make([]string, 0, len(t.Domains))
for _, d := range t.Domains {
domains = append(domains, d.Domain)
}
return tenantSummary{
ID: t.ID,
Name: t.Name,
Slug: t.Slug,
Description: t.Description,
Status: t.Status,
Domains: domains,
CreatedAt: t.CreatedAt.Format(time.RFC3339),
UpdatedAt: t.UpdatedAt.Format(time.RFC3339),
}