-
-
Notifications
You must be signed in to change notification settings - Fork 9
/
persistence.go
146 lines (135 loc) · 5.68 KB
/
persistence.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package sessions
// PersistenceLayer provides the methods which read/write user information
// from/to the permanent data store.
type PersistenceLayer interface {
// LoadSession retrieves a session from the permanent data store and returns
// it. If no session is found for the given ID, that's not an error. A nil
// session should be returned in that case.
//
// Session stores are typically key-value databases. We can use encoding/gob
// to unserialize sessions. For example, if your session store accepts only
// string pairs, this is how we can load a Base64-encoded session:
//
// func LoadSession(id string) (*Session, error) {
// // Load Base64-string s from database first...
// data, err := base64.StdEncoding.DecodeString(s)
// if err != nil {
// return nil, err
// }
// r := bytes.NewReader(data)
// decoder := gob.NewDecoder(r)
// var session Session
// if err := decoder.Decode(&session); err != nil {
// return nil, err
// }
// return &session, nil
// }
//
// Alternatively, the json.Unmarshaler interface may be used.
//
// When using the built-in decoders (gob or json) and a User was attached to
// the session, LoadUser() is called implicitly with the stored user ID.
LoadSession(id string) (*Session, error)
// SaveSession saves a session to the permanent data store. If the store does
// not contain the session yet, it is inserted. Otherwise, it is simply
// updated. Session stores are typically key-value databases. We can use
// encoding/gob to serialize sessions. For example, if your session store
// accepts only string pairs, this is how we can save a Base64-encoded
// session:
//
// func SaveSession(id string, session *Session) error {
// var buffer bytes.Buffer
// encoder := gob.NewEncoder(&buffer)
// if err := encoder.Encode(session); err != nil {
// return err
// }
// s := base64.StdEncoding.EncodeToString(buffer.Bytes())
// // Now save id + s to database.
// return nil
// }
//
// Alternatively, the json.Marshaler interface may be used. Note, however,
// that while JSON serialization allows you to peek into the serialized data,
// it may not convert values back the same as they were stored: Any numeric
// values will convert back as float64 types, all slices will convert back
// as []interface{}, and all maps will convert back as map[string]interface{}.
//
// The internal encoders (gob or json) do not save the full User object but
// only the user ID.
//
// Session IDs are always Base64-encoded strings with a length of 24.
//
// The session object is locked while this function is called.
SaveSession(id string, session *Session) error
// DeleteSession deletes a session from the permanent data store. It is not
// an error if the session ID does not exist.
//
// Note that this package only deletes expired sessions that are accessed. If
// a session expires because e.g. the user does not come back, it will not
// be deleted via this method. It is suggested that you periodically run a
// cron job to purge sessions that have expired. Use session.Expired() for
// this or, if you can access session data directly:
//
// session.referenceID != "" &&
// time.Since(session.lastAccess) >= SessionIDGracePeriod ||
// time.Since(session.lastAccess) >= SessionExpiry &&
// time.Since(session.created) >= SessionIDExpiry+SessionIDGracePeriod
DeleteSession(id string) error
// UserSessions returns all session IDs of sessions which have the given user
// (specified by their user ID) attached to them. This is only used to log
// users out of all of their existing sessions. You may return nil, which will
// allow users to be logged on with multiple different sessions at the same
// time.
UserSessions(userID interface{}) ([]string, error)
// LoadUser loads the user with the given unqiue user ID (typically the
// primary key) from the data store.
LoadUser(id interface{}) (User, error)
}
// ExtendablePersistenceLayer implements the PersistenceLayer interface by doing
// nothing (or the absolute minimum) or, if one of the field functions are set,
// calling those instead.
//
// Use this type if you only intend to use a small part of this package's
// functionality.
type ExtendablePersistenceLayer struct {
LoadSessionFunc func(id string) (*Session, error)
SaveSessionFunc func(id string, session *Session) error
DeleteSessionFunc func(id string) error
UserSessionsFunc func(userID interface{}) ([]string, error)
LoadUserFunc func(id interface{}) (User, error)
}
// LoadSession delegates to LoadSessionFunc or returns a nil session.
func (p ExtendablePersistenceLayer) LoadSession(id string) (*Session, error) {
if p.LoadSessionFunc != nil {
return p.LoadSessionFunc(id)
}
return nil, nil
}
// SaveSession delegates to SaveSessionFunc or does nothing.
func (p ExtendablePersistenceLayer) SaveSession(id string, session *Session) error {
if p.SaveSessionFunc != nil {
return p.SaveSessionFunc(id, session)
}
return nil
}
// DeleteSession delegates to DeleteSessionFunc or does nothing.
func (p ExtendablePersistenceLayer) DeleteSession(id string) error {
if p.DeleteSessionFunc != nil {
return p.DeleteSessionFunc(id)
}
return nil
}
// UserSessions delegates to UserSessionsFunc or returns nil.
func (p ExtendablePersistenceLayer) UserSessions(userID interface{}) ([]string, error) {
if p.UserSessionsFunc != nil {
return p.UserSessionsFunc(userID)
}
return nil, nil
}
// LoadUser delegates to LoadUserFunc or returns a nil user.
func (p ExtendablePersistenceLayer) LoadUser(id interface{}) (User, error) {
if p.LoadUserFunc != nil {
return p.LoadUserFunc(id)
}
return nil, nil
}