Something went wrong. Try again.
Monorepo for Tangled
Something went wrong. Try again.
Go
at sl/comment
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177// an sqlite3 backed secret managerpackage secrets
import ( "context" "database/sql" "fmt" "time"
_ "github.com/mattn/go-sqlite3")
type SqliteManager struct { db *sql.DB tableName string}
type SqliteManagerOpt func(*SqliteManager)
func WithTableName(name string) SqliteManagerOpt { return func(s *SqliteManager) { s.tableName = name }}
func NewSQLiteManager(dbPath string, opts ...SqliteManagerOpt) (*SqliteManager, error) { db, err := sql.Open("sqlite3", dbPath+"?_foreign_keys=1") if err != nil { return nil, fmt.Errorf("failed to open sqlite database: %w", err) }
manager := &SqliteManager{ db: db, tableName: "secrets", }
for _, o := range opts { o(manager) }
if err := manager.init(); err != nil { return nil, err }
return manager, nil}
// creates a table and sets up the schema, migrations if any can go herefunc (s *SqliteManager) init() error { createTable := `create table if not exists ` + s.tableName + `( id integer primary key autoincrement, repo text not null, key text not null, value text not null, created_at text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), created_by text not null,
unique(repo, key) );` _, err := s.db.Exec(createTable) return err}
func (s *SqliteManager) AddSecret(ctx context.Context, secret UnlockedSecret) error { query := fmt.Sprintf(` insert or ignore into %s (repo, key, value, created_at, created_by) values (?, ?, ?, ?, ?); `, s.tableName)
createdAt := secret.CreatedAt if createdAt.IsZero() { createdAt = time.Now() } res, err := s.db.ExecContext(ctx, query, secret.Repo, secret.Key, secret.Value, createdAt.UTC().Format(time.RFC3339), secret.CreatedBy) if err != nil { return err }
num, err := res.RowsAffected() if err != nil { return err }
if num == 0 { return ErrKeyAlreadyPresent }
return nil}
func (s *SqliteManager) RemoveSecret(ctx context.Context, secret Secret[any]) error { query := fmt.Sprintf(` delete from %s where repo = ? and key = ?; `, s.tableName)
res, err := s.db.ExecContext(ctx, query, secret.Repo, secret.Key) if err != nil { return err }
num, err := res.RowsAffected() if err != nil { return err }
if num == 0 { return ErrKeyNotFound }
return nil}
func (s *SqliteManager) GetSecretsLocked(ctx context.Context, didSlashRepo RepoIdentifier) ([]LockedSecret, error) { query := fmt.Sprintf(` select repo, key, created_at, created_by from %s where repo = ?; `, s.tableName)
rows, err := s.db.QueryContext(ctx, query, didSlashRepo) if err != nil { return nil, err }
var ls []LockedSecret for rows.Next() { var l LockedSecret var createdAt string if err = rows.Scan(&l.Repo, &l.Key, &createdAt, &l.CreatedBy); err != nil { return nil, err }
if t, err := time.Parse(time.RFC3339, createdAt); err == nil { l.CreatedAt = t }
ls = append(ls, l) }
if err = rows.Err(); err != nil { return nil, err }
return ls, nil}
func (s *SqliteManager) GetSecretsUnlocked(ctx context.Context, didSlashRepo RepoIdentifier) ([]UnlockedSecret, error) { query := fmt.Sprintf(` select repo, key, value, created_at, created_by from %s where repo = ?; `, s.tableName)
rows, err := s.db.QueryContext(ctx, query, didSlashRepo) if err != nil { return nil, err }
var ls []UnlockedSecret for rows.Next() { var l UnlockedSecret var createdAt string if err = rows.Scan(&l.Repo, &l.Key, &l.Value, &createdAt, &l.CreatedBy); err != nil { return nil, err }
if t, err := time.Parse(time.RFC3339, createdAt); err == nil { l.CreatedAt = t }
ls = append(ls, l) }
if err = rows.Err(); err != nil { return nil, err }
return ls, nil}