github.com/nats-io/jwt/v2@v2.5.6/v1compat/types.go (about) 1 /* 2 * Copyright 2018-2019 The NATS Authors 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 package jwt 17 18 import ( 19 "encoding/json" 20 "fmt" 21 "net" 22 "strings" 23 "time" 24 ) 25 26 // ExportType defines the type of import/export. 27 type ExportType int 28 29 const ( 30 // Unknown is used if we don't know the type 31 Unknown ExportType = iota 32 // Stream defines the type field value for a stream "stream" 33 Stream 34 // Service defines the type field value for a service "service" 35 Service 36 ) 37 38 func (t ExportType) String() string { 39 switch t { 40 case Stream: 41 return "stream" 42 case Service: 43 return "service" 44 } 45 return "unknown" 46 } 47 48 // MarshalJSON marshals the enum as a quoted json string 49 func (t *ExportType) MarshalJSON() ([]byte, error) { 50 switch *t { 51 case Stream: 52 return []byte("\"stream\""), nil 53 case Service: 54 return []byte("\"service\""), nil 55 } 56 return nil, fmt.Errorf("unknown export type") 57 } 58 59 // UnmarshalJSON unmashals a quoted json string to the enum value 60 func (t *ExportType) UnmarshalJSON(b []byte) error { 61 var j string 62 err := json.Unmarshal(b, &j) 63 if err != nil { 64 return err 65 } 66 switch j { 67 case "stream": 68 *t = Stream 69 return nil 70 case "service": 71 *t = Service 72 return nil 73 } 74 return fmt.Errorf("unknown export type") 75 } 76 77 // Subject is a string that represents a NATS subject 78 type Subject string 79 80 // Validate checks that a subject string is valid, ie not empty and without spaces 81 func (s Subject) Validate(vr *ValidationResults) { 82 v := string(s) 83 if v == "" { 84 vr.AddError("subject cannot be empty") 85 } 86 if strings.Contains(v, " ") { 87 vr.AddError("subject %q cannot have spaces", v) 88 } 89 } 90 91 // HasWildCards is used to check if a subject contains a > or * 92 func (s Subject) HasWildCards() bool { 93 v := string(s) 94 return strings.HasSuffix(v, ".>") || 95 strings.Contains(v, ".*.") || 96 strings.HasSuffix(v, ".*") || 97 strings.HasPrefix(v, "*.") || 98 v == "*" || 99 v == ">" 100 } 101 102 // IsContainedIn does a simple test to see if the subject is contained in another subject 103 func (s Subject) IsContainedIn(other Subject) bool { 104 otherArray := strings.Split(string(other), ".") 105 myArray := strings.Split(string(s), ".") 106 107 if len(myArray) > len(otherArray) && otherArray[len(otherArray)-1] != ">" { 108 return false 109 } 110 111 if len(myArray) < len(otherArray) { 112 return false 113 } 114 115 for ind, tok := range otherArray { 116 myTok := myArray[ind] 117 118 if ind == len(otherArray)-1 && tok == ">" { 119 return true 120 } 121 122 if tok != myTok && tok != "*" { 123 return false 124 } 125 } 126 127 return true 128 } 129 130 // NamedSubject is the combination of a subject and a name for it 131 type NamedSubject struct { 132 Name string `json:"name,omitempty"` 133 Subject Subject `json:"subject,omitempty"` 134 } 135 136 // Validate checks the subject 137 func (ns *NamedSubject) Validate(vr *ValidationResults) { 138 ns.Subject.Validate(vr) 139 } 140 141 // TimeRange is used to represent a start and end time 142 type TimeRange struct { 143 Start string `json:"start,omitempty"` 144 End string `json:"end,omitempty"` 145 } 146 147 // Validate checks the values in a time range struct 148 func (tr *TimeRange) Validate(vr *ValidationResults) { 149 format := "15:04:05" 150 151 if tr.Start == "" { 152 vr.AddError("time ranges start must contain a start") 153 } else { 154 _, err := time.Parse(format, tr.Start) 155 if err != nil { 156 vr.AddError("start in time range is invalid %q", tr.Start) 157 } 158 } 159 160 if tr.End == "" { 161 vr.AddError("time ranges end must contain an end") 162 } else { 163 _, err := time.Parse(format, tr.End) 164 if err != nil { 165 vr.AddError("end in time range is invalid %q", tr.End) 166 } 167 } 168 } 169 170 // Limits are used to control acccess for users and importing accounts 171 // Src is a comma separated list of CIDR specifications 172 type Limits struct { 173 Max int64 `json:"max,omitempty"` 174 Payload int64 `json:"payload,omitempty"` 175 Src string `json:"src,omitempty"` 176 Times []TimeRange `json:"times,omitempty"` 177 } 178 179 // Validate checks the values in a limit struct 180 func (l *Limits) Validate(vr *ValidationResults) { 181 if l.Max < 0 { 182 vr.AddError("limits cannot contain a negative maximum, %d", l.Max) 183 } 184 if l.Payload < 0 { 185 vr.AddError("limits cannot contain a negative payload, %d", l.Payload) 186 } 187 188 if l.Src != "" { 189 elements := strings.Split(l.Src, ",") 190 191 for _, cidr := range elements { 192 cidr = strings.TrimSpace(cidr) 193 _, ipNet, err := net.ParseCIDR(cidr) 194 if err != nil || ipNet == nil { 195 vr.AddError("invalid cidr %q in user src limits", cidr) 196 } 197 } 198 } 199 200 if l.Times != nil && len(l.Times) > 0 { 201 for _, t := range l.Times { 202 t.Validate(vr) 203 } 204 } 205 } 206 207 // Permission defines allow/deny subjects 208 type Permission struct { 209 Allow StringList `json:"allow,omitempty"` 210 Deny StringList `json:"deny,omitempty"` 211 } 212 213 // Validate the allow, deny elements of a permission 214 func (p *Permission) Validate(vr *ValidationResults) { 215 for _, subj := range p.Allow { 216 Subject(subj).Validate(vr) 217 } 218 for _, subj := range p.Deny { 219 Subject(subj).Validate(vr) 220 } 221 } 222 223 // ResponsePermission can be used to allow responses to any reply subject 224 // that is received on a valid subscription. 225 type ResponsePermission struct { 226 MaxMsgs int `json:"max"` 227 Expires time.Duration `json:"ttl"` 228 } 229 230 // Validate the response permission. 231 func (p *ResponsePermission) Validate(vr *ValidationResults) { 232 // Any values can be valid for now. 233 } 234 235 // Permissions are used to restrict subject access, either on a user or for everyone on a server by default 236 type Permissions struct { 237 Pub Permission `json:"pub,omitempty"` 238 Sub Permission `json:"sub,omitempty"` 239 Resp *ResponsePermission `json:"resp,omitempty"` 240 } 241 242 // Validate the pub and sub fields in the permissions list 243 func (p *Permissions) Validate(vr *ValidationResults) { 244 p.Pub.Validate(vr) 245 p.Sub.Validate(vr) 246 if p.Resp != nil { 247 p.Resp.Validate(vr) 248 } 249 } 250 251 // StringList is a wrapper for an array of strings 252 type StringList []string 253 254 // Contains returns true if the list contains the string 255 func (u *StringList) Contains(p string) bool { 256 for _, t := range *u { 257 if t == p { 258 return true 259 } 260 } 261 return false 262 } 263 264 // Add appends 1 or more strings to a list 265 func (u *StringList) Add(p ...string) { 266 for _, v := range p { 267 if !u.Contains(v) && v != "" { 268 *u = append(*u, v) 269 } 270 } 271 } 272 273 // Remove removes 1 or more strings from a list 274 func (u *StringList) Remove(p ...string) { 275 for _, v := range p { 276 for i, t := range *u { 277 if t == v { 278 a := *u 279 *u = append(a[:i], a[i+1:]...) 280 break 281 } 282 } 283 } 284 } 285 286 // TagList is a unique array of lower case strings 287 // All tag list methods lower case the strings in the arguments 288 type TagList []string 289 290 // Contains returns true if the list contains the tags 291 func (u *TagList) Contains(p string) bool { 292 p = strings.ToLower(p) 293 for _, t := range *u { 294 if t == p { 295 return true 296 } 297 } 298 return false 299 } 300 301 // Add appends 1 or more tags to a list 302 func (u *TagList) Add(p ...string) { 303 for _, v := range p { 304 v = strings.ToLower(v) 305 if !u.Contains(v) && v != "" { 306 *u = append(*u, v) 307 } 308 } 309 } 310 311 // Remove removes 1 or more tags from a list 312 func (u *TagList) Remove(p ...string) { 313 for _, v := range p { 314 v = strings.ToLower(v) 315 for i, t := range *u { 316 if t == v { 317 a := *u 318 *u = append(a[:i], a[i+1:]...) 319 break 320 } 321 } 322 } 323 } 324 325 // Identity is used to associate an account or operator with a real entity 326 type Identity struct { 327 ID string `json:"id,omitempty"` 328 Proof string `json:"proof,omitempty"` 329 } 330 331 // Validate checks the values in an Identity 332 func (u *Identity) Validate(vr *ValidationResults) { 333 //Fixme identity validation 334 }