Refactor connection string generator
This commit is contained in:
@@ -11,6 +11,10 @@ import (
|
|||||||
"github.com/sosedoff/pgweb/pkg/command"
|
"github.com/sosedoff/pgweb/pkg/command"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
formatError = errors.New("Invalid URL. Valid format: postgres://user:password@host:port/db?sslmode=mode")
|
||||||
|
)
|
||||||
|
|
||||||
func currentUser() (string, error) {
|
func currentUser() (string, error) {
|
||||||
u, err := user.Current()
|
u, err := user.Current()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -25,32 +29,57 @@ func currentUser() (string, error) {
|
|||||||
return "", errors.New("Unable to detect OS user")
|
return "", errors.New("Unable to detect OS user")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
func FormatUrl(opts command.Options) (string, error) {
|
func FormatUrl(opts command.Options) (string, error) {
|
||||||
url := opts.Url
|
url := opts.Url
|
||||||
|
|
||||||
// Make sure to only accept urls in a standard format
|
// Validate connection string prefix
|
||||||
if !strings.HasPrefix(url, "postgres://") && !strings.HasPrefix(url, "postgresql://") {
|
if !hasValidPrefix(url) {
|
||||||
return "", errors.New("Invalid URL. Valid format: postgres://user:password@host:port/db?sslmode=mode")
|
return "", formatError
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special handling for local connections
|
// Validate the URL
|
||||||
if strings.Contains(url, "localhost") || strings.Contains(url, "127.0.0.1") {
|
uri, err := neturl.Parse(url)
|
||||||
if !strings.Contains(url, "?sslmode") {
|
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 == "" {
|
if opts.Ssl == "" {
|
||||||
url += fmt.Sprintf("?sslmode=%s", "disable")
|
// Only modify sslmode for local connections
|
||||||
|
if strings.Contains(uri.Host, "localhost") || strings.Contains(uri.Host, "127.0.0.1") {
|
||||||
|
params["sslmode"] = "disable"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
url += fmt.Sprintf("?sslmode=%s", opts.Ssl)
|
params["sslmode"] = opts.Ssl
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append sslmode parameter only if its defined as a flag and not present
|
// Rebuild query params
|
||||||
// in the connection string.
|
query := neturl.Values{}
|
||||||
if !strings.Contains(url, "?sslmode") && opts.Ssl != "" {
|
for k, v := range params {
|
||||||
url += fmt.Sprintf("?sslmode=%s", opts.Ssl)
|
query.Add(k, v)
|
||||||
}
|
}
|
||||||
|
uri.RawQuery = query.Encode()
|
||||||
|
|
||||||
return url, nil
|
return uri.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsBlank(opts command.Options) bool {
|
func IsBlank(opts command.Options) bool {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ func Test_Invalid_Url(t *testing.T) {
|
|||||||
opts := command.Options{}
|
opts := command.Options{}
|
||||||
examples := []string{
|
examples := []string{
|
||||||
"postgre://foobar",
|
"postgre://foobar",
|
||||||
|
"tcp://blah",
|
||||||
"foobar",
|
"foobar",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,14 +49,12 @@ func Test_Localhost_Url_And_No_Ssl_Flag(t *testing.T) {
|
|||||||
str, err := BuildString(command.Options{
|
str, err := BuildString(command.Options{
|
||||||
Url: "postgres://localhost/database",
|
Url: "postgres://localhost/database",
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.Equal(t, nil, err)
|
assert.Equal(t, nil, err)
|
||||||
assert.Equal(t, "postgres://localhost/database?sslmode=disable", str)
|
assert.Equal(t, "postgres://localhost/database?sslmode=disable", str)
|
||||||
|
|
||||||
str, err = BuildString(command.Options{
|
str, err = BuildString(command.Options{
|
||||||
Url: "postgres://127.0.0.1/database",
|
Url: "postgres://127.0.0.1/database",
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.Equal(t, nil, err)
|
assert.Equal(t, nil, err)
|
||||||
assert.Equal(t, "postgres://127.0.0.1/database?sslmode=disable", str)
|
assert.Equal(t, "postgres://127.0.0.1/database?sslmode=disable", str)
|
||||||
}
|
}
|
||||||
@@ -65,7 +64,6 @@ func Test_Localhost_Url_And_Ssl_Flag(t *testing.T) {
|
|||||||
Url: "postgres://localhost/database",
|
Url: "postgres://localhost/database",
|
||||||
Ssl: "require",
|
Ssl: "require",
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.Equal(t, nil, err)
|
assert.Equal(t, nil, err)
|
||||||
assert.Equal(t, "postgres://localhost/database?sslmode=require", str)
|
assert.Equal(t, "postgres://localhost/database?sslmode=require", str)
|
||||||
|
|
||||||
@@ -73,7 +71,6 @@ func Test_Localhost_Url_And_Ssl_Flag(t *testing.T) {
|
|||||||
Url: "postgres://127.0.0.1/database",
|
Url: "postgres://127.0.0.1/database",
|
||||||
Ssl: "require",
|
Ssl: "require",
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.Equal(t, nil, err)
|
assert.Equal(t, nil, err)
|
||||||
assert.Equal(t, "postgres://127.0.0.1/database?sslmode=require", str)
|
assert.Equal(t, "postgres://127.0.0.1/database?sslmode=require", str)
|
||||||
}
|
}
|
||||||
@@ -82,14 +79,12 @@ func Test_Localhost_Url_And_Ssl_Arg(t *testing.T) {
|
|||||||
str, err := BuildString(command.Options{
|
str, err := BuildString(command.Options{
|
||||||
Url: "postgres://localhost/database?sslmode=require",
|
Url: "postgres://localhost/database?sslmode=require",
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.Equal(t, nil, err)
|
assert.Equal(t, nil, err)
|
||||||
assert.Equal(t, "postgres://localhost/database?sslmode=require", str)
|
assert.Equal(t, "postgres://localhost/database?sslmode=require", str)
|
||||||
|
|
||||||
str, err = BuildString(command.Options{
|
str, err = BuildString(command.Options{
|
||||||
Url: "postgres://127.0.0.1/database?sslmode=require",
|
Url: "postgres://127.0.0.1/database?sslmode=require",
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.Equal(t, nil, err)
|
assert.Equal(t, nil, err)
|
||||||
assert.Equal(t, "postgres://127.0.0.1/database?sslmode=require", str)
|
assert.Equal(t, "postgres://127.0.0.1/database?sslmode=require", str)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user