code.gitea.io/gitea@v1.19.3/modules/session/db.go (about) 1 // Copyright 2020 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package session 5 6 import ( 7 "log" 8 "sync" 9 10 "code.gitea.io/gitea/models/auth" 11 "code.gitea.io/gitea/modules/timeutil" 12 13 "gitea.com/go-chi/session" 14 ) 15 16 // DBStore represents a session store implementation based on the DB. 17 type DBStore struct { 18 sid string 19 lock sync.RWMutex 20 data map[interface{}]interface{} 21 } 22 23 // NewDBStore creates and returns a DB session store. 24 func NewDBStore(sid string, kv map[interface{}]interface{}) *DBStore { 25 return &DBStore{ 26 sid: sid, 27 data: kv, 28 } 29 } 30 31 // Set sets value to given key in session. 32 func (s *DBStore) Set(key, val interface{}) error { 33 s.lock.Lock() 34 defer s.lock.Unlock() 35 36 s.data[key] = val 37 return nil 38 } 39 40 // Get gets value by given key in session. 41 func (s *DBStore) Get(key interface{}) interface{} { 42 s.lock.RLock() 43 defer s.lock.RUnlock() 44 45 return s.data[key] 46 } 47 48 // Delete delete a key from session. 49 func (s *DBStore) Delete(key interface{}) error { 50 s.lock.Lock() 51 defer s.lock.Unlock() 52 53 delete(s.data, key) 54 return nil 55 } 56 57 // ID returns current session ID. 58 func (s *DBStore) ID() string { 59 return s.sid 60 } 61 62 // Release releases resource and save data to provider. 63 func (s *DBStore) Release() error { 64 // Skip encoding if the data is empty 65 if len(s.data) == 0 { 66 return nil 67 } 68 69 data, err := session.EncodeGob(s.data) 70 if err != nil { 71 return err 72 } 73 74 return auth.UpdateSession(s.sid, data) 75 } 76 77 // Flush deletes all session data. 78 func (s *DBStore) Flush() error { 79 s.lock.Lock() 80 defer s.lock.Unlock() 81 82 s.data = make(map[interface{}]interface{}) 83 return nil 84 } 85 86 // DBProvider represents a DB session provider implementation. 87 type DBProvider struct { 88 maxLifetime int64 89 } 90 91 // Init initializes DB session provider. 92 // connStr: username:password@protocol(address)/dbname?param=value 93 func (p *DBProvider) Init(maxLifetime int64, connStr string) error { 94 p.maxLifetime = maxLifetime 95 return nil 96 } 97 98 // Read returns raw session store by session ID. 99 func (p *DBProvider) Read(sid string) (session.RawStore, error) { 100 s, err := auth.ReadSession(sid) 101 if err != nil { 102 return nil, err 103 } 104 105 var kv map[interface{}]interface{} 106 if len(s.Data) == 0 || s.Expiry.Add(p.maxLifetime) <= timeutil.TimeStampNow() { 107 kv = make(map[interface{}]interface{}) 108 } else { 109 kv, err = session.DecodeGob(s.Data) 110 if err != nil { 111 return nil, err 112 } 113 } 114 115 return NewDBStore(sid, kv), nil 116 } 117 118 // Exist returns true if session with given ID exists. 119 func (p *DBProvider) Exist(sid string) bool { 120 has, err := auth.ExistSession(sid) 121 if err != nil { 122 panic("session/DB: error checking existence: " + err.Error()) 123 } 124 return has 125 } 126 127 // Destroy deletes a session by session ID. 128 func (p *DBProvider) Destroy(sid string) error { 129 return auth.DestroySession(sid) 130 } 131 132 // Regenerate regenerates a session store from old session ID to new one. 133 func (p *DBProvider) Regenerate(oldsid, sid string) (_ session.RawStore, err error) { 134 s, err := auth.RegenerateSession(oldsid, sid) 135 if err != nil { 136 return nil, err 137 } 138 139 var kv map[interface{}]interface{} 140 if len(s.Data) == 0 || s.Expiry.Add(p.maxLifetime) <= timeutil.TimeStampNow() { 141 kv = make(map[interface{}]interface{}) 142 } else { 143 kv, err = session.DecodeGob(s.Data) 144 if err != nil { 145 return nil, err 146 } 147 } 148 149 return NewDBStore(sid, kv), nil 150 } 151 152 // Count counts and returns number of sessions. 153 func (p *DBProvider) Count() int { 154 total, err := auth.CountSessions() 155 if err != nil { 156 panic("session/DB: error counting records: " + err.Error()) 157 } 158 return int(total) 159 } 160 161 // GC calls GC to clean expired sessions. 162 func (p *DBProvider) GC() { 163 if err := auth.CleanupSessions(p.maxLifetime); err != nil { 164 log.Printf("session/DB: error garbage collecting: %v", err) 165 } 166 } 167 168 func init() { 169 session.Register("db", &DBProvider{}) 170 }