forked from cyverse-de/user-info
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sessionsdb.go
157 lines (135 loc) · 4.2 KB
/
sessionsdb.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
147
148
149
150
151
152
153
154
155
156
157
package main
import (
"database/sql"
"encoding/json"
"github.com/cyverse-de/queries"
)
// UserSessionRecord represents a user session stored in the database
type UserSessionRecord struct {
ID string
Session string
UserID string
}
// convert makes sure that the JSON has the correct format. "wrap" tells convert
// whether to wrap the object in a map with "session" as the key.
func convertSessions(record *UserSessionRecord, wrap bool) (map[string]interface{}, error) {
var values map[string]interface{}
if record.Session != "" {
if err := json.Unmarshal([]byte(record.Session), &values); err != nil {
return nil, err
}
}
// We don't want the return value wrapped in a session object, so unwrap it
// if it is wrapped.
if !wrap {
if _, ok := values["session"]; ok {
return values["session"].(map[string]interface{}), nil
}
return values, nil
}
// We do want the return value wrapped in a session object, so wrap it if it
// isn't already.
if _, ok := values["session"]; !ok {
newmap := make(map[string]interface{})
newmap["session"] = values
return newmap, nil
}
return values, nil
}
type sDB interface {
isUser(username string) (bool, error)
// DB defines the interface for interacting with the user-sessions database.
hasSessions(username string) (bool, error)
getSessions(username string) ([]UserSessionRecord, error)
insertSession(username, session string) error
updateSession(username, session string) error
deleteSession(username string) error
}
// SessionsDB handles interacting with the sessions database.
type SessionsDB struct {
db *sql.DB
}
// NewSessionsDB returns a newly created *SessionsDB
func NewSessionsDB(db *sql.DB) *SessionsDB {
return &SessionsDB{
db: db,
}
}
// isUser returnes whether or not the user is present in the sessions database.
func (s *SessionsDB) isUser(username string) (bool, error) {
return queries.IsUser(s.db, username)
}
// hasSessions returns whether or not the given user has a session already.
func (s *SessionsDB) hasSessions(username string) (bool, error) {
query := `SELECT COUNT(s.*)
FROM user_sessions s,
users u
WHERE s.user_id = u.id
AND u.username = $1`
var count int64
if err := s.db.QueryRow(query, username).Scan(&count); err != nil {
return false, err
}
return count > 0, nil
}
// getSessions returns a []UserSessionRecord of all of the sessions associated
// with the provided username.
func (s *SessionsDB) getSessions(username string) ([]UserSessionRecord, error) {
query := `SELECT s.id AS id,
s.user_id AS user_id,
s.session AS session
FROM user_sessions s,
users u
WHERE s.user_id = u.id
AND u.username = $1`
rows, err := s.db.Query(query, username)
if err != nil {
return nil, err
}
defer rows.Close()
var sessions []UserSessionRecord
for rows.Next() {
var session UserSessionRecord
if err := rows.Scan(&session.ID, &session.UserID, &session.Session); err != nil {
return nil, err
}
sessions = append(sessions, session)
}
if err := rows.Err(); err != nil {
return sessions, err
}
return sessions, nil
}
// insertSession adds a new session to the database for the user.
func (s *SessionsDB) insertSession(username, session string) error {
query := `INSERT INTO user_sessions (user_id, session)
VALUES ($1, $2)`
userID, err := queries.UserID(s.db, username)
if err != nil {
return err
}
_, err = s.db.Exec(query, userID, session)
return err
}
// updateSession updates the session in the database for the user.
func (s *SessionsDB) updateSession(username, session string) error {
query := `UPDATE ONLY user_sessions
SET session = $2
WHERE user_id = $1`
userID, err := queries.UserID(s.db, username)
if err != nil {
return err
}
_, err = s.db.Exec(query, userID, session)
return err
}
// deleteSession deletes the user's session from the database.
func (s *SessionsDB) deleteSession(username string) error {
query := `DELETE FROM ONLY user_sessions WHERE user_id = $1`
userID, err := queries.UserID(s.db, username)
if err != nil {
return err
}
_, err = s.db.Exec(query, userID)
return err
}