github.com/greenpau/go-identity@v1.1.6/api_key.go (about) 1 // Copyright 2020 Paul Greenberg greenpau@outlook.com 2 // 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 package identity 16 17 import ( 18 "github.com/greenpau/go-identity/pkg/errors" 19 "github.com/greenpau/go-identity/pkg/requests" 20 "golang.org/x/crypto/bcrypt" 21 "time" 22 ) 23 24 // APIKeyBundle is a collection of API keys. 25 type APIKeyBundle struct { 26 keys []*APIKey 27 size int 28 } 29 30 // APIKey is an API key. 31 type APIKey struct { 32 ID string `json:"id,omitempty" xml:"id,omitempty" yaml:"id,omitempty"` 33 Prefix string `json:"prefix,omitempty" xml:"prefix,omitempty" yaml:"prefix,omitempty"` 34 Usage string `json:"usage,omitempty" xml:"usage,omitempty" yaml:"usage,omitempty"` 35 Comment string `json:"comment,omitempty" xml:"comment,omitempty" yaml:"comment,omitempty"` 36 Payload string `json:"payload,omitempty" xml:"payload,omitempty" yaml:"payload,omitempty"` 37 Expired bool `json:"expired,omitempty" xml:"expired,omitempty" yaml:"expired,omitempty"` 38 ExpiredAt time.Time `json:"expired_at,omitempty" xml:"expired_at,omitempty" yaml:"expired_at,omitempty"` 39 CreatedAt time.Time `json:"created_at,omitempty" xml:"created_at,omitempty" yaml:"created_at,omitempty"` 40 Disabled bool `json:"disabled,omitempty" xml:"disabled,omitempty" yaml:"disabled,omitempty"` 41 DisabledAt time.Time `json:"disabled_at,omitempty" xml:"disabled_at,omitempty" yaml:"disabled_at,omitempty"` 42 } 43 44 // NewAPIKeyBundle returns an instance of APIKeyBundle. 45 func NewAPIKeyBundle() *APIKeyBundle { 46 return &APIKeyBundle{ 47 keys: []*APIKey{}, 48 } 49 } 50 51 // Add adds APIKey to APIKeyBundle. 52 func (b *APIKeyBundle) Add(k *APIKey) { 53 b.keys = append(b.keys, k) 54 b.size++ 55 } 56 57 // Get returns APIKey instances of the APIKeyBundle. 58 func (b *APIKeyBundle) Get() []*APIKey { 59 return b.keys 60 } 61 62 // Size returns the number of APIKey instances in APIKeyBundle. 63 func (b *APIKeyBundle) Size() int { 64 return b.size 65 } 66 67 // NewAPIKey returns an instance of APIKey. 68 func NewAPIKey(r *requests.Request) (*APIKey, error) { 69 if r.Key.Payload == "" { 70 return nil, errors.ErrAPIKeyPayloadEmpty 71 } 72 if r.Key.Usage == "" { 73 return nil, errors.ErrAPIKeyUsageEmpty 74 } 75 if r.Key.Usage != "api" { 76 return nil, errors.ErrAPIKeyUsageUnsupported.WithArgs(r.Key.Usage) 77 } 78 if r.Key.Comment == "" { 79 return nil, errors.ErrAPIKeyCommentEmpty 80 } 81 p := &APIKey{ 82 Comment: r.Key.Comment, 83 ID: GetRandomString(40), 84 Prefix: r.Key.Prefix, 85 Payload: r.Key.Payload, 86 Usage: r.Key.Usage, 87 CreatedAt: time.Now().UTC(), 88 } 89 if r.Key.Disabled { 90 p.Disabled = true 91 p.DisabledAt = time.Now().UTC() 92 } 93 return p, nil 94 } 95 96 // Disable disables APIKey instance. 97 func (p *APIKey) Disable() { 98 p.Expired = true 99 p.ExpiredAt = time.Now().UTC() 100 p.Disabled = true 101 p.DisabledAt = time.Now().UTC() 102 } 103 104 // Match returns true when the provided API matches. 105 func (p *APIKey) Match(s string) bool { 106 if err := bcrypt.CompareHashAndPassword([]byte(p.Payload), []byte(s)); err == nil { 107 return true 108 } 109 return false 110 }