forked from baron/baron-sso
조직현황 구조변경. 총괄센터삼안 실 조직 삽입확인
This commit is contained in:
@@ -391,7 +391,12 @@ func (h *TenantHandler) ImportTenantsCSV(c *fiber.Ctx) error {
|
||||
}
|
||||
}
|
||||
|
||||
tenant, err := h.createTenantCSVRecord(c, record, creatorID)
|
||||
recordCreatorID := creatorID
|
||||
if record.Type == domain.TenantTypeOrganization {
|
||||
recordCreatorID = ""
|
||||
}
|
||||
|
||||
tenant, err := h.createTenantCSVRecord(c, record, recordCreatorID)
|
||||
if err != nil {
|
||||
result.Failed++
|
||||
result.Errors = append(result.Errors, fmt.Sprintf("row %d: %s", rowNumber, err.Error()))
|
||||
@@ -632,11 +637,142 @@ func normalizeTenantConfig(config map[string]any) (domain.JSONMap, error) {
|
||||
normalized[key] = fields
|
||||
continue
|
||||
}
|
||||
if key == "visibility" {
|
||||
visibility, ok := value.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("visibility must be public, internal, or private")
|
||||
}
|
||||
visibility = strings.TrimSpace(strings.ToLower(visibility))
|
||||
if visibility == "" || visibility == "public" {
|
||||
normalized[key] = "public"
|
||||
continue
|
||||
}
|
||||
if visibility != "internal" && visibility != "private" {
|
||||
return nil, fmt.Errorf("visibility must be public, internal, or private")
|
||||
}
|
||||
normalized[key] = visibility
|
||||
continue
|
||||
}
|
||||
if key == "orgUnitType" {
|
||||
orgUnitType, ok := value.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("orgUnitType must be one of 실, 팀, 디비전, 셀, 본부, 지역본부, 부")
|
||||
}
|
||||
orgUnitType = strings.TrimSpace(orgUnitType)
|
||||
if orgUnitType == "" {
|
||||
continue
|
||||
}
|
||||
if !isAllowedOrgUnitType(orgUnitType) {
|
||||
return nil, fmt.Errorf("orgUnitType must be one of 실, 팀, 디비전, 셀, 본부, 지역본부, 부")
|
||||
}
|
||||
normalized[key] = orgUnitType
|
||||
continue
|
||||
}
|
||||
normalized[key] = value
|
||||
}
|
||||
return normalized, nil
|
||||
}
|
||||
|
||||
func isAllowedOrgUnitType(value string) bool {
|
||||
switch value {
|
||||
case "실", "팀", "디비전", "셀", "본부", "지역본부", "부":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func hasTenantOrgConfig(config domain.JSONMap) bool {
|
||||
if config == nil {
|
||||
return false
|
||||
}
|
||||
_, hasVisibility := config["visibility"]
|
||||
_, hasOrgUnitType := config["orgUnitType"]
|
||||
return hasVisibility || hasOrgUnitType
|
||||
}
|
||||
|
||||
func isHanmacFamilyDescendantTenant(tenant domain.Tenant, tenants []domain.Tenant) bool {
|
||||
if strings.EqualFold(tenant.Slug, "hanmac-family") {
|
||||
return false
|
||||
}
|
||||
|
||||
byID := make(map[string]domain.Tenant, len(tenants)+1)
|
||||
for _, item := range tenants {
|
||||
byID[item.ID] = item
|
||||
}
|
||||
byID[tenant.ID] = tenant
|
||||
|
||||
parentID := tenant.ParentID
|
||||
visited := make(map[string]bool)
|
||||
for parentID != nil && *parentID != "" {
|
||||
if visited[*parentID] {
|
||||
return false
|
||||
}
|
||||
visited[*parentID] = true
|
||||
|
||||
parent, ok := byID[*parentID]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if strings.EqualFold(parent.Slug, "hanmac-family") {
|
||||
return true
|
||||
}
|
||||
parentID = parent.ParentID
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func validateTenantOrgConfigScope(tenant domain.Tenant, tenants []domain.Tenant, config domain.JSONMap) error {
|
||||
if !hasTenantOrgConfig(config) {
|
||||
return nil
|
||||
}
|
||||
if isHanmacFamilyDescendantTenant(tenant, tenants) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("tenant org config is allowed only hanmac-family descendants")
|
||||
}
|
||||
|
||||
func tenantVisibility(config domain.JSONMap) string {
|
||||
visibility, _ := config["visibility"].(string)
|
||||
switch strings.ToLower(strings.TrimSpace(visibility)) {
|
||||
case "internal":
|
||||
return "internal"
|
||||
case "private":
|
||||
return "private"
|
||||
default:
|
||||
return "public"
|
||||
}
|
||||
}
|
||||
|
||||
func filterPublicTenants(tenants []domain.Tenant) []domain.Tenant {
|
||||
excludedIDs := make(map[string]bool)
|
||||
for _, tenant := range tenants {
|
||||
visibility := tenantVisibility(tenant.Config)
|
||||
if visibility == "internal" || visibility == "private" {
|
||||
excludedIDs[tenant.ID] = true
|
||||
}
|
||||
}
|
||||
|
||||
changed := true
|
||||
for changed {
|
||||
changed = false
|
||||
for _, tenant := range tenants {
|
||||
if tenant.ParentID != nil && excludedIDs[*tenant.ParentID] && !excludedIDs[tenant.ID] {
|
||||
excludedIDs[tenant.ID] = true
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filtered := make([]domain.Tenant, 0, len(tenants))
|
||||
for _, tenant := range tenants {
|
||||
if !excludedIDs[tenant.ID] {
|
||||
filtered = append(filtered, tenant)
|
||||
}
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
func normalizeTenantUserSchema(value any) ([]any, error) {
|
||||
if value == nil {
|
||||
return nil, nil
|
||||
@@ -1023,6 +1159,15 @@ func (h *TenantHandler) CreateTenant(c *fiber.Ctx) error {
|
||||
if err != nil {
|
||||
return errorJSON(c, fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
var tenants []domain.Tenant
|
||||
if hasTenantOrgConfig(config) {
|
||||
if err := h.DB.Find(&tenants).Error; err != nil {
|
||||
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
if err := validateTenantOrgConfigScope(*tenant, tenants, config); err != nil {
|
||||
return errorJSON(c, fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
}
|
||||
tenant.Config = config
|
||||
h.DB.Save(tenant)
|
||||
summary.Config = tenant.Config
|
||||
@@ -1162,6 +1307,15 @@ func (h *TenantHandler) UpdateTenant(c *fiber.Ctx) error {
|
||||
if err != nil {
|
||||
return errorJSON(c, fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
var tenants []domain.Tenant
|
||||
if hasTenantOrgConfig(config) {
|
||||
if err := h.DB.Find(&tenants).Error; err != nil {
|
||||
return errorJSON(c, fiber.StatusInternalServerError, err.Error())
|
||||
}
|
||||
if err := validateTenantOrgConfigScope(tenant, tenants, config); err != nil {
|
||||
return errorJSON(c, fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
}
|
||||
tenant.Config = config
|
||||
}
|
||||
|
||||
@@ -1696,10 +1850,13 @@ func (h *TenantHandler) GetPublicOrgChart(c *fiber.Ctx) error {
|
||||
for _, t := range allTenants {
|
||||
if findRoot(t.ID) == sharedRootID {
|
||||
filteredTenants = append(filteredTenants, t)
|
||||
tenantIDs = append(tenantIDs, t.ID)
|
||||
slugs = append(slugs, t.Slug)
|
||||
}
|
||||
}
|
||||
filteredTenants = filterPublicTenants(filteredTenants)
|
||||
for _, t := range filteredTenants {
|
||||
tenantIDs = append(tenantIDs, t.ID)
|
||||
slugs = append(slugs, t.Slug)
|
||||
}
|
||||
|
||||
type publicUserSummary struct {
|
||||
ID string `json:"id"`
|
||||
|
||||
Reference in New Issue
Block a user