added test / naming
This commit is contained in:
parent
f0149ef2d3
commit
b859560fb9
16
session.go
16
session.go
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue