-
Notifications
You must be signed in to change notification settings - Fork 10
/
users_profile_manager.go
93 lines (82 loc) · 3.18 KB
/
users_profile_manager.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
88
89
90
91
92
93
package toolbox
import (
"context"
"encoding/json"
"github.com/cloudtrust/keycloak-client/v2"
)
// ProfileRetriever interface
type ProfileRetriever interface {
GetRealm(accessToken string, realmName string) (keycloak.RealmRepresentation, error)
GetUserProfile(accessToken string, realmName string) (keycloak.UserProfileRepresentation, error)
}
// DefaultProfileProviderFunc function type
type DefaultProfileProviderFunc func(realmName string) (keycloak.UserProfileRepresentation, error)
// UserProfileCache struct
type UserProfileCache struct {
tokenProvider OidcTokenProvider
retriever ProfileRetriever
cachedProfiles map[string][]byte
defProfileProvider DefaultProfileProviderFunc
}
func NewUserProfileCache(retriever ProfileRetriever, tokenProvider OidcTokenProvider, defProfileProvider DefaultProfileProviderFunc) *UserProfileCache {
return &UserProfileCache{
tokenProvider: tokenProvider,
retriever: retriever,
defProfileProvider: defProfileProvider,
cachedProfiles: map[string][]byte{},
}
}
// GetRealmUserProfile gets the realm users profile using the token provider provided when creating the UserProfileCache instance
func (upc *UserProfileCache) GetRealmUserProfile(ctx context.Context, realmName string) (keycloak.UserProfileRepresentation, error) {
return upc.getRealmUserProfile(func() (string, error) {
return upc.tokenProvider.ProvideTokenForRealm(ctx, realmName)
}, realmName)
}
// GetRealmUserProfileWithToken gets the realm users profile using the provided access token
func (upc *UserProfileCache) GetRealmUserProfileWithToken(accessToken string, realmName string) (keycloak.UserProfileRepresentation, error) {
var f = func() (string, error) {
return accessToken, nil
}
return upc.getRealmUserProfile(f, realmName)
}
func (upc *UserProfileCache) getRealmUserProfile(provideToken func() (string, error), realmName string) (keycloak.UserProfileRepresentation, error) {
// Already loaded profile?
if profile, ok := upc.getProfile(realmName); ok {
return profile, nil
}
// Get access token
var accessToken, err = provideToken()
if err != nil {
return keycloak.UserProfileRepresentation{}, err
}
// Is user profile enabled for this realm?
var realmRep keycloak.RealmRepresentation
realmRep, err = upc.retriever.GetRealm(accessToken, realmName)
if err != nil {
return keycloak.UserProfileRepresentation{}, err
}
if !realmRep.IsUserProfileEnabled() {
return upc.defProfileProvider(realmName)
}
// Retrieve the profile
var profile keycloak.UserProfileRepresentation
profile, err = upc.retriever.GetUserProfile(accessToken, realmName)
if err != nil {
return keycloak.UserProfileRepresentation{}, err
}
// Write profile in cache then return it
upc.setProfile(realmName, profile)
return profile, nil
}
func (upc *UserProfileCache) getProfile(realm string) (keycloak.UserProfileRepresentation, bool) {
var res keycloak.UserProfileRepresentation
if bytes, ok := upc.cachedProfiles[realm]; ok {
json.Unmarshal(bytes, &res)
return res, true
}
return res, false
}
func (upc *UserProfileCache) setProfile(realm string, profile keycloak.UserProfileRepresentation) {
var bytes, _ = json.Marshal(profile)
upc.cachedProfiles[realm] = bytes
}