github.com/greenpau/go-authcrunch@v1.0.50/pkg/authz/cache/cache.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 cache
    16  
    17  import (
    18  	"github.com/greenpau/go-authcrunch/pkg/errors"
    19  	"github.com/greenpau/go-authcrunch/pkg/user"
    20  	"sync"
    21  	"time"
    22  )
    23  
    24  // TokenCache contains cached tokens
    25  type TokenCache struct {
    26  	mu      sync.RWMutex
    27  	Entries map[string]*user.User `json:"entries,omitempty" xml:"entries,omitempty" yaml:"entries,omitempty"`
    28  }
    29  
    30  // NewTokenCache returns TokenCache instance.
    31  func NewTokenCache(i int) *TokenCache {
    32  	c := &TokenCache{
    33  		Entries: make(map[string]*user.User),
    34  	}
    35  	go manageTokenCache(i, c)
    36  	return c
    37  }
    38  
    39  func manageTokenCache(i int, cache *TokenCache) {
    40  	if i == 0 {
    41  		i = 300000
    42  	}
    43  	// intervals := time.NewTicker(time.Minute * time.Duration(5))
    44  	intervals := time.NewTicker(time.Millisecond * time.Duration(i))
    45  	for range intervals.C {
    46  		// if cache == nil {
    47  		//	break
    48  		// }
    49  		cache.mu.RLock()
    50  		if cache.Entries == nil {
    51  			cache.mu.RUnlock()
    52  			continue
    53  		}
    54  		cache.mu.RUnlock()
    55  		cache.mu.Lock()
    56  		for k, usr := range cache.Entries {
    57  			if err := usr.Claims.Valid(); err != nil {
    58  				delete(cache.Entries, k)
    59  			}
    60  		}
    61  		cache.mu.Unlock()
    62  	}
    63  }
    64  
    65  // Add adds a token and the associated claim to cache.
    66  func (c *TokenCache) Add(usr *user.User) error {
    67  	if usr == nil {
    68  		return errors.ErrCacheNilUser
    69  	}
    70  	if usr.Token == "" {
    71  		return errors.ErrCacheEmptyToken
    72  	}
    73  	c.mu.Lock()
    74  	defer c.mu.Unlock()
    75  	usr.Cached = true
    76  	c.Entries[usr.Token] = usr
    77  	return nil
    78  }
    79  
    80  // Delete removes cached token from
    81  func (c *TokenCache) Delete(token string) error {
    82  	c.mu.Lock()
    83  	defer c.mu.Unlock()
    84  	delete(c.Entries, token)
    85  	return nil
    86  }
    87  
    88  // Get returns User instance if the token associated with
    89  // the claim exists in cache. If the token is expired, it
    90  // will be removed from the cache.
    91  func (c *TokenCache) Get(token string) *user.User {
    92  	c.mu.RLock()
    93  	usr, exists := c.Entries[token]
    94  	c.mu.RUnlock()
    95  	if !exists {
    96  		return nil
    97  	}
    98  	if usr.Claims.ExpiresAt < time.Now().Unix() {
    99  		c.Delete(token)
   100  		return nil
   101  	}
   102  	return usr
   103  }