summaryrefslogtreecommitdiff
path: root/db/session.go
diff options
context:
space:
mode:
Diffstat (limited to 'db/session.go')
-rw-r--r--db/session.go127
1 files changed, 127 insertions, 0 deletions
diff --git a/db/session.go b/db/session.go
new file mode 100644
index 0000000..bddedda
--- /dev/null
+++ b/db/session.go
@@ -0,0 +1,127 @@
+package db
+
+import (
+ "database/sql"
+ "crypto/rand"
+ "encoding/base64"
+ "errors"
+ "time"
+)
+
+
+func (p *Phlox) CreateSession(user User) (Session, error) {
+ bytes := make([]byte, 32)
+ _, err := rand.Read(bytes)
+ if err != nil {
+ return Session{}, err
+ }
+
+ sessionid := base64.StdEncoding.EncodeToString(bytes)
+ userid := user.Id
+ now := time.Now().UTC()
+ nowStr := now.Format(time.RFC3339)
+
+ _, err = p.db.Exec(
+ "insert into sessions (sessionid, userid, created, modified) values (?, ?, ?, ?);",
+ sessionid,
+ userid,
+ nowStr, nowStr,
+ )
+ if err != nil {
+ return Session{}, err
+ }
+
+ return Session{
+ Id: sessionid,
+ UserId: userid,
+ Created: now,
+ Modified: now,
+ }, nil
+}
+
+
+func (p *Phlox) DeleteSession(session Session) error {
+ _, err := p.db.Exec("delete from sessions where sessionid = ?;", session.Id)
+ return err
+}
+
+
+func extractSession(s Scanner) (Session, error) {
+ var (
+ session Session
+ createdStr string
+ modifiedStr string
+ )
+
+ // scan
+ err := s.Scan(&session.Id, &session.UserId, &createdStr, &modifiedStr)
+ if err != nil {
+ return Session{}, err
+ }
+
+ // parse times
+ session.Created, err = time.Parse(time.RFC3339, createdStr)
+ if err != nil {
+ return Session{}, err
+ }
+ session.Modified, err = time.Parse(time.RFC3339, modifiedStr)
+ if err != nil {
+ return Session{}, err
+ }
+
+ return session, nil
+}
+
+
+func (p *Phlox) CheckSession(session Session) (bool, error) {
+ row := p.db.QueryRow("select * from sessions where sessionid = ?", session.Id)
+ session, err := extractSession(row)
+ if err != nil {
+ if errors.Is(err, sql.ErrNoRows) {
+ // no row returned, so invalid session
+ return false, nil
+ } else {
+ // some other error
+ return false, err
+ }
+ }
+
+ return true, nil
+}
+
+
+func (p *Phlox) TouchSession(session Session) error {
+ now := time.Now().UTC().Format(time.RFC3339)
+ _, err := p.db.Exec(
+ "update sessions set modified = ? where sessionid = ?;",
+ now, session.Id,
+ )
+ return err
+}
+
+
+func (p *Phlox) CleanSessions(maxIdle time.Duration) error {
+ expire := time.Now().UTC().Add(-maxIdle).Format(time.RFC3339)
+ _, err := p.db.Exec("delete from sessions where modified < ?;", expire)
+ return err
+}
+
+
+func (p *Phlox) AllSessions() ([]Session, error) {
+ sessions := make([]Session, 0)
+ rows, err := p.db.Query("select * from sessions;")
+ if err != nil {
+ return sessions, err
+ }
+ defer rows.Close()
+
+ for rows.Next() {
+ session, err := extractSession(rows)
+ if err != nil {
+ return sessions, err
+ }
+ sessions = append(sessions, session)
+ }
+
+ return sessions, nil
+}