Mercurial > gemma
comparison pkg/auth/store.go @ 498:22e1bf563a04 metamorph-for-all
Throw away the connection level for sessions.
This is not needed any more because the db connection are not bound to the sessions any more.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Fri, 24 Aug 2018 15:12:22 +0200 |
parents | 5c08afd15ce7 |
children | b6796cd91604 |
comparison
equal
deleted
inserted
replaced
495:5c08afd15ce7 | 498:22e1bf563a04 |
---|---|
1 package auth | 1 package auth |
2 | 2 |
3 import ( | 3 import ( |
4 "bytes" | 4 "bytes" |
5 "errors" | |
5 "log" | 6 "log" |
6 "time" | 7 "time" |
7 | 8 |
8 bolt "github.com/coreos/bbolt" | 9 bolt "github.com/coreos/bbolt" |
9 ) | 10 ) |
10 | 11 |
12 var ErrNoSuchToken = errors.New("No such token") | |
13 | |
11 // Sessions is the global connection pool. | 14 // Sessions is the global connection pool. |
12 var Sessions *SessionStore | 15 var Sessions *SessionStore |
13 | 16 |
14 type SessionStore struct { | 17 type SessionStore struct { |
15 storage *bolt.DB | 18 storage *bolt.DB |
16 conns map[string]*Connection | 19 sessions map[string]*Session |
17 cmds chan func(*SessionStore) | 20 cmds chan func(*SessionStore) |
18 } | 21 } |
19 | 22 |
20 var sessionsBucket = []byte("sessions") | 23 var sessionsBucket = []byte("sessions") |
21 | 24 |
22 func NewSessionStore(filename string) (*SessionStore, error) { | 25 func NewSessionStore(filename string) (*SessionStore, error) { |
23 | 26 |
24 pcp := &SessionStore{ | 27 pcp := &SessionStore{ |
25 conns: make(map[string]*Connection), | 28 sessions: make(map[string]*Session), |
26 cmds: make(chan func(*SessionStore)), | 29 cmds: make(chan func(*SessionStore)), |
27 } | 30 } |
28 if err := pcp.openStorage(filename); err != nil { | 31 if err := pcp.openStorage(filename); err != nil { |
29 return nil, err | 32 return nil, err |
30 } | 33 } |
31 go pcp.run() | 34 go pcp.run() |
53 | 56 |
54 // pre-load sessions | 57 // pre-load sessions |
55 c := b.Cursor() | 58 c := b.Cursor() |
56 | 59 |
57 for k, v := c.First(); k != nil; k, v = c.Next() { | 60 for k, v := c.First(); k != nil; k, v = c.Next() { |
58 var conn Connection | 61 var session Session |
59 if err := conn.deserialize(bytes.NewReader(v)); err != nil { | 62 if err := session.deserialize(bytes.NewReader(v)); err != nil { |
60 return err | 63 return err |
61 } | 64 } |
62 pcp.conns[string(k)] = &conn | 65 pcp.sessions[string(k)] = &session |
63 } | 66 } |
64 | 67 |
65 return nil | 68 return nil |
66 }) | 69 }) |
67 | 70 |
85 } | 88 } |
86 } | 89 } |
87 | 90 |
88 func (pcp *SessionStore) cleanToken() { | 91 func (pcp *SessionStore) cleanToken() { |
89 now := time.Now() | 92 now := time.Now() |
90 for token, con := range pcp.conns { | 93 for token, session := range pcp.sessions { |
91 expires := time.Unix(con.session.ExpiresAt, 0) | 94 expires := time.Unix(session.ExpiresAt, 0) |
92 if expires.Before(now) { | 95 if expires.Before(now) { |
93 delete(pcp.conns, token) | 96 delete(pcp.sessions, token) |
94 pcp.remove(token) | 97 pcp.remove(token) |
95 } | 98 } |
96 } | 99 } |
97 } | 100 } |
98 | 101 |
110 } | 113 } |
111 | 114 |
112 func (pcp *SessionStore) Delete(token string) bool { | 115 func (pcp *SessionStore) Delete(token string) bool { |
113 res := make(chan bool) | 116 res := make(chan bool) |
114 pcp.cmds <- func(pcp *SessionStore) { | 117 pcp.cmds <- func(pcp *SessionStore) { |
115 if _, found := pcp.conns[token]; !found { | 118 if _, found := pcp.sessions[token]; !found { |
116 res <- false | 119 res <- false |
117 return | 120 return |
118 } | 121 } |
119 delete(pcp.conns, token) | 122 delete(pcp.sessions, token) |
120 pcp.remove(token) | 123 pcp.remove(token) |
121 res <- true | 124 res <- true |
122 } | 125 } |
123 return <-res | 126 return <-res |
124 } | 127 } |
125 | 128 |
126 func (pcp *SessionStore) store(token string, con *Connection) { | 129 func (pcp *SessionStore) store(token string, session *Session) { |
127 if pcp.storage == nil { | 130 if pcp.storage == nil { |
128 return | 131 return |
129 } | 132 } |
130 err := pcp.storage.Update(func(tx *bolt.Tx) error { | 133 err := pcp.storage.Update(func(tx *bolt.Tx) error { |
131 b := tx.Bucket(sessionsBucket) | 134 b := tx.Bucket(sessionsBucket) |
132 var buf bytes.Buffer | 135 var buf bytes.Buffer |
133 if err := con.serialize(&buf); err != nil { | 136 if err := session.serialize(&buf); err != nil { |
134 return err | 137 return err |
135 } | 138 } |
136 return b.Put([]byte(token), buf.Bytes()) | 139 return b.Put([]byte(token), buf.Bytes()) |
137 }) | 140 }) |
138 if err != nil { | 141 if err != nil { |
139 log.Printf("error: %v\n", err) | 142 log.Printf("error: %v\n", err) |
140 } | 143 } |
141 } | 144 } |
142 | 145 |
143 func (pcp *SessionStore) Add(token string, session *Session) *Connection { | 146 func (pcp *SessionStore) Add(token string, session *Session) *Session { |
144 res := make(chan *Connection) | 147 res := make(chan *Session) |
145 | 148 |
146 pcp.cmds <- func(cp *SessionStore) { | 149 pcp.cmds <- func(cp *SessionStore) { |
147 con := pcp.conns[token] | 150 s := pcp.sessions[token] |
148 if con == nil { | 151 if s == nil { |
149 con = &Connection{} | 152 s = session |
150 pcp.conns[token] = con | 153 pcp.sessions[token] = session |
151 } | 154 } |
152 con.set(session) | 155 s.touch() |
153 pcp.store(token, con) | 156 pcp.store(token, s) |
154 res <- con | 157 res <- s |
155 } | 158 } |
156 | 159 |
157 con := <-res | 160 s := <-res |
158 return con | 161 return s |
159 } | 162 } |
160 | 163 |
161 func (pcp *SessionStore) Renew(token string) (string, error) { | 164 func (pcp *SessionStore) Renew(token string) (string, error) { |
162 | 165 |
163 type result struct { | 166 type result struct { |
166 } | 169 } |
167 | 170 |
168 resCh := make(chan result) | 171 resCh := make(chan result) |
169 | 172 |
170 pcp.cmds <- func(cp *SessionStore) { | 173 pcp.cmds <- func(cp *SessionStore) { |
171 con := pcp.conns[token] | 174 session := pcp.sessions[token] |
172 if con == nil { | 175 if session == nil { |
173 resCh <- result{err: ErrNoSuchToken} | 176 resCh <- result{err: ErrNoSuchToken} |
174 } else { | 177 } else { |
175 delete(pcp.conns, token) | 178 delete(pcp.sessions, token) |
176 pcp.remove(token) | 179 pcp.remove(token) |
177 newToken := GenerateSessionKey() | 180 newToken := GenerateSessionKey() |
178 // TODO: Ensure that this is not racy! | 181 // TODO: Ensure that this is not racy! |
179 con.session.ExpiresAt = time.Now().Add(maxTokenValid).Unix() | 182 session.ExpiresAt = time.Now().Add(maxTokenValid).Unix() |
180 pcp.conns[newToken] = con | 183 pcp.sessions[newToken] = session |
181 pcp.store(newToken, con) | 184 pcp.store(newToken, session) |
182 resCh <- result{newToken: newToken} | 185 resCh <- result{newToken: newToken} |
183 } | 186 } |
184 } | 187 } |
185 | 188 |
186 r := <-resCh | 189 r := <-resCh |
187 return r.newToken, r.err | 190 return r.newToken, r.err |
188 } | |
189 | |
190 func (pcp *SessionStore) Do(token string) (*Session, error) { | |
191 | |
192 type result struct { | |
193 session *Session | |
194 err error | |
195 } | |
196 | |
197 res := make(chan result) | |
198 | |
199 pcp.cmds <- func(pcp *SessionStore) { | |
200 con := pcp.conns[token] | |
201 if con == nil { | |
202 res <- result{err: ErrNoSuchToken} | |
203 return | |
204 } | |
205 con.touch() | |
206 pcp.store(token, con) | |
207 | |
208 res <- result{session: con.session} | |
209 } | |
210 | |
211 r := <-res | |
212 | |
213 if r.err != nil { | |
214 return nil, r.err | |
215 } | |
216 | |
217 return r.session, nil | |
218 } | 191 } |
219 | 192 |
220 func (pcp *SessionStore) Session(token string) *Session { | 193 func (pcp *SessionStore) Session(token string) *Session { |
221 res := make(chan *Session) | 194 res := make(chan *Session) |
222 pcp.cmds <- func(pcp *SessionStore) { | 195 pcp.cmds <- func(pcp *SessionStore) { |
223 con := pcp.conns[token] | 196 session := pcp.sessions[token] |
224 if con == nil { | 197 if session == nil { |
225 res <- nil | 198 res <- nil |
226 } else { | 199 } else { |
227 con.touch() | 200 session.touch() |
228 pcp.store(token, con) | 201 pcp.store(token, session) |
229 res <- con.session | 202 res <- session |
230 } | 203 } |
231 } | 204 } |
232 return <-res | 205 return <-res |
233 } | 206 } |
234 | 207 |
235 func (pcp *SessionStore) Logout(user string) { | 208 func (pcp *SessionStore) Logout(user string) { |
236 pcp.cmds <- func(pcp *SessionStore) { | 209 pcp.cmds <- func(pcp *SessionStore) { |
237 for token, con := range pcp.conns { | 210 for token, session := range pcp.sessions { |
238 if con.session.User == user { | 211 if session.User == user { |
239 delete(pcp.conns, token) | 212 delete(pcp.sessions, token) |
240 pcp.remove(token) | 213 pcp.remove(token) |
241 } | 214 } |
242 } | 215 } |
243 } | 216 } |
244 } | 217 } |