mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-11-14 21:04:10 +01:00
Merge pull request #810 from AnthonyMichaelTDM/eventpayload-interface-improvements
feat(event system): Flesh out EventPayload interface
This commit is contained in:
@@ -10,6 +10,8 @@
|
|||||||
# jemmy1794 maintains the stream proxy module
|
# jemmy1794 maintains the stream proxy module
|
||||||
/src/mod/streamproxy @jemmy1794
|
/src/mod/streamproxy @jemmy1794
|
||||||
|
|
||||||
# AnthonyMichaelTDM maintains the plugins module
|
# AnthonyMichaelTDM maintains the plugin and event systems
|
||||||
/src/mod/plugins @AnthonyMichaelTDM
|
/src/mod/plugins @AnthonyMichaelTDM
|
||||||
/example/plugins @AnthonyMichaelTDM
|
/example/plugins @AnthonyMichaelTDM
|
||||||
|
/src/**/plugin_*.go @AnthonyMichaelTDM
|
||||||
|
/src/mod/eventsystem @AnthonyMichaelTDM
|
||||||
|
|||||||
@@ -12,12 +12,16 @@ type EventName string
|
|||||||
type EventPayload interface {
|
type EventPayload interface {
|
||||||
// GetName returns the event type
|
// GetName returns the event type
|
||||||
GetName() EventName
|
GetName() EventName
|
||||||
|
|
||||||
|
// Returns the "source" of the event, that is, the component or plugin that emitted the event
|
||||||
|
GetEventSource() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,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
|
||||||
)
|
)
|
||||||
@@ -36,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
|
||||||
}
|
}
|
||||||
@@ -59,6 +67,10 @@ func (e *BlacklistedIPBlockedEvent) GetName() EventName {
|
|||||||
return EventBlacklistedIPBlocked
|
return EventBlacklistedIPBlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistedIPBlockedEvent) GetEventSource() string {
|
||||||
|
return "proxy-access"
|
||||||
|
}
|
||||||
|
|
||||||
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
||||||
type BlacklistToggledEvent struct {
|
type BlacklistToggledEvent struct {
|
||||||
RuleID string `json:"rule_id"`
|
RuleID string `json:"rule_id"`
|
||||||
@@ -69,6 +81,10 @@ func (e *BlacklistToggledEvent) GetName() EventName {
|
|||||||
return EventBlacklistToggled
|
return EventBlacklistToggled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistToggledEvent) GetEventSource() string {
|
||||||
|
return "accesslist-api"
|
||||||
|
}
|
||||||
|
|
||||||
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
||||||
type AccessRuleCreatedEvent struct {
|
type AccessRuleCreatedEvent struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
@@ -82,12 +98,31 @@ func (e *AccessRuleCreatedEvent) GetName() EventName {
|
|||||||
return EventAccessRuleCreated
|
return EventAccessRuleCreated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// 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
|
||||||
var temp struct {
|
var temp struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -96,6 +131,7 @@ func ParseEvent(jsonData []byte, event *Event) error {
|
|||||||
// Set the event name and timestamp
|
// Set the event name and timestamp
|
||||||
event.Name = temp.Name
|
event.Name = temp.Name
|
||||||
event.Timestamp = temp.Timestamp
|
event.Timestamp = temp.Timestamp
|
||||||
|
event.UUID = temp.UUID
|
||||||
|
|
||||||
// Now, based on the event type, unmarshal the specific payload
|
// Now, based on the event type, unmarshal the specific payload
|
||||||
switch temp.Name {
|
switch temp.Name {
|
||||||
@@ -126,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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,11 @@
|
|||||||
echo "Copying zoraxy_plugin to all mods"
|
echo "Copying zoraxy_plugin to all mods"
|
||||||
for dir in ./*; do
|
for dir in ./*; do
|
||||||
if [ -d "$dir" ]; then
|
if [ -d "$dir" ]; then
|
||||||
|
# remove existing zoraxy_plugin module, if it exists
|
||||||
|
if [ -d "${dir}/mod/zoraxy_plugin" ]; then
|
||||||
|
rm -r $dir/mod/zoraxy_plugin
|
||||||
|
fi
|
||||||
|
# copy over updated module
|
||||||
cp -r ../../src/mod/plugins/zoraxy_plugin "$dir/mod"
|
cp -r ../../src/mod/plugins/zoraxy_plugin "$dir/mod"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -12,12 +12,16 @@ type EventName string
|
|||||||
type EventPayload interface {
|
type EventPayload interface {
|
||||||
// GetName returns the event type
|
// GetName returns the event type
|
||||||
GetName() EventName
|
GetName() EventName
|
||||||
|
|
||||||
|
// Returns the "source" of the event, that is, the component or plugin that emitted the event
|
||||||
|
GetEventSource() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,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
|
||||||
)
|
)
|
||||||
@@ -36,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
|
||||||
}
|
}
|
||||||
@@ -59,6 +67,10 @@ func (e *BlacklistedIPBlockedEvent) GetName() EventName {
|
|||||||
return EventBlacklistedIPBlocked
|
return EventBlacklistedIPBlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistedIPBlockedEvent) GetEventSource() string {
|
||||||
|
return "proxy-access"
|
||||||
|
}
|
||||||
|
|
||||||
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
||||||
type BlacklistToggledEvent struct {
|
type BlacklistToggledEvent struct {
|
||||||
RuleID string `json:"rule_id"`
|
RuleID string `json:"rule_id"`
|
||||||
@@ -69,6 +81,10 @@ func (e *BlacklistToggledEvent) GetName() EventName {
|
|||||||
return EventBlacklistToggled
|
return EventBlacklistToggled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistToggledEvent) GetEventSource() string {
|
||||||
|
return "accesslist-api"
|
||||||
|
}
|
||||||
|
|
||||||
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
||||||
type AccessRuleCreatedEvent struct {
|
type AccessRuleCreatedEvent struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
@@ -82,12 +98,31 @@ func (e *AccessRuleCreatedEvent) GetName() EventName {
|
|||||||
return EventAccessRuleCreated
|
return EventAccessRuleCreated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// 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
|
||||||
var temp struct {
|
var temp struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -96,6 +131,7 @@ func ParseEvent(jsonData []byte, event *Event) error {
|
|||||||
// Set the event name and timestamp
|
// Set the event name and timestamp
|
||||||
event.Name = temp.Name
|
event.Name = temp.Name
|
||||||
event.Timestamp = temp.Timestamp
|
event.Timestamp = temp.Timestamp
|
||||||
|
event.UUID = temp.UUID
|
||||||
|
|
||||||
// Now, based on the event type, unmarshal the specific payload
|
// Now, based on the event type, unmarshal the specific payload
|
||||||
switch temp.Name {
|
switch temp.Name {
|
||||||
@@ -126,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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,12 +12,16 @@ type EventName string
|
|||||||
type EventPayload interface {
|
type EventPayload interface {
|
||||||
// GetName returns the event type
|
// GetName returns the event type
|
||||||
GetName() EventName
|
GetName() EventName
|
||||||
|
|
||||||
|
// Returns the "source" of the event, that is, the component or plugin that emitted the event
|
||||||
|
GetEventSource() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,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
|
||||||
)
|
)
|
||||||
@@ -36,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
|
||||||
}
|
}
|
||||||
@@ -59,6 +67,10 @@ func (e *BlacklistedIPBlockedEvent) GetName() EventName {
|
|||||||
return EventBlacklistedIPBlocked
|
return EventBlacklistedIPBlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistedIPBlockedEvent) GetEventSource() string {
|
||||||
|
return "proxy-access"
|
||||||
|
}
|
||||||
|
|
||||||
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
||||||
type BlacklistToggledEvent struct {
|
type BlacklistToggledEvent struct {
|
||||||
RuleID string `json:"rule_id"`
|
RuleID string `json:"rule_id"`
|
||||||
@@ -69,6 +81,10 @@ func (e *BlacklistToggledEvent) GetName() EventName {
|
|||||||
return EventBlacklistToggled
|
return EventBlacklistToggled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistToggledEvent) GetEventSource() string {
|
||||||
|
return "accesslist-api"
|
||||||
|
}
|
||||||
|
|
||||||
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
||||||
type AccessRuleCreatedEvent struct {
|
type AccessRuleCreatedEvent struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
@@ -82,12 +98,31 @@ func (e *AccessRuleCreatedEvent) GetName() EventName {
|
|||||||
return EventAccessRuleCreated
|
return EventAccessRuleCreated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// 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
|
||||||
var temp struct {
|
var temp struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -96,6 +131,7 @@ func ParseEvent(jsonData []byte, event *Event) error {
|
|||||||
// Set the event name and timestamp
|
// Set the event name and timestamp
|
||||||
event.Name = temp.Name
|
event.Name = temp.Name
|
||||||
event.Timestamp = temp.Timestamp
|
event.Timestamp = temp.Timestamp
|
||||||
|
event.UUID = temp.UUID
|
||||||
|
|
||||||
// Now, based on the event type, unmarshal the specific payload
|
// Now, based on the event type, unmarshal the specific payload
|
||||||
switch temp.Name {
|
switch temp.Name {
|
||||||
@@ -126,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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
EventLog = make([]plugin.Event, 0) // A slice to store events
|
EventLog = make([]events.Event, 0) // A slice to store events
|
||||||
EventLogMutex = &sync.Mutex{} // Mutex to protect access to the event log
|
EventLogMutex = &sync.Mutex{} // Mutex to protect access to the event log
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ func main() {
|
|||||||
})
|
})
|
||||||
http.HandleFunc(EVENT_PATH, func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc(EVENT_PATH, func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method == http.MethodPost {
|
if r.Method == http.MethodPost {
|
||||||
var event plugin.Event
|
var event events.Event
|
||||||
|
|
||||||
// read the request body
|
// read the request body
|
||||||
if r.Body == nil || r.ContentLength == 0 {
|
if r.Body == nil || r.ContentLength == 0 {
|
||||||
@@ -74,7 +74,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse the event from the request body
|
// parse the event from the request body
|
||||||
if err := plugin.ParseEvent(buffer.Bytes(), &event); err != nil {
|
if err := events.ParseEvent(buffer.Bytes(), &event); err != nil {
|
||||||
http.Error(w, fmt.Sprintf("Failed to parse event: %v", err), http.StatusBadRequest)
|
http.Error(w, fmt.Sprintf("Failed to parse event: %v", err), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,120 +0,0 @@
|
|||||||
package zoraxy_plugin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// EventName represents the type of event
|
|
||||||
type EventName string
|
|
||||||
|
|
||||||
// EventPayload interface for all event payloads
|
|
||||||
type EventPayload interface {
|
|
||||||
// GetName returns the event type
|
|
||||||
GetName() EventName
|
|
||||||
}
|
|
||||||
|
|
||||||
// Event represents a system event
|
|
||||||
type Event struct {
|
|
||||||
Name EventName `json:"name"`
|
|
||||||
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
|
||||||
Data EventPayload `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
// EventBlacklistedIPBlocked is emitted when a blacklisted IP is blocked
|
|
||||||
EventBlacklistedIPBlocked EventName = "blacklistedIpBlocked"
|
|
||||||
// EventBlacklistToggled is emitted when the blacklist is toggled for an access rule
|
|
||||||
EventBlacklistToggled EventName = "blacklistToggled"
|
|
||||||
// EventAccessRuleCreated is emitted when a new access ruleset is created
|
|
||||||
EventAccessRuleCreated EventName = "accessRuleCreated"
|
|
||||||
|
|
||||||
// Add more event types as needed
|
|
||||||
)
|
|
||||||
|
|
||||||
// BlacklistedIPBlockedEvent represents an event when a blacklisted IP is blocked
|
|
||||||
type BlacklistedIPBlockedEvent struct {
|
|
||||||
IP string `json:"ip"`
|
|
||||||
Comment string `json:"comment"`
|
|
||||||
RequestedURL string `json:"requested_url"`
|
|
||||||
Hostname string `json:"hostname"`
|
|
||||||
UserAgent string `json:"user_agent"`
|
|
||||||
Method string `json:"method"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *BlacklistedIPBlockedEvent) GetName() EventName {
|
|
||||||
return EventBlacklistedIPBlocked
|
|
||||||
}
|
|
||||||
|
|
||||||
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
|
||||||
type BlacklistToggledEvent struct {
|
|
||||||
RuleID string `json:"rule_id"`
|
|
||||||
Enabled bool `json:"enabled"` // Whether the blacklist is enabled or disabled
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *BlacklistToggledEvent) GetName() EventName {
|
|
||||||
return EventBlacklistToggled
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
|
||||||
type AccessRuleCreatedEvent struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
BlacklistEnabled bool `json:"blacklist_enabled"`
|
|
||||||
WhitelistEnabled bool `json:"whitelist_enabled"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *AccessRuleCreatedEvent) GetName() EventName {
|
|
||||||
return EventAccessRuleCreated
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
var temp struct {
|
|
||||||
Name EventName `json:"name"`
|
|
||||||
Timestamp int64 `json:"timestamp"`
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the event name and timestamp
|
|
||||||
event.Name = temp.Name
|
|
||||||
event.Timestamp = temp.Timestamp
|
|
||||||
|
|
||||||
// Now, based on the event type, unmarshal the specific payload
|
|
||||||
switch temp.Name {
|
|
||||||
case EventBlacklistedIPBlocked:
|
|
||||||
type tempData struct {
|
|
||||||
Data BlacklistedIPBlockedEvent `json:"data"`
|
|
||||||
}
|
|
||||||
var payload tempData
|
|
||||||
if err := json.Unmarshal(jsonData, &payload); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
event.Data = &payload.Data
|
|
||||||
case EventBlacklistToggled:
|
|
||||||
type tempData struct {
|
|
||||||
Data BlacklistToggledEvent `json:"data"`
|
|
||||||
}
|
|
||||||
var payload tempData
|
|
||||||
if err := json.Unmarshal(jsonData, &payload); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
event.Data = &payload.Data
|
|
||||||
case EventAccessRuleCreated:
|
|
||||||
type tempData struct {
|
|
||||||
Data AccessRuleCreatedEvent `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)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -12,12 +12,16 @@ type EventName string
|
|||||||
type EventPayload interface {
|
type EventPayload interface {
|
||||||
// GetName returns the event type
|
// GetName returns the event type
|
||||||
GetName() EventName
|
GetName() EventName
|
||||||
|
|
||||||
|
// Returns the "source" of the event, that is, the component or plugin that emitted the event
|
||||||
|
GetEventSource() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,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
|
||||||
)
|
)
|
||||||
@@ -36,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
|
||||||
}
|
}
|
||||||
@@ -59,6 +67,10 @@ func (e *BlacklistedIPBlockedEvent) GetName() EventName {
|
|||||||
return EventBlacklistedIPBlocked
|
return EventBlacklistedIPBlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistedIPBlockedEvent) GetEventSource() string {
|
||||||
|
return "proxy-access"
|
||||||
|
}
|
||||||
|
|
||||||
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
||||||
type BlacklistToggledEvent struct {
|
type BlacklistToggledEvent struct {
|
||||||
RuleID string `json:"rule_id"`
|
RuleID string `json:"rule_id"`
|
||||||
@@ -69,6 +81,10 @@ func (e *BlacklistToggledEvent) GetName() EventName {
|
|||||||
return EventBlacklistToggled
|
return EventBlacklistToggled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistToggledEvent) GetEventSource() string {
|
||||||
|
return "accesslist-api"
|
||||||
|
}
|
||||||
|
|
||||||
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
||||||
type AccessRuleCreatedEvent struct {
|
type AccessRuleCreatedEvent struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
@@ -82,12 +98,31 @@ func (e *AccessRuleCreatedEvent) GetName() EventName {
|
|||||||
return EventAccessRuleCreated
|
return EventAccessRuleCreated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// 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
|
||||||
var temp struct {
|
var temp struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -96,6 +131,7 @@ func ParseEvent(jsonData []byte, event *Event) error {
|
|||||||
// Set the event name and timestamp
|
// Set the event name and timestamp
|
||||||
event.Name = temp.Name
|
event.Name = temp.Name
|
||||||
event.Timestamp = temp.Timestamp
|
event.Timestamp = temp.Timestamp
|
||||||
|
event.UUID = temp.UUID
|
||||||
|
|
||||||
// Now, based on the event type, unmarshal the specific payload
|
// Now, based on the event type, unmarshal the specific payload
|
||||||
switch temp.Name {
|
switch temp.Name {
|
||||||
@@ -126,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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,12 +12,16 @@ type EventName string
|
|||||||
type EventPayload interface {
|
type EventPayload interface {
|
||||||
// GetName returns the event type
|
// GetName returns the event type
|
||||||
GetName() EventName
|
GetName() EventName
|
||||||
|
|
||||||
|
// Returns the "source" of the event, that is, the component or plugin that emitted the event
|
||||||
|
GetEventSource() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,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
|
||||||
)
|
)
|
||||||
@@ -36,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
|
||||||
}
|
}
|
||||||
@@ -59,6 +67,10 @@ func (e *BlacklistedIPBlockedEvent) GetName() EventName {
|
|||||||
return EventBlacklistedIPBlocked
|
return EventBlacklistedIPBlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistedIPBlockedEvent) GetEventSource() string {
|
||||||
|
return "proxy-access"
|
||||||
|
}
|
||||||
|
|
||||||
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
||||||
type BlacklistToggledEvent struct {
|
type BlacklistToggledEvent struct {
|
||||||
RuleID string `json:"rule_id"`
|
RuleID string `json:"rule_id"`
|
||||||
@@ -69,6 +81,10 @@ func (e *BlacklistToggledEvent) GetName() EventName {
|
|||||||
return EventBlacklistToggled
|
return EventBlacklistToggled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistToggledEvent) GetEventSource() string {
|
||||||
|
return "accesslist-api"
|
||||||
|
}
|
||||||
|
|
||||||
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
||||||
type AccessRuleCreatedEvent struct {
|
type AccessRuleCreatedEvent struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
@@ -82,12 +98,31 @@ func (e *AccessRuleCreatedEvent) GetName() EventName {
|
|||||||
return EventAccessRuleCreated
|
return EventAccessRuleCreated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// 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
|
||||||
var temp struct {
|
var temp struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -96,6 +131,7 @@ func ParseEvent(jsonData []byte, event *Event) error {
|
|||||||
// Set the event name and timestamp
|
// Set the event name and timestamp
|
||||||
event.Name = temp.Name
|
event.Name = temp.Name
|
||||||
event.Timestamp = temp.Timestamp
|
event.Timestamp = temp.Timestamp
|
||||||
|
event.UUID = temp.UUID
|
||||||
|
|
||||||
// Now, based on the event type, unmarshal the specific payload
|
// Now, based on the event type, unmarshal the specific payload
|
||||||
switch temp.Name {
|
switch temp.Name {
|
||||||
@@ -126,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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,12 +12,16 @@ type EventName string
|
|||||||
type EventPayload interface {
|
type EventPayload interface {
|
||||||
// GetName returns the event type
|
// GetName returns the event type
|
||||||
GetName() EventName
|
GetName() EventName
|
||||||
|
|
||||||
|
// Returns the "source" of the event, that is, the component or plugin that emitted the event
|
||||||
|
GetEventSource() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,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
|
||||||
)
|
)
|
||||||
@@ -36,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
|
||||||
}
|
}
|
||||||
@@ -59,6 +67,10 @@ func (e *BlacklistedIPBlockedEvent) GetName() EventName {
|
|||||||
return EventBlacklistedIPBlocked
|
return EventBlacklistedIPBlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistedIPBlockedEvent) GetEventSource() string {
|
||||||
|
return "proxy-access"
|
||||||
|
}
|
||||||
|
|
||||||
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
||||||
type BlacklistToggledEvent struct {
|
type BlacklistToggledEvent struct {
|
||||||
RuleID string `json:"rule_id"`
|
RuleID string `json:"rule_id"`
|
||||||
@@ -69,6 +81,10 @@ func (e *BlacklistToggledEvent) GetName() EventName {
|
|||||||
return EventBlacklistToggled
|
return EventBlacklistToggled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistToggledEvent) GetEventSource() string {
|
||||||
|
return "accesslist-api"
|
||||||
|
}
|
||||||
|
|
||||||
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
||||||
type AccessRuleCreatedEvent struct {
|
type AccessRuleCreatedEvent struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
@@ -82,12 +98,31 @@ func (e *AccessRuleCreatedEvent) GetName() EventName {
|
|||||||
return EventAccessRuleCreated
|
return EventAccessRuleCreated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// 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
|
||||||
var temp struct {
|
var temp struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -96,6 +131,7 @@ func ParseEvent(jsonData []byte, event *Event) error {
|
|||||||
// Set the event name and timestamp
|
// Set the event name and timestamp
|
||||||
event.Name = temp.Name
|
event.Name = temp.Name
|
||||||
event.Timestamp = temp.Timestamp
|
event.Timestamp = temp.Timestamp
|
||||||
|
event.UUID = temp.UUID
|
||||||
|
|
||||||
// Now, based on the event type, unmarshal the specific payload
|
// Now, based on the event type, unmarshal the specific payload
|
||||||
switch temp.Name {
|
switch temp.Name {
|
||||||
@@ -126,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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,12 +12,16 @@ type EventName string
|
|||||||
type EventPayload interface {
|
type EventPayload interface {
|
||||||
// GetName returns the event type
|
// GetName returns the event type
|
||||||
GetName() EventName
|
GetName() EventName
|
||||||
|
|
||||||
|
// Returns the "source" of the event, that is, the component or plugin that emitted the event
|
||||||
|
GetEventSource() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,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
|
||||||
)
|
)
|
||||||
@@ -36,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
|
||||||
}
|
}
|
||||||
@@ -59,6 +67,10 @@ func (e *BlacklistedIPBlockedEvent) GetName() EventName {
|
|||||||
return EventBlacklistedIPBlocked
|
return EventBlacklistedIPBlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistedIPBlockedEvent) GetEventSource() string {
|
||||||
|
return "proxy-access"
|
||||||
|
}
|
||||||
|
|
||||||
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
||||||
type BlacklistToggledEvent struct {
|
type BlacklistToggledEvent struct {
|
||||||
RuleID string `json:"rule_id"`
|
RuleID string `json:"rule_id"`
|
||||||
@@ -69,6 +81,10 @@ func (e *BlacklistToggledEvent) GetName() EventName {
|
|||||||
return EventBlacklistToggled
|
return EventBlacklistToggled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistToggledEvent) GetEventSource() string {
|
||||||
|
return "accesslist-api"
|
||||||
|
}
|
||||||
|
|
||||||
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
||||||
type AccessRuleCreatedEvent struct {
|
type AccessRuleCreatedEvent struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
@@ -82,12 +98,31 @@ func (e *AccessRuleCreatedEvent) GetName() EventName {
|
|||||||
return EventAccessRuleCreated
|
return EventAccessRuleCreated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// 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
|
||||||
var temp struct {
|
var temp struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -96,6 +131,7 @@ func ParseEvent(jsonData []byte, event *Event) error {
|
|||||||
// Set the event name and timestamp
|
// Set the event name and timestamp
|
||||||
event.Name = temp.Name
|
event.Name = temp.Name
|
||||||
event.Timestamp = temp.Timestamp
|
event.Timestamp = temp.Timestamp
|
||||||
|
event.UUID = temp.UUID
|
||||||
|
|
||||||
// Now, based on the event type, unmarshal the specific payload
|
// Now, based on the event type, unmarshal the specific payload
|
||||||
switch temp.Name {
|
switch temp.Name {
|
||||||
@@ -126,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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,12 +12,16 @@ type EventName string
|
|||||||
type EventPayload interface {
|
type EventPayload interface {
|
||||||
// GetName returns the event type
|
// GetName returns the event type
|
||||||
GetName() EventName
|
GetName() EventName
|
||||||
|
|
||||||
|
// Returns the "source" of the event, that is, the component or plugin that emitted the event
|
||||||
|
GetEventSource() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,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
|
||||||
)
|
)
|
||||||
@@ -36,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
|
||||||
}
|
}
|
||||||
@@ -59,6 +67,10 @@ func (e *BlacklistedIPBlockedEvent) GetName() EventName {
|
|||||||
return EventBlacklistedIPBlocked
|
return EventBlacklistedIPBlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistedIPBlockedEvent) GetEventSource() string {
|
||||||
|
return "proxy-access"
|
||||||
|
}
|
||||||
|
|
||||||
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
||||||
type BlacklistToggledEvent struct {
|
type BlacklistToggledEvent struct {
|
||||||
RuleID string `json:"rule_id"`
|
RuleID string `json:"rule_id"`
|
||||||
@@ -69,6 +81,10 @@ func (e *BlacklistToggledEvent) GetName() EventName {
|
|||||||
return EventBlacklistToggled
|
return EventBlacklistToggled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistToggledEvent) GetEventSource() string {
|
||||||
|
return "accesslist-api"
|
||||||
|
}
|
||||||
|
|
||||||
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
||||||
type AccessRuleCreatedEvent struct {
|
type AccessRuleCreatedEvent struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
@@ -82,12 +98,31 @@ func (e *AccessRuleCreatedEvent) GetName() EventName {
|
|||||||
return EventAccessRuleCreated
|
return EventAccessRuleCreated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// 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
|
||||||
var temp struct {
|
var temp struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -96,6 +131,7 @@ func ParseEvent(jsonData []byte, event *Event) error {
|
|||||||
// Set the event name and timestamp
|
// Set the event name and timestamp
|
||||||
event.Name = temp.Name
|
event.Name = temp.Name
|
||||||
event.Timestamp = temp.Timestamp
|
event.Timestamp = temp.Timestamp
|
||||||
|
event.UUID = temp.UUID
|
||||||
|
|
||||||
// Now, based on the event type, unmarshal the specific payload
|
// Now, based on the event type, unmarshal the specific payload
|
||||||
switch temp.Name {
|
switch temp.Name {
|
||||||
@@ -126,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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"imuslab.com/zoraxy/mod/info/logger"
|
"imuslab.com/zoraxy/mod/info/logger"
|
||||||
// "imuslab.com/zoraxy/mod/plugins"
|
|
||||||
|
|
||||||
"imuslab.com/zoraxy/mod/plugins/zoraxy_plugin/events"
|
"imuslab.com/zoraxy/mod/plugins/zoraxy_plugin/events"
|
||||||
)
|
)
|
||||||
@@ -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 listeners specified
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
defer em.mutex.RUnlock()
|
||||||
|
subscribers, exists := em.subscriptions[eventName]
|
||||||
|
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,22 +126,38 @@ 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
|
||||||
event := events.Event{
|
event := events.Event{
|
||||||
Name: eventName,
|
Name: eventName,
|
||||||
Timestamp: time.Now().Unix(),
|
Timestamp: time.Now().Unix(),
|
||||||
|
UUID: uuid.New().String(),
|
||||||
Data: payload,
|
Data: payload,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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()
|
||||||
|
listenersToUnregister := []ListenerID{}
|
||||||
|
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)
|
||||||
|
// Mark for removal
|
||||||
|
listenersToUnregister = append(listenersToUnregister, listenerID)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,5 +168,10 @@ func (em *eventManager) Emit(payload events.EventPayload) error {
|
|||||||
}(listener)
|
}(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
// Unregister any listeners that no longer exist, asynchronously
|
||||||
|
go func() {
|
||||||
|
for _, id := range listenersToUnregister {
|
||||||
|
em.UnregisterSubscriber(id)
|
||||||
|
}
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"imuslab.com/zoraxy/mod/info/logger"
|
||||||
"imuslab.com/zoraxy/mod/plugins/zoraxy_plugin/events"
|
"imuslab.com/zoraxy/mod/plugins/zoraxy_plugin/events"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,6 +20,7 @@ func TestEventDeSerialization(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
timestamp := time.Now().Unix()
|
timestamp := time.Now().Unix()
|
||||||
|
uuid := uuid.New().String()
|
||||||
|
|
||||||
tests := []SerializationTest{
|
tests := []SerializationTest{
|
||||||
{
|
{
|
||||||
@@ -25,6 +28,7 @@ func TestEventDeSerialization(t *testing.T) {
|
|||||||
event: events.Event{
|
event: events.Event{
|
||||||
Name: events.EventBlacklistedIPBlocked,
|
Name: events.EventBlacklistedIPBlocked,
|
||||||
Timestamp: timestamp,
|
Timestamp: timestamp,
|
||||||
|
UUID: uuid,
|
||||||
Data: &events.BlacklistedIPBlockedEvent{
|
Data: &events.BlacklistedIPBlockedEvent{
|
||||||
IP: "192.168.1.1",
|
IP: "192.168.1.1",
|
||||||
Comment: "Test comment",
|
Comment: "Test comment",
|
||||||
@@ -34,25 +38,27 @@ func TestEventDeSerialization(t *testing.T) {
|
|||||||
Method: "GET",
|
Method: "GET",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedJson: `{"name":"blacklistedIpBlocked","timestamp":` + fmt.Sprintf("%d", timestamp) + `,"data":{"ip":"192.168.1.1","comment":"Test comment","requested_url":"http://example.com","hostname":"example.com","user_agent":"TestUserAgent","method":"GET"}}`,
|
expectedJson: `{"name":"blacklistedIpBlocked","timestamp":` + fmt.Sprintf("%d", timestamp) + `,"uuid":"` + uuid + `","data":{"ip":"192.168.1.1","comment":"Test comment","requested_url":"http://example.com","hostname":"example.com","user_agent":"TestUserAgent","method":"GET"}}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "BlacklistToggled",
|
name: "BlacklistToggled",
|
||||||
event: events.Event{
|
event: events.Event{
|
||||||
Name: events.EventBlacklistToggled,
|
Name: events.EventBlacklistToggled,
|
||||||
Timestamp: timestamp,
|
Timestamp: timestamp,
|
||||||
|
UUID: uuid,
|
||||||
Data: &events.BlacklistToggledEvent{
|
Data: &events.BlacklistToggledEvent{
|
||||||
RuleID: "rule123",
|
RuleID: "rule123",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedJson: `{"name":"blacklistToggled","timestamp":` + fmt.Sprintf("%d", timestamp) + `,"data":{"rule_id":"rule123","enabled":true}}`,
|
expectedJson: `{"name":"blacklistToggled","timestamp":` + fmt.Sprintf("%d", timestamp) + `,"uuid":"` + uuid + `","data":{"rule_id":"rule123","enabled":true}}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "AccessRuleCreated",
|
name: "AccessRuleCreated",
|
||||||
event: events.Event{
|
event: events.Event{
|
||||||
Name: events.EventAccessRuleCreated,
|
Name: events.EventAccessRuleCreated,
|
||||||
Timestamp: timestamp,
|
Timestamp: timestamp,
|
||||||
|
UUID: uuid,
|
||||||
Data: &events.AccessRuleCreatedEvent{
|
Data: &events.AccessRuleCreatedEvent{
|
||||||
ID: "rule456",
|
ID: "rule456",
|
||||||
Name: "New Access Rule",
|
Name: "New Access Rule",
|
||||||
@@ -61,7 +67,7 @@ func TestEventDeSerialization(t *testing.T) {
|
|||||||
WhitelistEnabled: false,
|
WhitelistEnabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedJson: `{"name":"accessRuleCreated","timestamp":` + fmt.Sprintf("%d", timestamp) + `,"data":{"id":"rule456","name":"New Access Rule","desc":"A dummy access rule","blacklist_enabled":true,"whitelist_enabled":false}}`,
|
expectedJson: `{"name":"accessRuleCreated","timestamp":` + fmt.Sprintf("%d", timestamp) + `,"uuid":"` + uuid + `","data":{"id":"rule456","name":"New Access Rule","desc":"A dummy access rule","blacklist_enabled":true,"whitelist_enabled":false}}`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,3 +117,271 @@ func TestEventDeSerialization(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TestListener struct {
|
||||||
|
id ListenerID
|
||||||
|
receivedEvents chan events.Event
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tl *TestListener) GetID() ListenerID {
|
||||||
|
return tl.id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tl *TestListener) Notify(event events.Event) error {
|
||||||
|
tl.receivedEvents <- event
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEventEmission(t *testing.T) {
|
||||||
|
logger, err := logger.NewFmtLogger()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create logger: %v", err)
|
||||||
|
}
|
||||||
|
em := eventManager{
|
||||||
|
subscriptions: make(map[events.EventName][]ListenerID),
|
||||||
|
subscribers: make(map[ListenerID]Listener),
|
||||||
|
logger: logger,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a test listener
|
||||||
|
listenerID := ListenerID("testListener")
|
||||||
|
testListener := &TestListener{
|
||||||
|
id: listenerID,
|
||||||
|
receivedEvents: make(chan events.Event, 10),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the listener for BlacklistedIPBlocked events
|
||||||
|
if err := em.RegisterSubscriberToEvent(testListener, events.EventBlacklistedIPBlocked); err != nil {
|
||||||
|
t.Fatalf("Failed to register subscriber: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit a BlacklistedIPBlocked event
|
||||||
|
testEvent := &events.BlacklistedIPBlockedEvent{
|
||||||
|
IP: "192.168.1.1",
|
||||||
|
Comment: "Malicious activity detected",
|
||||||
|
RequestedURL: "http://mysite.com/admin",
|
||||||
|
Hostname: "mysite.com",
|
||||||
|
UserAgent: "BadBot/1.0",
|
||||||
|
Method: "GET",
|
||||||
|
}
|
||||||
|
em.Emit(testEvent)
|
||||||
|
|
||||||
|
// Verify that the listener received the event
|
||||||
|
select {
|
||||||
|
case receivedEvent := <-testListener.receivedEvents:
|
||||||
|
if receivedEvent.Name != events.EventBlacklistedIPBlocked {
|
||||||
|
t.Fatalf("Unexpected event received by listener.\nGot: %+v\nWant: %+v", receivedEvent, testEvent)
|
||||||
|
}
|
||||||
|
case <-time.After(1 * time.Second):
|
||||||
|
t.Fatal("Timeout waiting for event to be received by listener")
|
||||||
|
}
|
||||||
|
// Unregister the listener
|
||||||
|
if err := em.UnregisterSubscriber(listenerID); err != nil {
|
||||||
|
t.Fatalf("Failed to unregister subscriber: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEventEmissionToSpecificListener(t *testing.T) {
|
||||||
|
logger, err := logger.NewFmtLogger()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create logger: %v", err)
|
||||||
|
}
|
||||||
|
em := eventManager{
|
||||||
|
subscriptions: make(map[events.EventName][]ListenerID),
|
||||||
|
subscribers: make(map[ListenerID]Listener),
|
||||||
|
logger: logger,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a few test listeners
|
||||||
|
// listener1 and listener2 are plugins that will send events to each other
|
||||||
|
// moderator is a plugin that is subscribed to EventCustom, so it will receive all custom events
|
||||||
|
// otherListener is neither subscribed to EventCustom nor a recipient of any custom event, so it should not receive any events
|
||||||
|
listener1ID := ListenerID("pluginA")
|
||||||
|
listener1 := &TestListener{
|
||||||
|
id: listener1ID,
|
||||||
|
receivedEvents: make(chan events.Event, 10),
|
||||||
|
}
|
||||||
|
em.RegisterSubscriberToEvent(listener1, events.EventAccessRuleCreated) // We need to register to some event to be a valid subscriber
|
||||||
|
|
||||||
|
listener2ID := ListenerID("pluginB")
|
||||||
|
listener2 := &TestListener{
|
||||||
|
id: listener2ID,
|
||||||
|
receivedEvents: make(chan events.Event, 10),
|
||||||
|
}
|
||||||
|
em.RegisterSubscriberToEvent(listener2, events.EventAccessRuleCreated) // We need to register to some event to be a valid subscriber
|
||||||
|
|
||||||
|
moderatorID := ListenerID("moderator")
|
||||||
|
moderator := &TestListener{
|
||||||
|
id: moderatorID,
|
||||||
|
receivedEvents: make(chan events.Event, 10),
|
||||||
|
}
|
||||||
|
em.RegisterSubscriberToEvent(moderator, events.EventCustom)
|
||||||
|
|
||||||
|
otherListenerID := ListenerID("pluginD")
|
||||||
|
otherListener := &TestListener{
|
||||||
|
id: otherListenerID,
|
||||||
|
receivedEvents: make(chan events.Event, 10),
|
||||||
|
}
|
||||||
|
em.RegisterSubscriberToEvent(otherListener, events.EventAccessRuleCreated) // We need to register to some event to be a valid subscriber
|
||||||
|
|
||||||
|
// Send a custom event from listener1 to listener2
|
||||||
|
customEvent := &events.CustomEvent{
|
||||||
|
SourcePlugin: "pluginA",
|
||||||
|
Recipients: []string{"pluginB"},
|
||||||
|
Payload: map[string]interface{}{
|
||||||
|
"message": "Hello from pluginA",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
em.EmitToSubscribersAnd([]ListenerID{listener2ID}, customEvent)
|
||||||
|
|
||||||
|
// Verify that listener2 received the event
|
||||||
|
select {
|
||||||
|
case receivedEvent := <-listener2.receivedEvents:
|
||||||
|
if receivedEvent.Name != events.EventCustom {
|
||||||
|
t.Fatalf("Unexpected event received by listener2.\nGot: %+v\nWant: %+v", receivedEvent, customEvent)
|
||||||
|
}
|
||||||
|
case <-time.After(1 * time.Second):
|
||||||
|
t.Fatal("Timeout waiting for event to be received by listener2")
|
||||||
|
}
|
||||||
|
// Verify that listener1 did not receive the event
|
||||||
|
select {
|
||||||
|
case <-listener1.receivedEvents:
|
||||||
|
t.Fatal("Listener1 should not have received any events")
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
// No event received, as expected
|
||||||
|
}
|
||||||
|
|
||||||
|
// send a custom event from listener2 to listener1
|
||||||
|
customEvent2 := &events.CustomEvent{
|
||||||
|
SourcePlugin: "pluginB",
|
||||||
|
Recipients: []string{"pluginA"},
|
||||||
|
Payload: map[string]interface{}{
|
||||||
|
"message": "Hello from pluginB",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
em.EmitToSubscribersAnd([]ListenerID{listener1ID}, customEvent2)
|
||||||
|
|
||||||
|
// Verify that listener1 received the event
|
||||||
|
select {
|
||||||
|
case receivedEvent := <-listener1.receivedEvents:
|
||||||
|
if receivedEvent.Name != events.EventCustom {
|
||||||
|
t.Fatalf("Unexpected event received by listener1.\nGot: %+v\nWant: %+v", receivedEvent, customEvent2)
|
||||||
|
}
|
||||||
|
case <-time.After(1 * time.Second):
|
||||||
|
t.Fatal("Timeout waiting for event to be received by listener1")
|
||||||
|
}
|
||||||
|
// Verify that listener2 did not receive any new event
|
||||||
|
select {
|
||||||
|
case <-listener2.receivedEvents:
|
||||||
|
t.Fatal("Listener2 should not have received any new events")
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
// No event received, as expected
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure the moderator received both events
|
||||||
|
expectedMessagesSeen := map[string]bool{
|
||||||
|
"Hello from pluginA": false,
|
||||||
|
"Hello from pluginB": false,
|
||||||
|
}
|
||||||
|
for range expectedMessagesSeen {
|
||||||
|
select {
|
||||||
|
case receivedEvent := <-moderator.receivedEvents:
|
||||||
|
if receivedEvent.Name != events.EventCustom {
|
||||||
|
t.Fatalf("Unexpected event received by moderator.\nGot: %+v\nWant: %+v", receivedEvent, customEvent)
|
||||||
|
}
|
||||||
|
data, ok := receivedEvent.Data.(*events.CustomEvent)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("Unexpected data type in event received by moderator.\nGot: %T\nWant: *events.CustomEvent", receivedEvent.Data)
|
||||||
|
}
|
||||||
|
message, ok := data.Payload["message"].(string)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("Unexpected payload format in event received by moderator.\nGot: %+v\nWant: map with 'message' key", data.Payload)
|
||||||
|
}
|
||||||
|
if alreadySeen, exists := expectedMessagesSeen[message]; exists {
|
||||||
|
if alreadySeen {
|
||||||
|
t.Fatalf("Duplicate message in event received by moderator: %s", message)
|
||||||
|
}
|
||||||
|
expectedMessagesSeen[message] = true
|
||||||
|
} else {
|
||||||
|
t.Fatalf("Unexpected message in event received by moderator: %s", message)
|
||||||
|
}
|
||||||
|
case <-time.After(1 * time.Second):
|
||||||
|
t.Fatal("Timeout waiting for event to be received by moderator")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for msg, seen := range expectedMessagesSeen {
|
||||||
|
if !seen {
|
||||||
|
t.Fatalf("Moderator did not receive expected message: %s", msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the events were not seen by the other listener
|
||||||
|
select {
|
||||||
|
case <-otherListener.receivedEvents:
|
||||||
|
t.Fatal("otherListener should not have received any events")
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
// No event received, as expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmissionToNonExistentListener(t *testing.T) {
|
||||||
|
// Create a test listener and register it
|
||||||
|
listenerID := ListenerID("testListener")
|
||||||
|
testListener := &TestListener{
|
||||||
|
id: listenerID,
|
||||||
|
receivedEvents: make(chan events.Event, 10),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create event manager with the test listener marked as subscribed to BlacklistToggledEvents,
|
||||||
|
// but not actually registered
|
||||||
|
logger, err := logger.NewFmtLogger()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create logger: %v", err)
|
||||||
|
}
|
||||||
|
em := eventManager{
|
||||||
|
subscriptions: map[events.EventName][]ListenerID{
|
||||||
|
events.EventBlacklistToggled: {listenerID},
|
||||||
|
},
|
||||||
|
subscribers: make(map[ListenerID]Listener),
|
||||||
|
logger: logger,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit a BlacklistToggled event
|
||||||
|
testEvent := &events.BlacklistToggledEvent{
|
||||||
|
RuleID: "rule123",
|
||||||
|
Enabled: false,
|
||||||
|
}
|
||||||
|
eventEmitted := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
em.Emit(testEvent)
|
||||||
|
time.Sleep(10 * time.Millisecond) // Give some time for the emission to process
|
||||||
|
close(eventEmitted)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Wait for the event emission to complete
|
||||||
|
select {
|
||||||
|
case <-eventEmitted:
|
||||||
|
case <-time.After(1 * time.Second):
|
||||||
|
t.Fatal("Timeout waiting for event emission to complete, likely due to deadlock")
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the listener is still tracked by the event manager
|
||||||
|
em.mutex.RLock()
|
||||||
|
_, isRegistered := em.subscribers[listenerID]
|
||||||
|
subscribers := em.subscriptions[events.EventBlacklistToggled]
|
||||||
|
em.mutex.RUnlock()
|
||||||
|
if len(subscribers) != 0 {
|
||||||
|
t.Fatal("Listener should have been removed from subscriptions after failed dispatch")
|
||||||
|
}
|
||||||
|
if isRegistered {
|
||||||
|
t.Fatal("Listener was somehow registered")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since the listener was unregistered, it should not receive any events
|
||||||
|
select {
|
||||||
|
case <-testListener.receivedEvents:
|
||||||
|
t.Fatal("Listener should not have received any events after being unregistered")
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
// No event received, as expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,12 +12,16 @@ type EventName string
|
|||||||
type EventPayload interface {
|
type EventPayload interface {
|
||||||
// GetName returns the event type
|
// GetName returns the event type
|
||||||
GetName() EventName
|
GetName() EventName
|
||||||
|
|
||||||
|
// Returns the "source" of the event, that is, the component or plugin that emitted the event
|
||||||
|
GetEventSource() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event represents a system event
|
// Event represents a system event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
Timestamp int64 `json:"timestamp"` // Unix timestamp
|
||||||
|
UUID string `json:"uuid"` // UUID for the event
|
||||||
Data EventPayload `json:"data"`
|
Data EventPayload `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,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
|
||||||
)
|
)
|
||||||
@@ -36,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
|
||||||
}
|
}
|
||||||
@@ -59,6 +67,10 @@ func (e *BlacklistedIPBlockedEvent) GetName() EventName {
|
|||||||
return EventBlacklistedIPBlocked
|
return EventBlacklistedIPBlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistedIPBlockedEvent) GetEventSource() string {
|
||||||
|
return "proxy-access"
|
||||||
|
}
|
||||||
|
|
||||||
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
// BlacklistToggledEvent represents an event when the blacklist is disabled for an access rule
|
||||||
type BlacklistToggledEvent struct {
|
type BlacklistToggledEvent struct {
|
||||||
RuleID string `json:"rule_id"`
|
RuleID string `json:"rule_id"`
|
||||||
@@ -69,6 +81,10 @@ func (e *BlacklistToggledEvent) GetName() EventName {
|
|||||||
return EventBlacklistToggled
|
return EventBlacklistToggled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *BlacklistToggledEvent) GetEventSource() string {
|
||||||
|
return "accesslist-api"
|
||||||
|
}
|
||||||
|
|
||||||
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
// AccessRuleCreatedEvent represents an event when a new access ruleset is created
|
||||||
type AccessRuleCreatedEvent struct {
|
type AccessRuleCreatedEvent struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
@@ -82,12 +98,31 @@ func (e *AccessRuleCreatedEvent) GetName() EventName {
|
|||||||
return EventAccessRuleCreated
|
return EventAccessRuleCreated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// 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
|
||||||
var temp struct {
|
var temp struct {
|
||||||
Name EventName `json:"name"`
|
Name EventName `json:"name"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
if err := json.Unmarshal(jsonData, &temp); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -96,6 +131,7 @@ func ParseEvent(jsonData []byte, event *Event) error {
|
|||||||
// Set the event name and timestamp
|
// Set the event name and timestamp
|
||||||
event.Name = temp.Name
|
event.Name = temp.Name
|
||||||
event.Timestamp = temp.Timestamp
|
event.Timestamp = temp.Timestamp
|
||||||
|
event.UUID = temp.UUID
|
||||||
|
|
||||||
// Now, based on the event type, unmarshal the specific payload
|
// Now, based on the event type, unmarshal the specific payload
|
||||||
switch temp.Name {
|
switch temp.Name {
|
||||||
@@ -126,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