-
Notifications
You must be signed in to change notification settings - Fork 0
/
cache.go
87 lines (71 loc) · 2.23 KB
/
cache.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
75
76
77
78
79
80
81
82
83
84
85
86
87
package entity
import (
"context"
"errors"
"fmt"
"github.com/common-fate/apikit/logger"
"github.com/common-fate/sdk/eid"
entityv1alpha1 "github.com/common-fate/sdk/gen/commonfate/entity/v1alpha1"
"github.com/patrickmn/go-cache"
"go.uber.org/zap"
)
type AttrCache struct {
client *Client
}
// AttrCache returns a cach for looking up entity attributes.
// This cache should ONLY be used for attributes not related to authorization
// decisions, such as displaying names, email addresses and labels.
func (c *Client) AttrCache() *AttrCache {
return &AttrCache{client: c}
}
// String obtains a cached string attribute for an entity. Attributes like names do not change that often, so they are cached in memory.
// If the attribute does not exist for an entity or there is an error, an empty string is returned
//
// An error is logged if there was an issue reaching the Authz service.
func (c *AttrCache) String(ctx context.Context, eid eid.EID, attr string) string {
log := logger.Get(ctx).Named("namecache").With("eid", eid, "attr", attr)
cached, ok := c.client.cache.Get(eid.String())
if ok {
// cache hit
res, err := extractStringAttr(cached, attr)
if err != nil {
log.Errorw("error extracting attribute from cached entity", zap.Error(err))
return ""
}
// renew the cached duration
c.client.cache.Set(eid.String(), cached, cache.DefaultExpiration)
return res
}
log.Debugw("cache miss")
res, err := c.client.GetEntity(ctx, GetInput{
EID: eid,
})
if err != nil {
log.Errorw("error loading entity from authz", zap.Error(err))
return ""
}
if res == nil {
log.Errorw("entity did not exist", zap.Error(err))
return ""
}
for _, a := range res.Entity.Attributes {
if a.Key == attr {
return a.Value.GetStr()
}
}
err = fmt.Errorf("entity did not have attribute %s", attr)
log.Errorw("error extracting attribute from loaded entity", zap.Error(err))
return ""
}
func extractStringAttr(cached any, attr string) (string, error) {
entity, ok := cached.(*entityv1alpha1.Entity)
if !ok {
return "", errors.New("could not cast to *authzv1alpha1.Entity")
}
for _, a := range entity.Attributes {
if a.Key == attr {
return a.Value.GetStr(), nil
}
}
return "", fmt.Errorf("entity did not have attribute %s", attr)
}