Allow setting readonly mode in bookmarks (#707)

This commit is contained in:
Dan Sosedoff 2024-01-12 21:17:14 -06:00 committed by GitHub
parent e560f07de6
commit 408e23adb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 16 deletions

View File

@ -20,6 +20,7 @@ type Bookmark struct {
Database string // Database name Database string // Database name
SSLMode string // Connection SSL mode SSLMode string // Connection SSL mode
SSH *shared.SSHInfo // SSH tunnel config SSH *shared.SSHInfo // SSH tunnel config
ReadOnly bool // Enable read-only transaction mode
} }
// SSHInfoIsEmpty returns true if ssh configuration is not provided // SSHInfoIsEmpty returns true if ssh configuration is not provided
@ -40,12 +41,13 @@ func (b Bookmark) ConvertToOptions() command.Options {
} }
return command.Options{ return command.Options{
URL: b.URL, URL: b.URL,
Host: b.Host, Host: b.Host,
Port: b.Port, Port: b.Port,
User: user, User: user,
Pass: pass, Pass: pass,
DbName: b.Database, DbName: b.Database,
SSLMode: b.SSLMode, SSLMode: b.SSLMode,
ReadOnly: b.ReadOnly,
} }
} }

View File

@ -68,6 +68,7 @@ func TestBookmarkWithVarsConvertToOptions(t *testing.T) {
t.Setenv("DB_USER", "user123") t.Setenv("DB_USER", "user123")
t.Setenv("DB_PASSWORD", "password123") t.Setenv("DB_PASSWORD", "password123")
opt := b.ConvertToOptions() opt := b.ConvertToOptions()
assert.Equal(t, expOpt, opt) assert.Equal(t, expOpt, opt)
}) })
@ -87,6 +88,7 @@ func TestBookmarkWithVarsConvertToOptions(t *testing.T) {
t.Setenv("DB_USER", "user123") t.Setenv("DB_USER", "user123")
t.Setenv("DB_PASSWORD", "password123") t.Setenv("DB_PASSWORD", "password123")
opt := b.ConvertToOptions() opt := b.ConvertToOptions()
assert.Equal(t, expOpt, opt) assert.Equal(t, expOpt, opt)
}) })
@ -101,16 +103,18 @@ func TestBookmarkConvertToOptions(t *testing.T) {
Password: "password", Password: "password",
Database: "mydatabase", Database: "mydatabase",
SSLMode: "disable", SSLMode: "disable",
ReadOnly: true,
} }
expOpt := command.Options{ expOpt := command.Options{
URL: "postgres://username:password@host:port/database?sslmode=disable", URL: "postgres://username:password@host:port/database?sslmode=disable",
Host: "localhost", Host: "localhost",
Port: 5432, Port: 5432,
User: "postgres", User: "postgres",
Pass: "password", Pass: "password",
DbName: "mydatabase", DbName: "mydatabase",
SSLMode: "disable", SSLMode: "disable",
ReadOnly: true,
} }
opt := b.ConvertToOptions() opt := b.ConvertToOptions()

View File

@ -41,6 +41,7 @@ type Client struct {
serverType string serverType string
lastQueryTime time.Time lastQueryTime time.Time
queryTimeout time.Duration queryTimeout time.Duration
readonly bool
closed bool closed bool
External bool `json:"external"` External bool `json:"external"`
History []history.Record `json:"history"` History []history.Record `json:"history"`
@ -166,7 +167,16 @@ func NewFromBookmark(bookmark *bookmarks.Bookmark) (*Client, error) {
sshInfo = bookmark.SSH sshInfo = bookmark.SSH
} }
return NewFromUrl(connStr, sshInfo) client, err := NewFromUrl(connStr, sshInfo)
if err != nil {
return nil, err
}
if bookmark.ReadOnly {
client.readonly = true
}
return client, nil
} }
func (client *Client) init() { func (client *Client) init() {
@ -476,7 +486,7 @@ func (client *Client) query(query string, args ...interface{}) (*Result, error)
// We're going to force-set transaction mode on every query. // We're going to force-set transaction mode on every query.
// This is needed so that default mode could not be changed by user. // This is needed so that default mode could not be changed by user.
if command.Opts.ReadOnly { if command.Opts.ReadOnly || client.readonly {
if err := client.SetReadOnlyMode(); err != nil { if err := client.SetReadOnlyMode(); err != nil {
return nil, err return nil, err
} }

View File

@ -679,6 +679,14 @@ func testReadOnlyMode(t *testing.T) {
_, err = client.Query("/* CREATE TABLE foobar(id integer); */ SELECT 'foo';") _, err = client.Query("/* CREATE TABLE foobar(id integer); */ SELECT 'foo';")
assert.NoError(t, err) assert.NoError(t, err)
t.Run("with local readonly flag", func(t *testing.T) {
command.Opts.ReadOnly = false
client.readonly = true
_, err := client.Query("INSERT INTO foobar(id) VALUES(1)")
assert.Error(t, err, "query contains keywords not allowed in read-only mode")
})
} }
func testTablesStats(t *testing.T) { func testTablesStats(t *testing.T) {