package workflow import ( "context" "fmt" "log" "strings" "sync" "time" ) // MiddlewareManager manages middleware execution chain type MiddlewareManager struct { middlewares []Middleware cache map[string]*MiddlewareResult mutex sync.RWMutex } // MiddlewareFunc is the function signature for middleware type MiddlewareFunc func(ctx context.Context, data map[string]interface{}, next func(context.Context, map[string]interface{}) MiddlewareResult) MiddlewareResult // MiddlewareChain represents a chain of middleware functions type MiddlewareChain struct { middlewares []MiddlewareFunc } // NewMiddlewareManager creates a new middleware manager func NewMiddlewareManager() *MiddlewareManager { return &MiddlewareManager{ middlewares: make([]Middleware, 0), cache: make(map[string]*MiddlewareResult), } } // AddMiddleware adds a middleware to the chain func (m *MiddlewareManager) AddMiddleware(middleware Middleware) { m.mutex.Lock() defer m.mutex.Unlock() // Insert middleware in priority order inserted := false for i, existing := range m.middlewares { if middleware.Priority < existing.Priority { m.middlewares = append(m.middlewares[:i], append([]Middleware{middleware}, m.middlewares[i:]...)...) inserted = true break } } if !inserted { m.middlewares = append(m.middlewares, middleware) } } // Execute runs the middleware chain func (m *MiddlewareManager) Execute(ctx context.Context, data map[string]interface{}) MiddlewareResult { m.mutex.RLock() defer m.mutex.RUnlock() if len(m.middlewares) == 0 { return MiddlewareResult{Continue: true, Data: data} } return m.executeChain(ctx, data, 0) } // executeChain recursively executes middleware chain func (m *MiddlewareManager) executeChain(ctx context.Context, data map[string]interface{}, index int) MiddlewareResult { if index >= len(m.middlewares) { return MiddlewareResult{Continue: true, Data: data} } middleware := m.middlewares[index] if !middleware.Enabled { return m.executeChain(ctx, data, index+1) } // Create the next function next := func(ctx context.Context, data map[string]interface{}) MiddlewareResult { return m.executeChain(ctx, data, index+1) } // Execute current middleware return m.executeMiddleware(ctx, middleware, data, next) } // executeMiddleware executes a single middleware func (m *MiddlewareManager) executeMiddleware(ctx context.Context, middleware Middleware, data map[string]interface{}, next func(context.Context, map[string]interface{}) MiddlewareResult) MiddlewareResult { switch middleware.Type { case MiddlewareAuth: return m.executeAuthMiddleware(ctx, middleware, data, next) case MiddlewareLogging: return m.executeLoggingMiddleware(ctx, middleware, data, next) case MiddlewareRateLimit: return m.executeRateLimitMiddleware(ctx, middleware, data, next) case MiddlewareValidate: return m.executeValidateMiddleware(ctx, middleware, data, next) case MiddlewareTransform: return m.executeTransformMiddleware(ctx, middleware, data, next) case MiddlewareCustom: return m.executeCustomMiddleware(ctx, middleware, data, next) default: // Unknown middleware type, continue return next(ctx, data) } } // Auth middleware implementation func (m *MiddlewareManager) executeAuthMiddleware(ctx context.Context, middleware Middleware, data map[string]interface{}, next func(context.Context, map[string]interface{}) MiddlewareResult) MiddlewareResult { // Extract token from data or context token, exists := data["auth_token"].(string) if !exists { if authHeader, ok := data["headers"].(map[string]string); ok { if auth, ok := authHeader["Authorization"]; ok { token = auth } } } if token == "" { return MiddlewareResult{ Continue: false, Error: fmt.Errorf("authentication token required"), Data: data, } } // Validate token (simplified) if !isValidToken(token) { return MiddlewareResult{ Continue: false, Error: fmt.Errorf("invalid authentication token"), Data: data, } } // Add user context username := extractUsernameFromToken(token) user := &User{ ID: username, Username: username, Role: UserRoleOperator, Permissions: getUserPermissions(username), } authContext := &AuthContext{ User: user, Token: token, Permissions: user.Permissions, } data["auth_context"] = authContext data["user"] = user return next(ctx, data) } // Logging middleware implementation func (m *MiddlewareManager) executeLoggingMiddleware(ctx context.Context, middleware Middleware, data map[string]interface{}, next func(context.Context, map[string]interface{}) MiddlewareResult) MiddlewareResult { startTime := time.Now() // Log request log.Printf("[MIDDLEWARE] %s - Started processing request", middleware.Name) // Continue to next middleware result := next(ctx, data) // Log response duration := time.Since(startTime) if result.Error != nil { log.Printf("[MIDDLEWARE] %s - Completed with error in %v: %v", middleware.Name, duration, result.Error) } else { log.Printf("[MIDDLEWARE] %s - Completed successfully in %v", middleware.Name, duration) } return result } // Rate limiting middleware implementation func (m *MiddlewareManager) executeRateLimitMiddleware(ctx context.Context, middleware Middleware, data map[string]interface{}, next func(context.Context, map[string]interface{}) MiddlewareResult) MiddlewareResult { // Get user/IP for rate limiting identifier := "anonymous" if user, exists := data["user"].(*User); exists { identifier = user.ID } else if ip, exists := data["client_ip"].(string); exists { identifier = ip } // Check rate limit (simplified implementation) limit := getConfigInt(middleware.Config, "requests_per_minute", 60) if !checkRateLimit(identifier, limit) { return MiddlewareResult{ Continue: false, Error: fmt.Errorf("rate limit exceeded for %s", identifier), Data: data, } } return next(ctx, data) } // Validation middleware implementation func (m *MiddlewareManager) executeValidateMiddleware(ctx context.Context, middleware Middleware, data map[string]interface{}, next func(context.Context, map[string]interface{}) MiddlewareResult) MiddlewareResult { // Get validation rules from config rules, exists := middleware.Config["rules"].([]interface{}) if !exists { return next(ctx, data) } // Validate data for _, rule := range rules { if ruleMap, ok := rule.(map[string]interface{}); ok { field := ruleMap["field"].(string) ruleType := ruleMap["type"].(string) if err := validateDataField(data, field, ruleType, ruleMap); err != nil { return MiddlewareResult{ Continue: false, Error: fmt.Errorf("validation failed: %v", err), Data: data, } } } } return next(ctx, data) } // Transform middleware implementation func (m *MiddlewareManager) executeTransformMiddleware(ctx context.Context, middleware Middleware, data map[string]interface{}, next func(context.Context, map[string]interface{}) MiddlewareResult) MiddlewareResult { // Get transformation rules from config transforms, exists := middleware.Config["transforms"].(map[string]interface{}) if !exists { return next(ctx, data) } // Apply transformations for field, transform := range transforms { if transformType, ok := transform.(string); ok { switch transformType { case "lowercase": if value, exists := data[field].(string); exists { data[field] = strings.ToLower(value) } case "uppercase": if value, exists := data[field].(string); exists { data[field] = strings.ToUpper(value) } case "trim": if value, exists := data[field].(string); exists { data[field] = strings.TrimSpace(value) } } } } return next(ctx, data) } // Custom middleware implementation func (m *MiddlewareManager) executeCustomMiddleware(ctx context.Context, middleware Middleware, data map[string]interface{}, next func(context.Context, map[string]interface{}) MiddlewareResult) MiddlewareResult { // Custom middleware can be implemented by users // For now, just pass through return next(ctx, data) } // Permission checking type PermissionChecker struct { permissions map[string][]Permission mutex sync.RWMutex } // NewPermissionChecker creates a new permission checker func NewPermissionChecker() *PermissionChecker { return &PermissionChecker{ permissions: make(map[string][]Permission), } } // AddPermission adds a permission for a user func (p *PermissionChecker) AddPermission(userID string, permission Permission) { p.mutex.Lock() defer p.mutex.Unlock() if p.permissions[userID] == nil { p.permissions[userID] = make([]Permission, 0) } p.permissions[userID] = append(p.permissions[userID], permission) } // CheckPermission checks if a user has permission for an action func (p *PermissionChecker) CheckPermission(userID, resource string, action PermissionAction) bool { p.mutex.RLock() defer p.mutex.RUnlock() permissions, exists := p.permissions[userID] if !exists { return false } for _, perm := range permissions { if perm.Resource == resource && perm.Action == action { return true } // Check for admin permission if perm.Action == PermissionAdmin { return true } } return false } // Utility functions for middleware // Rate limiting cache var rateLimitCache = make(map[string][]time.Time) var rateLimitMutex sync.RWMutex func checkRateLimit(identifier string, requestsPerMinute int) bool { rateLimitMutex.Lock() defer rateLimitMutex.Unlock() now := time.Now() cutoff := now.Add(-time.Minute) // Initialize if not exists if rateLimitCache[identifier] == nil { rateLimitCache[identifier] = make([]time.Time, 0) } // Remove old entries requests := rateLimitCache[identifier] validRequests := make([]time.Time, 0) for _, req := range requests { if req.After(cutoff) { validRequests = append(validRequests, req) } } // Check if limit exceeded if len(validRequests) >= requestsPerMinute { return false } // Add current request validRequests = append(validRequests, now) rateLimitCache[identifier] = validRequests return true } func getConfigInt(config map[string]interface{}, key string, defaultValue int) int { if value, exists := config[key]; exists { if intValue, ok := value.(int); ok { return intValue } if floatValue, ok := value.(float64); ok { return int(floatValue) } } return defaultValue } func validateDataField(data map[string]interface{}, field, ruleType string, rule map[string]interface{}) error { value, exists := data[field] switch ruleType { case "required": if !exists || value == nil || value == "" { return fmt.Errorf("field '%s' is required", field) } case "type": expectedType := rule["expected"].(string) if !isCorrectType(value, expectedType) { return fmt.Errorf("field '%s' must be of type %s", field, expectedType) } case "length": if str, ok := value.(string); ok { minLen := int(rule["min"].(float64)) maxLen := int(rule["max"].(float64)) if len(str) < minLen || len(str) > maxLen { return fmt.Errorf("field '%s' length must be between %d and %d", field, minLen, maxLen) } } } return nil } // User management system type UserManager struct { users map[string]*User sessions map[string]*AuthContext permissionChecker *PermissionChecker mutex sync.RWMutex } // NewUserManager creates a new user manager func NewUserManager() *UserManager { return &UserManager{ users: make(map[string]*User), sessions: make(map[string]*AuthContext), permissionChecker: NewPermissionChecker(), } } // CreateUser creates a new user func (u *UserManager) CreateUser(user *User) error { u.mutex.Lock() defer u.mutex.Unlock() if _, exists := u.users[user.ID]; exists { return fmt.Errorf("user %s already exists", user.ID) } user.CreatedAt = time.Now() user.UpdatedAt = time.Now() u.users[user.ID] = user // Add default permissions based on role u.addDefaultPermissions(user) return nil } // GetUser retrieves a user by ID func (u *UserManager) GetUser(userID string) (*User, error) { u.mutex.RLock() defer u.mutex.RUnlock() user, exists := u.users[userID] if !exists { return nil, fmt.Errorf("user %s not found", userID) } return user, nil } // AuthenticateUser authenticates a user and creates a session func (u *UserManager) AuthenticateUser(username, password string) (*AuthContext, error) { u.mutex.Lock() defer u.mutex.Unlock() // Find user by username var user *User for _, u := range u.users { if u.Username == username { user = u break } } if user == nil { return nil, fmt.Errorf("invalid credentials") } // In production, properly hash and verify password if password != "password" { return nil, fmt.Errorf("invalid credentials") } // Create session sessionID := generateSessionID() token := generateToken(user) authContext := &AuthContext{ User: user, SessionID: sessionID, Token: token, Permissions: user.Permissions, } u.sessions[sessionID] = authContext return authContext, nil } // ValidateSession validates a session token func (u *UserManager) ValidateSession(token string) (*AuthContext, error) { u.mutex.RLock() defer u.mutex.RUnlock() for _, session := range u.sessions { if session.Token == token { return session, nil } } return nil, fmt.Errorf("invalid session token") } // addDefaultPermissions adds default permissions based on user role func (u *UserManager) addDefaultPermissions(user *User) { switch user.Role { case UserRoleAdmin: u.permissionChecker.AddPermission(user.ID, Permission{ Resource: "*", Action: PermissionAdmin, }) case UserRoleManager: u.permissionChecker.AddPermission(user.ID, Permission{ Resource: "workflow", Action: PermissionRead, }) u.permissionChecker.AddPermission(user.ID, Permission{ Resource: "workflow", Action: PermissionWrite, }) u.permissionChecker.AddPermission(user.ID, Permission{ Resource: "workflow", Action: PermissionExecute, }) case UserRoleOperator: u.permissionChecker.AddPermission(user.ID, Permission{ Resource: "workflow", Action: PermissionRead, }) u.permissionChecker.AddPermission(user.ID, Permission{ Resource: "workflow", Action: PermissionExecute, }) case UserRoleViewer: u.permissionChecker.AddPermission(user.ID, Permission{ Resource: "workflow", Action: PermissionRead, }) } } func generateSessionID() string { return fmt.Sprintf("session_%d", time.Now().UnixNano()) } // Helper functions for authentication middleware func isValidToken(token string) bool { // Simple token validation - in real implementation, verify JWT or session token return token != "" && len(token) > 10 } func extractUsernameFromToken(token string) string { // Simple username extraction - in real implementation, decode JWT claims if strings.HasPrefix(token, "bearer_") { return strings.TrimPrefix(token, "bearer_") } return "unknown" } func getUserPermissions(username string) []string { // Simple permission mapping - in real implementation, fetch from database switch username { case "admin": return []string{"read", "write", "execute", "delete"} case "manager": return []string{"read", "write", "execute"} default: return []string{"read"} } } func isCorrectType(value interface{}, expectedType string) bool { switch expectedType { case "string": _, ok := value.(string) return ok case "number": _, ok := value.(float64) if !ok { _, ok = value.(int) } return ok case "boolean": _, ok := value.(bool) return ok case "array": _, ok := value.([]interface{}) return ok case "object": _, ok := value.(map[string]interface{}) return ok default: return false } } func generateToken(user *User) string { // Simple token generation - in real implementation, create JWT return fmt.Sprintf("token_%s_%d", user.Username, time.Now().Unix()) }