forked from baron/baron-sso
fix(backend): fix CSV export authentication by moving role validation inside the handler
This commit is contained in:
@@ -643,7 +643,7 @@ func main() {
|
|||||||
|
|
||||||
// Admin User Management
|
// Admin User Management
|
||||||
admin.Get("/users", requireAdmin, userHandler.ListUsers)
|
admin.Get("/users", requireAdmin, userHandler.ListUsers)
|
||||||
admin.Get("/users/export", requireAdmin, userHandler.ExportUsersCSV)
|
admin.Get("/users/export", userHandler.ExportUsersCSV) // Removed requireAdmin to handle mock role in query param
|
||||||
admin.Post("/users", requireAdmin, userHandler.CreateUser)
|
admin.Post("/users", requireAdmin, userHandler.CreateUser)
|
||||||
admin.Post("/users/bulk", requireAdmin, userHandler.BulkCreateUsers)
|
admin.Post("/users/bulk", requireAdmin, userHandler.BulkCreateUsers)
|
||||||
admin.Put("/users/bulk", requireAdmin, userHandler.BulkUpdateUsers)
|
admin.Put("/users/bulk", requireAdmin, userHandler.BulkUpdateUsers)
|
||||||
|
|||||||
@@ -549,24 +549,41 @@ func (h *UserHandler) ExportUsersCSV(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
var requesterRole string
|
var requesterRole string
|
||||||
var manageableSlugs []string
|
var manageableSlugs []string
|
||||||
|
var profile *domain.UserProfileResponse
|
||||||
|
|
||||||
profile, _ := c.Locals("user_profile").(*domain.UserProfileResponse)
|
// [New] Manual profile resolution to support query-param role mocking
|
||||||
|
// This is needed because browsers cannot send custom headers for direct downloads
|
||||||
// [New] Support Role Mocking for Download (which doesn't have custom headers)
|
mockRole := c.Query("x-test-role")
|
||||||
if profile == nil {
|
|
||||||
appEnv := strings.ToLower(os.Getenv("APP_ENV"))
|
appEnv := strings.ToLower(os.Getenv("APP_ENV"))
|
||||||
isDev := appEnv == "dev" || appEnv == "development" || appEnv == ""
|
isDev := appEnv == "dev" || appEnv == "development" || appEnv == ""
|
||||||
mockRole := c.Query("x-test-role")
|
|
||||||
if isDev && mockRole != "" {
|
if isDev && mockRole != "" {
|
||||||
slog.Info("🔑 [AUTH] Using mock role from query for export", "role", mockRole)
|
slog.Info("🔑 [AUTH] Using mock role from query for export", "role", mockRole)
|
||||||
requesterRole = mockRole
|
requesterRole = mockRole
|
||||||
// For tenant_admin, we might need more data, but let's assume super_admin for full export in dev
|
// In dev mocking, we might not have a full profile, but we need to know the manageable tenants if it's a tenant_admin
|
||||||
} else {
|
if requesterRole == domain.RoleTenantAdmin {
|
||||||
return errorJSON(c, fiber.StatusUnauthorized, "invalid session (trace:export_profile)")
|
// Try to get actual profile if possible to get manageableTenants
|
||||||
|
p, _ := c.Locals("user_profile").(*domain.UserProfileResponse)
|
||||||
|
if p != nil {
|
||||||
|
profile = p
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Use real profile from middleware
|
||||||
|
p, ok := c.Locals("user_profile").(*domain.UserProfileResponse)
|
||||||
|
if !ok || p == nil {
|
||||||
|
return errorJSON(c, fiber.StatusUnauthorized, "invalid session (trace:export_auth)")
|
||||||
|
}
|
||||||
|
profile = p
|
||||||
requesterRole = profile.Role
|
requesterRole = profile.Role
|
||||||
if requesterRole == domain.RoleTenantAdmin {
|
}
|
||||||
|
|
||||||
|
// [New] Access Control: only admin roles can export
|
||||||
|
if requesterRole != domain.RoleSuperAdmin && requesterRole != domain.RoleTenantAdmin {
|
||||||
|
return errorJSON(c, fiber.StatusForbidden, "forbidden: insufficient permissions for export")
|
||||||
|
}
|
||||||
|
|
||||||
|
if profile != nil && requesterRole == domain.RoleTenantAdmin {
|
||||||
for _, t := range profile.ManageableTenants {
|
for _, t := range profile.ManageableTenants {
|
||||||
manageableSlugs = append(manageableSlugs, strings.ToLower(t.Slug))
|
manageableSlugs = append(manageableSlugs, strings.ToLower(t.Slug))
|
||||||
}
|
}
|
||||||
@@ -574,7 +591,6 @@ func (h *UserHandler) ExportUsersCSV(c *fiber.Ctx) error {
|
|||||||
manageableSlugs = append(manageableSlugs, strings.ToLower(profile.CompanyCode))
|
manageableSlugs = append(manageableSlugs, strings.ToLower(profile.CompanyCode))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 1. Fetch Users using Repo for efficiency
|
// 1. Fetch Users using Repo for efficiency
|
||||||
users, _, err := h.UserRepo.List(c.Context(), 10000, 0, search, companyCode)
|
users, _, err := h.UserRepo.List(c.Context(), 10000, 0, search, companyCode)
|
||||||
|
|||||||
Reference in New Issue
Block a user