github.com/volatiletech/authboss@v2.4.1+incompatible/events.go (about) 1 package authboss 2 3 import ( 4 "net/http" 5 ) 6 7 //go:generate stringer -output stringers.go -type "Event" 8 9 // Event type is for describing events 10 type Event int 11 12 // Event kinds 13 const ( 14 EventRegister Event = iota 15 EventAuth 16 // EventAuthHijack is used to steal the authentication process after a 17 // successful auth but before any session variable has been put in. 18 // Most useful for defining an additional step for authentication 19 // (like 2fa). It needs to be separate to EventAuth because other modules 20 // do checks that would also interrupt event handlers with an authentication 21 // failure so there's an ordering problem. 22 EventAuthHijack 23 EventOAuth2 24 EventAuthFail 25 EventOAuth2Fail 26 EventRecoverStart 27 EventRecoverEnd 28 EventGetUser 29 EventGetUserSession 30 EventPasswordReset 31 EventLogout 32 ) 33 34 // EventHandler reacts to events that are fired by Authboss controllers. 35 // These controllers will normally process a request by themselves, but if 36 // there is special consideration for example a successful login, but the 37 // user is locked, the lock module's controller may seize control over the 38 // request. 39 // 40 // Very much a controller level middleware. 41 type EventHandler func(w http.ResponseWriter, r *http.Request, handled bool) (bool, error) 42 43 // Events is a collection of Events that fire before and after certain methods. 44 type Events struct { 45 before map[Event][]EventHandler 46 after map[Event][]EventHandler 47 } 48 49 // NewEvents creates a new set of before and after Events. 50 func NewEvents() *Events { 51 return &Events{ 52 before: make(map[Event][]EventHandler), 53 after: make(map[Event][]EventHandler), 54 } 55 } 56 57 // Before event, call f. 58 func (c *Events) Before(e Event, f EventHandler) { 59 events := c.before[e] 60 events = append(events, f) 61 c.before[e] = events 62 } 63 64 // After event, call f. 65 func (c *Events) After(e Event, f EventHandler) { 66 events := c.after[e] 67 events = append(events, f) 68 c.after[e] = events 69 } 70 71 // FireBefore executes the handlers that were registered to fire before 72 // the event passed in. 73 // 74 // If it encounters an error it will stop immediately without calling 75 // other handlers. 76 // 77 // If a handler handles the request, it will pass this information both 78 // to handlers further down the chain (to let them know that w has been used) 79 // as well as set w to nil as a precaution. 80 func (c *Events) FireBefore(e Event, w http.ResponseWriter, r *http.Request) (bool, error) { 81 return c.call(c.before[e], w, r) 82 } 83 84 // FireAfter event to all the Events with a context. The error can safely be 85 // ignored as it is logged. 86 func (c *Events) FireAfter(e Event, w http.ResponseWriter, r *http.Request) (bool, error) { 87 return c.call(c.after[e], w, r) 88 } 89 90 func (c *Events) call(evs []EventHandler, w http.ResponseWriter, r *http.Request) (bool, error) { 91 handled := false 92 93 for _, fn := range evs { 94 interrupt, err := fn(w, r, handled) 95 if err != nil { 96 return false, err 97 } 98 if interrupt { 99 handled = true 100 } 101 } 102 103 return handled, nil 104 }