forked from shaj13/go-guardian
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cached.go
74 lines (61 loc) · 1.82 KB
/
cached.go
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
package basic
import (
"context"
"net/http"
"github.com/m87carlson/go-guardian/v2/auth"
"github.com/m87carlson/go-guardian/v2/auth/internal"
)
// ExtensionKey represents a key for the password in info extensions.
// Typically used when basic strategy cache the authentication decisions.
//
// Deprecated: No longer used.
const ExtensionKey = "x-go-guardian-basic-password"
// NewCached return new auth.Strategy.
// The returned strategy, caches the invocation result of authenticate function.
func NewCached(f AuthenticateFunc, cache auth.Cache, opts ...auth.Option) auth.Strategy {
cb := new(cachedBasic)
cb.fn = f
cb.cache = cache
cb.comparator = plainText{}
cb.hasher = internal.PlainTextHasher{}
for _, opt := range opts {
opt.Apply(cb)
}
return New(cb.authenticate, opts...)
}
type entry struct {
password string
info auth.Info
}
type cachedBasic struct {
fn AuthenticateFunc
comparator Comparator
cache auth.Cache
hasher internal.Hasher
}
func (c *cachedBasic) authenticate(ctx context.Context, r *http.Request, userName, pass string) (auth.Info, error) { // nolint:lll
hash := c.hasher.Hash(userName)
v, ok := c.cache.Load(hash)
// if info not found invoke user authenticate function
if !ok {
return c.authenticatAndHash(ctx, r, hash, userName, pass)
}
ent, ok := v.(entry)
if !ok {
return nil, auth.NewTypeError("strategies/basic:", entry{}, v)
}
return ent.info, c.comparator.Compare(ent.password, pass)
}
func (c *cachedBasic) authenticatAndHash(ctx context.Context, r *http.Request, hash string, userName, pass string) (auth.Info, error) { //nolint:lll
info, err := c.fn(ctx, r, userName, pass)
if err != nil {
return nil, err
}
hashedPass, _ := c.comparator.Hash(pass)
ent := entry{
password: hashedPass,
info: info,
}
c.cache.Store(hash, ent)
return info, nil
}