package database import ( "fmt" "os" "path/filepath" "time" bolt "go.etcd.io/bbolt" ) const ( usersBucket string = "users" ) func New(path string) (*bolt.DB, error) { dir := filepath.Dir(path) if err := os.MkdirAll(dir, 0o700); err != nil { return nil, fmt.Errorf("unable to create directory %q: %w", dir, err) } opts := bolt.Options{ Timeout: 1 * time.Second, } boltdb, err := bolt.Open(path, 0o600, &opts) if err != nil { return nil, fmt.Errorf( "unable to open the database at %q: %w", path, err, ) } if err := ensureBuckets(boltdb); err != nil { return nil, fmt.Errorf( "unable to ensure that the required buckets are present in the database: %w", err, ) } return boltdb, nil } func ensureBuckets(boltdb *bolt.DB) error { err := boltdb.Update(func(tx *bolt.Tx) error { for _, bucket := range getBuckets() { if _, err := tx.CreateBucketIfNotExists(bucket); err != nil { return fmt.Errorf( "unable to ensure the existence of the %q bucket: %w", string(bucket), err, ) } } return nil }) if err != nil { return fmt.Errorf( "error ensuring the existence of the buckets in the database: %w", err, ) } return nil } func getBuckets() [][]byte { return [][]byte{[]byte(usersBucket)} }