forked from baron/baron-sso
조직도 M2M조회 추가, 자동로그인 보완
This commit is contained in:
155
backend/internal/handler/tenant_assignment_policy.go
Normal file
155
backend/internal/handler/tenant_assignment_policy.go
Normal file
@@ -0,0 +1,155 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"baron-sso-backend/internal/domain"
|
||||
"baron-sso-backend/internal/service"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func representativeTenantIDFromTraits(traits map[string]any) string {
|
||||
if value := tenantClaimString(traits, "tenant_id"); value != "" {
|
||||
return value
|
||||
}
|
||||
if value := tenantClaimString(traits, "primaryTenantId"); value != "" {
|
||||
return value
|
||||
}
|
||||
if metadata, ok := traits["metadata"].(map[string]any); ok {
|
||||
if value := tenantClaimString(metadata, "primaryTenantId"); value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
appointments := tenantAssignmentAppointmentsFromTraits(traits)
|
||||
for _, appointment := range appointments {
|
||||
if tenantAssignmentBool(appointment, "isPrimary", "primary", "representative", "isRepresentative") {
|
||||
if value := tenantAssignmentTenantID(appointment); value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, appointment := range appointments {
|
||||
if value := tenantAssignmentTenantID(appointment); value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
for _, tenantID := range tenantNamespaceIDsFromTraits(traits) {
|
||||
return tenantID
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func joinedTenantIDsFromTraits(traits map[string]any, representativeTenantID string) []string {
|
||||
values := make([]string, 0)
|
||||
if representativeTenantID != "" {
|
||||
values = append(values, representativeTenantID)
|
||||
}
|
||||
if value := tenantClaimString(traits, "tenant_id"); value != "" {
|
||||
values = append(values, value)
|
||||
}
|
||||
for _, appointment := range tenantAssignmentAppointmentsFromTraits(traits) {
|
||||
if value := tenantAssignmentTenantID(appointment); value != "" {
|
||||
values = append(values, value)
|
||||
}
|
||||
}
|
||||
values = append(values, tenantNamespaceIDsFromTraits(traits)...)
|
||||
return uniqueSortedStrings(values)
|
||||
}
|
||||
|
||||
func tenantAssignmentAppointmentsFromTraits(traits map[string]any) []map[string]any {
|
||||
raw := rawAdditionalAppointments(traits)
|
||||
switch values := raw.(type) {
|
||||
case []any:
|
||||
appointments := make([]map[string]any, 0, len(values))
|
||||
for _, item := range values {
|
||||
if appointment, ok := item.(map[string]any); ok {
|
||||
appointments = append(appointments, appointment)
|
||||
}
|
||||
}
|
||||
return appointments
|
||||
case []map[string]any:
|
||||
return values
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func tenantAssignmentTenantID(appointment map[string]any) string {
|
||||
for _, key := range []string{"tenantId", "tenant_id"} {
|
||||
if value := tenantClaimString(appointment, key); value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func tenantAssignmentBool(values map[string]any, keys ...string) bool {
|
||||
for _, key := range keys {
|
||||
raw, ok := values[key]
|
||||
if !ok || raw == nil {
|
||||
continue
|
||||
}
|
||||
switch value := raw.(type) {
|
||||
case bool:
|
||||
if value {
|
||||
return true
|
||||
}
|
||||
case string:
|
||||
normalized := strings.ToLower(strings.TrimSpace(value))
|
||||
if normalized == "true" || normalized == "1" || normalized == "yes" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func tenantNamespaceIDsFromTraits(traits map[string]any) []string {
|
||||
if traits == nil {
|
||||
return nil
|
||||
}
|
||||
ids := make([]string, 0)
|
||||
for key, value := range traits {
|
||||
if key == "" || key == "metadata" {
|
||||
continue
|
||||
}
|
||||
switch value.(type) {
|
||||
case map[string]any:
|
||||
ids = append(ids, key)
|
||||
}
|
||||
}
|
||||
return uniqueSortedStrings(ids)
|
||||
}
|
||||
|
||||
func createPersonalTenantForUser(ctx context.Context, tenantService service.TenantService, email string) (*domain.Tenant, error) {
|
||||
if tenantService == nil {
|
||||
return nil, errors.New("tenant service unavailable")
|
||||
}
|
||||
normalizedEmail := strings.ToLower(strings.TrimSpace(email))
|
||||
if normalizedEmail == "" {
|
||||
normalizedEmail = "user"
|
||||
}
|
||||
slug := "personal-" + strings.ReplaceAll(uuid.NewString(), "-", "")
|
||||
tenant, err := tenantService.RegisterTenant(
|
||||
ctx,
|
||||
fmt.Sprintf("Personal - %s", normalizedEmail),
|
||||
slug,
|
||||
domain.TenantTypePersonal,
|
||||
"Automatically provisioned personal tenant",
|
||||
nil,
|
||||
nil,
|
||||
"",
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if tenant == nil {
|
||||
return nil, errors.New("personal tenant not created")
|
||||
}
|
||||
return tenant, nil
|
||||
}
|
||||
Reference in New Issue
Block a user