1
0
forked from baron/baron-sso

feat: implement bulk user group/tenant move functionality

This commit is contained in:
2026-03-04 16:15:13 +09:00
parent 5034785582
commit f55374f827
3 changed files with 230 additions and 11 deletions

View File

@@ -673,9 +673,11 @@ func (h *UserHandler) ExportUsersCSV(c *fiber.Ctx) error {
func (h *UserHandler) BulkUpdateUsers(c *fiber.Ctx) error {
var req struct {
UserIDs []string `json:"userIds"`
Status *string `json:"status"`
Role *string `json:"role"`
UserIDs []string `json:"userIds"`
Status *string `json:"status"`
Role *string `json:"role"`
CompanyCode *string `json:"companyCode"`
Department *string `json:"department"`
}
if err := c.BodyParser(&req); err != nil {
return errorJSON(c, fiber.StatusBadRequest, "invalid request body")
@@ -690,7 +692,13 @@ func (h *UserHandler) BulkUpdateUsers(c *fiber.Ctx) error {
return errorJSON(c, fiber.StatusUnauthorized, "unauthorized")
}
// Build manageable slugs map if tenant_admin
// [New] Pre-fetch tenant cache if companyCode is being changed
type tenantCacheItem struct {
ID string
Schema []interface{}
}
tenantCache := make(map[string]tenantCacheItem)
manageableSlugs := make(map[string]bool)
if requester.Role == domain.RoleTenantAdmin {
for _, t := range requester.ManageableTenants {
@@ -711,12 +719,19 @@ func (h *UserHandler) BulkUpdateUsers(c *fiber.Ctx) error {
}
// Authorization check
userComp := strings.ToLower(extractTraitString(identity.Traits, "companyCode"))
if requester.Role == domain.RoleTenantAdmin {
userComp := strings.ToLower(extractTraitString(identity.Traits, "companyCode"))
if !manageableSlugs[userComp] {
results = append(results, map[string]any{"id": id, "success": false, "message": "forbidden: user belongs to another tenant"})
continue
}
// If changing companyCode, must be to a manageable one
if req.CompanyCode != nil {
if !manageableSlugs[strings.ToLower(*req.CompanyCode)] {
results = append(results, map[string]any{"id": id, "success": false, "message": "forbidden: target tenant not manageable"})
continue
}
}
}
// Prepare updates
@@ -724,6 +739,24 @@ func (h *UserHandler) BulkUpdateUsers(c *fiber.Ctx) error {
if req.Role != nil {
traits["role"] = *req.Role
}
if req.CompanyCode != nil {
traits["companyCode"] = *req.CompanyCode
// Resolve and update tenant_id in traits if changed
if tItem, exists := tenantCache[*req.CompanyCode]; exists {
traits["tenant_id"] = tItem.ID
} else if h.TenantService != nil {
tenant, err := h.TenantService.GetTenantBySlug(c.Context(), *req.CompanyCode)
if err == nil && tenant != nil {
tItem.ID = tenant.ID
tenantCache[*req.CompanyCode] = tItem
traits["tenant_id"] = tenant.ID
}
}
}
if req.Department != nil {
traits["department"] = *req.Department
}
state := identity.State
if req.Status != nil {
@@ -743,12 +776,10 @@ func (h *UserHandler) BulkUpdateUsers(c *fiber.Ctx) error {
// Sync to local DB
if h.UserRepo != nil {
localUser := h.mapToLocalUser(*identity)
if req.Role != nil {
localUser.Role = *req.Role
}
if req.Status != nil {
localUser.Status = *req.Status
}
if req.Role != nil { localUser.Role = *req.Role }
if req.Status != nil { localUser.Status = *req.Status }
if req.CompanyCode != nil { localUser.CompanyCode = *req.CompanyCode }
if req.Department != nil { localUser.Department = *req.Department }
_ = h.UserRepo.Update(c.Context(), localUser)
}