-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathuser.go
156 lines (132 loc) · 3.72 KB
/
user.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
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package security
import (
"errors"
"net/http"
"github.com/go-openapi/runtime"
"golang.org/x/net/context"
)
// A User is the current user who is executing a rest function.
type User struct {
EMail string
Name string
Groups []ResourceAccess
Tenant string
Issuer string
Subject string
}
var (
guest = User{
EMail: "[email protected]",
Name: "anonymous",
Groups: []ResourceAccess{},
}
errNoAuthFound = errors.New("no auth found")
)
// ResourceAccess is the type for our groups
type ResourceAccess string
type accessGroup []ResourceAccess
type resourceSet map[ResourceAccess]bool
func (ra accessGroup) asSet() resourceSet {
groupset := make(resourceSet)
for _, g := range ra {
groupset[g] = true
}
return groupset
}
// HasGroup returns true if the user has at least one of the given groups.
func (u *User) HasGroup(grps ...ResourceAccess) bool {
acc := accessGroup(u.Groups).asSet()
for _, grp := range grps {
if ok := acc[grp]; ok {
return true
}
}
return false
}
// A UserGetter returns the authenticated user from the request.
type UserGetter interface {
User(rq *http.Request) (*User, error)
}
// UserCreds stores different methods for user extraction from a request.
type UserCreds struct {
dex UserGetter
macauther []HMACAuth
}
// CredsOpt is a option setter for UserCreds
type CredsOpt func(*UserCreds)
// NewCreds returns a credential checker which tries to pull out the current user
// of a request. You can set many different HMAC auth'ers but only one for bearer tokens.
func NewCreds(opts ...CredsOpt) *UserCreds {
res := &UserCreds{}
for _, o := range opts {
o(res)
}
return res
}
// WithDex sets the dex auther.
func WithDex(d UserGetter) CredsOpt {
return func(uc *UserCreds) {
uc.dex = d
}
}
// WithHMAC appends the given HMACAuth to the list of allowed authers.
func WithHMAC(hma HMACAuth) CredsOpt {
return func(uc *UserCreds) {
uc.macauther = append(uc.macauther, hma)
}
}
// User pulls out a user from the request. It uses all authers
// which where specified when creating this usercred. the first
// auther which returns a user wins.
// if no auther returns a user, a guest with no rights will be returned.
func (uc *UserCreds) User(rq *http.Request) (*User, error) {
authers := make([]UserGetter, 0, len(uc.macauther)+1)
for i := range uc.macauther {
authers = append(authers, &uc.macauther[i])
}
if uc.dex != nil {
authers = append(authers, uc.dex)
}
for _, auth := range authers {
u, err := auth.User(rq)
if err == nil {
return u, nil
}
if !errors.Is(err, errNoAuthFound) && !errors.Is(err, errIllegalAuthFound) && !errors.Is(err, errUnknownAuthFound) {
return nil, err
}
}
return &guest, nil
}
// AddUserToken adds the given token as a bearer token to the request.
func AddUserToken(rq *http.Request, token string) {
rq.Header.Add("Authorization", "Bearer "+token)
}
// AddUserTokenToClientRequest to support openapi
func AddUserTokenToClientRequest(rq runtime.ClientRequest, token string) {
// FIXME add errcheck
//nolint:errcheck
rq.SetHeaderParam("Authorization", "Bearer "+token)
}
// use a private type and value for the key inside the context
type key int
var (
userkey = key(0)
)
// GetUserFromContext returns the current user from the context. If no user is set
// it returns a guest with no rights.
func GetUserFromContext(ctx context.Context) *User {
u, ok := ctx.Value(userkey).(*User)
if ok {
return u
}
return &guest
}
// PutUserInContext puts the given user as a value in the context.
func PutUserInContext(ctx context.Context, u *User) context.Context {
return context.WithValue(ctx, userkey, u)
}
// GetUser reads the current user from the request.
func GetUser(rq *http.Request) *User {
return GetUserFromContext(rq.Context())
}