forked from openshift/origin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
strategy.go
139 lines (114 loc) · 4.66 KB
/
strategy.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
package oauthclientauthorization
import (
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation/field"
apirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
kstorage "k8s.io/apiserver/pkg/storage"
kapi "k8s.io/kubernetes/pkg/api"
scopeauthorizer "github.com/openshift/origin/pkg/authorization/authorizer/scope"
oauthapi "github.com/openshift/origin/pkg/oauth/apis/oauth"
"github.com/openshift/origin/pkg/oauth/apis/oauth/validation"
"github.com/openshift/origin/pkg/oauth/registry/oauthclient"
)
// strategy implements behavior for OAuthClientAuthorization objects
type strategy struct {
runtime.ObjectTyper
clientGetter oauthclient.Getter
}
func NewStrategy(clientGetter oauthclient.Getter) strategy {
return strategy{ObjectTyper: kapi.Scheme, clientGetter: clientGetter}
}
func (strategy) DefaultGarbageCollectionPolicy() rest.GarbageCollectionPolicy {
return rest.Unsupported
}
func (strategy) PrepareForUpdate(ctx apirequest.Context, obj, old runtime.Object) {
auth := obj.(*oauthapi.OAuthClientAuthorization)
auth.Name = fmt.Sprintf("%s:%s", auth.UserName, auth.ClientName)
}
// NamespaceScoped is false for OAuth objects
func (strategy) NamespaceScoped() bool {
return false
}
func (strategy) GenerateName(base string) string {
return base
}
func (strategy) PrepareForCreate(ctx apirequest.Context, obj runtime.Object) {
auth := obj.(*oauthapi.OAuthClientAuthorization)
auth.Name = fmt.Sprintf("%s:%s", auth.UserName, auth.ClientName)
}
// Canonicalize normalizes the object after validation.
func (strategy) Canonicalize(obj runtime.Object) {
}
// Validate validates a new client
func (s strategy) Validate(ctx apirequest.Context, obj runtime.Object) field.ErrorList {
auth := obj.(*oauthapi.OAuthClientAuthorization)
validationErrors := validation.ValidateClientAuthorization(auth)
client, err := s.clientGetter.GetClient(ctx, auth.ClientName, &metav1.GetOptions{})
if err != nil {
return append(validationErrors, field.InternalError(field.NewPath("clientName"), err))
}
if err := scopeauthorizer.ValidateScopeRestrictions(client, auth.Scopes...); err != nil {
return append(validationErrors, field.InternalError(field.NewPath("clientName"), err))
}
return validationErrors
}
// ValidateUpdate validates a client auth update
func (s strategy) ValidateUpdate(ctx apirequest.Context, obj runtime.Object, old runtime.Object) field.ErrorList {
clientAuth := obj.(*oauthapi.OAuthClientAuthorization)
oldClientAuth := old.(*oauthapi.OAuthClientAuthorization)
validationErrors := validation.ValidateClientAuthorizationUpdate(clientAuth, oldClientAuth)
// only do a live client check if the scopes were increased by the update
if containsNewScopes(clientAuth.Scopes, oldClientAuth.Scopes) {
client, err := s.clientGetter.GetClient(ctx, clientAuth.ClientName, &metav1.GetOptions{})
if err != nil {
return append(validationErrors, field.InternalError(field.NewPath("clientName"), err))
}
if err := scopeauthorizer.ValidateScopeRestrictions(client, clientAuth.Scopes...); err != nil {
return append(validationErrors, field.InternalError(field.NewPath("clientName"), err))
}
}
return validationErrors
}
func containsNewScopes(obj []string, old []string) bool {
// an empty slice of scopes means all scopes, so we consider that a new scope
newHasAllScopes := len(obj) == 0
oldHasAllScopes := len(old) == 0
if newHasAllScopes && !oldHasAllScopes {
return true
}
newScopes := sets.NewString(obj...)
oldScopes := sets.NewString(old...)
return len(newScopes.Difference(oldScopes)) > 0
}
func (strategy) AllowCreateOnUpdate() bool {
return true
}
func (strategy) AllowUnconditionalUpdate() bool {
return false
}
// GetAttrs returns labels and fields of a given object for filtering purposes
func GetAttrs(o runtime.Object) (labels.Set, fields.Set, bool, error) {
obj, ok := o.(*oauthapi.OAuthClientAuthorization)
if !ok {
return nil, nil, false, fmt.Errorf("not a OAuthClientAuthorization")
}
return labels.Set(obj.Labels), SelectableFields(obj), obj.Initializers != nil, nil
}
// Matcher returns a generic matcher for a given label and field selector.
func Matcher(label labels.Selector, field fields.Selector) kstorage.SelectionPredicate {
return kstorage.SelectionPredicate{
Label: label,
Field: field,
GetAttrs: GetAttrs,
}
}
// SelectableFields returns a field set that can be used for filter selection
func SelectableFields(obj *oauthapi.OAuthClientAuthorization) fields.Set {
return oauthapi.OAuthClientAuthorizationToSelectableFields(obj)
}