Add support for a bookmarks-only mode (#716)

* Add support for bookmarks-only mode

* Add error for missing bookmarks in bookmarks-only mode

* Error when settings url or connect backend together with bookmarks-only

* Add tests for parsing options
This commit is contained in:
Alexandru Gologan 2024-03-15 06:36:53 +02:00 committed by GitHub
parent 605c483d5b
commit f4e7643e22
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 63 additions and 5 deletions

View File

@ -154,6 +154,8 @@ func Connect(c *gin.Context) {
if bookmarkID := c.Request.FormValue("bookmark_id"); bookmarkID != "" { if bookmarkID := c.Request.FormValue("bookmark_id"); bookmarkID != "" {
cl, err = ConnectWithBookmark(bookmarkID) cl, err = ConnectWithBookmark(bookmarkID)
} else if command.Opts.BookmarksOnly {
err = errNotPermitted
} else { } else {
cl, err = ConnectWithURL(c) cl, err = ConnectWithURL(c)
} }
@ -558,9 +560,10 @@ func GetInfo(c *gin.Context) {
successResponse(c, gin.H{ successResponse(c, gin.H{
"app": command.Info, "app": command.Info,
"features": gin.H{ "features": gin.H{
"session_lock": command.Opts.LockSession, "session_lock": command.Opts.LockSession,
"query_timeout": command.Opts.QueryTimeout, "query_timeout": command.Opts.QueryTimeout,
"local_queries": QueryStore != nil, "local_queries": QueryStore != nil,
"bookmarks_only": command.Opts.BookmarksOnly,
}, },
}) })
} }

View File

@ -50,6 +50,7 @@ type Options struct {
LockSession bool `long:"lock-session" description:"Lock session to a single database connection"` LockSession bool `long:"lock-session" description:"Lock session to a single database connection"`
Bookmark string `short:"b" long:"bookmark" description:"Bookmark to use for connection. Bookmark files are stored under $HOME/.pgweb/bookmarks/*.toml" default:""` Bookmark string `short:"b" long:"bookmark" description:"Bookmark to use for connection. Bookmark files are stored under $HOME/.pgweb/bookmarks/*.toml" default:""`
BookmarksDir string `long:"bookmarks-dir" description:"Overrides default directory for bookmark files to search" default:""` BookmarksDir string `long:"bookmarks-dir" description:"Overrides default directory for bookmark files to search" default:""`
BookmarksOnly bool `long:"bookmarks-only" description:"Allow only connections from bookmarks"`
QueriesDir string `long:"queries-dir" description:"Overrides default directory for local queries"` QueriesDir string `long:"queries-dir" description:"Overrides default directory for local queries"`
DisablePrettyJSON bool `long:"no-pretty-json" description:"Disable JSON formatting feature for result export"` DisablePrettyJSON bool `long:"no-pretty-json" description:"Disable JSON formatting feature for result export"`
DisableSSH bool `long:"no-ssh" description:"Disable database connections via SSH"` DisableSSH bool `long:"no-ssh" description:"Disable database connections via SSH"`
@ -118,6 +119,10 @@ func ParseOptions(args []string) (Options, error) {
} }
} }
if getPrefixedEnvVar("BOOKMARKS_ONLY") != "" {
opts.BookmarksOnly = true
}
if getPrefixedEnvVar("SESSIONS") != "" { if getPrefixedEnvVar("SESSIONS") != "" {
opts.Sessions = true opts.Sessions = true
} }
@ -162,6 +167,18 @@ func ParseOptions(args []string) (Options, error) {
} }
} }
if opts.BookmarksOnly {
if opts.URL != "" {
return opts, errors.New("--url not supported in bookmarks-only mode")
}
if opts.Host != "" && opts.Host != "localhost" {
return opts, errors.New("--host not supported in bookmarks-only mode")
}
if opts.ConnectBackend != "" {
return opts, errors.New("--connect-backend not supported in bookmarks-only mode")
}
}
homePath, err := homedir.Dir() homePath, err := homedir.Dir()
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "[WARN] cant detect home dir: %v", err) fmt.Fprintf(os.Stderr, "[WARN] cant detect home dir: %v", err)

View File

@ -80,4 +80,18 @@ func TestParseOptions(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "../../data/passfile", opts.Passfile) assert.Equal(t, "../../data/passfile", opts.Passfile)
}) })
t.Run("bookmarks only mode", func(t *testing.T) {
_, err := ParseOptions([]string{"--bookmarks-only"})
assert.NoError(t, err)
_, err = ParseOptions([]string{"--bookmarks-only", "--url", "test"})
assert.EqualError(t, err, "--url not supported in bookmarks-only mode")
_, err = ParseOptions([]string{"--bookmarks-only", "--host", "test", "--port", "5432"})
assert.EqualError(t, err, "--host not supported in bookmarks-only mode")
_, err = ParseOptions([]string{"--bookmarks-only", "--connect-backend", "test", "--sessions", "--connect-token", "token", "--url", "127.0.0.2"})
assert.EqualError(t, err, "--connect-backend not supported in bookmarks-only mode")
})
} }

View File

@ -189,14 +189,16 @@
</div> </div>
</div> </div>
<div class="connection-standard-group"> <div class="connection-bookmarks-group">
<div class="form-group bookmarks"> <div class="form-group bookmarks">
<label class="col-sm-3 control-label">Bookmark</label> <label class="col-sm-3 control-label">Bookmark</label>
<div class="col-sm-9"> <div class="col-sm-9">
<select class="form-control" id="connection_bookmarks"></select> <select class="form-control" id="connection_bookmarks"></select>
</div> </div>
</div> </div>
</div>
<div class="connection-standard-group">
<div class="form-group"> <div class="form-group">
<label class="col-sm-3 control-label">Host</label> <label class="col-sm-3 control-label">Host</label>
<div class="col-sm-9"> <div class="col-sm-9">

View File

@ -1091,6 +1091,7 @@ function showConnectionSettings() {
// Show the current postgres version // Show the current postgres version
$(".connection-settings .version").text("v" + appInfo.version).show(); $(".connection-settings .version").text("v" + appInfo.version).show();
$("#connection_window").show(); $("#connection_window").show();
initConnectionWindow();
// Check github release page for updates // Check github release page for updates
getLatestReleaseInfo(appInfo); getLatestReleaseInfo(appInfo);
@ -1119,11 +1120,32 @@ function showConnectionSettings() {
$(".bookmarks").show(); $(".bookmarks").show();
} }
else { else {
$(".bookmarks").hide(); if (appFeatures.bookmarks_only) {
$("#connection_error").html("Running in <b>bookmarks-only</b> mode but <b>NO</b> bookmarks configured.").show();
$(".open-connection").hide();
} else {
$(".bookmarks").hide();
}
} }
}); });
} }
function initConnectionWindow() {
if (appFeatures.bookmarks_only) {
$(".connection-group-switch").hide();
$(".connection-scheme-group").hide();
$(".connection-bookmarks-group").show();
$(".connection-standard-group").hide();
$(".connection-ssh-group").hide();
} else {
$(".connection-group-switch").show();
$(".connection-scheme-group").hide();
$(".connection-bookmarks-group").show();
$(".connection-standard-group").show();
$(".connection-ssh-group").hide();
}
}
function getConnectionString() { function getConnectionString() {
var url = $.trim($("#connection_url").val()); var url = $.trim($("#connection_url").val());
var mode = $(".connection-group-switch button.active").attr("data"); var mode = $(".connection-group-switch button.active").attr("data");