2015-01-10 22:52:39 -08:00
|
|
|
package authboss
|
|
|
|
|
2017-02-23 16:13:25 -08:00
|
|
|
import "context"
|
2015-02-20 23:01:45 -08:00
|
|
|
|
2015-04-10 19:28:11 -07:00
|
|
|
//go:generate stringer -output stringers.go -type "Event,Interrupt"
|
|
|
|
|
2015-01-12 14:02:07 -08:00
|
|
|
// Event is used for callback registration.
|
|
|
|
type Event int
|
|
|
|
|
2015-02-21 21:03:03 -08:00
|
|
|
// Event values
|
2015-01-12 14:02:07 -08:00
|
|
|
const (
|
|
|
|
EventRegister Event = iota
|
|
|
|
EventAuth
|
2015-03-13 16:23:43 -07:00
|
|
|
EventOAuth
|
2015-01-23 15:56:24 -08:00
|
|
|
EventAuthFail
|
2015-03-13 16:23:43 -07:00
|
|
|
EventOAuthFail
|
2015-01-20 22:41:31 -08:00
|
|
|
EventRecoverStart
|
|
|
|
EventRecoverEnd
|
2015-09-21 20:53:51 -07:00
|
|
|
EventGetUser
|
2015-03-01 20:40:09 -08:00
|
|
|
EventGetUserSession
|
2015-03-05 20:05:47 -08:00
|
|
|
EventPasswordReset
|
2015-01-12 14:02:07 -08:00
|
|
|
)
|
|
|
|
|
2015-02-21 21:03:03 -08:00
|
|
|
// Interrupt is used to signal to callback mechanisms
|
|
|
|
// that the current process should not continue.
|
|
|
|
type Interrupt int
|
|
|
|
|
|
|
|
// Interrupt values
|
|
|
|
const (
|
|
|
|
// InterruptNone means there was no interrupt present and the process should continue.
|
|
|
|
InterruptNone Interrupt = iota
|
|
|
|
// InterruptAccountLocked occurs if a user's account has been locked
|
|
|
|
// by the lock module.
|
|
|
|
InterruptAccountLocked
|
|
|
|
// InterruptAccountNotConfirmed occurs if a user's account is not confirmed
|
|
|
|
// and therefore cannot be used yet.
|
|
|
|
InterruptAccountNotConfirmed
|
2015-02-22 00:24:57 -08:00
|
|
|
// InterruptSessionExpired occurs when the user's account has had no activity for the
|
|
|
|
// configured duration.
|
|
|
|
InterruptSessionExpired
|
2015-02-21 21:03:03 -08:00
|
|
|
)
|
|
|
|
|
2018-02-01 16:31:08 -08:00
|
|
|
// Before Events can interrupt the flow by returning an interrupt value.
|
2017-02-21 15:04:30 -08:00
|
|
|
// This is used to stop the callback chain and the original handler from
|
|
|
|
// continuing execution. The execution should also stopped if there is an error.
|
2017-02-20 15:56:26 -08:00
|
|
|
type Before func(context.Context) (Interrupt, error)
|
2015-01-10 22:52:39 -08:00
|
|
|
|
|
|
|
// After is a request callback that happens after the event.
|
2017-02-20 15:56:26 -08:00
|
|
|
type After func(context.Context) error
|
2015-01-10 22:52:39 -08:00
|
|
|
|
2018-02-01 16:31:08 -08:00
|
|
|
// Events is a collection of Events that fire before and after certain
|
2015-01-10 22:52:39 -08:00
|
|
|
// methods.
|
2018-02-01 16:31:08 -08:00
|
|
|
type Events struct {
|
2015-01-12 14:02:07 -08:00
|
|
|
before map[Event][]Before
|
|
|
|
after map[Event][]After
|
2015-01-10 22:52:39 -08:00
|
|
|
}
|
|
|
|
|
2018-02-01 16:31:08 -08:00
|
|
|
// NewEvents creates a new set of before and after Events.
|
2015-03-16 14:42:45 -07:00
|
|
|
// Called only by authboss internals and for testing.
|
2018-02-01 16:31:08 -08:00
|
|
|
func NewEvents() *Events {
|
|
|
|
return &Events{
|
2017-02-23 16:13:25 -08:00
|
|
|
before: make(map[Event][]Before),
|
|
|
|
after: make(map[Event][]After),
|
2015-01-10 22:52:39 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-23 15:56:24 -08:00
|
|
|
// Before event, call f.
|
2018-02-01 16:31:08 -08:00
|
|
|
func (c *Events) Before(e Event, f Before) {
|
|
|
|
Events := c.before[e]
|
|
|
|
Events = append(Events, f)
|
|
|
|
c.before[e] = Events
|
2015-01-10 22:52:39 -08:00
|
|
|
}
|
|
|
|
|
2015-01-23 15:56:24 -08:00
|
|
|
// After event, call f.
|
2018-02-01 16:31:08 -08:00
|
|
|
func (c *Events) After(e Event, f After) {
|
|
|
|
Events := c.after[e]
|
|
|
|
Events = append(Events, f)
|
|
|
|
c.after[e] = Events
|
2015-01-10 22:52:39 -08:00
|
|
|
}
|
|
|
|
|
2018-02-01 16:31:08 -08:00
|
|
|
// FireBefore event to all the Events with a context. The error
|
2015-02-20 23:10:18 -08:00
|
|
|
// should be passed up despite being logged once here already so it
|
|
|
|
// can write an error out to the HTTP Client. If err is nil then
|
2015-02-21 21:03:03 -08:00
|
|
|
// check the value of interrupted. If error is nil then the interrupt
|
|
|
|
// value should be checked. If it is not InterruptNone then there is a reason
|
|
|
|
// the current process should stop it's course of action.
|
2018-02-01 16:31:08 -08:00
|
|
|
func (c *Events) FireBefore(ctx context.Context, e Event) (interrupt Interrupt, err error) {
|
|
|
|
Events := c.before[e]
|
|
|
|
for _, fn := range Events {
|
2015-02-21 21:03:03 -08:00
|
|
|
interrupt, err = fn(ctx)
|
2015-01-10 22:52:39 -08:00
|
|
|
if err != nil {
|
2015-02-21 21:03:03 -08:00
|
|
|
return InterruptNone, err
|
2015-02-19 14:34:29 -08:00
|
|
|
}
|
2015-02-21 21:03:03 -08:00
|
|
|
if interrupt != InterruptNone {
|
|
|
|
return interrupt, nil
|
2015-01-10 22:52:39 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-21 21:03:03 -08:00
|
|
|
return InterruptNone, nil
|
2015-01-10 22:52:39 -08:00
|
|
|
}
|
|
|
|
|
2018-02-01 16:31:08 -08:00
|
|
|
// FireAfter event to all the Events with a context. The error can safely be
|
2015-02-20 23:01:45 -08:00
|
|
|
// ignored as it is logged.
|
2018-02-01 16:31:08 -08:00
|
|
|
func (c *Events) FireAfter(ctx context.Context, e Event) (err error) {
|
|
|
|
Events := c.after[e]
|
|
|
|
for _, fn := range Events {
|
2015-02-19 14:34:29 -08:00
|
|
|
if err = fn(ctx); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-01-10 22:52:39 -08:00
|
|
|
}
|
2015-02-20 04:03:22 -08:00
|
|
|
|
|
|
|
return nil
|
2015-01-10 22:52:39 -08:00
|
|
|
}
|