1package queries
2
3import (
4 "database/sql"
5 "fmt"
6 "time"
7
8 "github.com/bnema/gordon/internal/db"
9 "github.com/bnema/gordon/internal/server"
10)
11
12// createSession creates a session for the user.
13func createDBSession(a *server.App, browserInfo string, accessToken string, accountID string) error {
14 expireTime := time.Now().Add(time.Hour * 24).Format(time.RFC3339)
15 sessions := &db.Sessions{
16 ID: generateUUID(),
17 AccessToken: accessToken,
18 }
19
20 query := "INSERT INTO sessions (id, account_id, access_token, browser_info, expires, is_online) VALUES (?, ?, ?, ?, ?, ?)"
21 _, err := a.DB.Exec(query, sessions.ID, accountID, accessToken, browserInfo, expireTime, true)
22 if err != nil {
23 return err
24 }
25
26 // Update global state here if really necessary
27 a.DBTables.Sessions.ID = sessions.ID
28 a.DBTables.Sessions.AccessToken = accessToken
29 a.DBTables.Sessions.Expires = expireTime
30
31 return nil
32}
33
34// GetDBUserSession gets the user session from the database based on the access token and browser info.
35func GetDBUserSession(a *server.App, accessToken string, browserInfo string) (*db.Sessions, error) {
36 query := "SELECT sessions.id, sessions.account_id, sessions.access_token, sessions.browser_info, sessions.expires, sessions.is_online FROM sessions INNER JOIN account ON sessions.account_id = account.id INNER JOIN provider ON account.id = provider.account_id WHERE sessions.access_token = ? AND sessions.browser_info = ?"
37 err := a.DB.QueryRow(query, accessToken, browserInfo).Scan(&a.DBTables.Sessions.ID, &a.DBTables.Sessions.AccountID, &a.DBTables.Sessions.AccessToken, &a.DBTables.Sessions.BrowserInfo, &a.DBTables.Sessions.Expires, &a.DBTables.Sessions.IsOnline)
38 if err != nil {
39 if err == sql.ErrNoRows {
40 return nil, nil
41 }
42 return nil, fmt.Errorf("error getting session: %w", err)
43 }
44
45 return &a.DBTables.Sessions, nil
46}
47
48func updateDBSession(a *server.App, accessToken string, browserInfo string) error {
49 expireTime := time.Now().Add(time.Hour * 24).Format(time.RFC3339)
50 query := "UPDATE sessions SET access_token = ?, expires = ? WHERE id = ?"
51 _, err := a.DB.Exec(query, accessToken, expireTime, a.DBTables.Sessions.ID)
52 if err != nil {
53 return err
54 }
55
56 return nil
57}
58
59func CreateOrUpdateDBSession(a *server.App, accessToken string, browserInfo string) error {
60 // Check if the session exists using the access token and browser info
61 session, err := GetDBUserSession(a, accessToken, browserInfo)
62 if err != nil && err != sql.ErrNoRows {
63 return fmt.Errorf("error checking for session: %w", err)
64 }
65
66 // If the session exists, update the session
67 if session != nil {
68 err := updateDBSession(a, accessToken, browserInfo)
69 if err != nil {
70 return fmt.Errorf("error updating session: %w", err)
71 }
72 }
73
74 // If the session does not exist, create the session
75 if session == nil {
76 err := createDBSession(a, browserInfo, accessToken, a.DBTables.Account.ID)
77 if err != nil {
78 return fmt.Errorf("error creating session: %w", err)
79 }
80 }
81
82 return nil
83}
84
85// DeleteSession deletes the session from the database.
86func DeleteDBSession(a *server.App, accountID string, sessionID string) error {
87 query := "DELETE FROM sessions WHERE account_id = ? AND id = ?"
88 _, err := a.DB.Exec(query, accountID, sessionID)
89 if err != nil {
90 return err
91 }
92
93 return nil
94}
95
96func GetSessionExpiration(a *server.App, accountID string, sessionID string, currentTime time.Time) (time.Time, error) {
97 var expirationTime string
98 // with userID and sessionID we can get the expiration time
99 query := "SELECT expires FROM sessions WHERE account_id = ? AND id = ?"
100 err := a.DB.QueryRow(query, accountID, sessionID).Scan(&expirationTime)
101 if err != nil {
102 return currentTime, err
103 }
104
105 // convert the expiration time to a time.Time
106 expirationTimeParsed, err := time.Parse(time.RFC3339, expirationTime)
107 if err != nil {
108 return currentTime, err
109 }
110
111 return expirationTimeParsed, nil
112}
113
114func ExtendSessionExpiration(a *server.App, accountID string, sessionID string, newExpirationTime time.Time) error {
115 query := "UPDATE sessions SET expires = ? WHERE account_id = ? AND id = ?"
116 _, err := a.DB.Exec(query, newExpirationTime.Format(time.RFC3339), accountID, sessionID)
117 if err != nil {
118 return err
119 }
120
121 return nil
122}
123
124func CheckDBSessionExists(a *server.App, sessionID string) (bool, error) {
125 var sessionExists bool
126 query := "SELECT EXISTS(SELECT 1 FROM sessions WHERE id = ?)"
127 err := a.DB.QueryRow(query, sessionID).Scan(&sessionExists)
128 if err != nil {
129 return false, err
130 }
131
132 return sessionExists, nil
133}
134
135func InvalidateDBSession(a *server.App, sessionID string) error {
136 query := "UPDATE sessions SET is_online = ? WHERE id = ?"
137 _, err := a.DB.Exec(query, false, sessionID)
138 if err != nil {
139 return err
140 }
141
142 return nil
143}