You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
4.5 KiB

  1. // Copyright 2013 Beego Authors
  2. // Copyright 2014 The Macaron Authors
  3. // Copyright 2019 The Gitea Authors
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License"): you may
  6. // not use this file except in compliance with the License. You may obtain
  7. // a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  14. // License for the specific language governing permissions and limitations
  15. // under the License.
  16. package session
  17. import (
  18. "container/list"
  19. "fmt"
  20. "sync"
  21. "time"
  22. "gitea.com/macaron/session"
  23. )
  24. // MemStore represents a in-memory session store implementation.
  25. type MemStore struct {
  26. sid string
  27. lock sync.RWMutex
  28. data map[interface{}]interface{}
  29. lastAccess time.Time
  30. }
  31. // NewMemStore creates and returns a memory session store.
  32. func NewMemStore(sid string) *MemStore {
  33. return &MemStore{
  34. sid: sid,
  35. data: make(map[interface{}]interface{}),
  36. lastAccess: time.Now(),
  37. }
  38. }
  39. // Set sets value to given key in session.
  40. func (s *MemStore) Set(key, val interface{}) error {
  41. s.lock.Lock()
  42. defer s.lock.Unlock()
  43. s.data[key] = val
  44. return nil
  45. }
  46. // Get gets value by given key in session.
  47. func (s *MemStore) Get(key interface{}) interface{} {
  48. s.lock.RLock()
  49. defer s.lock.RUnlock()
  50. return s.data[key]
  51. }
  52. // Delete deletes a key from session.
  53. func (s *MemStore) Delete(key interface{}) error {
  54. s.lock.Lock()
  55. defer s.lock.Unlock()
  56. delete(s.data, key)
  57. return nil
  58. }
  59. // ID returns current session ID.
  60. func (s *MemStore) ID() string {
  61. return s.sid
  62. }
  63. // Release releases resource and save data to provider.
  64. func (*MemStore) Release() error {
  65. return nil
  66. }
  67. // Flush deletes all session data.
  68. func (s *MemStore) Flush() error {
  69. s.lock.Lock()
  70. defer s.lock.Unlock()
  71. s.data = make(map[interface{}]interface{})
  72. return nil
  73. }
  74. // MemProvider represents a in-memory session provider implementation.
  75. type MemProvider struct {
  76. lock sync.RWMutex
  77. maxLifetime int64
  78. data map[string]*list.Element
  79. // A priority list whose lastAccess newer gets higher priority.
  80. list *list.List
  81. }
  82. // Init initializes memory session provider.
  83. func (p *MemProvider) Init(maxLifetime int64, _ string) error {
  84. p.lock.Lock()
  85. p.maxLifetime = maxLifetime
  86. p.lock.Unlock()
  87. return nil
  88. }
  89. // update expands time of session store by given ID.
  90. func (p *MemProvider) update(sid string) error {
  91. p.lock.Lock()
  92. defer p.lock.Unlock()
  93. if e, ok := p.data[sid]; ok {
  94. e.Value.(*MemStore).lastAccess = time.Now()
  95. p.list.MoveToFront(e)
  96. return nil
  97. }
  98. return nil
  99. }
  100. // Read returns raw session store by session ID.
  101. func (p *MemProvider) Read(sid string) (_ session.RawStore, err error) {
  102. p.lock.RLock()
  103. e, ok := p.data[sid]
  104. p.lock.RUnlock()
  105. if ok {
  106. if err = p.update(sid); err != nil {
  107. return nil, err
  108. }
  109. return e.Value.(*MemStore), nil
  110. }
  111. // Create a new session.
  112. p.lock.Lock()
  113. defer p.lock.Unlock()
  114. s := NewMemStore(sid)
  115. p.data[sid] = p.list.PushBack(s)
  116. return s, nil
  117. }
  118. // Exist returns true if session with given ID exists.
  119. func (p *MemProvider) Exist(sid string) bool {
  120. p.lock.RLock()
  121. defer p.lock.RUnlock()
  122. _, ok := p.data[sid]
  123. return ok
  124. }
  125. // Destroy deletes a session by session ID.
  126. func (p *MemProvider) Destroy(sid string) error {
  127. p.lock.Lock()
  128. defer p.lock.Unlock()
  129. e, ok := p.data[sid]
  130. if !ok {
  131. return nil
  132. }
  133. p.list.Remove(e)
  134. delete(p.data, sid)
  135. return nil
  136. }
  137. // Regenerate regenerates a session store from old session ID to new one.
  138. func (p *MemProvider) Regenerate(oldsid, sid string) (session.RawStore, error) {
  139. if p.Exist(sid) {
  140. return nil, fmt.Errorf("new sid '%s' already exists", sid)
  141. }
  142. s, err := p.Read(oldsid)
  143. if err != nil {
  144. return nil, err
  145. }
  146. if err = p.Destroy(oldsid); err != nil {
  147. return nil, err
  148. }
  149. s.(*MemStore).sid = sid
  150. p.lock.Lock()
  151. defer p.lock.Unlock()
  152. p.data[sid] = p.list.PushBack(s)
  153. return s, nil
  154. }
  155. // Count counts and returns number of sessions.
  156. func (p *MemProvider) Count() int {
  157. return p.list.Len()
  158. }
  159. // GC calls GC to clean expired sessions.
  160. func (p *MemProvider) GC() {
  161. p.lock.RLock()
  162. for {
  163. // No session in the list.
  164. e := p.list.Back()
  165. if e == nil {
  166. break
  167. }
  168. if (e.Value.(*MemStore).lastAccess.Unix() + p.maxLifetime) < time.Now().Unix() {
  169. p.lock.RUnlock()
  170. p.lock.Lock()
  171. p.list.Remove(e)
  172. delete(p.data, e.Value.(*MemStore).sid)
  173. p.lock.Unlock()
  174. p.lock.RLock()
  175. } else {
  176. break
  177. }
  178. }
  179. p.lock.RUnlock()
  180. }