package lishwist import ( "database/sql" "errors" "fmt" "time" "lishwist/core/internal/db" "lishwist/core/internal/id" ) type Session struct { user User Key string Expiry time.Time } // Returns a copy of the user associated with this session func (s *Session) User() User { return s.user } func SessionFromKey(key string) (*Session, error) { s := Session{} query := "SELECT user.id, user.name, user.display_name, user.reference, user.is_admin, user.is_live, session.key, session.expiry FROM v_user as user JOIN session ON user.id = session.user_id WHERE session.key = ?" var expiry string err := db.Connection.QueryRow(query, key).Scan( &s.user.Id, &s.user.NormalName, &s.user.Name, &s.user.Reference, &s.user.IsAdmin, &s.user.IsLive, &s.Key, &expiry, ) if errors.Is(err, sql.ErrNoRows) { return nil, nil } if err != nil { return nil, fmt.Errorf("failed to fetch session: %w", err) } s.Expiry, err = time.Parse(time.RFC3339Nano, expiry) if err != nil { return nil, fmt.Errorf("failed to parse session expiry: %w", err) } if time.Now().After(s.Expiry) { return nil, nil } return &s, err } func insertSession(user User, maxAge time.Duration) (*Session, error) { s := Session{ user: user, Key: id.Generate(), Expiry: time.Now().Add(maxAge), } stmt := "INSERT INTO session (key, user_id, expiry) VALUES (?, ?, ?)" _, err := db.Connection.Exec(stmt, &s.Key, &user.Id, &s.Expiry) if err != nil { return nil, fmt.Errorf("failed to execute query: %w", err) } return &s, nil }