From 0e9dcc950064fff5823e5bde0d99f42a8f68f2c1 Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Wed, 2 Sep 2020 18:51:56 -0400 Subject: [PATCH] When reading expired sessions - expire them (#12686) (#12690) * When reading expired sessions - expire them Update to latest macaron/session following merge of https://gitea.com/macaron/session/pulls/11 Also remove old memory provider as 11 updates the memory provider to make it unnecessary. Signed-off-by: Andrew Thornton * and macaron/session/pulls/12 Signed-off-by: Andrew Thornton Co-authored-by: zeripath --- go.mod | 2 +- go.sum | 4 +- modules/session/memory.go | 216 ------------------ modules/session/virtual.go | 3 +- vendor/gitea.com/macaron/session/file.go | 8 + vendor/gitea.com/macaron/session/memory.go | 12 +- .../gitea.com/macaron/session/mysql/mysql.go | 8 +- .../macaron/session/postgres/postgres.go | 8 +- vendor/modules.txt | 2 +- 9 files changed, 32 insertions(+), 231 deletions(-) delete mode 100644 modules/session/memory.go diff --git a/go.mod b/go.mod index 0554ef7ba904..bcb2d87ad22d 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( gitea.com/macaron/i18n v0.0.0-20190822004228-474e714e2223 gitea.com/macaron/inject v0.0.0-20190805023432-d4c86e31027a gitea.com/macaron/macaron v1.4.0 - gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d + gitea.com/macaron/session v0.0.0-20200902202411-e3a87877db6e gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7 github.com/BurntSushi/toml v0.3.1 github.com/PuerkitoBio/goquery v1.5.0 diff --git a/go.sum b/go.sum index e369bb07f347..e5f538ab5fe2 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,8 @@ gitea.com/macaron/macaron v1.4.0 h1:FY1QDGqyuUzs21K6ChkbYbRUfwL7v2aUrhNEJ0IgsAw= gitea.com/macaron/macaron v1.4.0/go.mod h1:P7hfDbQjcW22lkYkXlxdRIfWOXxH2+K4EogN4Q0UlLY= gitea.com/macaron/session v0.0.0-20190821211443-122c47c5f705 h1:mvkQGAlON1Z6Y8pqa/+FpYIskk54mazuECUfZK5oTg0= gitea.com/macaron/session v0.0.0-20190821211443-122c47c5f705/go.mod h1:1ujH0jD6Ca4iK9NL0Q2a7fG2chvXx5hVa7hBfABwpkA= -gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d h1:XLww3CvnFZkXVwauN67fniDaIpIqsE+9KVcxlZKlvLU= -gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d/go.mod h1:FanKy3WjWb5iw/iZBPk4ggoQT9FcM6bkBPvmDmsH6tY= +gitea.com/macaron/session v0.0.0-20200902202411-e3a87877db6e h1:BHoJ/xWNt6FrVsL54JennM9HPIQlnbmRvmaC5DO65pU= +gitea.com/macaron/session v0.0.0-20200902202411-e3a87877db6e/go.mod h1:FanKy3WjWb5iw/iZBPk4ggoQT9FcM6bkBPvmDmsH6tY= gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7 h1:N9QFoeNsUXLhl14mefLzGluqV7w2mGU3u+iZU+jCeWk= gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7/go.mod h1:kgsbFPPS4P+acDYDOPDa3N4IWWOuDJt5/INKRUz7aks= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= diff --git a/modules/session/memory.go b/modules/session/memory.go deleted file mode 100644 index 4f72feac9b8b..000000000000 --- a/modules/session/memory.go +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright 2013 Beego Authors -// Copyright 2014 The Macaron Authors -// Copyright 2019 The Gitea Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"): you may -// not use this file except in compliance with the License. You may obtain -// a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations -// under the License. - -package session - -import ( - "container/list" - "fmt" - "sync" - "time" - - "gitea.com/macaron/session" -) - -// MemStore represents a in-memory session store implementation. -type MemStore struct { - sid string - lock sync.RWMutex - data map[interface{}]interface{} - lastAccess time.Time -} - -// NewMemStore creates and returns a memory session store. -func NewMemStore(sid string) *MemStore { - return &MemStore{ - sid: sid, - data: make(map[interface{}]interface{}), - lastAccess: time.Now(), - } -} - -// Set sets value to given key in session. -func (s *MemStore) Set(key, val interface{}) error { - s.lock.Lock() - defer s.lock.Unlock() - - s.data[key] = val - return nil -} - -// Get gets value by given key in session. -func (s *MemStore) Get(key interface{}) interface{} { - s.lock.RLock() - defer s.lock.RUnlock() - - return s.data[key] -} - -// Delete deletes a key from session. -func (s *MemStore) Delete(key interface{}) error { - s.lock.Lock() - defer s.lock.Unlock() - - delete(s.data, key) - return nil -} - -// ID returns current session ID. -func (s *MemStore) ID() string { - return s.sid -} - -// Release releases resource and save data to provider. -func (*MemStore) Release() error { - return nil -} - -// Flush deletes all session data. -func (s *MemStore) Flush() error { - s.lock.Lock() - defer s.lock.Unlock() - - s.data = make(map[interface{}]interface{}) - return nil -} - -// MemProvider represents a in-memory session provider implementation. -type MemProvider struct { - lock sync.RWMutex - maxLifetime int64 - data map[string]*list.Element - // A priority list whose lastAccess newer gets higher priority. - list *list.List -} - -// Init initializes memory session provider. -func (p *MemProvider) Init(maxLifetime int64, _ string) error { - p.lock.Lock() - p.maxLifetime = maxLifetime - p.lock.Unlock() - return nil -} - -// update expands time of session store by given ID. -func (p *MemProvider) update(sid string) error { - p.lock.Lock() - defer p.lock.Unlock() - - if e, ok := p.data[sid]; ok { - e.Value.(*MemStore).lastAccess = time.Now() - p.list.MoveToFront(e) - return nil - } - return nil -} - -// Read returns raw session store by session ID. -func (p *MemProvider) Read(sid string) (_ session.RawStore, err error) { - p.lock.RLock() - e, ok := p.data[sid] - p.lock.RUnlock() - - if ok { - if err = p.update(sid); err != nil { - return nil, err - } - return e.Value.(*MemStore), nil - } - - // Create a new session. - p.lock.Lock() - defer p.lock.Unlock() - - s := NewMemStore(sid) - p.data[sid] = p.list.PushBack(s) - return s, nil -} - -// Exist returns true if session with given ID exists. -func (p *MemProvider) Exist(sid string) bool { - p.lock.RLock() - defer p.lock.RUnlock() - - _, ok := p.data[sid] - return ok -} - -// Destroy deletes a session by session ID. -func (p *MemProvider) Destroy(sid string) error { - p.lock.Lock() - defer p.lock.Unlock() - - e, ok := p.data[sid] - if !ok { - return nil - } - - p.list.Remove(e) - delete(p.data, sid) - return nil -} - -// Regenerate regenerates a session store from old session ID to new one. -func (p *MemProvider) Regenerate(oldsid, sid string) (session.RawStore, error) { - if p.Exist(sid) { - return nil, fmt.Errorf("new sid '%s' already exists", sid) - } - - s, err := p.Read(oldsid) - if err != nil { - return nil, err - } - - if err = p.Destroy(oldsid); err != nil { - return nil, err - } - - s.(*MemStore).sid = sid - - p.lock.Lock() - defer p.lock.Unlock() - p.data[sid] = p.list.PushBack(s) - return s, nil -} - -// Count counts and returns number of sessions. -func (p *MemProvider) Count() int { - return p.list.Len() -} - -// GC calls GC to clean expired sessions. -func (p *MemProvider) GC() { - p.lock.RLock() - for { - // No session in the list. - e := p.list.Back() - if e == nil { - break - } - - if (e.Value.(*MemStore).lastAccess.Unix() + p.maxLifetime) < time.Now().Unix() { - p.lock.RUnlock() - p.lock.Lock() - p.list.Remove(e) - delete(p.data, e.Value.(*MemStore).sid) - p.lock.Unlock() - p.lock.RLock() - } else { - break - } - } - p.lock.RUnlock() -} diff --git a/modules/session/virtual.go b/modules/session/virtual.go index 967192016740..c8e1e210cb2d 100644 --- a/modules/session/virtual.go +++ b/modules/session/virtual.go @@ -5,7 +5,6 @@ package session import ( - "container/list" "encoding/json" "fmt" "sync" @@ -37,7 +36,7 @@ func (o *VirtualSessionProvider) Init(gclifetime int64, config string) error { // This is only slightly more wrong than modules/setting/session.go:23 switch opts.Provider { case "memory": - o.provider = &MemProvider{list: list.New(), data: make(map[string]*list.Element)} + o.provider = &session.MemProvider{} case "file": o.provider = &session.FileProvider{} case "redis": diff --git a/vendor/gitea.com/macaron/session/file.go b/vendor/gitea.com/macaron/session/file.go index 3e575564ee83..ce915344fb79 100644 --- a/vendor/gitea.com/macaron/session/file.go +++ b/vendor/gitea.com/macaron/session/file.go @@ -133,7 +133,15 @@ func (p *FileProvider) Read(sid string) (_ RawStore, err error) { defer p.lock.RUnlock() var f *os.File + ok := false if com.IsFile(filename) { + modTime, err := com.FileMTime(filename) + if err != nil { + return nil, err + } + ok = (modTime + p.maxlifetime) >= time.Now().Unix() + } + if ok { f, err = os.OpenFile(filename, os.O_RDONLY, 0600) } else { f, err = os.Create(filename) diff --git a/vendor/gitea.com/macaron/session/memory.go b/vendor/gitea.com/macaron/session/memory.go index fbb5b8013f9c..0769225752e6 100644 --- a/vendor/gitea.com/macaron/session/memory.go +++ b/vendor/gitea.com/macaron/session/memory.go @@ -96,6 +96,8 @@ type MemProvider struct { // Init initializes memory session provider. func (p *MemProvider) Init(maxLifetime int64, _ string) error { p.lock.Lock() + p.list = list.New() + p.data = make(map[string]*list.Element) p.maxLifetime = maxLifetime p.lock.Unlock() return nil @@ -120,7 +122,8 @@ func (p *MemProvider) Read(sid string) (_ RawStore, err error) { e, ok := p.data[sid] p.lock.RUnlock() - if ok { + // Only restore if the session is still alive. + if ok && (e.Value.(*MemStore).lastAccess.Unix()+p.maxLifetime) >= time.Now().Unix() { if err = p.update(sid); err != nil { return nil, err } @@ -130,7 +133,10 @@ func (p *MemProvider) Read(sid string) (_ RawStore, err error) { // Create a new session. p.lock.Lock() defer p.lock.Unlock() - + if ok { + p.list.Remove(e) + delete(p.data, sid) + } s := NewMemStore(sid) p.data[sid] = p.list.PushBack(s) return s, nil @@ -213,5 +219,5 @@ func (p *MemProvider) GC() { } func init() { - Register("memory", &MemProvider{list: list.New(), data: make(map[string]*list.Element)}) + Register("memory", &MemProvider{}) } diff --git a/vendor/gitea.com/macaron/session/mysql/mysql.go b/vendor/gitea.com/macaron/session/mysql/mysql.go index da5079b24a78..af1cd9dd1b1e 100644 --- a/vendor/gitea.com/macaron/session/mysql/mysql.go +++ b/vendor/gitea.com/macaron/session/mysql/mysql.go @@ -120,18 +120,20 @@ func (p *MysqlProvider) Init(expire int64, connStr string) (err error) { // Read returns raw session store by session ID. func (p *MysqlProvider) Read(sid string) (session.RawStore, error) { + now := time.Now().Unix() var data []byte - err := p.c.QueryRow("SELECT data FROM session WHERE `key`=?", sid).Scan(&data) + expiry := now + err := p.c.QueryRow("SELECT data, expiry FROM session WHERE `key`=?", sid).Scan(&data, &expiry) if err == sql.ErrNoRows { _, err = p.c.Exec("INSERT INTO session(`key`,data,expiry) VALUES(?,?,?)", - sid, "", time.Now().Unix()) + sid, "", now) } if err != nil { return nil, err } var kv map[interface{}]interface{} - if len(data) == 0 { + if len(data) == 0 || expiry+p.expire <= now { kv = make(map[interface{}]interface{}) } else { kv, err = session.DecodeGob(data) diff --git a/vendor/gitea.com/macaron/session/postgres/postgres.go b/vendor/gitea.com/macaron/session/postgres/postgres.go index c307241a3c9d..f173021d515c 100644 --- a/vendor/gitea.com/macaron/session/postgres/postgres.go +++ b/vendor/gitea.com/macaron/session/postgres/postgres.go @@ -121,18 +121,20 @@ func (p *PostgresProvider) Init(maxlifetime int64, connStr string) (err error) { // Read returns raw session store by session ID. func (p *PostgresProvider) Read(sid string) (session.RawStore, error) { + now := time.Now().Unix() var data []byte - err := p.c.QueryRow("SELECT data FROM session WHERE key=$1", sid).Scan(&data) + expiry := now + err := p.c.QueryRow("SELECT data, expiry FROM session WHERE key=$1", sid).Scan(&data, &expiry) if err == sql.ErrNoRows { _, err = p.c.Exec("INSERT INTO session(key,data,expiry) VALUES($1,$2,$3)", - sid, "", time.Now().Unix()) + sid, "", now) } if err != nil { return nil, err } var kv map[interface{}]interface{} - if len(data) == 0 { + if len(data) == 0 || expiry+p.maxlifetime <= now { kv = make(map[interface{}]interface{}) } else { kv, err = session.DecodeGob(data) diff --git a/vendor/modules.txt b/vendor/modules.txt index fce7ad492d2b..2a69c1077d47 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -37,7 +37,7 @@ gitea.com/macaron/inject # gitea.com/macaron/macaron v1.4.0 ## explicit gitea.com/macaron/macaron -# gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d +# gitea.com/macaron/session v0.0.0-20200902202411-e3a87877db6e ## explicit gitea.com/macaron/session gitea.com/macaron/session/couchbase