mirror of
				https://github.com/tobychui/zoraxy.git
				synced 2025-11-03 23:44:08 +01:00 
			
		
		
		
	feat(eventsystem): plumbing for plugin<->plugin comms
The only thing left is to add an API endpoint for broadcasting EventCustom events (other event types should not be emittible by plugins, the use-case isn't there since plugins can already talk to Zoraxy via the API). Input to the endput should be a json-encoded `CustomEvent`
This commit is contained in:
		@@ -20,10 +20,8 @@ type EventPayload interface {
 | 
			
		||||
// Event represents a system event
 | 
			
		||||
type Event struct {
 | 
			
		||||
	Name      EventName    `json:"name"`
 | 
			
		||||
	// Unix timestamp
 | 
			
		||||
	Timestamp int64        `json:"timestamp"`
 | 
			
		||||
	// UUID for the event
 | 
			
		||||
	UUID      string       `json:"uuid"`
 | 
			
		||||
	Timestamp int64        `json:"timestamp"` // Unix timestamp
 | 
			
		||||
	UUID      string       `json:"uuid"`      // UUID for the event
 | 
			
		||||
	Data      EventPayload `json:"data"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +32,9 @@ const (
 | 
			
		||||
	EventBlacklistToggled EventName = "blacklistToggled"
 | 
			
		||||
	// EventAccessRuleCreated is emitted when a new access ruleset is created
 | 
			
		||||
	EventAccessRuleCreated EventName = "accessRuleCreated"
 | 
			
		||||
	// A custom event emitted by a plugin, with the intention of being broadcast
 | 
			
		||||
	// to the designated recipient(s)
 | 
			
		||||
	EventCustom EventName = "customEvent"
 | 
			
		||||
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
)
 | 
			
		||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
 | 
			
		||||
	EventBlacklistedIPBlocked: true,
 | 
			
		||||
	EventBlacklistToggled:     true,
 | 
			
		||||
	EventAccessRuleCreated:    true,
 | 
			
		||||
	EventCustom:               true,
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
	// NOTE: Keep up-to-date with event names specified above
 | 
			
		||||
}
 | 
			
		||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
 | 
			
		||||
	return "accesslist-api"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CustomEvent struct {
 | 
			
		||||
	SourcePlugin string         `json:"source_plugin"`
 | 
			
		||||
	Recipients   []string       `json:"recipients"`
 | 
			
		||||
	Payload      map[string]any `json:"payload"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetName() EventName {
 | 
			
		||||
	return EventCustom
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetEventSource() string {
 | 
			
		||||
	return e.SourcePlugin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseEvent parses a JSON byte slice into an Event struct
 | 
			
		||||
func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
	// First, determine the event type, and parse shared fields, from the JSON data
 | 
			
		||||
@@ -146,6 +162,15 @@ func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	case EventCustom:
 | 
			
		||||
		type tempData struct {
 | 
			
		||||
			Data CustomEvent `json:"data"`
 | 
			
		||||
		}
 | 
			
		||||
		var payload tempData
 | 
			
		||||
		if err := json.Unmarshal(jsonData, &payload); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,10 +20,8 @@ type EventPayload interface {
 | 
			
		||||
// Event represents a system event
 | 
			
		||||
type Event struct {
 | 
			
		||||
	Name      EventName    `json:"name"`
 | 
			
		||||
	// Unix timestamp
 | 
			
		||||
	Timestamp int64        `json:"timestamp"`
 | 
			
		||||
	// UUID for the event
 | 
			
		||||
	UUID      string       `json:"uuid"`
 | 
			
		||||
	Timestamp int64        `json:"timestamp"` // Unix timestamp
 | 
			
		||||
	UUID      string       `json:"uuid"`      // UUID for the event
 | 
			
		||||
	Data      EventPayload `json:"data"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +32,9 @@ const (
 | 
			
		||||
	EventBlacklistToggled EventName = "blacklistToggled"
 | 
			
		||||
	// EventAccessRuleCreated is emitted when a new access ruleset is created
 | 
			
		||||
	EventAccessRuleCreated EventName = "accessRuleCreated"
 | 
			
		||||
	// A custom event emitted by a plugin, with the intention of being broadcast
 | 
			
		||||
	// to the designated recipient(s)
 | 
			
		||||
	EventCustom EventName = "customEvent"
 | 
			
		||||
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
)
 | 
			
		||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
 | 
			
		||||
	EventBlacklistedIPBlocked: true,
 | 
			
		||||
	EventBlacklistToggled:     true,
 | 
			
		||||
	EventAccessRuleCreated:    true,
 | 
			
		||||
	EventCustom:               true,
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
	// NOTE: Keep up-to-date with event names specified above
 | 
			
		||||
}
 | 
			
		||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
 | 
			
		||||
	return "accesslist-api"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CustomEvent struct {
 | 
			
		||||
	SourcePlugin string         `json:"source_plugin"`
 | 
			
		||||
	Recipients   []string       `json:"recipients"`
 | 
			
		||||
	Payload      map[string]any `json:"payload"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetName() EventName {
 | 
			
		||||
	return EventCustom
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetEventSource() string {
 | 
			
		||||
	return e.SourcePlugin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseEvent parses a JSON byte slice into an Event struct
 | 
			
		||||
func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
	// First, determine the event type, and parse shared fields, from the JSON data
 | 
			
		||||
@@ -146,6 +162,15 @@ func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	case EventCustom:
 | 
			
		||||
		type tempData struct {
 | 
			
		||||
			Data CustomEvent `json:"data"`
 | 
			
		||||
		}
 | 
			
		||||
		var payload tempData
 | 
			
		||||
		if err := json.Unmarshal(jsonData, &payload); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,10 +20,8 @@ type EventPayload interface {
 | 
			
		||||
// Event represents a system event
 | 
			
		||||
type Event struct {
 | 
			
		||||
	Name      EventName    `json:"name"`
 | 
			
		||||
	// Unix timestamp
 | 
			
		||||
	Timestamp int64        `json:"timestamp"`
 | 
			
		||||
	// UUID for the event
 | 
			
		||||
	UUID      string       `json:"uuid"`
 | 
			
		||||
	Timestamp int64        `json:"timestamp"` // Unix timestamp
 | 
			
		||||
	UUID      string       `json:"uuid"`      // UUID for the event
 | 
			
		||||
	Data      EventPayload `json:"data"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +32,9 @@ const (
 | 
			
		||||
	EventBlacklistToggled EventName = "blacklistToggled"
 | 
			
		||||
	// EventAccessRuleCreated is emitted when a new access ruleset is created
 | 
			
		||||
	EventAccessRuleCreated EventName = "accessRuleCreated"
 | 
			
		||||
	// A custom event emitted by a plugin, with the intention of being broadcast
 | 
			
		||||
	// to the designated recipient(s)
 | 
			
		||||
	EventCustom EventName = "customEvent"
 | 
			
		||||
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
)
 | 
			
		||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
 | 
			
		||||
	EventBlacklistedIPBlocked: true,
 | 
			
		||||
	EventBlacklistToggled:     true,
 | 
			
		||||
	EventAccessRuleCreated:    true,
 | 
			
		||||
	EventCustom:               true,
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
	// NOTE: Keep up-to-date with event names specified above
 | 
			
		||||
}
 | 
			
		||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
 | 
			
		||||
	return "accesslist-api"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CustomEvent struct {
 | 
			
		||||
	SourcePlugin string         `json:"source_plugin"`
 | 
			
		||||
	Recipients   []string       `json:"recipients"`
 | 
			
		||||
	Payload      map[string]any `json:"payload"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetName() EventName {
 | 
			
		||||
	return EventCustom
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetEventSource() string {
 | 
			
		||||
	return e.SourcePlugin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseEvent parses a JSON byte slice into an Event struct
 | 
			
		||||
func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
	// First, determine the event type, and parse shared fields, from the JSON data
 | 
			
		||||
@@ -146,6 +162,15 @@ func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	case EventCustom:
 | 
			
		||||
		type tempData struct {
 | 
			
		||||
			Data CustomEvent `json:"data"`
 | 
			
		||||
		}
 | 
			
		||||
		var payload tempData
 | 
			
		||||
		if err := json.Unmarshal(jsonData, &payload); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,10 +20,8 @@ type EventPayload interface {
 | 
			
		||||
// Event represents a system event
 | 
			
		||||
type Event struct {
 | 
			
		||||
	Name      EventName    `json:"name"`
 | 
			
		||||
	// Unix timestamp
 | 
			
		||||
	Timestamp int64        `json:"timestamp"`
 | 
			
		||||
	// UUID for the event
 | 
			
		||||
	UUID      string       `json:"uuid"`
 | 
			
		||||
	Timestamp int64        `json:"timestamp"` // Unix timestamp
 | 
			
		||||
	UUID      string       `json:"uuid"`      // UUID for the event
 | 
			
		||||
	Data      EventPayload `json:"data"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +32,9 @@ const (
 | 
			
		||||
	EventBlacklistToggled EventName = "blacklistToggled"
 | 
			
		||||
	// EventAccessRuleCreated is emitted when a new access ruleset is created
 | 
			
		||||
	EventAccessRuleCreated EventName = "accessRuleCreated"
 | 
			
		||||
	// A custom event emitted by a plugin, with the intention of being broadcast
 | 
			
		||||
	// to the designated recipient(s)
 | 
			
		||||
	EventCustom EventName = "customEvent"
 | 
			
		||||
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
)
 | 
			
		||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
 | 
			
		||||
	EventBlacklistedIPBlocked: true,
 | 
			
		||||
	EventBlacklistToggled:     true,
 | 
			
		||||
	EventAccessRuleCreated:    true,
 | 
			
		||||
	EventCustom:               true,
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
	// NOTE: Keep up-to-date with event names specified above
 | 
			
		||||
}
 | 
			
		||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
 | 
			
		||||
	return "accesslist-api"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CustomEvent struct {
 | 
			
		||||
	SourcePlugin string         `json:"source_plugin"`
 | 
			
		||||
	Recipients   []string       `json:"recipients"`
 | 
			
		||||
	Payload      map[string]any `json:"payload"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetName() EventName {
 | 
			
		||||
	return EventCustom
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetEventSource() string {
 | 
			
		||||
	return e.SourcePlugin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseEvent parses a JSON byte slice into an Event struct
 | 
			
		||||
func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
	// First, determine the event type, and parse shared fields, from the JSON data
 | 
			
		||||
@@ -146,6 +162,15 @@ func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	case EventCustom:
 | 
			
		||||
		type tempData struct {
 | 
			
		||||
			Data CustomEvent `json:"data"`
 | 
			
		||||
		}
 | 
			
		||||
		var payload tempData
 | 
			
		||||
		if err := json.Unmarshal(jsonData, &payload); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,10 +20,8 @@ type EventPayload interface {
 | 
			
		||||
// Event represents a system event
 | 
			
		||||
type Event struct {
 | 
			
		||||
	Name      EventName    `json:"name"`
 | 
			
		||||
	// Unix timestamp
 | 
			
		||||
	Timestamp int64        `json:"timestamp"`
 | 
			
		||||
	// UUID for the event
 | 
			
		||||
	UUID      string       `json:"uuid"`
 | 
			
		||||
	Timestamp int64        `json:"timestamp"` // Unix timestamp
 | 
			
		||||
	UUID      string       `json:"uuid"`      // UUID for the event
 | 
			
		||||
	Data      EventPayload `json:"data"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +32,9 @@ const (
 | 
			
		||||
	EventBlacklistToggled EventName = "blacklistToggled"
 | 
			
		||||
	// EventAccessRuleCreated is emitted when a new access ruleset is created
 | 
			
		||||
	EventAccessRuleCreated EventName = "accessRuleCreated"
 | 
			
		||||
	// A custom event emitted by a plugin, with the intention of being broadcast
 | 
			
		||||
	// to the designated recipient(s)
 | 
			
		||||
	EventCustom EventName = "customEvent"
 | 
			
		||||
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
)
 | 
			
		||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
 | 
			
		||||
	EventBlacklistedIPBlocked: true,
 | 
			
		||||
	EventBlacklistToggled:     true,
 | 
			
		||||
	EventAccessRuleCreated:    true,
 | 
			
		||||
	EventCustom:               true,
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
	// NOTE: Keep up-to-date with event names specified above
 | 
			
		||||
}
 | 
			
		||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
 | 
			
		||||
	return "accesslist-api"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CustomEvent struct {
 | 
			
		||||
	SourcePlugin string         `json:"source_plugin"`
 | 
			
		||||
	Recipients   []string       `json:"recipients"`
 | 
			
		||||
	Payload      map[string]any `json:"payload"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetName() EventName {
 | 
			
		||||
	return EventCustom
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetEventSource() string {
 | 
			
		||||
	return e.SourcePlugin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseEvent parses a JSON byte slice into an Event struct
 | 
			
		||||
func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
	// First, determine the event type, and parse shared fields, from the JSON data
 | 
			
		||||
@@ -146,6 +162,15 @@ func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	case EventCustom:
 | 
			
		||||
		type tempData struct {
 | 
			
		||||
			Data CustomEvent `json:"data"`
 | 
			
		||||
		}
 | 
			
		||||
		var payload tempData
 | 
			
		||||
		if err := json.Unmarshal(jsonData, &payload); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,10 +20,8 @@ type EventPayload interface {
 | 
			
		||||
// Event represents a system event
 | 
			
		||||
type Event struct {
 | 
			
		||||
	Name      EventName    `json:"name"`
 | 
			
		||||
	// Unix timestamp
 | 
			
		||||
	Timestamp int64        `json:"timestamp"`
 | 
			
		||||
	// UUID for the event
 | 
			
		||||
	UUID      string       `json:"uuid"`
 | 
			
		||||
	Timestamp int64        `json:"timestamp"` // Unix timestamp
 | 
			
		||||
	UUID      string       `json:"uuid"`      // UUID for the event
 | 
			
		||||
	Data      EventPayload `json:"data"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +32,9 @@ const (
 | 
			
		||||
	EventBlacklistToggled EventName = "blacklistToggled"
 | 
			
		||||
	// EventAccessRuleCreated is emitted when a new access ruleset is created
 | 
			
		||||
	EventAccessRuleCreated EventName = "accessRuleCreated"
 | 
			
		||||
	// A custom event emitted by a plugin, with the intention of being broadcast
 | 
			
		||||
	// to the designated recipient(s)
 | 
			
		||||
	EventCustom EventName = "customEvent"
 | 
			
		||||
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
)
 | 
			
		||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
 | 
			
		||||
	EventBlacklistedIPBlocked: true,
 | 
			
		||||
	EventBlacklistToggled:     true,
 | 
			
		||||
	EventAccessRuleCreated:    true,
 | 
			
		||||
	EventCustom:               true,
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
	// NOTE: Keep up-to-date with event names specified above
 | 
			
		||||
}
 | 
			
		||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
 | 
			
		||||
	return "accesslist-api"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CustomEvent struct {
 | 
			
		||||
	SourcePlugin string         `json:"source_plugin"`
 | 
			
		||||
	Recipients   []string       `json:"recipients"`
 | 
			
		||||
	Payload      map[string]any `json:"payload"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetName() EventName {
 | 
			
		||||
	return EventCustom
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetEventSource() string {
 | 
			
		||||
	return e.SourcePlugin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseEvent parses a JSON byte slice into an Event struct
 | 
			
		||||
func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
	// First, determine the event type, and parse shared fields, from the JSON data
 | 
			
		||||
@@ -146,6 +162,15 @@ func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	case EventCustom:
 | 
			
		||||
		type tempData struct {
 | 
			
		||||
			Data CustomEvent `json:"data"`
 | 
			
		||||
		}
 | 
			
		||||
		var payload tempData
 | 
			
		||||
		if err := json.Unmarshal(jsonData, &payload); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,10 +20,8 @@ type EventPayload interface {
 | 
			
		||||
// Event represents a system event
 | 
			
		||||
type Event struct {
 | 
			
		||||
	Name      EventName    `json:"name"`
 | 
			
		||||
	// Unix timestamp
 | 
			
		||||
	Timestamp int64        `json:"timestamp"`
 | 
			
		||||
	// UUID for the event
 | 
			
		||||
	UUID      string       `json:"uuid"`
 | 
			
		||||
	Timestamp int64        `json:"timestamp"` // Unix timestamp
 | 
			
		||||
	UUID      string       `json:"uuid"`      // UUID for the event
 | 
			
		||||
	Data      EventPayload `json:"data"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +32,9 @@ const (
 | 
			
		||||
	EventBlacklistToggled EventName = "blacklistToggled"
 | 
			
		||||
	// EventAccessRuleCreated is emitted when a new access ruleset is created
 | 
			
		||||
	EventAccessRuleCreated EventName = "accessRuleCreated"
 | 
			
		||||
	// A custom event emitted by a plugin, with the intention of being broadcast
 | 
			
		||||
	// to the designated recipient(s)
 | 
			
		||||
	EventCustom EventName = "customEvent"
 | 
			
		||||
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
)
 | 
			
		||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
 | 
			
		||||
	EventBlacklistedIPBlocked: true,
 | 
			
		||||
	EventBlacklistToggled:     true,
 | 
			
		||||
	EventAccessRuleCreated:    true,
 | 
			
		||||
	EventCustom:               true,
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
	// NOTE: Keep up-to-date with event names specified above
 | 
			
		||||
}
 | 
			
		||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
 | 
			
		||||
	return "accesslist-api"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CustomEvent struct {
 | 
			
		||||
	SourcePlugin string         `json:"source_plugin"`
 | 
			
		||||
	Recipients   []string       `json:"recipients"`
 | 
			
		||||
	Payload      map[string]any `json:"payload"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetName() EventName {
 | 
			
		||||
	return EventCustom
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetEventSource() string {
 | 
			
		||||
	return e.SourcePlugin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseEvent parses a JSON byte slice into an Event struct
 | 
			
		||||
func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
	// First, determine the event type, and parse shared fields, from the JSON data
 | 
			
		||||
@@ -146,6 +162,15 @@ func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	case EventCustom:
 | 
			
		||||
		type tempData struct {
 | 
			
		||||
			Data CustomEvent `json:"data"`
 | 
			
		||||
		}
 | 
			
		||||
		var payload tempData
 | 
			
		||||
		if err := json.Unmarshal(jsonData, &payload); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,10 +20,8 @@ type EventPayload interface {
 | 
			
		||||
// Event represents a system event
 | 
			
		||||
type Event struct {
 | 
			
		||||
	Name      EventName    `json:"name"`
 | 
			
		||||
	// Unix timestamp
 | 
			
		||||
	Timestamp int64        `json:"timestamp"`
 | 
			
		||||
	// UUID for the event
 | 
			
		||||
	UUID      string       `json:"uuid"`
 | 
			
		||||
	Timestamp int64        `json:"timestamp"` // Unix timestamp
 | 
			
		||||
	UUID      string       `json:"uuid"`      // UUID for the event
 | 
			
		||||
	Data      EventPayload `json:"data"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +32,9 @@ const (
 | 
			
		||||
	EventBlacklistToggled EventName = "blacklistToggled"
 | 
			
		||||
	// EventAccessRuleCreated is emitted when a new access ruleset is created
 | 
			
		||||
	EventAccessRuleCreated EventName = "accessRuleCreated"
 | 
			
		||||
	// A custom event emitted by a plugin, with the intention of being broadcast
 | 
			
		||||
	// to the designated recipient(s)
 | 
			
		||||
	EventCustom EventName = "customEvent"
 | 
			
		||||
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
)
 | 
			
		||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
 | 
			
		||||
	EventBlacklistedIPBlocked: true,
 | 
			
		||||
	EventBlacklistToggled:     true,
 | 
			
		||||
	EventAccessRuleCreated:    true,
 | 
			
		||||
	EventCustom:               true,
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
	// NOTE: Keep up-to-date with event names specified above
 | 
			
		||||
}
 | 
			
		||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
 | 
			
		||||
	return "accesslist-api"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CustomEvent struct {
 | 
			
		||||
	SourcePlugin string         `json:"source_plugin"`
 | 
			
		||||
	Recipients   []string       `json:"recipients"`
 | 
			
		||||
	Payload      map[string]any `json:"payload"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetName() EventName {
 | 
			
		||||
	return EventCustom
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetEventSource() string {
 | 
			
		||||
	return e.SourcePlugin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseEvent parses a JSON byte slice into an Event struct
 | 
			
		||||
func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
	// First, determine the event type, and parse shared fields, from the JSON data
 | 
			
		||||
@@ -146,6 +162,15 @@ func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	case EventCustom:
 | 
			
		||||
		type tempData struct {
 | 
			
		||||
			Data CustomEvent `json:"data"`
 | 
			
		||||
		}
 | 
			
		||||
		var payload tempData
 | 
			
		||||
		if err := json.Unmarshal(jsonData, &payload); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -86,8 +86,39 @@ func (em *eventManager) UnregisterSubscriber(listenerID ListenerID) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EmitToSubscribersAnd dispatches an event to the specific listeners in addition to the events subscribers.
 | 
			
		||||
//
 | 
			
		||||
// The primary use-case of this function is for plugin-to-plugin communication
 | 
			
		||||
func (em *eventManager) EmitToSubscribersAnd(listenerIDs []ListenerID, payload events.EventPayload) {
 | 
			
		||||
	eventName := payload.GetName()
 | 
			
		||||
 | 
			
		||||
	if len(listenerIDs) == 0 {
 | 
			
		||||
		return // No subscribers
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Create the event
 | 
			
		||||
	event := events.Event{
 | 
			
		||||
		Name:      eventName,
 | 
			
		||||
		Timestamp: time.Now().Unix(),
 | 
			
		||||
		UUID:      uuid.New().String(),
 | 
			
		||||
		Data:      payload,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Dispatch to all specified listeners asynchronously
 | 
			
		||||
	em.emitTo(listenerIDs, event)
 | 
			
		||||
 | 
			
		||||
	// Also emit to all subscribers of the event as usual
 | 
			
		||||
	em.mutex.RLock()
 | 
			
		||||
	subscribers, exists := em.subscriptions[eventName]
 | 
			
		||||
	em.mutex.RUnlock()
 | 
			
		||||
	if !exists || len(subscribers) == 0 {
 | 
			
		||||
		return // No subscribers
 | 
			
		||||
	}
 | 
			
		||||
	em.emitTo(subscribers, event)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Emit dispatches an event to all subscribed listeners
 | 
			
		||||
func (em *eventManager) Emit(payload events.EventPayload) error {
 | 
			
		||||
func (em *eventManager) Emit(payload events.EventPayload) {
 | 
			
		||||
	eventName := payload.GetName()
 | 
			
		||||
 | 
			
		||||
	em.mutex.RLock()
 | 
			
		||||
@@ -95,7 +126,7 @@ func (em *eventManager) Emit(payload events.EventPayload) error {
 | 
			
		||||
	subscribers, exists := em.subscriptions[eventName]
 | 
			
		||||
 | 
			
		||||
	if !exists || len(subscribers) == 0 {
 | 
			
		||||
		return nil // No subscribers
 | 
			
		||||
		return // No subscribers
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Create the event
 | 
			
		||||
@@ -107,11 +138,26 @@ func (em *eventManager) Emit(payload events.EventPayload) error {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Dispatch to all subscribers asynchronously
 | 
			
		||||
	for _, listenerID := range subscribers {
 | 
			
		||||
	em.emitTo(subscribers, event)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Dispatch event to all specified listeners asynchronously
 | 
			
		||||
func (em *eventManager) emitTo(listenerIDs []ListenerID, event events.Event) {
 | 
			
		||||
	if len(listenerIDs) == 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Dispatch to all specified listeners asynchronously
 | 
			
		||||
	em.mutex.RLock()
 | 
			
		||||
	defer em.mutex.RUnlock()
 | 
			
		||||
	for _, listenerID := range listenerIDs {
 | 
			
		||||
		listener, exists := em.subscribers[listenerID]
 | 
			
		||||
 | 
			
		||||
		if !exists {
 | 
			
		||||
			em.logger.PrintAndLog("event-system", "Failed to get listener for event dispatch, removing "+string(listenerID)+" from subscriptions", nil)
 | 
			
		||||
			// Remove the listener from the subscription list
 | 
			
		||||
			// This is done in a separate goroutine to avoid deadlock
 | 
			
		||||
			go em.UnregisterSubscriber(listenerID)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -121,6 +167,4 @@ func (em *eventManager) Emit(payload events.EventPayload) error {
 | 
			
		||||
			}
 | 
			
		||||
		}(listener)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,10 +20,8 @@ type EventPayload interface {
 | 
			
		||||
// Event represents a system event
 | 
			
		||||
type Event struct {
 | 
			
		||||
	Name      EventName    `json:"name"`
 | 
			
		||||
	// Unix timestamp
 | 
			
		||||
	Timestamp int64        `json:"timestamp"`
 | 
			
		||||
	// UUID for the event
 | 
			
		||||
	UUID      string       `json:"uuid"`
 | 
			
		||||
	Timestamp int64        `json:"timestamp"` // Unix timestamp
 | 
			
		||||
	UUID      string       `json:"uuid"`      // UUID for the event
 | 
			
		||||
	Data      EventPayload `json:"data"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -34,6 +32,9 @@ const (
 | 
			
		||||
	EventBlacklistToggled EventName = "blacklistToggled"
 | 
			
		||||
	// EventAccessRuleCreated is emitted when a new access ruleset is created
 | 
			
		||||
	EventAccessRuleCreated EventName = "accessRuleCreated"
 | 
			
		||||
	// A custom event emitted by a plugin, with the intention of being broadcast
 | 
			
		||||
	// to the designated recipient(s)
 | 
			
		||||
	EventCustom EventName = "customEvent"
 | 
			
		||||
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
)
 | 
			
		||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
 | 
			
		||||
	EventBlacklistedIPBlocked: true,
 | 
			
		||||
	EventBlacklistToggled:     true,
 | 
			
		||||
	EventAccessRuleCreated:    true,
 | 
			
		||||
	EventCustom:               true,
 | 
			
		||||
	// Add more event types as needed
 | 
			
		||||
	// NOTE: Keep up-to-date with event names specified above
 | 
			
		||||
}
 | 
			
		||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
 | 
			
		||||
	return "accesslist-api"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type CustomEvent struct {
 | 
			
		||||
	SourcePlugin string         `json:"source_plugin"`
 | 
			
		||||
	Recipients   []string       `json:"recipients"`
 | 
			
		||||
	Payload      map[string]any `json:"payload"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetName() EventName {
 | 
			
		||||
	return EventCustom
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *CustomEvent) GetEventSource() string {
 | 
			
		||||
	return e.SourcePlugin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseEvent parses a JSON byte slice into an Event struct
 | 
			
		||||
func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
	// First, determine the event type, and parse shared fields, from the JSON data
 | 
			
		||||
@@ -146,6 +162,15 @@ func ParseEvent(jsonData []byte, event *Event) error {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	case EventCustom:
 | 
			
		||||
		type tempData struct {
 | 
			
		||||
			Data CustomEvent `json:"data"`
 | 
			
		||||
		}
 | 
			
		||||
		var payload tempData
 | 
			
		||||
		if err := json.Unmarshal(jsonData, &payload); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		event.Data = &payload.Data
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user