-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathsession_store_database.go
More file actions
123 lines (107 loc) · 3.08 KB
/
Copy pathsession_store_database.go
File metadata and controls
123 lines (107 loc) · 3.08 KB
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
package limen
import (
"context"
"fmt"
"maps"
)
type databaseSessionStore struct {
core *LimenCore
schema *SessionSchema
}
func newDatabaseSessionStore(core *LimenCore) *databaseSessionStore {
return &databaseSessionStore{
core: core,
schema: core.Schema.Session,
}
}
func (s *databaseSessionStore) Get(ctx context.Context, token string) (*Session, error) {
session, err := s.core.FindOne(ctx, s.schema, []Where{
Eq(s.schema.GetTokenField(), token),
}, nil)
if err != nil {
return nil, err
}
return session.(*Session), nil
}
func (s *databaseSessionStore) Set(ctx context.Context, data any) error {
switch v := data.(type) {
case *Session:
payload := make(map[SchemaField]any)
for column, value := range s.schema.ToStorage(v) {
payload[SchemaField(column)] = value
}
if v.ID == nil {
return s.core.Create(ctx, s.schema, payload, nil)
}
return s.write(ctx, payload)
case map[SchemaField]any:
return s.write(ctx, maps.Clone(v))
default:
return errUnsupportedSessionData(data)
}
}
func (s *databaseSessionStore) write(ctx context.Context, payload map[SchemaField]any) error {
token, err := sessionPayloadToken(payload)
if err != nil {
return err
}
update := maps.Clone(payload)
delete(update, SessionSchemaTokenField)
if len(update) == 0 {
return nil
}
result, err := s.core.UpdateWithResult(ctx, s.schema, update, []Where{
Eq(s.schema.GetTokenField(), token),
})
if err != nil {
return err
}
if result.RowsAffected > 0 {
return nil
}
return s.core.Create(ctx, s.schema, payload, nil)
}
func (s *databaseSessionStore) UpdateSessions(ctx context.Context, data map[SchemaField]any, match map[SchemaField]any) error {
columns, err := s.schema.sessionColumns(match)
if err != nil {
return err
}
conditions := make([]Where, 0, len(columns))
for column, value := range columns {
conditions = append(conditions, Eq(column, value))
}
return s.core.Update(ctx, s.schema, data, conditions)
}
func sessionPayloadToken(payload map[SchemaField]any) (string, error) {
token, ok := payload[SessionSchemaTokenField].(string)
if !ok || token == "" {
return "", fmt.Errorf("session store: session data requires %q", SessionSchemaTokenField)
}
return token, nil
}
func errUnsupportedSessionData(data any) error {
return fmt.Errorf("session store: unsupported data type %T, want *limen.Session or map[limen.SchemaField]any", data)
}
func (s *databaseSessionStore) Delete(ctx context.Context, token string) error {
return s.core.Delete(ctx, s.schema, []Where{
Eq(s.schema.GetTokenField(), token),
})
}
func (s *databaseSessionStore) DeleteByUserID(ctx context.Context, userID any) error {
return s.core.Delete(ctx, s.schema, []Where{
Eq(s.schema.GetUserIDField(), userID),
})
}
func (s *databaseSessionStore) ListByUserID(ctx context.Context, userID any) ([]Session, error) {
models, err := s.core.FindMany(ctx, s.schema, []Where{
Eq(s.schema.GetUserIDField(), userID),
})
if err != nil {
return nil, err
}
sessions := make([]Session, 0, len(models))
for _, m := range models {
sessions = append(sessions, *m.(*Session))
}
return sessions, nil
}