Monorepo for Tangled tangled.org
6

Configure Feed

Select the types of activity you want to include in your feed.

1// an sqlite3 backed secret manager 2package secrets 3 4import ( 5 "context" 6 "database/sql" 7 "fmt" 8 "time" 9 10 _ "github.com/mattn/go-sqlite3" 11) 12 13type SqliteManager struct { 14 db *sql.DB 15 tableName string 16} 17 18type SqliteManagerOpt func(*SqliteManager) 19 20func WithTableName(name string) SqliteManagerOpt { 21 return func(s *SqliteManager) { 22 s.tableName = name 23 } 24} 25 26func NewSQLiteManager(dbPath string, opts ...SqliteManagerOpt) (*SqliteManager, error) { 27 db, err := sql.Open("sqlite3", dbPath+"?_foreign_keys=1") 28 if err != nil { 29 return nil, fmt.Errorf("failed to open sqlite database: %w", err) 30 } 31 32 manager := &SqliteManager{ 33 db: db, 34 tableName: "secrets", 35 } 36 37 for _, o := range opts { 38 o(manager) 39 } 40 41 if err := manager.init(); err != nil { 42 return nil, err 43 } 44 45 return manager, nil 46} 47 48// creates a table and sets up the schema, migrations if any can go here 49func (s *SqliteManager) init() error { 50 createTable := 51 `create table if not exists ` + s.tableName + `( 52 id integer primary key autoincrement, 53 repo text not null, 54 key text not null, 55 value text not null, 56 created_at text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')), 57 created_by text not null, 58 59 unique(repo, key) 60 );` 61 _, err := s.db.Exec(createTable) 62 return err 63} 64 65func (s *SqliteManager) AddSecret(ctx context.Context, secret UnlockedSecret) error { 66 query := fmt.Sprintf(` 67 insert or ignore into %s (repo, key, value, created_at, created_by) 68 values (?, ?, ?, ?, ?); 69 `, s.tableName) 70 71 createdAt := secret.CreatedAt 72 if createdAt.IsZero() { 73 createdAt = time.Now() 74 } 75 res, err := s.db.ExecContext(ctx, query, secret.Repo, secret.Key, secret.Value, createdAt.UTC().Format(time.RFC3339), secret.CreatedBy) 76 if err != nil { 77 return err 78 } 79 80 num, err := res.RowsAffected() 81 if err != nil { 82 return err 83 } 84 85 if num == 0 { 86 return ErrKeyAlreadyPresent 87 } 88 89 return nil 90} 91 92func (s *SqliteManager) RemoveSecret(ctx context.Context, secret Secret[any]) error { 93 query := fmt.Sprintf(` 94 delete from %s where repo = ? and key = ?; 95 `, s.tableName) 96 97 res, err := s.db.ExecContext(ctx, query, secret.Repo, secret.Key) 98 if err != nil { 99 return err 100 } 101 102 num, err := res.RowsAffected() 103 if err != nil { 104 return err 105 } 106 107 if num == 0 { 108 return ErrKeyNotFound 109 } 110 111 return nil 112} 113 114func (s *SqliteManager) GetSecretsLocked(ctx context.Context, didSlashRepo RepoIdentifier) ([]LockedSecret, error) { 115 query := fmt.Sprintf(` 116 select repo, key, created_at, created_by from %s where repo = ?; 117 `, s.tableName) 118 119 rows, err := s.db.QueryContext(ctx, query, didSlashRepo) 120 if err != nil { 121 return nil, err 122 } 123 124 var ls []LockedSecret 125 for rows.Next() { 126 var l LockedSecret 127 var createdAt string 128 if err = rows.Scan(&l.Repo, &l.Key, &createdAt, &l.CreatedBy); err != nil { 129 return nil, err 130 } 131 132 if t, err := time.Parse(time.RFC3339, createdAt); err == nil { 133 l.CreatedAt = t 134 } 135 136 ls = append(ls, l) 137 } 138 139 if err = rows.Err(); err != nil { 140 return nil, err 141 } 142 143 return ls, nil 144} 145 146func (s *SqliteManager) GetSecretsUnlocked(ctx context.Context, didSlashRepo RepoIdentifier) ([]UnlockedSecret, error) { 147 query := fmt.Sprintf(` 148 select repo, key, value, created_at, created_by from %s where repo = ?; 149 `, s.tableName) 150 151 rows, err := s.db.QueryContext(ctx, query, didSlashRepo) 152 if err != nil { 153 return nil, err 154 } 155 156 var ls []UnlockedSecret 157 for rows.Next() { 158 var l UnlockedSecret 159 var createdAt string 160 if err = rows.Scan(&l.Repo, &l.Key, &l.Value, &createdAt, &l.CreatedBy); err != nil { 161 return nil, err 162 } 163 164 if t, err := time.Parse(time.RFC3339, createdAt); err == nil { 165 l.CreatedAt = t 166 } 167 168 ls = append(ls, l) 169 } 170 171 if err = rows.Err(); err != nil { 172 return nil, err 173 } 174 175 return ls, nil 176}