Mercurial > gemma
annotate pkg/auth/store.go @ 5591:0011f50cf216 surveysperbottleneckid
Removed no longer used alternative api for surveys/ endpoint.
As bottlenecks in the summary for SR imports are now identified by
their id and no longer by the (not guarantied to be unique!) name,
there is no longer the need to request survey data by the name+date
tuple (which isn't reliable anyway). So the workaround was now
reversed.
author | Sascha Wilde <wilde@sha-bang.de> |
---|---|
date | Wed, 06 Apr 2022 13:30:29 +0200 |
parents | 5f47eeea988d |
children |
rev | line source |
---|---|
1017
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
614
diff
changeset
|
1 // This is Free Software under GNU Affero General Public License v >= 3.0 |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
614
diff
changeset
|
2 // without warranty, see README.md and license for details. |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
614
diff
changeset
|
3 // |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
614
diff
changeset
|
4 // SPDX-License-Identifier: AGPL-3.0-or-later |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
614
diff
changeset
|
5 // License-Filename: LICENSES/AGPL-3.0.txt |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
614
diff
changeset
|
6 // |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
614
diff
changeset
|
7 // Copyright (C) 2018 by via donau |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
614
diff
changeset
|
8 // – Österreichische Wasserstraßen-Gesellschaft mbH |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
614
diff
changeset
|
9 // Software engineering by Intevation GmbH |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
614
diff
changeset
|
10 // |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
614
diff
changeset
|
11 // Author(s): |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
614
diff
changeset
|
12 // * Sascha L. Teichmann <sascha.teichmann@intevation.de> |
a244b18cb916
Added GNU Affero General Public License.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
614
diff
changeset
|
13 |
190
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
14 package auth |
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
15 |
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
16 import ( |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
17 "bytes" |
498
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
18 "errors" |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
19 "time" |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
20 |
5490
5f47eeea988d
Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
5320
diff
changeset
|
21 bolt "go.etcd.io/bbolt" |
5f47eeea988d
Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
5320
diff
changeset
|
22 |
2639
0db742c7813d
Make session timeout configurable
Tom Gottfried <tom@intevation.de>
parents:
1343
diff
changeset
|
23 "gemma.intevation.de/gemma/pkg/config" |
5490
5f47eeea988d
Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
5320
diff
changeset
|
24 "gemma.intevation.de/gemma/pkg/log" |
190
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
25 ) |
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
26 |
1343
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
27 // ErrNoSuchToken is returned if a given token does not |
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
28 // exists th the session store. |
4160
7cccf7fef3e8
Made 'golint' and 'staticcheck' happy with auth package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
2639
diff
changeset
|
29 var ErrNoSuchToken = errors.New("no such token") |
498
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
30 |
493
8a0737aa6ab6
The connection pool is now only a session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
31 // Sessions is the global connection pool. |
8a0737aa6ab6
The connection pool is now only a session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
32 var Sessions *SessionStore |
220
11d1a488b08f
Depend command line parsing on Viper/Cobra. Configuration should be persistent now.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
213
diff
changeset
|
33 |
1343
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
34 // SessionStore encapsulates a set of currently active sessions. |
493
8a0737aa6ab6
The connection pool is now only a session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
35 type SessionStore struct { |
498
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
36 storage *bolt.DB |
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
37 sessions map[string]*Session |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
38 cmds chan func() |
190
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
39 } |
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
40 |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
41 var sessionsBucket = []byte("sessions") |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
42 |
1343
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
43 // NewSessionStore creates a new session store. |
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
44 // If the filename is empty the session are only hold in memory. |
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
45 // If the filename is not empty the sessions are mirrored to |
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
46 // a file with this name. Use the later option if you want |
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
47 // a persistent session store. |
493
8a0737aa6ab6
The connection pool is now only a session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
486
diff
changeset
|
48 func NewSessionStore(filename string) (*SessionStore, error) { |
204
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
49 |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
50 ss := &SessionStore{ |
498
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
51 sessions: make(map[string]*Session), |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
52 cmds: make(chan func()), |
204
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
53 } |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
54 if err := ss.openStorage(filename); err != nil { |
204
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
55 return nil, err |
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
56 } |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
57 go ss.run() |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
58 return ss, nil |
204
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
59 } |
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
60 |
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
61 // openStorage opens a storage file. |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
62 func (ss *SessionStore) openStorage(filename string) error { |
204
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
63 |
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
64 // No file, nothing to restore/persist. |
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
65 if filename == "" { |
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
66 return nil |
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
67 } |
190
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
68 |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
69 db, err := bolt.Open(filename, 0600, nil) |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
70 if err != nil { |
204
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
71 return err |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
72 } |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
73 |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
74 err = db.Update(func(tx *bolt.Tx) error { |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
75 b, err := tx.CreateBucketIfNotExists(sessionsBucket) |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
76 if err != nil { |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
77 return err |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
78 } |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
79 |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
80 // pre-load sessions |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
81 c := b.Cursor() |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
82 |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
83 for k, v := c.First(); k != nil; k, v = c.Next() { |
498
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
84 var session Session |
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
85 if err := session.deserialize(bytes.NewReader(v)); err != nil { |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
86 return err |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
87 } |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
88 ss.sessions[string(k)] = &session |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
89 } |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
90 |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
91 return nil |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
92 }) |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
93 |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
94 if err != nil { |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
95 db.Close() |
204
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
96 return err |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
97 } |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
98 |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
99 ss.storage = db |
204
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
100 return nil |
190
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
101 } |
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
102 |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
103 func (ss *SessionStore) run() { |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
104 for { |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
105 select { |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
106 case cmd := <-ss.cmds: |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
107 cmd() |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
108 case <-time.After(time.Minute * 5): |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
109 ss.cleanToken() |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
110 } |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
111 } |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
112 } |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
113 |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
114 func (ss *SessionStore) cleanToken() { |
203
6a802aed7f99
Persistent session store: Implemented cleanDB/cleanToken.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
202
diff
changeset
|
115 now := time.Now() |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
116 for token, session := range ss.sessions { |
498
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
117 expires := time.Unix(session.ExpiresAt, 0) |
203
6a802aed7f99
Persistent session store: Implemented cleanDB/cleanToken.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
202
diff
changeset
|
118 if expires.Before(now) { |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
119 delete(ss.sessions, token) |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
120 ss.remove(token) |
203
6a802aed7f99
Persistent session store: Implemented cleanDB/cleanToken.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
202
diff
changeset
|
121 } |
6a802aed7f99
Persistent session store: Implemented cleanDB/cleanToken.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
202
diff
changeset
|
122 } |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
123 } |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
124 |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
125 func (ss *SessionStore) remove(token string) { |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
126 if ss.storage == nil { |
204
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
127 return |
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
128 } |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
129 err := ss.storage.Update(func(tx *bolt.Tx) error { |
200
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
130 b := tx.Bucket(sessionsBucket) |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
131 return b.Delete([]byte(token)) |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
132 }) |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
133 if err != nil { |
5490
5f47eeea988d
Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
5320
diff
changeset
|
134 log.Errorf("%v\n", err) |
200
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
135 } |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
136 } |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
137 |
1343
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
138 // Delete removes a session identified by its token from the |
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
139 // session store. Returns true if there was such s session. |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
140 func (ss *SessionStore) Delete(token string) bool { |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
141 res := make(chan bool) |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
142 ss.cmds <- func() { |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
143 if _, found := ss.sessions[token]; !found { |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
144 res <- false |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
145 return |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
146 } |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
147 delete(ss.sessions, token) |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
148 ss.remove(token) |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
149 res <- true |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
150 } |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
151 return <-res |
190
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
152 } |
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
153 |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
154 func (ss *SessionStore) store(token string, session *Session) { |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
155 if ss.storage == nil { |
204
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
156 return |
3d0988d9f867
De-virtualize the connection pool implementation.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
203
diff
changeset
|
157 } |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
158 err := ss.storage.Update(func(tx *bolt.Tx) error { |
200
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
159 b := tx.Bucket(sessionsBucket) |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
160 var buf bytes.Buffer |
498
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
161 if err := session.serialize(&buf); err != nil { |
200
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
162 return err |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
163 } |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
164 return b.Put([]byte(token), buf.Bytes()) |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
165 }) |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
166 if err != nil { |
5490
5f47eeea988d
Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
5320
diff
changeset
|
167 log.Errorf("%v\n", err) |
200
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
168 } |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
169 } |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
170 |
1343
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
171 // Add puts a session into the session store identified by |
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
172 // a given token. An old session with the same key will |
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
173 // be replaced. |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
174 func (ss *SessionStore) Add(token string, session *Session) { |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
175 res := make(chan struct{}) |
199
ddc7ef95c247
Implemented Add of persistent sessions.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
197
diff
changeset
|
176 |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
177 ss.cmds <- func() { |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
178 defer close(res) |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
179 s := ss.sessions[token] |
498
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
180 if s == nil { |
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
181 s = session |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
182 ss.sessions[token] = session |
199
ddc7ef95c247
Implemented Add of persistent sessions.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
197
diff
changeset
|
183 } |
498
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
184 s.touch() |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
185 ss.store(token, s) |
199
ddc7ef95c247
Implemented Add of persistent sessions.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
197
diff
changeset
|
186 } |
ddc7ef95c247
Implemented Add of persistent sessions.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
197
diff
changeset
|
187 |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
188 <-res |
190
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
189 } |
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
190 |
1343
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
191 // Renew refreshes a session. It takes an old token to |
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
192 // identify a session and returns a new token with the |
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
193 // freshed up one. |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
194 func (ss *SessionStore) Renew(token string) (string, error) { |
200
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
195 |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
196 type result struct { |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
197 newToken string |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
198 err error |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
199 } |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
200 |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
201 resCh := make(chan result) |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
202 |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
203 ss.cmds <- func() { |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
204 session := ss.sessions[token] |
498
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
205 if session == nil { |
200
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
206 resCh <- result{err: ErrNoSuchToken} |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
207 } else { |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
208 delete(ss.sessions, token) |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
209 ss.remove(token) |
1342
20b9c3f261db
Added comments how to create a new session for a given user and password.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1017
diff
changeset
|
210 newToken := generateSessionKey() |
200
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
211 // TODO: Ensure that this is not racy! |
2639
0db742c7813d
Make session timeout configurable
Tom Gottfried <tom@intevation.de>
parents:
1343
diff
changeset
|
212 session.ExpiresAt = time.Now().Add(config.SessionTimeout()).Unix() |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
213 ss.sessions[newToken] = session |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
214 ss.store(newToken, session) |
200
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
215 resCh <- result{newToken: newToken} |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
216 } |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
217 } |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
218 |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
219 r := <-resCh |
8426a92fda00
Persistent session store: Implmented Renew.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
199
diff
changeset
|
220 return r.newToken, r.err |
190
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
221 } |
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
222 |
1343
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
223 // Session returns the session associated with given token. |
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
224 // Returns nil if no matching session was found. |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
225 func (ss *SessionStore) Session(token string) *Session { |
202
dba50c51cda7
Persistent session store: Implemented Session.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
201
diff
changeset
|
226 res := make(chan *Session) |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
227 ss.cmds <- func() { |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
228 session := ss.sessions[token] |
498
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
229 if session == nil { |
202
dba50c51cda7
Persistent session store: Implemented Session.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
201
diff
changeset
|
230 res <- nil |
dba50c51cda7
Persistent session store: Implemented Session.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
201
diff
changeset
|
231 } else { |
498
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
232 session.touch() |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
233 ss.store(token, session) |
498
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
234 res <- session |
202
dba50c51cda7
Persistent session store: Implemented Session.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
201
diff
changeset
|
235 } |
dba50c51cda7
Persistent session store: Implemented Session.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
201
diff
changeset
|
236 } |
dba50c51cda7
Persistent session store: Implemented Session.
Sascha L. Teichmann <teichmann@intevation.de>
parents:
201
diff
changeset
|
237 return <-res |
190
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
238 } |
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
239 |
1343
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
240 // Logout removes all sessions of a given user from the session store. |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
241 func (ss *SessionStore) Logout(user string) { |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
242 ss.cmds <- func() { |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
243 for token, session := range ss.sessions { |
498
22e1bf563a04
Throw away the connection level for sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
495
diff
changeset
|
244 if session.User == user { |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
245 delete(ss.sessions, token) |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
246 ss.remove(token) |
240
9012e4045da4
Implemented /user delete controller.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
220
diff
changeset
|
247 } |
9012e4045da4
Implemented /user delete controller.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
220
diff
changeset
|
248 } |
9012e4045da4
Implemented /user delete controller.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
220
diff
changeset
|
249 } |
9012e4045da4
Implemented /user delete controller.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
220
diff
changeset
|
250 } |
9012e4045da4
Implemented /user delete controller.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
220
diff
changeset
|
251 |
1343
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
252 // Shutdown closes the session store. |
9e0beb373690
Added comments how to use the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
1342
diff
changeset
|
253 // If using the persistent mode the backing session database is closed. |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
254 func (ss *SessionStore) Shutdown() error { |
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
255 if db := ss.storage; db != nil { |
5490
5f47eeea988d
Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
5320
diff
changeset
|
256 log.Infof("shutdown persistent session store.") |
513
b6796cd91604
Simplified the function channel inside the session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
498
diff
changeset
|
257 ss.storage = nil |
193
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
258 return db.Close() |
1585c334e8a7
More on persisting sessions.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
190
diff
changeset
|
259 } |
5490
5f47eeea988d
Use own logging package.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
5320
diff
changeset
|
260 log.Infof("shutdown in-memory session store.") |
190
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
261 return nil |
3457a60fb12d
Added stub for a persistent session store.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff
changeset
|
262 } |