1
0
mirror of https://github.com/volatiletech/authboss.git synced 2024-11-30 09:06:45 +02:00
authboss/callbacks.go

142 lines
4.1 KiB
Go
Raw Normal View History

package authboss
2015-02-21 09:01:45 +02:00
import (
"fmt"
"reflect"
"runtime"
)
// Event is used for callback registration.
type Event int
2015-02-22 07:03:03 +02:00
// Event values
const (
EventRegister Event = iota
EventAuth
EventOAuth
EventAuthFail
EventOAuthFail
EventRecoverStart
EventRecoverEnd
EventGet
EventGetUserSession
EventPasswordReset
)
const eventNames = "EventRegisterEventAuthEventOAuthEventAuthFailEventOAuthFailEventRecoverStartEventRecoverEndEventGetEventGetUserSessionEventPasswordReset"
2015-02-22 07:03:03 +02:00
var eventIndexes = [...]uint8{0, 13, 22, 32, 45, 59, 76, 91, 99, 118, 136}
2015-02-22 07:03:03 +02:00
func (i Event) String() string {
if i < 0 || i+1 >= Event(len(eventIndexes)) {
return fmt.Sprintf("Event(%d)", i)
}
2015-02-22 07:03:03 +02:00
return eventNames[eventIndexes[i]:eventIndexes[i+1]]
}
// 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 10:24:57 +02:00
// InterruptSessionExpired occurs when the user's account has had no activity for the
// configured duration.
InterruptSessionExpired
2015-02-22 07:03:03 +02:00
)
2015-02-22 10:24:57 +02:00
const interruptNames = "InterruptNoneInterruptAccountLockedInterruptAccountNotConfirmedInterruptSessionExpired"
2015-02-22 07:03:03 +02:00
2015-02-22 10:24:57 +02:00
var interruptIndexes = [...]uint8{0, 13, 35, 63, 86}
2015-02-22 07:03:03 +02:00
func (i Interrupt) String() string {
if i < 0 || i+1 >= Interrupt(len(interruptIndexes)) {
return fmt.Sprintf("Interrupt(%d)", i)
}
return interruptNames[interruptIndexes[i]:interruptIndexes[i+1]]
}
2015-02-21 09:01:45 +02:00
// Before callbacks can interrupt the flow by returning a bool. 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 (and therefore if error is set
// the bool is automatically considered set).
2015-02-22 07:03:03 +02:00
type Before func(*Context) (Interrupt, error)
// After is a request callback that happens after the event.
type After func(*Context) error
// Callbacks is a collection of callbacks that fire before and after certain
// methods.
type Callbacks struct {
before map[Event][]Before
after map[Event][]After
}
// NewCallbacks creates a new set of before and after callbacks.
2015-03-16 23:42:45 +02:00
// Called only by authboss internals and for testing.
func NewCallbacks() *Callbacks {
return &Callbacks{
make(map[Event][]Before),
make(map[Event][]After),
}
}
// Before event, call f.
func (c *Callbacks) Before(e Event, f Before) {
callbacks := c.before[e]
callbacks = append(callbacks, f)
c.before[e] = callbacks
}
// After event, call f.
func (c *Callbacks) After(e Event, f After) {
callbacks := c.after[e]
callbacks = append(callbacks, f)
c.after[e] = callbacks
}
2015-02-21 09:01:45 +02:00
// FireBefore event to all the callbacks with a context. The error
2015-02-21 09:10:18 +02: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-22 07:03:03 +02: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.
func (c *Callbacks) FireBefore(e Event, ctx *Context) (interrupt Interrupt, err error) {
callbacks := c.before[e]
for _, fn := range callbacks {
2015-02-22 07:03:03 +02:00
interrupt, err = fn(ctx)
if err != nil {
fmt.Fprintf(ctx.LogWriter, "Callback error (%s): %v\n", runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name(), err)
2015-02-22 07:03:03 +02:00
return InterruptNone, err
}
2015-02-22 07:03:03 +02:00
if interrupt != InterruptNone {
return interrupt, nil
}
}
2015-02-22 07:03:03 +02:00
return InterruptNone, nil
}
2015-02-21 09:01:45 +02:00
// FireAfter event to all the callbacks with a context. The error can safely be
// ignored as it is logged.
func (c *Callbacks) FireAfter(e Event, ctx *Context) (err error) {
callbacks := c.after[e]
for _, fn := range callbacks {
if err = fn(ctx); err != nil {
fmt.Fprintf(ctx.LogWriter, "Callback error (%s): %v\n", runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name(), err)
return err
}
}
2015-02-20 14:03:22 +02:00
return nil
}