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