added test / naming

This commit is contained in:
Lars Hoogestraat 2021-05-24 18:26:10 +02:00
parent f0149ef2d3
commit b859560fb9
5 changed files with 100 additions and 38 deletions

View File

@ -1,6 +1,8 @@
// Copyright 2018 Lars Hoogestraat
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// Package session
package session
import (
@ -8,7 +10,7 @@ import (
"time"
)
//Session contains the session
// Session contains the session
type Session struct {
sid string
lastTouched time.Time
@ -17,32 +19,32 @@ type Session struct {
mutex sync.RWMutex
}
//GetLastTouchTime recveives the date when the session was touched
// GetLastTouchTime receives the date when the session was touched last time
func (s *Session) GetLastTouchTime() time.Time {
return s.lastTouched
}
//SessionID gets the sessionID
// SessionID gets the sessionID
func (s *Session) SessionID() string {
return s.sid
}
//SetValue sets a value into the session
// SetValue sets a value into the session
func (s *Session) SetValue(key string, value interface{}) {
s.mutex.Lock()
defer s.mutex.Unlock()
s.values[key] = value
}
//GetValue receives a value from the session
// GetValue receives a value from the session
func (s *Session) GetValue(key string) interface{} {
s.mutex.RLock()
defer s.mutex.RUnlock()
return s.values[key]
}
//RemoveValue removes a previously set value from the session
func (s *Session) RemoveValue(key string) {
// RemoveKey removes a key from the session
func (s *Session) RemoveKey(key string) {
s.mutex.Lock()
defer s.mutex.Unlock()
delete(s.values, key)

View File

@ -10,29 +10,29 @@ import (
"time"
)
//SessionProvider an interface for storing and accessing sessions
type SessionProvider interface {
// Provider an interface for storing and accessing sessions
type Provider interface {
Create(sid string) *Session
Get(sid string) (*Session, error)
FindSessionsByValue(key string, value interface{}) []Session
FindByValue(key string, value interface{}) []*Session
Remove(sid string)
Clean(ticker *time.Ticker, timeoutAfter time.Duration)
}
//InMemoryProvider implements a in memory storage for sessions
// InMemoryProvider implements a in memory storage for sessions
type InMemoryProvider struct {
sessions map[string]*Session
mutex sync.RWMutex
}
//NewInMemoryProvider creates a new in memory provider
// NewInMemoryProvider creates a new in memory provider
func NewInMemoryProvider() *InMemoryProvider {
return &InMemoryProvider{
sessions: make(map[string]*Session),
}
}
//Create stores a session in the map
// Create stores a session in the map
func (imp *InMemoryProvider) Create(sid string) *Session {
imp.mutex.Lock()
@ -47,7 +47,7 @@ func (imp *InMemoryProvider) Create(sid string) *Session {
return imp.sessions[sid]
}
//Get receives the session from the map by the session identifier
// Get receives the session from the map by the session identifier
func (imp *InMemoryProvider) Get(sid string) (*Session, error) {
imp.mutex.RLock()
defer imp.mutex.RUnlock()
@ -59,24 +59,24 @@ func (imp *InMemoryProvider) Get(sid string) (*Session, error) {
return nil, fmt.Errorf("no session with id %s found", sid)
}
//FindSessionsByValues finds all sessions from the map found by the key and value
func (imp *InMemoryProvider) FindSessionsByValue(key string, value interface{}) []Session {
// FindByValue finds all sessions from the map found by the key and value
func (imp *InMemoryProvider) FindByValue(key string, value interface{}) []*Session {
imp.mutex.RLock()
defer imp.mutex.RUnlock()
var sessions []Session
var sessions []*Session
for _, s := range imp.sessions {
if s.values[key] == value {
sessions = append(sessions, *s)
sessions = append(sessions, s)
}
}
return sessions
}
//Remove removes a session by the session identifier from the map
// Remove removes a session by the session identifier from the map
func (imp *InMemoryProvider) Remove(sid string) {
imp.mutex.Lock()
defer imp.mutex.Unlock()
@ -84,7 +84,7 @@ func (imp *InMemoryProvider) Remove(sid string) {
delete(imp.sessions, sid)
}
//Clean clean sessions after the specified timeout
// Clean clean sessions after the specified timeout
func (imp *InMemoryProvider) Clean(ticker *time.Ticker, timeoutAfter time.Duration) {
go func() {
for range ticker.C {

60
session_provider_test.go Normal file
View File

@ -0,0 +1,60 @@
// Copyright 2018 Lars Hoogestraat
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package session_test
import (
"git.hoogi.eu/snafu/session"
"testing"
)
func TestInMemoryStore(t *testing.T) {
prov := session.NewInMemoryProvider()
s1 := prov.Create("1234567890")
s1.SetValue("userid", 8)
s2 := prov.Create("1234567891")
s2.SetValue("userid", 8)
s3 := prov.Create("1234567892")
s3.SetValue("userid", 8)
s4 := prov.Create("1234567893")
s4.SetValue("userid", 7)
sessions := prov.FindByValue("userid", 8)
if len(sessions) != 3 {
t.Errorf("invalid length of sessions expected '3' bot got '%d'", len(sessions))
}
prov.Remove("1234567892")
sessions = prov.FindByValue("userid", 8)
if len(sessions) != 2 {
t.Errorf("invalid length of sessions expected '2' bot got '%d'", len(sessions))
}
sess, err := prov.Get("1234567893")
if err != nil {
t.Error(err)
}
if sess.SessionID() != "1234567893" {
t.Errorf("invalid session id returned expected '1234567893' bot got '%s'", sess.SessionID())
}
if uid := sess.GetValue("userid"); uid != 7 {
t.Errorf("invalid user id returned expected '7' bot got '%d'", uid)
}
sess.RemoveKey("userid")
if uid := sess.GetValue("userid"); uid != nil {
t.Errorf("user id should be removed but got '%d'", uid)
}
}

View File

@ -12,19 +12,19 @@ import (
"time"
)
//SessionService contains settings for the session
type SessionService struct {
// Service contains settings for the session
type Service struct {
Path string
HTTPOnly bool
Name string
Secure bool
IdleSessionTTL int64
SessionProvider SessionProvider
SessionProvider Provider
}
//Create creates the session for the request
func (sc SessionService) Create(rw http.ResponseWriter, r *http.Request) *Session {
// Create creates the session for the request
func (sc Service) Create(rw http.ResponseWriter, r *http.Request) *Session {
sid := base64.StdEncoding.EncodeToString(randomSecureKey(64))
s := sc.SessionProvider.Create(sid)
@ -42,8 +42,8 @@ func (sc SessionService) Create(rw http.ResponseWriter, r *http.Request) *Sessio
return s
}
//Get receives the session from the cookie
func (sc SessionService) Get(rw http.ResponseWriter, r *http.Request) (*Session, error) {
// Get receives the session from the cookie
func (sc Service) Get(rw http.ResponseWriter, r *http.Request) (*Session, error) {
cookie, err := r.Cookie(sc.Name)
if err != nil {
@ -69,8 +69,8 @@ func (sc SessionService) Get(rw http.ResponseWriter, r *http.Request) (*Session,
return sess, nil
}
//Renew renews the session
func (sc SessionService) Renew(rw http.ResponseWriter, r *http.Request) (*Session, error) {
// Renew renews the session
func (sc Service) Renew(rw http.ResponseWriter, r *http.Request) (*Session, error) {
cookie, err := r.Cookie(sc.Name)
if err != nil {
@ -111,8 +111,8 @@ func (sc SessionService) Renew(rw http.ResponseWriter, r *http.Request) (*Sessio
return s, nil
}
//Remove removes the session from the session map and the cookie
func (sc SessionService) Remove(rw http.ResponseWriter, r *http.Request) error {
// Remove removes the session from the session map and the cookie
func (sc Service) Remove(rw http.ResponseWriter, r *http.Request) error {
cookie, err := r.Cookie(sc.Name)
if err != nil {
@ -133,8 +133,8 @@ func (sc SessionService) Remove(rw http.ResponseWriter, r *http.Request) error {
return nil
}
//InitGC initialized the garbage collection for removing the session after the TTL has reached
func (sc SessionService) InitGC(ticker *time.Ticker, timeoutAfter time.Duration) {
// InitGC initializes the garbage collection for removing the session after the TTL has reached
func (sc Service) InitGC(ticker *time.Ticker, timeoutAfter time.Duration) {
sc.SessionProvider.Clean(ticker, timeoutAfter)
}

View File

@ -13,8 +13,8 @@ import (
"git.hoogi.eu/snafu/session"
)
func sampleSessionService() session.SessionService {
sessionService := session.SessionService{
func sampleSessionService() session.Service {
sessionService := session.Service{
Secure: true,
Path: "/test",
HTTPOnly: true,
@ -102,7 +102,7 @@ func TestSessionGarbageCollection(t *testing.T) {
}
}
func createSession(t *testing.T, sc session.SessionService) (*session.Session, *http.Cookie) {
func createSession(t *testing.T, sc session.Service) (*session.Session, *http.Cookie) {
req, err := http.NewRequest("GET", "/", nil)
if err != nil {
t.Fatal(err)
@ -117,7 +117,7 @@ func createSession(t *testing.T, sc session.SessionService) (*session.Session, *
return createdSession, cookies[0]
}
func getSession(t *testing.T, rawCookieValue string, sc session.SessionService) (*session.Session, error) {
func getSession(t *testing.T, rawCookieValue string, sc session.Service) (*session.Session, error) {
req, err := http.NewRequest("GET", "/", nil)
if err != nil {
t.Fatal(err)
@ -128,7 +128,7 @@ func getSession(t *testing.T, rawCookieValue string, sc session.SessionService)
return getSession, err
}
func removeSession(t *testing.T, rawCookieValue string, cs session.SessionService) {
func removeSession(t *testing.T, rawCookieValue string, cs session.Service) {
req, err := http.NewRequest("GET", "/", nil)
if err != nil {
t.Fatal(err)