Skip to content

Commit

Permalink
Merge pull request #6864 from influxdata/js-6397-allow-use-database-w…
Browse files Browse the repository at this point in the history
…ith-non-admin

Allow a non-admin to call "use" for the influx cli
  • Loading branch information
jsternberg authored Jun 22, 2016
2 parents 7bdcd66 + 1d20498 commit e6cd4c7
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 26 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ With this release the systemd configuration files for InfluxDB will use the syst
- [#6869](https://github.com/influxdata/influxdb/issues/6869): Remove FieldCodec from tsdb package.
- [#6882](https://github.com/influxdata/influxdb/pull/6882): Remove a double lock in the tsm1 index writer.
- [#6883](https://github.com/influxdata/influxdb/pull/6883): Rename dumptsmdev to dumptsm in influx_inspect.
- [#6864](https://github.com/influxdata/influxdb/pull/6864): Allow a non-admin to call "use" for the influx cli.

## v0.13.0 [2016-05-12]

Expand Down
53 changes: 29 additions & 24 deletions cmd/influx/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,41 +337,46 @@ func (c *CommandLine) use(cmd string) {
}
d := args[1]

// validate if specified database exists
// Validate if specified database exists
response, err := c.Client.Query(client.Query{Command: "SHOW DATABASES"})
if err != nil {
fmt.Printf("ERR: %s\n", err)
return
}

if err := response.Error(); err != nil {
fmt.Printf("ERR: %s\n", err)
return
}

// verify the provided database exists
databaseExists := func() bool {
for _, result := range response.Results {
for _, row := range result.Series {
if row.Name == "databases" {
for _, values := range row.Values {
for _, database := range values {
if database == d {
return true
} else if err := response.Error(); err != nil {
if c.Username == "" {
fmt.Printf("ERR: %s\n", err)
return
}
// TODO(jsternberg): Fix SHOW DATABASES to be user-aware #6397.
// If we are unable to run SHOW DATABASES, display a warning and use the
// database anyway in case the person doesn't have permission to run the
// command, but does have permission to use the database.
fmt.Printf("WARN: %s\n", err)
} else {
// Verify the provided database exists
if databaseExists := func() bool {
for _, result := range response.Results {
for _, row := range result.Series {
if row.Name == "databases" {
for _, values := range row.Values {
for _, database := range values {
if database == d {
return true
}
}
}
}
}
}
return false
}(); !databaseExists {
fmt.Printf("ERR: Database %s doesn't exist. Run SHOW DATABASES for a list of existing databases.\n", d)
return
}
return false
}()
if databaseExists {
c.Database = d
fmt.Printf("Using database %s\n", d)
} else {
fmt.Printf("ERR: Database %s doesn't exist. Run SHOW DATABASES for a list of existing databases.\n", d)
}

c.Database = d
fmt.Printf("Using database %s\n", d)
}

// SetPrecision sets client precision
Expand Down
71 changes: 69 additions & 2 deletions cmd/influx/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cli_test
import (
"bufio"
"bytes"
"fmt"
"io"
"net"
"net/http"
Expand Down Expand Up @@ -272,7 +273,6 @@ func TestParseCommand_Use(t *testing.T) {
if err != nil {
t.Fatalf("unexpected error. expected %v, actual %v", nil, err)
}
m := cli.CommandLine{Client: c}

tests := []struct {
cmd string
Expand All @@ -286,6 +286,7 @@ func TestParseCommand_Use(t *testing.T) {
}

for _, test := range tests {
m := cli.CommandLine{Client: c}
if err := m.ParseCommand(test.cmd); err != nil {
t.Fatalf(`Got error %v for command %q, expected nil.`, err, test.cmd)
}
Expand All @@ -296,6 +297,59 @@ func TestParseCommand_Use(t *testing.T) {
}
}

func TestParseCommand_UseAuth(t *testing.T) {
t.Parallel()
ts := emptyTestServer()
defer ts.Close()

u, _ := url.Parse(ts.URL)
tests := []struct {
cmd string
user string
database string
}{
{
cmd: "use db",
user: "admin",
database: "db",
},
{
cmd: "use blank",
user: "admin",
database: "",
},
{
cmd: "use db",
user: "anonymous",
database: "db",
},
{
cmd: "use blank",
user: "anonymous",
database: "blank",
},
}

for i, tt := range tests {
config := client.Config{URL: *u, Username: tt.user}
fmt.Println("using auth:", tt.user)
c, err := client.NewClient(config)
if err != nil {
t.Errorf("%d. unexpected error. expected %v, actual %v", i, nil, err)
continue
}
m := cli.CommandLine{Client: c, Username: tt.user}

if err := m.ParseCommand(tt.cmd); err != nil {
t.Fatalf(`%d. Got error %v for command %q, expected nil.`, i, err, tt.cmd)
}

if m.Database != tt.database {
t.Fatalf(`%d. Command "use" changed database to %q. Expected %q`, i, m.Database, tt.database)
}
}
}

func TestParseCommand_Consistency(t *testing.T) {
t.Parallel()
c := cli.CommandLine{}
Expand Down Expand Up @@ -490,6 +544,14 @@ func emptyTestServer() *httptest.Server {
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Influxdb-Version", SERVER_VERSION)

// Fake authorization entirely based on the username.
authorized := false
user, _, _ := r.BasicAuth()
switch user {
case "", "admin":
authorized = true
}

switch r.URL.Path {
case "/query":
values := r.URL.Query()
Expand All @@ -503,7 +565,12 @@ func emptyTestServer() *httptest.Server {

switch stmt.(type) {
case *influxql.ShowDatabasesStatement:
io.WriteString(w, `{"results":[{"series":[{"name":"databases","columns":["name"],"values":[["db"]]}]}]}`)
if authorized {
io.WriteString(w, `{"results":[{"series":[{"name":"databases","columns":["name"],"values":[["db"]]}]}]}`)
} else {
w.WriteHeader(http.StatusUnauthorized)
io.WriteString(w, fmt.Sprintf(`{"error":"error authorizing query: %s not authorized to execute statement 'SHOW DATABASES', requires admin privilege"}`, user))
}
case *influxql.ShowDiagnosticsStatement:
io.WriteString(w, `{"results":[{}]}`)
}
Expand Down

0 comments on commit e6cd4c7

Please sign in to comment.