Files
ziti/events/session.go
T
2021-08-19 14:18:30 -04:00

143 lines
3.9 KiB
Go

package events
import (
"fmt"
"github.com/michaelquigley/pfxlog"
"github.com/openziti/edge/controller/persistence"
"github.com/openziti/foundation/util/cowslice"
"github.com/openziti/foundation/util/stringz"
"github.com/pkg/errors"
"reflect"
"time"
)
const SessionEventTypeCreated = "created"
const SessionEventTypeDeleted = "deleted"
const SessionEventNS = "edge.sessions"
type SessionEvent struct {
Namespace string `json:"namespace"`
EventType string `json:"event_type"`
Id string `json:"id"`
Timestamp time.Time `json:"timestamp"`
Token string `json:"token"`
ApiSessionId string `json:"api_session_id"`
IdentityId string `json:"identity_id"`
}
func (event *SessionEvent) String() string {
return fmt.Sprintf("%v.%v id=%v timestamp=%v token=%v apiSessionId=%v identityId=%v",
event.Namespace, event.EventType, event.Id, event.Timestamp, event.Token, event.ApiSessionId, event.IdentityId)
}
type SessionEventHandler interface {
AcceptSessionEvent(event *SessionEvent)
}
var sessionEventHandlerRegistry = cowslice.NewCowSlice(make([]SessionEventHandler, 0))
func getSessionEventHandlers() []SessionEventHandler {
return sessionEventHandlerRegistry.Value().([]SessionEventHandler)
}
func sessionCreated(args ...interface{}) {
var session *persistence.Session
if len(args) == 1 {
session, _ = args[0].(*persistence.Session)
}
if session == nil {
log := pfxlog.Logger()
log.Error("could not cast event args to event details")
return
}
event := &SessionEvent{
Namespace: SessionEventNS,
EventType: SessionEventTypeCreated,
Id: session.Id,
Timestamp: time.Now(),
Token: session.Token,
ApiSessionId: session.ApiSessionId,
IdentityId: session.ApiSession.IdentityId,
}
for _, handler := range getSessionEventHandlers() {
go handler.AcceptSessionEvent(event)
}
}
func sessionDeleted(args ...interface{}) {
var session *persistence.Session
if len(args) == 1 {
session, _ = args[0].(*persistence.Session)
}
if session == nil {
log := pfxlog.Logger()
log.Error("could not cast event args to event details")
return
}
event := &SessionEvent{
Namespace: SessionEventNS,
EventType: SessionEventTypeDeleted,
Id: session.Id,
Timestamp: time.Now(),
Token: session.Token,
}
for _, handler := range getSessionEventHandlers() {
go handler.AcceptSessionEvent(event)
}
}
func registerSessionEventHandler(val interface{}, config map[interface{}]interface{}) error {
handler, ok := val.(SessionEventHandler)
if !ok {
return errors.Errorf("type %v doesn't implement github.com/openziti/edge/events/SessionEventHandler interface.", reflect.TypeOf(val))
}
var includeList []string
if includeVar, ok := config["include"]; ok {
if includeStr, ok := includeVar.(string); ok {
includeList = append(includeList, includeStr)
} else if includeIntfList, ok := includeVar.([]interface{}); ok {
for _, val := range includeIntfList {
includeList = append(includeList, fmt.Sprintf("%v", val))
}
} else {
return errors.Errorf("invalid type %v for edge.sessions include configuration", reflect.TypeOf(includeVar))
}
}
if len(includeList) == 0 || (len(includeList) == 2 && stringz.ContainsAll(includeList, SessionEventTypeCreated, SessionEventTypeDeleted)) {
AddSessionEventHandler(handler)
} else {
for _, include := range includeList {
if include != SessionEventTypeCreated && include != SessionEventTypeDeleted {
return errors.Errorf("invalid include %v for edge.sessions. valid values are ['created', 'deleted']", include)
}
}
AddSessionEventHandler(&sessionEventAdapter{
wrapped: handler,
includeList: includeList,
})
}
return nil
}
type sessionEventAdapter struct {
wrapped SessionEventHandler
includeList []string
}
func (adapter *sessionEventAdapter) AcceptSessionEvent(event *SessionEvent) {
if stringz.Contains(adapter.includeList, event.EventType) {
adapter.wrapped.AcceptSessionEvent(event)
}
}