/
attribute.go
213 lines (166 loc) · 6.35 KB
/
attribute.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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// Copyright 2019 Aporeto Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package elemental
import "reflect"
// An AttributeSpecifiable is the interface an object must implement in order to access specification of its attributes.
type AttributeSpecifiable interface {
SpecificationForAttribute(string) AttributeSpecification
AttributeSpecifications() map[string]AttributeSpecification
ValueForAttribute(name string) interface{}
}
// An AttributeSpecification represents all the metadata of an attribute.
//
// This information is coming from the Monolithe Specifications.
type AttributeSpecification struct {
// AllowedChars is a regexp that will be used to validate
// what value a string attribute can take.
//
// This is enforced by elemental.
AllowedChars string
// AllowedChoices is a list of possible values for an attribute.
//
// This is enforced by elemental.
AllowedChoices []string
// Autogenerated defines if the attribute is autogenerated by the server.
// It can be used in conjunction with ReadOnly.
//
// This is not enforced by elemental. You must write your own business logic to honor this.
Autogenerated bool
// Availability is reserved for later use.
Availability string
// ConvertedName contains the name after local conversion.
ConvertedName string
// Channel is reserved for later use.
Channel string
// CreationOnly defines if the attribute can be set only during creation.
//
// This is not enforced by elemental. You must write your own business logic to honor this.
CreationOnly bool
// DefaultOrder defines if the attribute is used as the default ordering key.
//
// This is not enforced by elemental. You must write your own business logic to honor this.
DefaultOrder bool
// DefaultValue holds the default value declared in specification.
DefaultValue interface{}
// Deprecated defines if the attribute is deprecated.
Deprecated bool
// Description contains the description of the attribute.
Description string
// Exposed defines if the attribute is exposed through the north bound API.
Exposed bool
// Filterable defines if it is possible to filter based on this attribute.
//
// This is not enforced by elemental. You must write your own business logic to honor this.
Filterable bool
// ForeignKey defines if the attribute is a foreign key.
ForeignKey bool
// Getter defines if the attribute needs to define a getter method.
// This is useful if you can to define an Interface based on this attribute.
Getter bool
// Identifier defines if the attribute is used the access key from the
// northbound API.
Identifier bool
// Index defines if the attribute is indexed or not.
//
// This is not enforced by elemental. You must write your own business logic to honor this.
Index bool
// MaxLength defines what is the maximun length of the attribute.
// This only makes sense if the type is a string.
//
// This is enforced by elemental.
MaxLength uint
// MaxValue defines what is the maximun value of the attribute.
// This only makes sense if the type has a numeric type.
//
// This is enforced by elemental.
MaxValue float64
// MinLength defines what is the minimum length of the attribute.
// This only makes sense if the type is a string.
//
// This is enforced by elemental.
MinLength uint
// MinValue defines what is the minimum value of the attribute.
// This only makes sense if the type has a numeric type.
//
// This is enforced by elemental.
MinValue float64
// Name defines what is the name of the attribute.
// This will be the raw Monolithe Specification name, without
// Go translation.
Name string
// Orderable defines if it is possible to order based on the value of this attribute.
//
// This is not enforced by elemental. You must write your own business logic to honor this.
Orderable bool
// PrimaryKey defines if the attribute is used as a primary key.
PrimaryKey bool
// ReadOnly defines if the attribute is read only.
//
// This is not enforced by elemental. You must write your own business logic to honor this.
ReadOnly bool
// Required defines is the attribute must be set or not.
//
// This is enforced by elemental.
Required bool
// Secret defines if the attribute is secret.
// This is useful if you can to define perform sanity check on this field to be sure it
// is not sent for instance.
Secret bool
// Setter defines if the attribute needs to define a setter method.
// This is useful if you can to define an Interface based on this attribute.
Setter bool
// Stored defines if the attribute will be stored in the northbound API.
//
// If this is true, the backend tags will be generated by Monolithe.
Stored bool
// SubType defines the Monolithe Subtype.
SubType string
// Transient defines if the attributes is transient or not.
//
// This is not enforced by elemental. You must write your own business logic to honor this.
Transient bool
// Type defines the raw Monolithe type.
Type string
}
// ResetSecretAttributesValues will reset any attributes marked
// as `secret` in the given obj if it is an elemental.Identifiable
// or an elemental.Identifiables.
// The given Identifiables must implement the elemental.AttributeSpecifiable
// interface or this function will have no effect.
//
// If you pass anything else, this function does nothing.
func ResetSecretAttributesValues(obj interface{}) {
strip := func(o Identifiable) {
oo := o
if sp, ok := o.(SparseIdentifiable); ok {
oo = sp.ToPlain()
}
if attrspec, ok := oo.(AttributeSpecifiable); ok {
var rv, val reflect.Value
for _, aspec := range attrspec.AttributeSpecifications() {
if !aspec.Secret {
continue
}
rv = reflect.Indirect(reflect.ValueOf(o))
val = rv.FieldByName(aspec.ConvertedName)
val.Set(reflect.Zero(val.Type()))
}
}
}
switch o := obj.(type) {
case Identifiable:
strip(o)
case Identifiables:
for _, i := range o.List() {
strip(i)
}
}
}