package metastore import ( "errors" "fmt" "strings" "time" "github.com/dgraph-io/badger/v4" "warpbox/lib/helpers" ) func (store *Store) CreateSession(userID string, ttl time.Duration) (Session, error) { userID = strings.TrimSpace(userID) if userID == "" { return Session{}, fmt.Errorf("%w: user id cannot be empty", ErrInvalid) } if ttl <= 0 { return Session{}, fmt.Errorf("%w: session ttl must be positive", ErrInvalid) } token, err := helpers.RandomHexID(32) if err != nil { return Session{}, err } csrfToken, err := helpers.RandomHexID(32) if err != nil { return Session{}, err } now := time.Now().UTC() session := Session{ Token: token, CSRFToken: csrfToken, UserID: userID, CreatedAt: now, ExpiresAt: now.Add(ttl), } err = store.db.Update(func(txn *badger.Txn) error { return putJSON(txn, sessionKey(token), session) }) return session, err } func (store *Store) GetSession(token string) (Session, bool, error) { token = strings.TrimSpace(token) if token == "" { return Session{}, false, nil } var session Session err := store.db.View(func(txn *badger.Txn) error { return getJSON(txn, sessionKey(token), &session) }) if errors.Is(err, ErrNotFound) { return Session{}, false, nil } if err != nil { return Session{}, false, err } if time.Now().UTC().After(session.ExpiresAt) { _ = store.DeleteSession(token) return Session{}, false, nil } return session, true, nil } func (store *Store) DeleteSession(token string) error { return store.db.Update(func(txn *badger.Txn) error { err := txn.Delete(sessionKey(token)) if errors.Is(err, badger.ErrKeyNotFound) { return nil } return err }) } func sessionKey(token string) []byte { return []byte("session/" + strings.TrimSpace(token)) }