comparison pkg/auth/pool.go @ 493:8a0737aa6ab6 metamorph-for-all

The connection pool is now only a session store.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 24 Aug 2018 14:25:05 +0200
parents b2dc9c2f69e0
children
comparison
equal deleted inserted replaced
486:b2dc9c2f69e0 493:8a0737aa6ab6
6 "time" 6 "time"
7 7
8 bolt "github.com/coreos/bbolt" 8 bolt "github.com/coreos/bbolt"
9 ) 9 )
10 10
11 // ConnPool is the global connection pool. 11 // Sessions is the global connection pool.
12 var ConnPool *ConnectionPool 12 var Sessions *SessionStore
13 13
14 type ConnectionPool struct { 14 type SessionStore struct {
15 storage *bolt.DB 15 storage *bolt.DB
16 conns map[string]*Connection 16 conns map[string]*Connection
17 cmds chan func(*ConnectionPool) 17 cmds chan func(*SessionStore)
18 } 18 }
19 19
20 var sessionsBucket = []byte("sessions") 20 var sessionsBucket = []byte("sessions")
21 21
22 func NewConnectionPool(filename string) (*ConnectionPool, error) { 22 func NewSessionStore(filename string) (*SessionStore, error) {
23 23
24 pcp := &ConnectionPool{ 24 pcp := &SessionStore{
25 conns: make(map[string]*Connection), 25 conns: make(map[string]*Connection),
26 cmds: make(chan func(*ConnectionPool)), 26 cmds: make(chan func(*SessionStore)),
27 } 27 }
28 if err := pcp.openStorage(filename); err != nil { 28 if err := pcp.openStorage(filename); err != nil {
29 return nil, err 29 return nil, err
30 } 30 }
31 go pcp.run() 31 go pcp.run()
32 return pcp, nil 32 return pcp, nil
33 } 33 }
34 34
35 // openStorage opens a storage file. 35 // openStorage opens a storage file.
36 func (pcp *ConnectionPool) openStorage(filename string) error { 36 func (pcp *SessionStore) openStorage(filename string) error {
37 37
38 // No file, nothing to restore/persist. 38 // No file, nothing to restore/persist.
39 if filename == "" { 39 if filename == "" {
40 return nil 40 return nil
41 } 41 }
72 72
73 pcp.storage = db 73 pcp.storage = db
74 return nil 74 return nil
75 } 75 }
76 76
77 func (pcp *ConnectionPool) run() { 77 func (pcp *SessionStore) run() {
78 for { 78 for {
79 select { 79 select {
80 case cmd := <-pcp.cmds: 80 case cmd := <-pcp.cmds:
81 cmd(pcp) 81 cmd(pcp)
82 case <-time.After(time.Minute):
83 pcp.cleanDB()
84 case <-time.After(time.Minute * 5): 82 case <-time.After(time.Minute * 5):
85 pcp.cleanToken() 83 pcp.cleanToken()
86 } 84 }
87 } 85 }
88 } 86 }
89 87
90 func (pcp *ConnectionPool) cleanDB() { 88 func (pcp *SessionStore) cleanToken() {
91 }
92
93 func (pcp *ConnectionPool) cleanToken() {
94 now := time.Now() 89 now := time.Now()
95 for token, con := range pcp.conns { 90 for token, con := range pcp.conns {
96 expires := time.Unix(con.session.ExpiresAt, 0) 91 expires := time.Unix(con.session.ExpiresAt, 0)
97 if expires.Before(now) { 92 if expires.Before(now) {
98 // TODO: Be more graceful here?
99 con.close()
100 delete(pcp.conns, token) 93 delete(pcp.conns, token)
101 pcp.remove(token) 94 pcp.remove(token)
102 } 95 }
103 } 96 }
104 } 97 }
105 98
106 func (pcp *ConnectionPool) remove(token string) { 99 func (pcp *SessionStore) remove(token string) {
107 if pcp.storage == nil { 100 if pcp.storage == nil {
108 return 101 return
109 } 102 }
110 err := pcp.storage.Update(func(tx *bolt.Tx) error { 103 err := pcp.storage.Update(func(tx *bolt.Tx) error {
111 b := tx.Bucket(sessionsBucket) 104 b := tx.Bucket(sessionsBucket)
114 if err != nil { 107 if err != nil {
115 log.Printf("error: %v\n", err) 108 log.Printf("error: %v\n", err)
116 } 109 }
117 } 110 }
118 111
119 func (pcp *ConnectionPool) Delete(token string) bool { 112 func (pcp *SessionStore) Delete(token string) bool {
120 res := make(chan bool) 113 res := make(chan bool)
121 pcp.cmds <- func(pcp *ConnectionPool) { 114 pcp.cmds <- func(pcp *SessionStore) {
122 conn, found := pcp.conns[token] 115 if _, found := pcp.conns[token]; !found {
123 if !found {
124 res <- false 116 res <- false
125 return 117 return
126 } 118 }
127 conn.close()
128 delete(pcp.conns, token) 119 delete(pcp.conns, token)
129 pcp.remove(token) 120 pcp.remove(token)
130 res <- true 121 res <- true
131 } 122 }
132 return <-res 123 return <-res
133 } 124 }
134 125
135 func (pcp *ConnectionPool) store(token string, con *Connection) { 126 func (pcp *SessionStore) store(token string, con *Connection) {
136 if pcp.storage == nil { 127 if pcp.storage == nil {
137 return 128 return
138 } 129 }
139 err := pcp.storage.Update(func(tx *bolt.Tx) error { 130 err := pcp.storage.Update(func(tx *bolt.Tx) error {
140 b := tx.Bucket(sessionsBucket) 131 b := tx.Bucket(sessionsBucket)
147 if err != nil { 138 if err != nil {
148 log.Printf("error: %v\n", err) 139 log.Printf("error: %v\n", err)
149 } 140 }
150 } 141 }
151 142
152 func (pcp *ConnectionPool) Add(token string, session *Session) *Connection { 143 func (pcp *SessionStore) Add(token string, session *Session) *Connection {
153 res := make(chan *Connection) 144 res := make(chan *Connection)
154 145
155 pcp.cmds <- func(cp *ConnectionPool) { 146 pcp.cmds <- func(cp *SessionStore) {
156 con := pcp.conns[token] 147 con := pcp.conns[token]
157 if con == nil { 148 if con == nil {
158 con = &Connection{} 149 con = &Connection{}
159 pcp.conns[token] = con 150 pcp.conns[token] = con
160 } 151 }
165 156
166 con := <-res 157 con := <-res
167 return con 158 return con
168 } 159 }
169 160
170 func (pcp *ConnectionPool) Renew(token string) (string, error) { 161 func (pcp *SessionStore) Renew(token string) (string, error) {
171 162
172 type result struct { 163 type result struct {
173 newToken string 164 newToken string
174 err error 165 err error
175 } 166 }
176 167
177 resCh := make(chan result) 168 resCh := make(chan result)
178 169
179 pcp.cmds <- func(cp *ConnectionPool) { 170 pcp.cmds <- func(cp *SessionStore) {
180 con := pcp.conns[token] 171 con := pcp.conns[token]
181 if con == nil { 172 if con == nil {
182 resCh <- result{err: ErrNoSuchToken} 173 resCh <- result{err: ErrNoSuchToken}
183 } else { 174 } else {
184 delete(pcp.conns, token) 175 delete(pcp.conns, token)
194 185
195 r := <-resCh 186 r := <-resCh
196 return r.newToken, r.err 187 return r.newToken, r.err
197 } 188 }
198 189
199 func (pcp *ConnectionPool) Do(token string) (*Session, error) { 190 func (pcp *SessionStore) Do(token string) (*Session, error) {
200 191
201 type result struct { 192 type result struct {
202 session *Session 193 session *Session
203 err error 194 err error
204 } 195 }
205 196
206 res := make(chan result) 197 res := make(chan result)
207 198
208 pcp.cmds <- func(pcp *ConnectionPool) { 199 pcp.cmds <- func(pcp *SessionStore) {
209 con := pcp.conns[token] 200 con := pcp.conns[token]
210 if con == nil { 201 if con == nil {
211 res <- result{err: ErrNoSuchToken} 202 res <- result{err: ErrNoSuchToken}
212 return 203 return
213 } 204 }
224 } 215 }
225 216
226 return r.session, nil 217 return r.session, nil
227 } 218 }
228 219
229 func (pcp *ConnectionPool) Session(token string) *Session { 220 func (pcp *SessionStore) Session(token string) *Session {
230 res := make(chan *Session) 221 res := make(chan *Session)
231 pcp.cmds <- func(pcp *ConnectionPool) { 222 pcp.cmds <- func(pcp *SessionStore) {
232 con := pcp.conns[token] 223 con := pcp.conns[token]
233 if con == nil { 224 if con == nil {
234 res <- nil 225 res <- nil
235 } else { 226 } else {
236 con.touch() 227 con.touch()
239 } 230 }
240 } 231 }
241 return <-res 232 return <-res
242 } 233 }
243 234
244 func (pcp *ConnectionPool) Logout(user string) { 235 func (pcp *SessionStore) Logout(user string) {
245 pcp.cmds <- func(pcp *ConnectionPool) { 236 pcp.cmds <- func(pcp *SessionStore) {
246 for token, con := range pcp.conns { 237 for token, con := range pcp.conns {
247 if con.session.User == user { 238 if con.session.User == user {
248 delete(pcp.conns, token) 239 delete(pcp.conns, token)
249 pcp.remove(token) 240 pcp.remove(token)
250 } 241 }
251 } 242 }
252 } 243 }
253 } 244 }
254 245
255 func (pcp *ConnectionPool) Shutdown() error { 246 func (pcp *SessionStore) Shutdown() error {
256 if db := pcp.storage; db != nil { 247 if db := pcp.storage; db != nil {
257 log.Println("info: shutdown persistent connection pool.") 248 log.Println("info: shutdown persistent connection pool.")
258 pcp.storage = nil 249 pcp.storage = nil
259 return db.Close() 250 return db.Close()
260 } 251 }