2015-04-30 11:47:07 -05:00
|
|
|
package connection
|
2014-12-17 21:32:50 -06:00
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
2015-08-15 21:11:09 -05:00
|
|
|
neturl "net/url"
|
2015-01-09 22:55:00 -06:00
|
|
|
"os"
|
2014-12-17 21:32:50 -06:00
|
|
|
"os/user"
|
|
|
|
"strings"
|
2015-04-30 11:47:07 -05:00
|
|
|
|
|
|
|
"github.com/sosedoff/pgweb/pkg/command"
|
2014-12-17 21:32:50 -06:00
|
|
|
)
|
|
|
|
|
2018-09-13 22:25:15 -05:00
|
|
|
var (
|
|
|
|
formatError = errors.New("Invalid URL. Valid format: postgres://user:password@host:port/db?sslmode=mode")
|
|
|
|
)
|
|
|
|
|
2015-01-09 22:55:00 -06:00
|
|
|
func currentUser() (string, error) {
|
|
|
|
u, err := user.Current()
|
|
|
|
if err == nil {
|
|
|
|
return u.Username, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
name := os.Getenv("USER")
|
|
|
|
if name != "" {
|
|
|
|
return name, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return "", errors.New("Unable to detect OS user")
|
|
|
|
}
|
|
|
|
|
2018-09-13 22:25:15 -05:00
|
|
|
// Check if connection url has a correct postgres prefix
|
|
|
|
func hasValidPrefix(str string) bool {
|
|
|
|
return strings.HasPrefix(str, "postgres://") || strings.HasPrefix(str, "postgresql://")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extract all query vals and return as a map
|
|
|
|
func valsFromQuery(vals neturl.Values) map[string]string {
|
|
|
|
result := map[string]string{}
|
|
|
|
for k, v := range vals {
|
|
|
|
result[strings.ToLower(k)] = v[0]
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2015-04-30 11:47:07 -05:00
|
|
|
func FormatUrl(opts command.Options) (string, error) {
|
2014-12-17 21:32:50 -06:00
|
|
|
url := opts.Url
|
|
|
|
|
2018-09-13 22:25:15 -05:00
|
|
|
// Validate connection string prefix
|
|
|
|
if !hasValidPrefix(url) {
|
|
|
|
return "", formatError
|
2014-12-17 21:32:50 -06:00
|
|
|
}
|
|
|
|
|
2018-09-13 22:25:15 -05:00
|
|
|
// Validate the URL
|
|
|
|
uri, err := neturl.Parse(url)
|
|
|
|
if err != nil {
|
|
|
|
return "", formatError
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get query params
|
|
|
|
params := valsFromQuery(uri.Query())
|
|
|
|
|
|
|
|
// Determine if we need to specify sslmode if it's missing
|
|
|
|
if params["sslmode"] == "" {
|
|
|
|
if opts.Ssl == "" {
|
|
|
|
// Only modify sslmode for local connections
|
|
|
|
if strings.Contains(uri.Host, "localhost") || strings.Contains(uri.Host, "127.0.0.1") {
|
|
|
|
params["sslmode"] = "disable"
|
2014-12-17 21:32:50 -06:00
|
|
|
}
|
2018-09-13 22:25:15 -05:00
|
|
|
} else {
|
|
|
|
params["sslmode"] = opts.Ssl
|
2014-12-17 21:32:50 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-13 22:25:15 -05:00
|
|
|
// Rebuild query params
|
|
|
|
query := neturl.Values{}
|
|
|
|
for k, v := range params {
|
|
|
|
query.Add(k, v)
|
2014-12-17 21:32:50 -06:00
|
|
|
}
|
2018-09-13 22:25:15 -05:00
|
|
|
uri.RawQuery = query.Encode()
|
2014-12-17 21:32:50 -06:00
|
|
|
|
2018-09-13 22:25:15 -05:00
|
|
|
return uri.String(), nil
|
2014-12-17 21:32:50 -06:00
|
|
|
}
|
|
|
|
|
2015-04-30 11:47:07 -05:00
|
|
|
func IsBlank(opts command.Options) bool {
|
2014-12-17 21:56:15 -06:00
|
|
|
return opts.Host == "" && opts.User == "" && opts.DbName == "" && opts.Url == ""
|
|
|
|
}
|
|
|
|
|
2015-04-30 11:47:07 -05:00
|
|
|
func BuildString(opts command.Options) (string, error) {
|
2014-12-17 21:32:50 -06:00
|
|
|
if opts.Url != "" {
|
2015-04-30 11:47:07 -05:00
|
|
|
return FormatUrl(opts)
|
2014-12-17 21:32:50 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Try to detect user from current OS user
|
|
|
|
if opts.User == "" {
|
2015-01-09 22:55:00 -06:00
|
|
|
u, err := currentUser()
|
2014-12-17 21:32:50 -06:00
|
|
|
if err == nil {
|
2015-01-09 22:55:00 -06:00
|
|
|
opts.User = u
|
2014-12-17 21:32:50 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Disable ssl for localhost connections, most users have it disabled
|
|
|
|
if opts.Host == "localhost" || opts.Host == "127.0.0.1" {
|
|
|
|
if opts.Ssl == "" {
|
|
|
|
opts.Ssl = "disable"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
url := "postgres://"
|
|
|
|
|
|
|
|
if opts.User != "" {
|
|
|
|
url += opts.User
|
|
|
|
}
|
|
|
|
|
|
|
|
if opts.Pass != "" {
|
2015-08-15 21:11:09 -05:00
|
|
|
url += fmt.Sprintf(":%s", neturl.QueryEscape(opts.Pass))
|
2014-12-17 21:32:50 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
url += fmt.Sprintf("@%s:%d", opts.Host, opts.Port)
|
|
|
|
|
|
|
|
if opts.DbName != "" {
|
|
|
|
url += fmt.Sprintf("/%s", opts.DbName)
|
|
|
|
}
|
|
|
|
|
|
|
|
if opts.Ssl != "" {
|
|
|
|
url += fmt.Sprintf("?sslmode=%s", opts.Ssl)
|
|
|
|
}
|
|
|
|
|
|
|
|
return url, nil
|
|
|
|
}
|