2015-04-30 11:47:07 -05:00
|
|
|
package bookmarks
|
2014-12-02 22:19:38 -06:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2022-11-14 15:47:36 -06:00
|
|
|
"os"
|
2014-12-02 22:19:38 -06:00
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/BurntSushi/toml"
|
|
|
|
"github.com/mitchellh/go-homedir"
|
2016-01-14 19:50:01 -06:00
|
|
|
|
2016-11-10 01:22:16 -05:00
|
|
|
"github.com/sosedoff/pgweb/pkg/command"
|
2016-01-14 19:50:01 -06:00
|
|
|
"github.com/sosedoff/pgweb/pkg/shared"
|
2014-12-02 22:19:38 -06:00
|
|
|
)
|
|
|
|
|
2019-11-02 13:00:23 -05:00
|
|
|
// Bookmark contains information about bookmarked database connection
|
2014-12-02 22:19:38 -06:00
|
|
|
type Bookmark struct {
|
2019-11-02 13:00:23 -05:00
|
|
|
URL string `json:"url"` // Postgres connection URL
|
2017-09-26 23:29:28 -05:00
|
|
|
Host string `json:"host"` // Server hostname
|
|
|
|
Port int `json:"port"` // Server port
|
|
|
|
User string `json:"user"` // Database user
|
|
|
|
Password string `json:"password"` // User password
|
|
|
|
Database string `json:"database"` // Database name
|
2022-11-23 16:21:30 -06:00
|
|
|
SSLMode string `json:"ssl"` // Connection SSL mode
|
2019-11-02 13:00:23 -05:00
|
|
|
SSH *shared.SSHInfo `json:"ssh"` // SSH tunnel config
|
2014-12-02 22:19:38 -06:00
|
|
|
}
|
|
|
|
|
2022-12-12 15:09:12 -06:00
|
|
|
// SSHInfoIsEmpty returns true if ssh configuration is not provided
|
2016-11-10 01:21:49 -05:00
|
|
|
func (b Bookmark) SSHInfoIsEmpty() bool {
|
2019-11-02 13:00:23 -05:00
|
|
|
return b.SSH == nil || b.SSH.User == "" && b.SSH.Host == "" && b.SSH.Port == ""
|
2016-11-10 01:21:49 -05:00
|
|
|
}
|
2016-11-10 01:22:16 -05:00
|
|
|
|
2019-11-02 13:00:23 -05:00
|
|
|
// ConvertToOptions returns an options struct from connection details
|
2016-11-15 22:03:32 -05:00
|
|
|
func (b Bookmark) ConvertToOptions() command.Options {
|
2016-11-10 01:22:16 -05:00
|
|
|
return command.Options{
|
2022-11-23 16:21:30 -06:00
|
|
|
URL: b.URL,
|
|
|
|
Host: b.Host,
|
|
|
|
Port: b.Port,
|
|
|
|
User: b.User,
|
|
|
|
Pass: b.Password,
|
|
|
|
DbName: b.Database,
|
|
|
|
SSLMode: b.SSLMode,
|
2016-11-15 22:03:32 -05:00
|
|
|
}
|
2016-11-10 01:22:16 -05:00
|
|
|
}
|
|
|
|
|
2014-12-02 22:19:38 -06:00
|
|
|
func readServerConfig(path string) (Bookmark, error) {
|
|
|
|
bookmark := Bookmark{}
|
|
|
|
|
2022-11-14 15:47:36 -06:00
|
|
|
buff, err := os.ReadFile(path)
|
2014-12-02 22:19:38 -06:00
|
|
|
if err != nil {
|
|
|
|
return bookmark, err
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = toml.Decode(string(buff), &bookmark)
|
2016-11-15 22:01:42 -06:00
|
|
|
|
|
|
|
if bookmark.Port == 0 {
|
|
|
|
bookmark.Port = 5432
|
|
|
|
}
|
|
|
|
|
2018-01-08 10:55:05 +01:00
|
|
|
// List of all supported postgres modes
|
2017-11-11 08:12:27 -06:00
|
|
|
modes := []string{"disable", "allow", "prefer", "require", "verify-ca", "verify-full"}
|
2017-06-05 21:29:09 -05:00
|
|
|
valid := false
|
|
|
|
|
|
|
|
for _, mode := range modes {
|
2022-11-23 16:21:30 -06:00
|
|
|
if bookmark.SSLMode == mode {
|
2017-06-05 21:29:09 -05:00
|
|
|
valid = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fall back to a default mode if mode is not set or invalid
|
|
|
|
// Typical typo: ssl mode set to "disabled"
|
2022-11-23 16:21:30 -06:00
|
|
|
if bookmark.SSLMode == "" || !valid {
|
|
|
|
bookmark.SSLMode = "disable"
|
2017-06-05 21:29:09 -05:00
|
|
|
}
|
|
|
|
|
2019-11-02 12:44:04 -05:00
|
|
|
// Set default SSH port if it's not provided by user
|
2019-11-02 13:00:23 -05:00
|
|
|
if bookmark.SSH != nil && bookmark.SSH.Port == "" {
|
|
|
|
bookmark.SSH.Port = "22"
|
2017-09-26 23:29:28 -05:00
|
|
|
}
|
|
|
|
|
2014-12-02 22:19:38 -06:00
|
|
|
return bookmark, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func fileBasename(path string) string {
|
|
|
|
filename := filepath.Base(path)
|
|
|
|
return strings.Replace(filename, filepath.Ext(path), "", 1)
|
|
|
|
}
|
|
|
|
|
2019-11-02 13:00:23 -05:00
|
|
|
// Path returns bookmarks storage path
|
2017-01-24 07:55:18 +07:00
|
|
|
func Path(overrideDir string) string {
|
|
|
|
if overrideDir == "" {
|
|
|
|
path, _ := homedir.Dir()
|
|
|
|
return fmt.Sprintf("%s/.pgweb/bookmarks", path)
|
|
|
|
}
|
|
|
|
return overrideDir
|
2014-12-02 22:19:38 -06:00
|
|
|
}
|
|
|
|
|
2019-11-02 13:00:23 -05:00
|
|
|
// ReadAll returns all available bookmarks
|
2015-04-30 11:47:07 -05:00
|
|
|
func ReadAll(path string) (map[string]Bookmark, error) {
|
2014-12-02 22:19:38 -06:00
|
|
|
results := map[string]Bookmark{}
|
|
|
|
|
2022-11-14 15:47:36 -06:00
|
|
|
files, err := os.ReadDir(path)
|
2014-12-02 22:19:38 -06:00
|
|
|
if err != nil {
|
|
|
|
return results, err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, file := range files {
|
|
|
|
if filepath.Ext(file.Name()) != ".toml" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2019-11-02 13:00:23 -05:00
|
|
|
fullPath := filepath.Join(path, file.Name())
|
2014-12-02 22:19:38 -06:00
|
|
|
key := fileBasename(file.Name())
|
|
|
|
config, err := readServerConfig(fullPath)
|
|
|
|
|
|
|
|
if err != nil {
|
2015-03-03 20:14:18 -06:00
|
|
|
fmt.Printf("%s parse error: %s\n", fullPath, err)
|
2014-12-02 22:19:38 -06:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
results[key] = config
|
|
|
|
}
|
|
|
|
|
|
|
|
return results, nil
|
|
|
|
}
|
2016-11-10 01:22:07 -05:00
|
|
|
|
2019-11-02 13:00:23 -05:00
|
|
|
// GetBookmark reads an existing bookmark
|
2016-11-10 01:22:07 -05:00
|
|
|
func GetBookmark(bookmarkPath string, bookmarkName string) (Bookmark, error) {
|
|
|
|
bookmarks, err := ReadAll(bookmarkPath)
|
|
|
|
if err != nil {
|
|
|
|
return Bookmark{}, err
|
|
|
|
}
|
2016-11-15 21:58:58 -06:00
|
|
|
|
2016-11-10 01:22:07 -05:00
|
|
|
bookmark, ok := bookmarks[bookmarkName]
|
|
|
|
if !ok {
|
2016-11-12 12:30:15 -05:00
|
|
|
return Bookmark{}, fmt.Errorf("couldn't find a bookmark with name %s", bookmarkName)
|
2016-11-10 01:22:07 -05:00
|
|
|
}
|
|
|
|
|
2016-11-15 21:58:58 -06:00
|
|
|
return bookmark, nil
|
2016-11-10 01:22:07 -05:00
|
|
|
}
|