package authboss import ( "net/http" ) //go:generate stringer -output stringers.go -type "Event" // Event type is for describing events type Event int // Event kinds const ( EventRegister Event = iota EventAuth EventOAuth2 EventAuthFail EventOAuth2Fail EventRecoverStart EventRecoverEnd EventGetUser EventGetUserSession EventPasswordReset ) // EventHandler reacts to events that are fired by Authboss controllers. // These controllers will normally process a request by themselves, but if // there is special consideration for example a successful login, but the // user is locked, the lock module's controller may seize control over the // request. // // Very much a controller level middleware. type EventHandler func(w http.ResponseWriter, r *http.Request, handled bool) (bool, error) // Events is a collection of Events that fire before and after certain methods. type Events struct { before map[Event][]EventHandler after map[Event][]EventHandler } // NewEvents creates a new set of before and after Events. func NewEvents() *Events { return &Events{ before: make(map[Event][]EventHandler), after: make(map[Event][]EventHandler), } } // Before event, call f. func (c *Events) Before(e Event, f EventHandler) { events := c.before[e] events = append(events, f) c.before[e] = events } // After event, call f. func (c *Events) After(e Event, f EventHandler) { events := c.after[e] events = append(events, f) c.after[e] = events } // FireBefore executes the handlers that were registered to fire before // the event passed in. // // If it encounters an error it will stop immediately without calling // other handlers. // // If a handler handles the request, it will pass this information both // to handlers further down the chain (to let them know that w has been used) // as well as set w to nil as a precaution. func (c *Events) FireBefore(e Event, w http.ResponseWriter, r *http.Request) (bool, error) { return c.call(c.before[e], w, r) } // FireAfter event to all the Events with a context. The error can safely be // ignored as it is logged. func (c *Events) FireAfter(e Event, w http.ResponseWriter, r *http.Request) (bool, error) { return c.call(c.after[e], w, r) } func (c *Events) call(evs []EventHandler, w http.ResponseWriter, r *http.Request) (bool, error) { handled := false for _, fn := range evs { interrupt, err := fn(w, r, handled) if err != nil { return false, err } if interrupt { handled = true } } return handled, nil }