fix: session storage

This commit is contained in:
Lakhan Samani
2023-04-08 13:06:15 +05:30
parent 9a284c03ca
commit 02c0ebb9c4
22 changed files with 290 additions and 137 deletions

View File

@@ -0,0 +1,14 @@
package inmemory
import (
"testing"
"github.com/authorizerdev/authorizer/server/memorystore/providers"
"github.com/stretchr/testify/assert"
)
func TestInMemoryProvider(t *testing.T) {
p, err := NewInMemoryProvider()
assert.NoError(t, err)
providers.ProviderTests(t, p)
}

View File

@@ -8,39 +8,31 @@ import (
)
// SetUserSession sets the user session for given user identifier in form recipe:user_id
func (c *provider) SetUserSession(userId, key, token string) error {
c.sessionStore.Set(userId, key, token)
func (c *provider) SetUserSession(userId, key, token string, expiration int64) error {
c.sessionStore.Set(userId, key, token, expiration)
return nil
}
// GetUserSession returns value for given session token
func (c *provider) GetUserSession(userId, sessionToken string) (string, error) {
return c.sessionStore.Get(userId, sessionToken), nil
val := c.sessionStore.Get(userId, sessionToken)
if val == "" {
return "", fmt.Errorf("Not found")
}
return val, nil
}
// DeleteAllUserSessions deletes all the user sessions from in-memory store.
func (c *provider) DeleteAllUserSessions(userId string) error {
namespaces := []string{
constants.AuthRecipeMethodBasicAuth,
constants.AuthRecipeMethodMagicLinkLogin,
constants.AuthRecipeMethodApple,
constants.AuthRecipeMethodFacebook,
constants.AuthRecipeMethodGithub,
constants.AuthRecipeMethodGoogle,
constants.AuthRecipeMethodLinkedIn,
constants.AuthRecipeMethodTwitter,
constants.AuthRecipeMethodMicrosoft,
}
for _, namespace := range namespaces {
c.sessionStore.RemoveAll(namespace + ":" + userId)
}
c.sessionStore.RemoveAll(userId)
return nil
}
// DeleteUserSession deletes the user session from the in-memory store.
func (c *provider) DeleteUserSession(userId, sessionToken string) error {
c.sessionStore.Remove(userId, sessionToken)
c.sessionStore.Remove(userId, constants.TokenTypeSessionToken+"_"+sessionToken)
c.sessionStore.Remove(userId, constants.TokenTypeAccessToken+"_"+sessionToken)
c.sessionStore.Remove(userId, constants.TokenTypeRefreshToken+"_"+sessionToken)
return nil
}

View File

@@ -1,8 +1,15 @@
package stores
import (
"fmt"
"strings"
"sync"
"time"
)
const (
// Maximum entries to keep in session storage
maxCacheSize = 1000
)
// SessionEntry is the struct for entry stored in store
@@ -13,15 +20,16 @@ type SessionEntry struct {
// SessionStore struct to store the env variables
type SessionStore struct {
mutex sync.Mutex
store map[string]map[string]*SessionEntry
mutex sync.Mutex
store map[string]*SessionEntry
itemsToEvict []string
}
// NewSessionStore create a new session store
func NewSessionStore() *SessionStore {
return &SessionStore{
mutex: sync.Mutex{},
store: make(map[string]map[string]*SessionEntry),
store: make(map[string]*SessionEntry),
}
}
@@ -29,53 +37,59 @@ func NewSessionStore() *SessionStore {
func (s *SessionStore) Get(key, subKey string) string {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.store[key][subKey].Value
currentTime := time.Now().Unix()
k := fmt.Sprintf("%s:%s", key, subKey)
if v, ok := s.store[k]; ok {
if v.ExpiresAt > currentTime {
return v.Value
}
s.itemsToEvict = append(s.itemsToEvict, k)
}
return ""
}
// Set sets the value of the key in state store
func (s *SessionStore) Set(key string, subKey, value string) {
func (s *SessionStore) Set(key string, subKey, value string, expiration int64) {
s.mutex.Lock()
defer s.mutex.Unlock()
if _, ok := s.store[key]; !ok {
s.store[key] = make(map[string]string)
k := fmt.Sprintf("%s:%s", key, subKey)
if _, ok := s.store[k]; !ok {
s.store[k] = &SessionEntry{
Value: value,
ExpiresAt: expiration,
// TODO add expire time
}
}
s.store[k] = &SessionEntry{
Value: value,
ExpiresAt: expiration,
// TODO add expire time
}
s.store[key][subKey] = value
}
// RemoveAll all values for given key
func (s *SessionStore) RemoveAll(key string) {
s.mutex.Lock()
defer s.mutex.Unlock()
delete(s.store, key)
for k := range s.store {
if strings.Contains(k, key) {
delete(s.store, k)
}
}
}
// Remove value for given key and subkey
func (s *SessionStore) Remove(key, subKey string) {
s.mutex.Lock()
defer s.mutex.Unlock()
if _, ok := s.store[key]; ok {
delete(s.store[key], subKey)
}
}
// Get all the values for given key
func (s *SessionStore) GetAll(key string) map[string]string {
s.mutex.Lock()
defer s.mutex.Unlock()
if _, ok := s.store[key]; !ok {
s.store[key] = make(map[string]string)
}
return s.store[key]
k := fmt.Sprintf("%s:%s", key, subKey)
delete(s.store, k)
}
// RemoveByNamespace to delete session for a given namespace example google,github
func (s *SessionStore) RemoveByNamespace(namespace string) error {
s.mutex.Lock()
defer s.mutex.Unlock()
for key := range s.store {
if strings.Contains(key, namespace+":") {
delete(s.store, key)