From efba38cf2bdf3228005892a52bb4f11407c25d7c Mon Sep 17 00:00:00 2001 From: Darko Luketic <2694548+dalu@users.noreply.github.com> Date: Fri, 27 Apr 2018 18:14:36 +0200 Subject: [PATCH] move to stores --- {sscookie => cookiestore}/LICENSE | 0 {sscookie => cookiestore}/cookie.go | 7 +- {ssredis => redisstore}/LICENSE | 0 {ssredis => redisstore}/redis.go | 11 +- sscookie/sessions.go => sessions.go | 0 sscookie/sessions_test.go => sessions_test.go | 0 sscookie/cookie_test.go | 30 --- ssredis/redis_test.go | 35 --- ssredis/sessions.go | 154 ------------ ssredis/sessions_test.go | 220 ------------------ 10 files changed, 11 insertions(+), 446 deletions(-) rename {sscookie => cookiestore}/LICENSE (100%) rename {sscookie => cookiestore}/cookie.go (88%) rename {ssredis => redisstore}/LICENSE (100%) rename {ssredis => redisstore}/redis.go (90%) rename sscookie/sessions.go => sessions.go (100%) rename sscookie/sessions_test.go => sessions_test.go (100%) delete mode 100644 sscookie/cookie_test.go delete mode 100644 ssredis/redis_test.go delete mode 100644 ssredis/sessions.go delete mode 100644 ssredis/sessions_test.go diff --git a/sscookie/LICENSE b/cookiestore/LICENSE similarity index 100% rename from sscookie/LICENSE rename to cookiestore/LICENSE diff --git a/sscookie/cookie.go b/cookiestore/cookie.go similarity index 88% rename from sscookie/cookie.go rename to cookiestore/cookie.go index 99415ef..814deee 100644 --- a/sscookie/cookie.go +++ b/cookiestore/cookie.go @@ -1,12 +1,13 @@ -package sessions +package cookiestore import ( + ginsessions "github.com/dalu/sessions" "github.com/gorilla/sessions" ) // CookieStore interface type CookieStore interface { - Store + ginsessions.Store } // NewCookieStore creates a new cookieStore. @@ -27,7 +28,7 @@ type cookieStore struct { *sessions.CookieStore } -func (c *cookieStore) Options(options Options) { +func (c *cookieStore) Options(options ginsessions.Options) { c.CookieStore.Options = &sessions.Options{ Path: options.Path, Domain: options.Domain, diff --git a/ssredis/LICENSE b/redisstore/LICENSE similarity index 100% rename from ssredis/LICENSE rename to redisstore/LICENSE diff --git a/ssredis/redis.go b/redisstore/redis.go similarity index 90% rename from ssredis/redis.go rename to redisstore/redis.go index 7afcb0a..a78e135 100644 --- a/ssredis/redis.go +++ b/redisstore/redis.go @@ -1,15 +1,18 @@ -package sessions +package redisstore import ( "github.com/boj/redistore" + ginsessions "github.com/dalu/sessions" "github.com/garyburd/redigo/redis" "github.com/gorilla/sessions" ) +// RedisStore interface type RedisStore interface { - Store + ginsessions.Store } +// NewRedisStore creates a new Redis Store // size: maximum number of idle connections. // network: tcp or udp // address: host:port @@ -58,12 +61,12 @@ type redisStore struct { *redistore.RediStore } -func (c *redisStore) Options(options Options) { +func (c *redisStore) Options(options ginsessions.Options) { c.RediStore.Options = &sessions.Options{ Path: options.Path, Domain: options.Domain, MaxAge: options.MaxAge, Secure: options.Secure, - HttpOnly: options.HttpOnly, + HttpOnly: options.HTTPOnly, } } diff --git a/sscookie/sessions.go b/sessions.go similarity index 100% rename from sscookie/sessions.go rename to sessions.go diff --git a/sscookie/sessions_test.go b/sessions_test.go similarity index 100% rename from sscookie/sessions_test.go rename to sessions_test.go diff --git a/sscookie/cookie_test.go b/sscookie/cookie_test.go deleted file mode 100644 index 9f79cc5..0000000 --- a/sscookie/cookie_test.go +++ /dev/null @@ -1,30 +0,0 @@ -package sessions - -import ( - "testing" -) - -var newCookieStore = func(_ *testing.T) Store { - store := NewCookieStore([]byte("secret")) - return store -} - -func TestCookie_SessionGetSet(t *testing.T) { - sessionGetSet(t, newCookieStore) -} - -func TestCookie_SessionDeleteKey(t *testing.T) { - sessionDeleteKey(t, newCookieStore) -} - -func TestCookie_SessionFlashes(t *testing.T) { - sessionFlashes(t, newCookieStore) -} - -func TestCookie_SessionClear(t *testing.T) { - sessionClear(t, newCookieStore) -} - -func TestCookie_SessionOptions(t *testing.T) { - sessionOptions(t, newCookieStore) -} diff --git a/ssredis/redis_test.go b/ssredis/redis_test.go deleted file mode 100644 index 301e16c..0000000 --- a/ssredis/redis_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package sessions - -import ( - "testing" -) - -const redisTestServer = "localhost:6379" - -var newRedisStore = func(_ *testing.T) Store { - store, err := NewRedisStore(10, "tcp", redisTestServer, "", []byte("secret")) - if err != nil { - panic(err) - } - return store -} - -func TestRedis_SessionGetSet(t *testing.T) { - sessionGetSet(t, newRedisStore) -} - -func TestRedis_SessionDeleteKey(t *testing.T) { - sessionDeleteKey(t, newRedisStore) -} - -func TestRedis_SessionFlashes(t *testing.T) { - sessionFlashes(t, newRedisStore) -} - -func TestRedis_SessionClear(t *testing.T) { - sessionClear(t, newRedisStore) -} - -func TestRedis_SessionOptions(t *testing.T) { - sessionOptions(t, newRedisStore) -} diff --git a/ssredis/sessions.go b/ssredis/sessions.go deleted file mode 100644 index 361bb41..0000000 --- a/ssredis/sessions.go +++ /dev/null @@ -1,154 +0,0 @@ -package sessions - -import ( - "log" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/gorilla/context" - "github.com/gorilla/sessions" -) - -const ( - DefaultKey = "github.com/gin-contrib/sessions" - errorFormat = "[sessions] ERROR! %s\n" -) - -type Store interface { - sessions.Store - Options(Options) -} - -// Options stores configuration for a session or session store. -// Fields are a subset of http.Cookie fields. -type Options struct { - Path string - Domain string - // MaxAge=0 means no 'Max-Age' attribute specified. - // MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'. - // MaxAge>0 means Max-Age attribute present and given in seconds. - MaxAge int - Secure bool - HttpOnly bool -} - -// Wraps thinly gorilla-session methods. -// Session stores the values and optional configuration for a session. -type Session interface { - // Get returns the session value associated to the given key. - Get(key interface{}) interface{} - // Set sets the session value associated to the given key. - Set(key interface{}, val interface{}) - // Delete removes the session value associated to the given key. - Delete(key interface{}) - // Clear deletes all values in the session. - Clear() - // AddFlash adds a flash message to the session. - // A single variadic argument is accepted, and it is optional: it defines the flash key. - // If not defined "_flash" is used by default. - AddFlash(value interface{}, vars ...string) - // Flashes returns a slice of flash messages from the session. - // A single variadic argument is accepted, and it is optional: it defines the flash key. - // If not defined "_flash" is used by default. - Flashes(vars ...string) []interface{} - // Options sets confuguration for a session. - Options(Options) - // Save saves all sessions used during the current request. - Save() error -} - -func Sessions(name string, store Store) gin.HandlerFunc { - return func(c *gin.Context) { - s := &session{ - name: name, - request: c.Request, - store: store, - session: nil, - written: false, - writer: c.Writer, - } - c.Set(DefaultKey, s) - defer context.Clear(c.Request) - c.Next() - } -} - -type session struct { - name string - request *http.Request - store Store - session *sessions.Session - written bool - writer http.ResponseWriter -} - -func (s *session) Get(key interface{}) interface{} { - return s.Session().Values[key] -} - -func (s *session) Set(key interface{}, val interface{}) { - s.Session().Values[key] = val - s.written = true -} - -func (s *session) Delete(key interface{}) { - delete(s.Session().Values, key) - s.written = true -} - -func (s *session) Clear() { - for key := range s.Session().Values { - s.Delete(key) - } -} - -func (s *session) AddFlash(value interface{}, vars ...string) { - s.Session().AddFlash(value, vars...) - s.written = true -} - -func (s *session) Flashes(vars ...string) []interface{} { - s.written = true - return s.Session().Flashes(vars...) -} - -func (s *session) Options(options Options) { - s.Session().Options = &sessions.Options{ - Path: options.Path, - Domain: options.Domain, - MaxAge: options.MaxAge, - Secure: options.Secure, - HttpOnly: options.HttpOnly, - } -} - -func (s *session) Save() error { - if s.Written() { - e := s.Session().Save(s.request, s.writer) - if e == nil { - s.written = false - } - return e - } - return nil -} - -func (s *session) Session() *sessions.Session { - if s.session == nil { - var err error - s.session, err = s.store.Get(s.request, s.name) - if err != nil { - log.Printf(errorFormat, err) - } - } - return s.session -} - -func (s *session) Written() bool { - return s.written -} - -// shortcut to get session -func Default(c *gin.Context) Session { - return c.MustGet(DefaultKey).(Session) -} diff --git a/ssredis/sessions_test.go b/ssredis/sessions_test.go deleted file mode 100644 index bb587b7..0000000 --- a/ssredis/sessions_test.go +++ /dev/null @@ -1,220 +0,0 @@ -package sessions - -import ( - "net/http" - "net/http/httptest" - "strings" - "testing" - - "github.com/gin-gonic/gin" -) - -type storeFactory func(*testing.T) Store - -const sessionName = "mysession" - -const ok = "ok" - -func sessionGetSet(t *testing.T, newStore storeFactory) { - r := gin.Default() - r.Use(Sessions(sessionName, newStore(t))) - - r.GET("/set", func(c *gin.Context) { - session := Default(c) - session.Set("key", ok) - session.Save() - c.String(200, ok) - }) - - r.GET("/get", func(c *gin.Context) { - session := Default(c) - if session.Get("key") != ok { - t.Error("Session writing failed") - } - session.Save() - c.String(200, ok) - }) - - res1 := httptest.NewRecorder() - req1, _ := http.NewRequest("GET", "/set", nil) - r.ServeHTTP(res1, req1) - - res2 := httptest.NewRecorder() - req2, _ := http.NewRequest("GET", "/get", nil) - req2.Header.Set("Cookie", res1.Header().Get("Set-Cookie")) - r.ServeHTTP(res2, req2) -} - -func sessionDeleteKey(t *testing.T, newStore storeFactory) { - r := gin.Default() - r.Use(Sessions(sessionName, newStore(t))) - - r.GET("/set", func(c *gin.Context) { - session := Default(c) - session.Set("key", ok) - session.Save() - c.String(200, ok) - }) - - r.GET("/delete", func(c *gin.Context) { - session := Default(c) - session.Delete("key") - session.Save() - c.String(200, ok) - }) - - r.GET("/get", func(c *gin.Context) { - session := Default(c) - if session.Get("key") != nil { - t.Error("Session deleting failed") - } - session.Save() - c.String(200, ok) - }) - - res1 := httptest.NewRecorder() - req1, _ := http.NewRequest("GET", "/set", nil) - r.ServeHTTP(res1, req1) - - res2 := httptest.NewRecorder() - req2, _ := http.NewRequest("GET", "/delete", nil) - req2.Header.Set("Cookie", res1.Header().Get("Set-Cookie")) - r.ServeHTTP(res2, req2) - - res3 := httptest.NewRecorder() - req3, _ := http.NewRequest("GET", "/get", nil) - req3.Header.Set("Cookie", res2.Header().Get("Set-Cookie")) - r.ServeHTTP(res3, req3) -} - -func sessionFlashes(t *testing.T, newStore storeFactory) { - r := gin.Default() - store := newStore(t) - store.Options(Options{ - Domain: "localhost", - }) - r.Use(Sessions(sessionName, store)) - - r.GET("/set", func(c *gin.Context) { - session := Default(c) - session.AddFlash(ok) - session.Save() - c.String(200, ok) - }) - - r.GET("/flash", func(c *gin.Context) { - session := Default(c) - l := len(session.Flashes()) - if l != 1 { - t.Error("Flashes count does not equal 1. Equals ", l) - } - session.Save() - c.String(200, ok) - }) - - r.GET("/check", func(c *gin.Context) { - session := Default(c) - l := len(session.Flashes()) - if l != 0 { - t.Error("flashes count is not 0 after reading. Equals ", l) - } - session.Save() - c.String(200, ok) - }) - - res1 := httptest.NewRecorder() - req1, _ := http.NewRequest("GET", "/set", nil) - r.ServeHTTP(res1, req1) - - res2 := httptest.NewRecorder() - req2, _ := http.NewRequest("GET", "/flash", nil) - req2.Header.Set("Cookie", res1.Header().Get("Set-Cookie")) - r.ServeHTTP(res2, req2) - - res3 := httptest.NewRecorder() - req3, _ := http.NewRequest("GET", "/check", nil) - req3.Header.Set("Cookie", res2.Header().Get("Set-Cookie")) - r.ServeHTTP(res3, req3) -} - -func sessionClear(t *testing.T, newStore storeFactory) { - data := map[string]string{ - "key": "val", - "foo": "bar", - } - r := gin.Default() - store := newStore(t) - r.Use(Sessions(sessionName, store)) - - r.GET("/set", func(c *gin.Context) { - session := Default(c) - for k, v := range data { - session.Set(k, v) - } - session.Clear() - session.Save() - c.String(200, ok) - }) - - r.GET("/check", func(c *gin.Context) { - session := Default(c) - for k, v := range data { - if session.Get(k) == v { - t.Fatal("Session clear failed") - } - } - session.Save() - c.String(200, ok) - }) - - res1 := httptest.NewRecorder() - req1, _ := http.NewRequest("GET", "/set", nil) - r.ServeHTTP(res1, req1) - - res2 := httptest.NewRecorder() - req2, _ := http.NewRequest("GET", "/check", nil) - req2.Header.Set("Cookie", res1.Header().Get("Set-Cookie")) - r.ServeHTTP(res2, req2) -} - -func sessionOptions(t *testing.T, newStore storeFactory) { - r := gin.Default() - store := newStore(t) - store.Options(Options{ - Domain: "localhost", - }) - r.Use(Sessions(sessionName, store)) - - r.GET("/domain", func(c *gin.Context) { - session := Default(c) - session.Set("key", ok) - session.Options(Options{ - Path: "/foo/bar/bat", - }) - session.Save() - c.String(200, ok) - }) - r.GET("/path", func(c *gin.Context) { - session := Default(c) - session.Set("key", ok) - session.Save() - c.String(200, ok) - }) - res1 := httptest.NewRecorder() - req1, _ := http.NewRequest("GET", "/domain", nil) - r.ServeHTTP(res1, req1) - - res2 := httptest.NewRecorder() - req2, _ := http.NewRequest("GET", "/path", nil) - r.ServeHTTP(res2, req2) - - s := strings.Split(res1.Header().Get("Set-Cookie"), ";") - if s[1] != " Path=/foo/bar/bat" { - t.Error("Error writing path with options:", s[1]) - } - - s = strings.Split(res2.Header().Get("Set-Cookie"), ";") - if s[1] != " Domain=localhost" { - t.Error("Error writing domain with options:", s[1]) - } -}