141 lines
3.6 KiB
Go
141 lines
3.6 KiB
Go
package middleware
|
|
|
|
import (
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/google/uuid"
|
|
"gorm.io/gorm"
|
|
customMiddleware "netidhub-saas-be/app/middleware"
|
|
)
|
|
|
|
// AddClientFilter adds client_id filter to GORM query
|
|
// Enhanced to support multi-client access and super admin
|
|
func AddClientFilter(db *gorm.DB, c *fiber.Ctx) *gorm.DB {
|
|
if c == nil {
|
|
return db
|
|
}
|
|
|
|
// Check if super admin
|
|
if customMiddleware.IsSuperAdmin(c) {
|
|
return db // No filtering for super admin
|
|
}
|
|
|
|
// Get accessible client IDs
|
|
accessibleClientIDs := customMiddleware.GetAccessibleClientIDs(c)
|
|
|
|
if accessibleClientIDs == nil {
|
|
// Super admin or no restriction
|
|
return db
|
|
}
|
|
|
|
if len(accessibleClientIDs) == 0 {
|
|
// User has no client access - return empty result
|
|
return db.Where("1 = 0")
|
|
}
|
|
|
|
if len(accessibleClientIDs) == 1 {
|
|
// Single client access (backward compatible)
|
|
return db.Where("client_id = ?", accessibleClientIDs[0])
|
|
}
|
|
|
|
// Multiple client access
|
|
return db.Where("client_id IN ?", accessibleClientIDs)
|
|
}
|
|
|
|
// SetClientID sets client_id in the given struct if it has a ClientId field
|
|
// Uses the current working client ID from context
|
|
func SetClientID(c *fiber.Ctx, model interface{}) {
|
|
if c == nil {
|
|
return
|
|
}
|
|
|
|
// Try to get current client ID first (multi-client support)
|
|
currentClientID := customMiddleware.GetCurrentClientID(c)
|
|
if currentClientID != nil {
|
|
if setter, ok := model.(interface{ SetClientID(*uuid.UUID) }); ok {
|
|
setter.SetClientID(currentClientID)
|
|
}
|
|
return
|
|
}
|
|
|
|
// Fallback to old GetClientID (backward compatibility)
|
|
clientID := customMiddleware.GetClientID(c)
|
|
if clientID != nil {
|
|
if setter, ok := model.(interface{ SetClientID(*uuid.UUID) }); ok {
|
|
setter.SetClientID(clientID)
|
|
}
|
|
}
|
|
}
|
|
|
|
// ValidateClientAccess validates if the current user has access to a resource
|
|
// Enhanced to check against all accessible clients for multi-client users
|
|
func ValidateClientAccess(db *gorm.DB, c *fiber.Ctx, tableName string, resourceID interface{}) error {
|
|
if c == nil {
|
|
return nil // Skip validation for background jobs
|
|
}
|
|
|
|
// Super admin has access to everything
|
|
if customMiddleware.IsSuperAdmin(c) {
|
|
return nil
|
|
}
|
|
|
|
accessibleClientIDs := customMiddleware.GetAccessibleClientIDs(c)
|
|
if accessibleClientIDs == nil {
|
|
// Super admin case (should not reach here, but for safety)
|
|
return nil
|
|
}
|
|
|
|
if len(accessibleClientIDs) == 0 {
|
|
return fiber.NewError(fiber.StatusForbidden, "No client access configured")
|
|
}
|
|
|
|
var count int64
|
|
var err error
|
|
|
|
if len(accessibleClientIDs) == 1 {
|
|
// Single client (backward compatible)
|
|
err = db.Table(tableName).
|
|
Where("id = ? AND client_id = ?", resourceID, accessibleClientIDs[0]).
|
|
Count(&count).Error
|
|
} else {
|
|
// Multiple clients
|
|
err = db.Table(tableName).
|
|
Where("id = ? AND client_id IN ?", resourceID, accessibleClientIDs).
|
|
Count(&count).Error
|
|
}
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if count == 0 {
|
|
return fiber.NewError(fiber.StatusForbidden, "Access denied to this resource")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// FilterByCurrentClient filters query by the current working client only
|
|
// Different from AddClientFilter - this only filters by the ACTIVE client
|
|
func FilterByCurrentClient(db *gorm.DB, c *fiber.Ctx) *gorm.DB {
|
|
if c == nil {
|
|
return db
|
|
}
|
|
|
|
// Super admin with no specific client selected
|
|
if customMiddleware.IsSuperAdmin(c) {
|
|
currentClientID := customMiddleware.GetCurrentClientID(c)
|
|
if currentClientID == nil {
|
|
return db // No filter
|
|
}
|
|
return db.Where("client_id = ?", currentClientID)
|
|
}
|
|
|
|
// Regular user - filter by current client
|
|
currentClientID := customMiddleware.GetCurrentClientID(c)
|
|
if currentClientID != nil {
|
|
return db.Where("client_id = ?", currentClientID)
|
|
}
|
|
|
|
return db
|
|
}
|