-
Notifications
You must be signed in to change notification settings - Fork 2
/
headers.go
107 lines (92 loc) · 3.19 KB
/
headers.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
package middleware
import (
"github.com/containerum/kube-client/pkg/model"
"github.com/containerum/events-api/pkg/eaerrors"
"net/textproto"
"encoding/base64"
"errors"
"github.com/containerum/cherry/adaptors/gonic"
"github.com/containerum/utils/httputil"
"github.com/gin-gonic/gin"
"github.com/json-iterator/go"
log "github.com/sirupsen/logrus"
)
type UserHeaderDataMap map[string]model.UserHeaderData
const (
UserNamespaces = "user-namespaces"
RoleUser = "user"
RoleAdmin = "admin"
)
func RequiredUserHeaders() gin.HandlerFunc {
return func(ctx *gin.Context) {
log.WithField("Headers", ctx.Request.Header).Debug("Header list")
notFoundHeaders := requireHeaders(ctx, httputil.UserRoleXHeader)
if len(notFoundHeaders) > 0 {
gonic.Gonic(eaerrors.ErrRequiredHeadersNotProvided().AddDetails(notFoundHeaders...), ctx)
return
}
// Check User-Role and User-Namespace
if isUser, err := checkIsUserRole(GetHeader(ctx, httputil.UserRoleXHeader)); err != nil {
log.WithField("Value", GetHeader(ctx, httputil.UserRoleXHeader)).WithError(err).Warn("check User-Role Error")
gonic.Gonic(eaerrors.ErrInvalidRole(), ctx)
} else {
//User-Role: user, check User-Namespace
if isUser {
notFoundHeaders := requireHeaders(ctx, httputil.UserNamespacesXHeader, httputil.UserIDXHeader)
if len(notFoundHeaders) > 0 {
gonic.Gonic(eaerrors.ErrRequiredHeadersNotProvided().AddDetails(notFoundHeaders...), ctx)
return
}
userNs, errNs := checkUserNamespace(GetHeader(ctx, httputil.UserNamespacesXHeader))
if errNs != nil {
log.WithField("Value", GetHeader(ctx, httputil.UserNamespacesXHeader)).WithError(errNs).Warn("Check User-Namespace header Error")
gonic.Gonic(eaerrors.ErrValidation().AddDetailF("%v: %v", httputil.UserNamespacesXHeader, errNs), ctx)
return
}
ctx.Set(UserNamespaces, userNs)
}
}
}
}
func checkIsUserRole(userRole string) (bool, error) {
switch userRole {
case "", RoleAdmin:
return false, nil
case RoleUser:
return true, nil
}
return false, errors.New("invalid user role")
}
func requireHeaders(ctx *gin.Context, headers ...string) (notFoundHeaders []string) {
for _, v := range headers {
if GetHeader(ctx, v) == "" {
notFoundHeaders = append(notFoundHeaders, v)
}
}
return
}
func GetHeader(ctx *gin.Context, header string) string {
return ctx.GetHeader(textproto.CanonicalMIMEHeaderKey(header))
}
func checkUserNamespace(userNamespace string) (*UserHeaderDataMap, error) {
return ParseUserHeaderData(userNamespace)
}
//ParseUserHeaderData decodes headers for substitutions
func ParseUserHeaderData(str string) (*UserHeaderDataMap, error) {
data, err := base64.StdEncoding.DecodeString(str)
if err != nil {
log.WithError(err).WithField("Value", str).Warn("unable to decode user header data")
return nil, errors.New("unable to decode user header data")
}
var userData []model.UserHeaderData
err = jsoniter.Unmarshal(data, &userData)
if err != nil {
log.WithError(err).WithField("Value", string(data)).Warn("unable to unmarshal user header data")
return nil, errors.New("unable to unmarshal user header data")
}
result := UserHeaderDataMap{}
for _, v := range userData {
result[v.ID] = v
}
return &result, nil
}