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// SessionCleaner, time as a string
86func SessionCleaner(a *server.App, currentTime string) error {
87 query := "DELETE FROM sessions WHERE expires < ?"
88 _, err := a.DB.Exec(query, currentTime)
89 if err != nil {
90 return err
91 }
92
93 return nil
94}
95
96// DeleteSession deletes the session from the database.
97func DeleteDBSession(a *server.App, accountID string, sessionID string) error {
98 query := "DELETE FROM sessions WHERE account_id = ? AND id = ?"
99 _, err := a.DB.Exec(query, accountID, sessionID)
100 if err != nil {
101 return err
102 }
103
104 return nil
105}
106
107func GetSessionExpiration(a *server.App, accountID string, sessionID string, currentTime time.Time) (time.Time, error) {
108 var expirationTime string
109 // with userID and sessionID we can get the expiration time
110 query := "SELECT expires FROM sessions WHERE account_id = ? AND id = ?"
111 err := a.DB.QueryRow(query, accountID, sessionID).Scan(&expirationTime)
112 if err != nil {
113 return currentTime, err
114 }
115
116 // convert the expiration time to a time.Time
117 expirationTimeParsed, err := time.Parse(time.RFC3339, expirationTime)
118 if err != nil {
119 return currentTime, err
120 }
121
122 return expirationTimeParsed, nil
123}