mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-11-16 13:54:52 +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
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
// Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
Timestamp int64 `json:"timestamp"`
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
// UUID for the event
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +32,9 @@ const (
|
|||||||
EventBlacklistToggled EventName = "blacklistToggled"
|
EventBlacklistToggled EventName = "blacklistToggled"
|
||||||
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
||||||
EventAccessRuleCreated EventName = "accessRuleCreated"
|
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
|
// Add more event types as needed
|
||||||
)
|
)
|
||||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
|
|||||||
EventBlacklistedIPBlocked: true,
|
EventBlacklistedIPBlocked: true,
|
||||||
EventBlacklistToggled: true,
|
EventBlacklistToggled: true,
|
||||||
EventAccessRuleCreated: true,
|
EventAccessRuleCreated: true,
|
||||||
|
EventCustom: true,
|
||||||
// Add more event types as needed
|
// Add more event types as needed
|
||||||
// NOTE: Keep up-to-date with event names specified above
|
// NOTE: Keep up-to-date with event names specified above
|
||||||
}
|
}
|
||||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
|
|||||||
return "accesslist-api"
|
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
|
// ParseEvent parses a JSON byte slice into an Event struct
|
||||||
func ParseEvent(jsonData []byte, event *Event) error {
|
func ParseEvent(jsonData []byte, event *Event) error {
|
||||||
// First, determine the event type, and parse shared fields, from the JSON data
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
event.Data = &payload.Data
|
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:
|
default:
|
||||||
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ type EventPayload interface {
|
|||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
// Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
Timestamp int64 `json:"timestamp"`
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
// UUID for the event
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +32,9 @@ const (
|
|||||||
EventBlacklistToggled EventName = "blacklistToggled"
|
EventBlacklistToggled EventName = "blacklistToggled"
|
||||||
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
||||||
EventAccessRuleCreated EventName = "accessRuleCreated"
|
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
|
// Add more event types as needed
|
||||||
)
|
)
|
||||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
|
|||||||
EventBlacklistedIPBlocked: true,
|
EventBlacklistedIPBlocked: true,
|
||||||
EventBlacklistToggled: true,
|
EventBlacklistToggled: true,
|
||||||
EventAccessRuleCreated: true,
|
EventAccessRuleCreated: true,
|
||||||
|
EventCustom: true,
|
||||||
// Add more event types as needed
|
// Add more event types as needed
|
||||||
// NOTE: Keep up-to-date with event names specified above
|
// NOTE: Keep up-to-date with event names specified above
|
||||||
}
|
}
|
||||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
|
|||||||
return "accesslist-api"
|
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
|
// ParseEvent parses a JSON byte slice into an Event struct
|
||||||
func ParseEvent(jsonData []byte, event *Event) error {
|
func ParseEvent(jsonData []byte, event *Event) error {
|
||||||
// First, determine the event type, and parse shared fields, from the JSON data
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
event.Data = &payload.Data
|
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:
|
default:
|
||||||
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ type EventPayload interface {
|
|||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
// Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
Timestamp int64 `json:"timestamp"`
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
// UUID for the event
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +32,9 @@ const (
|
|||||||
EventBlacklistToggled EventName = "blacklistToggled"
|
EventBlacklistToggled EventName = "blacklistToggled"
|
||||||
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
||||||
EventAccessRuleCreated EventName = "accessRuleCreated"
|
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
|
// Add more event types as needed
|
||||||
)
|
)
|
||||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
|
|||||||
EventBlacklistedIPBlocked: true,
|
EventBlacklistedIPBlocked: true,
|
||||||
EventBlacklistToggled: true,
|
EventBlacklistToggled: true,
|
||||||
EventAccessRuleCreated: true,
|
EventAccessRuleCreated: true,
|
||||||
|
EventCustom: true,
|
||||||
// Add more event types as needed
|
// Add more event types as needed
|
||||||
// NOTE: Keep up-to-date with event names specified above
|
// NOTE: Keep up-to-date with event names specified above
|
||||||
}
|
}
|
||||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
|
|||||||
return "accesslist-api"
|
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
|
// ParseEvent parses a JSON byte slice into an Event struct
|
||||||
func ParseEvent(jsonData []byte, event *Event) error {
|
func ParseEvent(jsonData []byte, event *Event) error {
|
||||||
// First, determine the event type, and parse shared fields, from the JSON data
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
event.Data = &payload.Data
|
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:
|
default:
|
||||||
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ type EventPayload interface {
|
|||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
// Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
Timestamp int64 `json:"timestamp"`
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
// UUID for the event
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +32,9 @@ const (
|
|||||||
EventBlacklistToggled EventName = "blacklistToggled"
|
EventBlacklistToggled EventName = "blacklistToggled"
|
||||||
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
||||||
EventAccessRuleCreated EventName = "accessRuleCreated"
|
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
|
// Add more event types as needed
|
||||||
)
|
)
|
||||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
|
|||||||
EventBlacklistedIPBlocked: true,
|
EventBlacklistedIPBlocked: true,
|
||||||
EventBlacklistToggled: true,
|
EventBlacklistToggled: true,
|
||||||
EventAccessRuleCreated: true,
|
EventAccessRuleCreated: true,
|
||||||
|
EventCustom: true,
|
||||||
// Add more event types as needed
|
// Add more event types as needed
|
||||||
// NOTE: Keep up-to-date with event names specified above
|
// NOTE: Keep up-to-date with event names specified above
|
||||||
}
|
}
|
||||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
|
|||||||
return "accesslist-api"
|
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
|
// ParseEvent parses a JSON byte slice into an Event struct
|
||||||
func ParseEvent(jsonData []byte, event *Event) error {
|
func ParseEvent(jsonData []byte, event *Event) error {
|
||||||
// First, determine the event type, and parse shared fields, from the JSON data
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
event.Data = &payload.Data
|
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:
|
default:
|
||||||
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ type EventPayload interface {
|
|||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
// Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
Timestamp int64 `json:"timestamp"`
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
// UUID for the event
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +32,9 @@ const (
|
|||||||
EventBlacklistToggled EventName = "blacklistToggled"
|
EventBlacklistToggled EventName = "blacklistToggled"
|
||||||
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
||||||
EventAccessRuleCreated EventName = "accessRuleCreated"
|
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
|
// Add more event types as needed
|
||||||
)
|
)
|
||||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
|
|||||||
EventBlacklistedIPBlocked: true,
|
EventBlacklistedIPBlocked: true,
|
||||||
EventBlacklistToggled: true,
|
EventBlacklistToggled: true,
|
||||||
EventAccessRuleCreated: true,
|
EventAccessRuleCreated: true,
|
||||||
|
EventCustom: true,
|
||||||
// Add more event types as needed
|
// Add more event types as needed
|
||||||
// NOTE: Keep up-to-date with event names specified above
|
// NOTE: Keep up-to-date with event names specified above
|
||||||
}
|
}
|
||||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
|
|||||||
return "accesslist-api"
|
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
|
// ParseEvent parses a JSON byte slice into an Event struct
|
||||||
func ParseEvent(jsonData []byte, event *Event) error {
|
func ParseEvent(jsonData []byte, event *Event) error {
|
||||||
// First, determine the event type, and parse shared fields, from the JSON data
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
event.Data = &payload.Data
|
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:
|
default:
|
||||||
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ type EventPayload interface {
|
|||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
// Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
Timestamp int64 `json:"timestamp"`
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
// UUID for the event
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +32,9 @@ const (
|
|||||||
EventBlacklistToggled EventName = "blacklistToggled"
|
EventBlacklistToggled EventName = "blacklistToggled"
|
||||||
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
||||||
EventAccessRuleCreated EventName = "accessRuleCreated"
|
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
|
// Add more event types as needed
|
||||||
)
|
)
|
||||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
|
|||||||
EventBlacklistedIPBlocked: true,
|
EventBlacklistedIPBlocked: true,
|
||||||
EventBlacklistToggled: true,
|
EventBlacklistToggled: true,
|
||||||
EventAccessRuleCreated: true,
|
EventAccessRuleCreated: true,
|
||||||
|
EventCustom: true,
|
||||||
// Add more event types as needed
|
// Add more event types as needed
|
||||||
// NOTE: Keep up-to-date with event names specified above
|
// NOTE: Keep up-to-date with event names specified above
|
||||||
}
|
}
|
||||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
|
|||||||
return "accesslist-api"
|
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
|
// ParseEvent parses a JSON byte slice into an Event struct
|
||||||
func ParseEvent(jsonData []byte, event *Event) error {
|
func ParseEvent(jsonData []byte, event *Event) error {
|
||||||
// First, determine the event type, and parse shared fields, from the JSON data
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
event.Data = &payload.Data
|
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:
|
default:
|
||||||
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ type EventPayload interface {
|
|||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
// Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
Timestamp int64 `json:"timestamp"`
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
// UUID for the event
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +32,9 @@ const (
|
|||||||
EventBlacklistToggled EventName = "blacklistToggled"
|
EventBlacklistToggled EventName = "blacklistToggled"
|
||||||
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
||||||
EventAccessRuleCreated EventName = "accessRuleCreated"
|
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
|
// Add more event types as needed
|
||||||
)
|
)
|
||||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
|
|||||||
EventBlacklistedIPBlocked: true,
|
EventBlacklistedIPBlocked: true,
|
||||||
EventBlacklistToggled: true,
|
EventBlacklistToggled: true,
|
||||||
EventAccessRuleCreated: true,
|
EventAccessRuleCreated: true,
|
||||||
|
EventCustom: true,
|
||||||
// Add more event types as needed
|
// Add more event types as needed
|
||||||
// NOTE: Keep up-to-date with event names specified above
|
// NOTE: Keep up-to-date with event names specified above
|
||||||
}
|
}
|
||||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
|
|||||||
return "accesslist-api"
|
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
|
// ParseEvent parses a JSON byte slice into an Event struct
|
||||||
func ParseEvent(jsonData []byte, event *Event) error {
|
func ParseEvent(jsonData []byte, event *Event) error {
|
||||||
// First, determine the event type, and parse shared fields, from the JSON data
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
event.Data = &payload.Data
|
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:
|
default:
|
||||||
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ type EventPayload interface {
|
|||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
// Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
Timestamp int64 `json:"timestamp"`
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
// UUID for the event
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +32,9 @@ const (
|
|||||||
EventBlacklistToggled EventName = "blacklistToggled"
|
EventBlacklistToggled EventName = "blacklistToggled"
|
||||||
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
||||||
EventAccessRuleCreated EventName = "accessRuleCreated"
|
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
|
// Add more event types as needed
|
||||||
)
|
)
|
||||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
|
|||||||
EventBlacklistedIPBlocked: true,
|
EventBlacklistedIPBlocked: true,
|
||||||
EventBlacklistToggled: true,
|
EventBlacklistToggled: true,
|
||||||
EventAccessRuleCreated: true,
|
EventAccessRuleCreated: true,
|
||||||
|
EventCustom: true,
|
||||||
// Add more event types as needed
|
// Add more event types as needed
|
||||||
// NOTE: Keep up-to-date with event names specified above
|
// NOTE: Keep up-to-date with event names specified above
|
||||||
}
|
}
|
||||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
|
|||||||
return "accesslist-api"
|
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
|
// ParseEvent parses a JSON byte slice into an Event struct
|
||||||
func ParseEvent(jsonData []byte, event *Event) error {
|
func ParseEvent(jsonData []byte, event *Event) error {
|
||||||
// First, determine the event type, and parse shared fields, from the JSON data
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
event.Data = &payload.Data
|
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:
|
default:
|
||||||
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,8 +86,39 @@ func (em *eventManager) UnregisterSubscriber(listenerID ListenerID) error {
|
|||||||
return nil
|
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
|
// 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()
|
eventName := payload.GetName()
|
||||||
|
|
||||||
em.mutex.RLock()
|
em.mutex.RLock()
|
||||||
@@ -95,7 +126,7 @@ func (em *eventManager) Emit(payload events.EventPayload) error {
|
|||||||
subscribers, exists := em.subscriptions[eventName]
|
subscribers, exists := em.subscriptions[eventName]
|
||||||
|
|
||||||
if !exists || len(subscribers) == 0 {
|
if !exists || len(subscribers) == 0 {
|
||||||
return nil // No subscribers
|
return // No subscribers
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the event
|
// Create the event
|
||||||
@@ -107,11 +138,26 @@ func (em *eventManager) Emit(payload events.EventPayload) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dispatch to all subscribers asynchronously
|
// 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]
|
listener, exists := em.subscribers[listenerID]
|
||||||
|
|
||||||
if !exists {
|
if !exists {
|
||||||
em.logger.PrintAndLog("event-system", "Failed to get listener for event dispatch, removing "+string(listenerID)+" from subscriptions", nil)
|
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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +167,4 @@ func (em *eventManager) Emit(payload events.EventPayload) error {
|
|||||||
}
|
}
|
||||||
}(listener)
|
}(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ type EventPayload interface {
|
|||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
// Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
Timestamp int64 `json:"timestamp"`
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
// UUID for the event
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +32,9 @@ const (
|
|||||||
EventBlacklistToggled EventName = "blacklistToggled"
|
EventBlacklistToggled EventName = "blacklistToggled"
|
||||||
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
||||||
EventAccessRuleCreated EventName = "accessRuleCreated"
|
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
|
// Add more event types as needed
|
||||||
)
|
)
|
||||||
@@ -42,6 +43,7 @@ var validEventNames = map[EventName]bool{
|
|||||||
EventBlacklistedIPBlocked: true,
|
EventBlacklistedIPBlocked: true,
|
||||||
EventBlacklistToggled: true,
|
EventBlacklistToggled: true,
|
||||||
EventAccessRuleCreated: true,
|
EventAccessRuleCreated: true,
|
||||||
|
EventCustom: true,
|
||||||
// Add more event types as needed
|
// Add more event types as needed
|
||||||
// NOTE: Keep up-to-date with event names specified above
|
// NOTE: Keep up-to-date with event names specified above
|
||||||
}
|
}
|
||||||
@@ -100,6 +102,20 @@ func (e *AccessRuleCreatedEvent) GetEventSource() string {
|
|||||||
return "accesslist-api"
|
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
|
// ParseEvent parses a JSON byte slice into an Event struct
|
||||||
func ParseEvent(jsonData []byte, event *Event) error {
|
func ParseEvent(jsonData []byte, event *Event) error {
|
||||||
// First, determine the event type, and parse shared fields, from the JSON data
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
event.Data = &payload.Data
|
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:
|
default:
|
||||||
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
return fmt.Errorf("unknown event: %s, %v", temp.Name, jsonData)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user