package storer import ( "bytes" "encoding/gob" "time" "github.com/dgraph-io/badger" "github.com/neonxp/sendsafe/internal/encryption" "github.com/rs/xid" ) type Store struct { db *badger.DB } func New(dbFile string) (*Store, error) { db, err := badger.Open(badger.DefaultOptions(dbFile)) if err != nil { return nil, err } return &Store{ db: db, }, nil } func (s *Store) Save(text string, pin string, ttl int) (string, error) { var err error encrypted := false if pin != "" { text, err = encryption.Encrypt([]byte(pin), text) if err != nil { return "", err } encrypted = true } record := memo{ Text: text, Encrypted: encrypted, } buf := bytes.NewBuffer([]byte{}) if err := gob.NewEncoder(buf).Encode(record); err != nil { return "", err } id := xid.New() err = s.db.Update(func(txn *badger.Txn) error { return txn.SetEntry(&badger.Entry{ Key: id.Bytes(), Value: buf.Bytes(), ExpiresAt: uint64(time.Now().Add(time.Duration(ttl) * time.Minute).Unix()), }) }) return id.String(), err } func (s *Store) IsEncrypted(id string) (bool, error) { var encrypted bool return encrypted, s.db.View(func(txn *badger.Txn) error { uid, err := xid.FromString(id) if err != nil { return err } value, err := txn.Get(uid.Bytes()) if err != nil { return err } record := new(memo) return value.Value(func(val []byte) error { if err := gob.NewDecoder(bytes.NewBuffer(val)).Decode(record); err != nil { return err } encrypted = record.Encrypted return nil }) }) } func (s *Store) Get(id string, pin string) (string, error) { var text string return text, s.db.Update(func(txn *badger.Txn) error { uid, err := xid.FromString(id) if err != nil { return err } value, err := txn.Get(uid.Bytes()) if err != nil { return err } record := new(memo) err = value.Value(func(val []byte) error { if err := gob.NewDecoder(bytes.NewBuffer(val)).Decode(record); err != nil { return err } return nil }) if err != nil { return err } text = record.Text if record.Encrypted { text, err = encryption.Decrypt([]byte(pin), text) if err != nil { return err } } return txn.Delete(uid.Bytes()) }) } func init() { gob.Register(memo{}) } type memo struct { Text string Encrypted bool }