forked from aarondl/authboss
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcallbacks.go
More file actions
141 lines (119 loc) · 4.1 KB
/
Copy pathcallbacks.go
File metadata and controls
141 lines (119 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package authboss
import (
"fmt"
"reflect"
"runtime"
)
// Event is used for callback registration.
type Event int
// Event values
const (
EventRegister Event = iota
EventAuth
EventOAuth
EventAuthFail
EventOAuthFail
EventRecoverStart
EventRecoverEnd
EventGet
EventGetUserSession
EventPasswordReset
)
const eventNames = "EventRegisterEventAuthEventOAuthEventAuthFailEventOAuthFailEventRecoverStartEventRecoverEndEventGetEventGetUserSessionEventPasswordReset"
var eventIndexes = [...]uint8{0, 13, 22, 32, 45, 59, 76, 91, 99, 118, 136}
func (i Event) String() string {
if i < 0 || i+1 >= Event(len(eventIndexes)) {
return fmt.Sprintf("Event(%d)", i)
}
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
// InterruptSessionExpired occurs when the user's account has had no activity for the
// configured duration.
InterruptSessionExpired
)
const interruptNames = "InterruptNoneInterruptAccountLockedInterruptAccountNotConfirmedInterruptSessionExpired"
var interruptIndexes = [...]uint8{0, 13, 35, 63, 86}
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]]
}
// 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).
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.
// 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
}
// FireBefore event to all the callbacks with a context. The error
// 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
// 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 {
interrupt, err = fn(ctx)
if err != nil {
fmt.Fprintf(ctx.LogWriter, "Callback error (%s): %v\n", runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name(), err)
return InterruptNone, err
}
if interrupt != InterruptNone {
return interrupt, nil
}
}
return InterruptNone, nil
}
// 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
}
}
return nil
}