From d48172986e40799e356e46cb69aa17f3eb89b5c3 Mon Sep 17 00:00:00 2001 From: Dan Sosedoff Date: Mon, 28 Jan 2019 14:03:45 -0600 Subject: [PATCH 1/2] Fix error when automatic user detection fails --- pkg/api/api.go | 2 +- pkg/command/options.go | 19 +++++++++++++++++++ pkg/connection/connection_string.go | 19 ++++++++++++------- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/pkg/api/api.go b/pkg/api/api.go index 4f27f8c..56a13e3 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -133,7 +133,7 @@ func Connect(c *gin.Context) { } opts := command.Options{Url: url} - url, err := connection.FormatUrl(opts) + url, err := connection.FormatURL(opts) if err != nil { badRequest(c, err) diff --git a/pkg/command/options.go b/pkg/command/options.go index 7503ac5..7d998f2 100644 --- a/pkg/command/options.go +++ b/pkg/command/options.go @@ -3,6 +3,7 @@ package command import ( "errors" "os" + "os/user" "strings" "github.com/jessevdk/go-flags" @@ -58,6 +59,14 @@ func ParseOptions(args []string) (Options, error) { opts.Prefix = os.Getenv("URL_PREFIX") } + if (opts.Host == "localhost" || opts.Host == "127.0.0.1") && opts.User == "" { + if username := GetCurrentUser(); username != "" { + opts.User = username + } else { + opts.Host = "" + } + } + if os.Getenv("SESSIONS") != "" { opts.Sessions = true } @@ -105,6 +114,7 @@ func ParseOptions(args []string) (Options, error) { return opts, nil } +// SetDefaultOptions parses and assigns the options func SetDefaultOptions() error { opts, err := ParseOptions([]string{}) if err != nil { @@ -113,3 +123,12 @@ func SetDefaultOptions() error { Opts = opts return nil } + +// GetCurrentUser returns a current user name +func GetCurrentUser() string { + u, _ := user.Current() + if u != nil { + return u.Username + } + return os.Getenv("USER") +} diff --git a/pkg/connection/connection_string.go b/pkg/connection/connection_string.go index 51aba00..5a06f80 100644 --- a/pkg/connection/connection_string.go +++ b/pkg/connection/connection_string.go @@ -11,10 +11,13 @@ import ( "github.com/sosedoff/pgweb/pkg/command" ) +// Common errors var ( - formatError = errors.New("Invalid URL. Valid format: postgres://user:password@host:port/db?sslmode=mode") + errCantDetectUser = errors.New("Could not detect default username") + errInvalidURLFormat = errors.New("Invalid URL. Valid format: postgres://user:password@host:port/db?sslmode=mode") ) +// currentUser returns a current user name func currentUser() (string, error) { u, err := user.Current() if err == nil { @@ -26,7 +29,7 @@ func currentUser() (string, error) { return name, nil } - return "", errors.New("Unable to detect OS user") + return "", errCantDetectUser } // Check if connection url has a correct postgres prefix @@ -43,18 +46,19 @@ func valsFromQuery(vals neturl.Values) map[string]string { return result } -func FormatUrl(opts command.Options) (string, error) { +// FormatURL reformats the existing connection string +func FormatURL(opts command.Options) (string, error) { url := opts.Url // Validate connection string prefix if !hasValidPrefix(url) { - return "", formatError + return "", errInvalidURLFormat } // Validate the URL uri, err := neturl.Parse(url) if err != nil { - return "", formatError + return "", errInvalidURLFormat } // Get query params @@ -82,15 +86,16 @@ func FormatUrl(opts command.Options) (string, error) { return uri.String(), nil } +// IsBlank returns true if command options do not contain connection details func IsBlank(opts command.Options) bool { return opts.Host == "" && opts.User == "" && opts.DbName == "" && opts.Url == "" } -// Build a new database connection string for the CLI options +// BuildStringFromOptions returns a new connection string built from options func BuildStringFromOptions(opts command.Options) (string, error) { // If connection string is provided we just use that if opts.Url != "" { - return FormatUrl(opts) + return FormatURL(opts) } // Try to detect user from current OS user From c32d68809bf921048487f01f5115c721943bcbb9 Mon Sep 17 00:00:00 2001 From: Dan Sosedoff Date: Mon, 28 Jan 2019 14:22:05 -0600 Subject: [PATCH 2/2] Add extra note --- pkg/command/options.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/command/options.go b/pkg/command/options.go index 7d998f2..47b4340 100644 --- a/pkg/command/options.go +++ b/pkg/command/options.go @@ -59,6 +59,8 @@ func ParseOptions(args []string) (Options, error) { opts.Prefix = os.Getenv("URL_PREFIX") } + // Handle edge case where pgweb is started with a default host `localhost` and no user. + // When user is not set the `lib/pq` connection will fail and cause pgweb's termination. if (opts.Host == "localhost" || opts.Host == "127.0.0.1") && opts.User == "" { if username := GetCurrentUser(); username != "" { opts.User = username