diff --git a/conv/go.mod b/conv/go.mod new file mode 100644 index 0000000..cab6c20 --- /dev/null +++ b/conv/go.mod @@ -0,0 +1,5 @@ +module github.com/vividvilla/simplesessions/conv + +go 1.14 + +require github.com/stretchr/testify v1.9.0 diff --git a/go.mod b/go.mod index a58de16..3aa6170 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/vividvilla/simplesessions +module github.com/vividvilla/simplesessions/v2 require github.com/stretchr/testify v1.9.0 diff --git a/session.go b/session.go index 0ea0b50..d9aa116 100644 --- a/session.go +++ b/session.go @@ -1,11 +1,9 @@ package simplesessions import ( - "crypto/rand" "errors" "net/http" "time" - "unicode" ) // Session is utility for get, set or clear session. @@ -34,20 +32,25 @@ type Session struct { var ( // ErrInvalidSession is raised when session is tried to access before setting it or its not set in store. // Handle this and create new session. + // Store code = 1 ErrInvalidSession = errors.New("simplesession: invalid session") + // ErrFieldNotFound is raised when given key is not found in store + // Store code = 2 ErrFieldNotFound = errors.New("simplesession: session field not found in store") + // ErrAssertType is raised when type assertion fails + // Store code = 3 ErrAssertType = errors.New("simplesession: invalid type assertion") + // ErrNil is raised when returned value is nil. + // Store code = 4 ErrNil = errors.New("simplesession: nil returned") - // Dictionary for generating random string - dictionary = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" ) -// NewSession creates a new session. Reads cookie info from `GetCookie`` callback +// NewSession creates a new session. Reads cookie info from `GetCookie“ callback // and validate the session with current store. If cookie not set then it creates -// new session and calls `SetCookie`` callback. If `DisableAutoSet` is set then it +// new session and calls `SetCookie“ callback. If `DisableAutoSet` is set then it // skips new session creation and should be manually done using `Create` method. // If a cookie is found but its invalid in store then `ErrInvalidSession` error is returned. func NewSession(m *Manager, r, w interface{}) (*Session, error) { @@ -73,7 +76,7 @@ func NewSession(m *Manager, r, w interface{}) (*Session, error) { // Create new cookie in store and write to front // Store also calls `WriteCookie`` to write to http interface - cv, err := m.store.Create(sess) + cv, err := m.store.Create() if err != nil { return nil, err } @@ -89,49 +92,12 @@ func NewSession(m *Manager, r, w interface{}) (*Session, error) { return nil, err } - if isValid, err := m.store.IsValid(sess, sess.cookie.Value); err != nil { - return nil, err - } else if !isValid { - return nil, ErrInvalidSession - } - // Set isSet flag sess.isSet = true return sess, nil } -// GenerateRandomString is a utility method which can be used by store to -// generate cryptographically random alphanumeric string of length n. -func (s *Session) GenerateRandomString(n int) (string, error) { - var bytes = make([]byte, n) - if _, err := rand.Read(bytes); err != nil { - return "", err - } - - for k, v := range bytes { - bytes[k] = dictionary[v%byte(len(dictionary))] - } - - return string(bytes), nil -} - -// IsValidRandomString validates the random string generated by `GenerateRandomString` method. -func (s *Session) IsValidRandomString(val string) bool { - return s.isAlphaNum(val) -} - -// isAlphaNum checks if the provided string is Alphanumeric -func (s *Session) isAlphaNum(val string) bool { - for _, r := range val { - if !unicode.IsDigit(r) && !unicode.IsLetter(r) { - return false - } - } - - return true -} - // WriteCookie updates the cookie and calls `SetCookie` callback. // This method can also be used by store to update cookie whenever the cookie value changes. func (s *Session) WriteCookie(cv string) error { @@ -171,7 +137,7 @@ func (s *Session) clearCookie() error { // else session has to be manually created before setting or getting values. func (s *Session) Create() error { // Create new cookie in store and write to front. - cv, err := s.manager.store.Create(s) + cv, err := s.manager.store.Create() if err != nil { return err } @@ -221,7 +187,7 @@ func (s *Session) GetAll() (map[string]interface{}, error) { return s.values, nil } - return s.manager.store.GetAll(s, s.cookie.Value) + return s.manager.store.GetAll(s.cookie.Value) } // GetMulti gets a map of values for multiple session keys. @@ -243,7 +209,7 @@ func (s *Session) GetMulti(keys ...string) (map[string]interface{}, error) { return vals, nil } - return s.manager.store.GetMulti(s, s.cookie.Value, keys...) + return s.manager.store.GetMulti(s.cookie.Value, keys...) } // Get gets a value for given key in session. @@ -263,7 +229,7 @@ func (s *Session) Get(key string) (interface{}, error) { } // Get from backend if not found in previous step - return s.manager.store.Get(s, s.cookie.Value, key) + return s.manager.store.Get(s.cookie.Value, key) } // Set sets a value for given key in session. Its up to store to commit @@ -274,7 +240,7 @@ func (s *Session) Set(key string, val interface{}) error { return ErrInvalidSession } - return s.manager.store.Set(s, s.cookie.Value, key, val) + return s.manager.store.Set(s.cookie.Value, key, val) } // Commit commits all set to store. Its up to store to commit @@ -285,7 +251,7 @@ func (s *Session) Commit() error { return ErrInvalidSession } - return s.manager.store.Commit(s, s.cookie.Value) + return s.manager.store.Commit(s.cookie.Value) } // Delete deletes a field from session. @@ -295,7 +261,7 @@ func (s *Session) Delete(key string) error { return ErrInvalidSession } - return s.manager.store.Delete(s, s.cookie.Value, key) + return s.manager.store.Delete(s.cookie.Value, key) } // Clear clears session data from store and clears the cookie @@ -305,7 +271,7 @@ func (s *Session) Clear() error { return ErrInvalidSession } - if err := s.manager.store.Clear(s, s.cookie.Value); err != nil { + if err := s.manager.store.Clear(s.cookie.Value); err != nil { return err } diff --git a/session_test.go b/session_test.go index 903604f..d85d45e 100644 --- a/session_test.go +++ b/session_test.go @@ -2,7 +2,6 @@ package simplesessions import ( "errors" - "math/rand" "net/http" "testing" "time" @@ -83,43 +82,6 @@ func TestSessionHelpers(t *testing.T) { assert.Error(err, "test error") } -func TestSessionGenerateRandomString(t *testing.T) { - assert := assert.New(t) - sess := Session{} - - // Create random length string - rand.Seed(time.Now().Unix()) - strLen := rand.Intn(1000-1) + 1 - randStr, err := sess.GenerateRandomString(strLen) - assert.NoError(err) - assert.Equal(strLen, len(randStr)) - - // Check if it doesn't generate same id - randStr1, err := sess.GenerateRandomString(100) - assert.NoError(err) - randStr2, err := sess.GenerateRandomString(100) - assert.NoError(err) - assert.NotEqual(randStr1, randStr2) -} - -func TestSessionisAlphaNum(t *testing.T) { - assert := assert.New(t) - sess := Session{} - - assert.Equal(sess.isAlphaNum("thisisvalidstring"), true) - assert.Equal(sess.isAlphaNum("thisisNot$ a .validstring"), false) -} - -func TestSessionIsValidRandomString(t *testing.T) { - assert := assert.New(t) - sess := Session{} - - randStr, err := sess.GenerateRandomString(100) - assert.NoError(err) - assert.Equal(sess.IsValidRandomString(randStr), true) - assert.Equal(sess.IsValidRandomString(dictionary), true) -} - func TestSessionNewSession(t *testing.T) { reader := "some reader" writer := "some writer" @@ -140,16 +102,6 @@ func TestSessionNewSession(t *testing.T) { assert.True(sess.isSet) } -func TestSessionNewSessionInvalidSession(t *testing.T) { - assert := assert.New(t) - mockStore := newMockStore() - mockManager := newMockManager(mockStore) - - sess, err := NewSession(mockManager, nil, nil) - assert.Error(err, ErrInvalidSession.Error()) - assert.Nil(sess) -} - func TestSessionNewSessionErrorStoreCreate(t *testing.T) { assert := assert.New(t) mockStore := newMockStore() @@ -190,19 +142,6 @@ func TestSessionNewSessionErrorWriteCookie(t *testing.T) { assert.Nil(sess) } -func TestSessionNewSessionErrorStoreIsValid(t *testing.T) { - assert := assert.New(t) - mockStore := newMockStore() - mockManager := newMockManager(mockStore) - - testError := errors.New("this is test error") - mockStore.err = testError - - sess, err := NewSession(mockManager, nil, nil) - assert.Error(err, testError.Error()) - assert.Nil(sess) -} - func TestSessionNewSessionInvalidGetCookie(t *testing.T) { assert := assert.New(t) mockStore := newMockStore() diff --git a/store.go b/store.go index 6d15c3a..5f22791 100644 --- a/store.go +++ b/store.go @@ -3,33 +3,30 @@ package simplesessions // Store represents store interface. This interface can be // implemented to create various backend stores for session. type Store interface { - // IsExist checks if session is set in store. - IsValid(session *Session, cookieValue string) (isExist bool, err error) - // Create creates new session in store and returns the cookie value. - Create(session *Session) (cookieValue string, err error) + Create() (cookieValue string, err error) // Get gets a value for given key from session. - Get(session *Session, cookieValue, key string) (value interface{}, err error) + Get(cookieValue, key string) (value interface{}, err error) // GetMulti gets a maps of multiple values for given keys. - GetMulti(session *Session, cookieValue string, keys ...string) (values map[string]interface{}, err error) + GetMulti(cookieValue string, keys ...string) (values map[string]interface{}, err error) // GetAll gets all key and value from session, - GetAll(session *Session, cookieValue string) (values map[string]interface{}, err error) + GetAll(cookieValue string) (values map[string]interface{}, err error) // Set sets an value for a field in session. // Its up to store to either store it in session right after set or after commit. - Set(session *Session, cookieValue, key string, value interface{}) error + Set(cookieValue, key string, value interface{}) error // Commit commits all the previously set values to store. - Commit(session *Session, cookieValue string) error + Commit(cookieValue string) error // Delete a field from session. - Delete(session *Session, cookieValue string, key string) error + Delete(cookieValue string, key string) error // Clear clears the session key from backend if exists. - Clear(session *Session, cookieValue string) error + Clear(cookieValue string) error // Helper method for typecasting/asserting. Int(interface{}, error) (int, error) diff --git a/store_test.go b/store_test.go index e58cfa7..4eba6fe 100644 --- a/store_test.go +++ b/store_test.go @@ -17,46 +17,42 @@ func (s *MockStore) reset() { s.isCommited = false } -func (s *MockStore) IsValid(ss *Session, cv string) (isExist bool, err error) { - return s.isValid, s.err -} - -func (s *MockStore) Create(ss *Session) (cv string, err error) { +func (s *MockStore) Create() (cv string, err error) { return s.val.(string), s.err } -func (s *MockStore) Get(ss *Session, cv, key string) (value interface{}, err error) { +func (s *MockStore) Get(cv, key string) (value interface{}, err error) { return s.val, s.err } -func (s *MockStore) GetMulti(ss *Session, cv string, keys ...string) (values map[string]interface{}, err error) { +func (s *MockStore) GetMulti(cv string, keys ...string) (values map[string]interface{}, err error) { vals := make(map[string]interface{}) vals["val"] = s.val return vals, s.err } -func (s *MockStore) GetAll(ss *Session, cv string) (values map[string]interface{}, err error) { +func (s *MockStore) GetAll(cv string) (values map[string]interface{}, err error) { vals := make(map[string]interface{}) vals["val"] = s.val return vals, s.err } -func (s *MockStore) Set(ss *Session, cv, key string, value interface{}) error { +func (s *MockStore) Set(cv, key string, value interface{}) error { s.val = value return s.err } -func (s *MockStore) Commit(ss *Session, cv string) error { +func (s *MockStore) Commit(cv string) error { s.isCommited = true return s.err } -func (s *MockStore) Delete(ss *Session, cv string, key string) error { +func (s *MockStore) Delete(cv string, key string) error { s.val = nil return s.err } -func (s *MockStore) Clear(ss *Session, cv string) error { +func (s *MockStore) Clear(cv string) error { s.val = nil return s.err }