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

@@ -3,6 +3,7 @@ package handler
import (
"baron-sso-backend/internal/domain"
"baron-sso-backend/internal/logger"
"baron-sso-backend/internal/repository"
"baron-sso-backend/internal/service"
"baron-sso-backend/internal/utils"
"bytes"
@@ -78,6 +79,8 @@ type AuthHandler struct {
IdpProvider domain.IdentityProvider
AuditRepo domain.AuditRepository
Hydra *service.HydraAdminService
TenantService service.TenantService
UserRepo repository.UserRepository
}
type signupState struct {
@@ -135,7 +138,7 @@ func checkPollInterval(redis *service.RedisService, key string, interval time.Du
return false, int(interval.Seconds())
}
func NewAuthHandler(redisService *service.RedisService, idpProvider domain.IdentityProvider, auditRepo domain.AuditRepository) *AuthHandler {
func NewAuthHandler(redisService *service.RedisService, idpProvider domain.IdentityProvider, auditRepo domain.AuditRepository, tenantService service.TenantService, userRepo repository.UserRepository) *AuthHandler {
projectID := os.Getenv("DESCOPE_PROJECT_ID")
managementKey := os.Getenv("DESCOPE_MANAGEMENT_KEY")
@@ -161,6 +164,8 @@ func NewAuthHandler(redisService *service.RedisService, idpProvider domain.Ident
IdpProvider: idpProvider,
AuditRepo: auditRepo,
Hydra: service.NewHydraAdminService(),
TenantService: tenantService,
UserRepo: userRepo,
}
}
@@ -357,6 +362,9 @@ func (h *AuthHandler) Signup(c *fiber.Ctx) error {
if req.Email == "" || req.Password == "" || req.Name == "" || req.Phone == "" {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Missing required fields"})
}
if !strings.Contains(req.Email, "@") || !strings.Contains(req.Email, ".") {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid email format"})
}
if !req.TermsAccepted {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Terms must be accepted"})
}
@@ -385,6 +393,20 @@ func (h *AuthHandler) Signup(c *fiber.Ctx) error {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Identity provider unavailable"})
}
// [New] Auto-Assign Tenant by Domain
companyCode := req.CompanyCode
if companyCode == "" {
parts := strings.Split(req.Email, "@")
if len(parts) == 2 {
domainName := parts[1]
tenant, err := h.TenantService.GetTenantByDomain(c.Context(), domainName)
if err == nil && tenant != nil {
slog.Info("[Signup] Auto-assigning tenant", "email", req.Email, "tenant", tenant.Slug)
companyCode = tenant.Slug
}
}
}
// Normalize Phone (E.164 형태로 보관)
normalizedPhone := strings.ReplaceAll(req.Phone, "-", "")
normalizedPhone = strings.ReplaceAll(normalizedPhone, " ", "")
@@ -398,7 +420,7 @@ func (h *AuthHandler) Signup(c *fiber.Ctx) error {
attributes := map[string]interface{}{
"department": req.Department,
"affiliationType": req.AffiliationType,
"companyCode": req.CompanyCode,
"companyCode": companyCode,
// grade는 기존 스키마 필수 키이므로 기본값을 설정
"grade": "member",
}
@@ -427,6 +449,31 @@ func (h *AuthHandler) Signup(c *fiber.Ctx) error {
slog.Info("[Signup] New user registered", "email", req.Email, "type", req.AffiliationType, "provider", h.IdpProvider.Name(), "subject", providerID)
// [New] Local DB Sync
localUser := &domain.User{
ID: providerID, // Match IDP Subject
Email: req.Email,
Name: req.Name,
Phone: normalizedPhone,
AffiliationType: req.AffiliationType,
CompanyCode: companyCode,
Department: req.Department,
Role: "user",
Status: "active",
}
// Link TenantID if possible
if companyCode != "" {
if tenant, err := h.TenantService.GetTenantBySlug(c.Context(), companyCode); err == nil && tenant != nil {
localUser.TenantID = &tenant.ID
}
}
if err := h.UserRepo.Create(c.Context(), localUser); err != nil {
slog.Error("[Signup] Failed to sync user to local DB", "email", req.Email, "error", err)
// We don't fail the whole signup if local sync fails
}
return c.JSON(fiber.Map{
"success": true,
"message": "User registered successfully",
@@ -2057,6 +2104,13 @@ func (h *AuthHandler) GetMe(c *fiber.Ctx) error {
AffiliationType: affType,
CompanyCode: compCode,
}
if compCode != "" {
if tenant, err := h.TenantService.GetTenantBySlug(c.Context(), compCode); err == nil && tenant != nil {
resp.Tenant = tenant
}
}
return c.JSON(resp)
}
}