Add tests for influx OSS user permissions

pull/101/head
Chris Goller 2017-02-19 12:16:39 -06:00
parent 19018c97ca
commit 6d287723a2
1 changed files with 732 additions and 0 deletions

View File

@ -6,6 +6,7 @@ import (
"net/http/httptest"
"net/url"
"reflect"
"strings"
"testing"
"github.com/influxdata/chronograf"
@ -90,6 +91,7 @@ func TestClient_userPermissions(t *testing.T) {
}
func TestClient_Add(t *testing.T) {
t.Parallel()
type args struct {
ctx context.Context
u *chronograf.User
@ -161,3 +163,733 @@ func TestClient_Add(t *testing.T) {
}
}
}
func TestClient_Delete(t *testing.T) {
type args struct {
ctx context.Context
u *chronograf.User
}
tests := []struct {
name string
status int
dropUser []byte
args args
wantErr bool
}{
{
name: "Drop User",
dropUser: []byte(`{"results":[{"series":[{"columns":["database","privilege"],"values":[["mydb","ALL PRIVILEGES"]]}]}]}`),
status: http.StatusOK,
args: args{
ctx: context.Background(),
u: &chronograf.User{
Name: "docbrown",
},
},
},
{
name: "No such user",
dropUser: []byte(`{"results":[{"error":"user not found"}]}`),
status: http.StatusOK,
args: args{
ctx: context.Background(),
u: &chronograf.User{
Name: "docbrown",
},
},
wantErr: true,
},
{
name: "Bad InfluxQL",
dropUser: []byte(`{"error":"error parsing query: found doody, expected ; at line 1, char 17"}`),
status: http.StatusBadRequest,
args: args{
ctx: context.Background(),
u: &chronograf.User{
Name: "docbrown",
},
},
wantErr: true,
},
{
name: "Bad JSON",
dropUser: []byte(`{"results":[{"error":breakhere}]}`),
status: http.StatusOK,
args: args{
ctx: context.Background(),
u: &chronograf.User{
Name: "docbrown",
},
},
wantErr: true,
},
}
for _, tt := range tests {
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
if path := r.URL.Path; path != "/query" {
t.Error("Expected the path to contain `/query` but was", path)
}
rw.WriteHeader(tt.status)
rw.Write(tt.dropUser)
}))
u, _ := url.Parse(ts.URL)
c := &Client{
URL: u,
Logger: log.New(log.DebugLevel),
}
defer ts.Close()
if err := c.Delete(tt.args.ctx, tt.args.u); (err != nil) != tt.wantErr {
t.Errorf("%q. Client.Delete() error = %v, wantErr %v", tt.name, err, tt.wantErr)
}
}
}
func TestClient_Get(t *testing.T) {
type args struct {
ctx context.Context
name string
}
tests := []struct {
name string
args args
statusUsers int
showUsers []byte
statusGrants int
showGrants []byte
want *chronograf.User
wantErr bool
}{
{
name: "Get User",
statusUsers: http.StatusOK,
showUsers: []byte(`{"results":[{"series":[{"columns":["user","admin"],"values":[["admin",true],["docbrown",true],["reader",false]]}]}]}`),
statusGrants: http.StatusOK,
showGrants: []byte(`{"results":[{"series":[{"columns":["database","privilege"],"values":[["mydb","ALL PRIVILEGES"]]}]}]}`),
args: args{
ctx: context.Background(),
name: "docbrown",
},
want: &chronograf.User{
Name: "docbrown",
Permissions: chronograf.Permissions{
chronograf.Permission{
Scope: "all",
Allowed: []string{"WRITE", "READ"},
},
chronograf.Permission{
Scope: "database",
Name: "mydb",
Allowed: []string{"WRITE", "READ"},
},
},
},
},
{
name: "Fail show users",
statusUsers: http.StatusBadRequest,
showUsers: []byte(`{"results":[{"series":[{"columns":["user","admin"],"values":[["admin",true],["docbrown",true],["reader",false]]}]}]}`),
args: args{
ctx: context.Background(),
name: "docbrown",
},
wantErr: true,
},
{
name: "Fail show grants",
statusUsers: http.StatusOK,
showUsers: []byte(`{"results":[{"series":[{"columns":["user","admin"],"values":[["admin",true],["docbrown",true],["reader",false]]}]}]}`),
statusGrants: http.StatusBadRequest,
showGrants: []byte(`{"results":[{"series":[{"columns":["database","privilege"],"values":[["mydb","ALL PRIVILEGES"]]}]}]}`),
args: args{
ctx: context.Background(),
name: "docbrown",
},
wantErr: true,
},
{
name: "Fail no such user",
statusUsers: http.StatusOK,
showUsers: []byte(`{"results":[{"series":[{"columns":["user","admin"],"values":[["admin",true]]}]}]}`),
args: args{
ctx: context.Background(),
name: "docbrown",
},
wantErr: true,
},
}
for _, tt := range tests {
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
if path := r.URL.Path; path != "/query" {
t.Error("Expected the path to contain `/query` but was", path)
}
query := r.URL.Query().Get("q")
if strings.Contains(query, "GRANTS") {
rw.WriteHeader(tt.statusGrants)
rw.Write(tt.showGrants)
} else if strings.Contains(query, "USERS") {
rw.WriteHeader(tt.statusUsers)
rw.Write(tt.showUsers)
}
}))
u, _ := url.Parse(ts.URL)
c := &Client{
URL: u,
Logger: log.New(log.DebugLevel),
}
defer ts.Close()
got, err := c.Get(tt.args.ctx, tt.args.name)
if (err != nil) != tt.wantErr {
t.Errorf("%q. Client.Get() error = %v, wantErr %v", tt.name, err, tt.wantErr)
continue
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("%q. Client.Get() = %v, want %v", tt.name, got, tt.want)
}
}
}
func TestClient_grantPermission(t *testing.T) {
type args struct {
ctx context.Context
username string
perm chronograf.Permission
}
tests := []struct {
name string
args args
status int
results []byte
wantQuery string
wantErr bool
}{
{
name: "simple grants",
status: http.StatusOK,
results: []byte(`{"results":[]}`),
args: args{
ctx: context.Background(),
username: "docbrown",
perm: chronograf.Permission{
Scope: "database",
Name: "mydb",
Allowed: []string{"WRITE", "READ"},
},
},
wantQuery: `GRANT ALL ON "mydb" TO "docbrown"`,
},
{
name: "bad grants",
status: http.StatusOK,
results: []byte(`{"results":[]}`),
args: args{
ctx: context.Background(),
username: "docbrown",
perm: chronograf.Permission{
Scope: "database",
Name: "mydb",
Allowed: []string{"howdy"},
},
},
wantQuery: ``,
},
{
name: "no grants",
status: http.StatusOK,
results: []byte(`{"results":[]}`),
args: args{
ctx: context.Background(),
username: "docbrown",
perm: chronograf.Permission{
Scope: "database",
Name: "mydb",
Allowed: []string{},
},
},
wantQuery: ``,
},
}
for _, tt := range tests {
query := ""
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
if path := r.URL.Path; path != "/query" {
t.Error("Expected the path to contain `/query` but was", path)
}
query = r.URL.Query().Get("q")
rw.WriteHeader(tt.status)
rw.Write(tt.results)
}))
u, _ := url.Parse(ts.URL)
c := &Client{
URL: u,
Logger: log.New(log.DebugLevel),
}
defer ts.Close()
if err := c.grantPermission(tt.args.ctx, tt.args.username, tt.args.perm); (err != nil) != tt.wantErr {
t.Errorf("%q. Client.grantPermission() error = %v, wantErr %v", tt.name, err, tt.wantErr)
}
if query != tt.wantQuery {
t.Errorf("%q. Client.grantPermission() = %v, want %v", tt.name, query, tt.wantQuery)
}
}
}
func TestClient_revokePermission(t *testing.T) {
type args struct {
ctx context.Context
username string
perm chronograf.Permission
}
tests := []struct {
name string
args args
status int
results []byte
wantQuery string
wantErr bool
}{
{
name: "simple revoke",
status: http.StatusOK,
results: []byte(`{"results":[]}`),
args: args{
ctx: context.Background(),
username: "docbrown",
perm: chronograf.Permission{
Scope: "database",
Name: "mydb",
Allowed: []string{"WRITE", "READ"},
},
},
wantQuery: `REVOKE ALL ON "mydb" FROM "docbrown"`,
},
{
name: "bad revoke",
status: http.StatusOK,
results: []byte(`{"results":[]}`),
args: args{
ctx: context.Background(),
username: "docbrown",
perm: chronograf.Permission{
Scope: "database",
Name: "mydb",
Allowed: []string{"howdy"},
},
},
wantQuery: ``,
},
{
name: "no permissions",
status: http.StatusOK,
results: []byte(`{"results":[]}`),
args: args{
ctx: context.Background(),
username: "docbrown",
perm: chronograf.Permission{
Scope: "database",
Name: "mydb",
Allowed: []string{},
},
},
wantQuery: `REVOKE ALL PRIVILEGES ON "mydb" FROM "docbrown"`,
},
}
for _, tt := range tests {
query := ""
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
if path := r.URL.Path; path != "/query" {
t.Error("Expected the path to contain `/query` but was", path)
}
query = r.URL.Query().Get("q")
rw.WriteHeader(tt.status)
rw.Write(tt.results)
}))
u, _ := url.Parse(ts.URL)
c := &Client{
URL: u,
Logger: log.New(log.DebugLevel),
}
defer ts.Close()
if err := c.revokePermission(tt.args.ctx, tt.args.username, tt.args.perm); (err != nil) != tt.wantErr {
t.Errorf("%q. Client.revokePermission() error = %v, wantErr %v", tt.name, err, tt.wantErr)
}
if query != tt.wantQuery {
t.Errorf("%q. Client.revokePermission() = %v, want %v", tt.name, query, tt.wantQuery)
}
}
}
func TestClient_All(t *testing.T) {
type args struct {
ctx context.Context
}
tests := []struct {
name string
args args
statusUsers int
showUsers []byte
statusGrants int
showGrants []byte
want []chronograf.User
wantErr bool
}{
{
name: "All Users",
statusUsers: http.StatusOK,
showUsers: []byte(`{"results":[{"series":[{"columns":["user","admin"],"values":[["admin",true],["docbrown",true],["reader",false]]}]}]}`),
statusGrants: http.StatusOK,
showGrants: []byte(`{"results":[{"series":[{"columns":["database","privilege"],"values":[["mydb","ALL PRIVILEGES"]]}]}]}`),
args: args{
ctx: context.Background(),
},
want: []chronograf.User{
{
Name: "admin",
Permissions: chronograf.Permissions{
chronograf.Permission{
Scope: "all",
Allowed: []string{"WRITE", "READ"},
},
chronograf.Permission{
Scope: "database",
Name: "mydb",
Allowed: []string{"WRITE", "READ"},
},
},
},
{
Name: "docbrown",
Permissions: chronograf.Permissions{
chronograf.Permission{
Scope: "all",
Allowed: []string{"WRITE", "READ"},
},
chronograf.Permission{
Scope: "database",
Name: "mydb",
Allowed: []string{"WRITE", "READ"},
},
},
},
{
Name: "reader",
Permissions: chronograf.Permissions{
chronograf.Permission{
Scope: "database",
Name: "mydb",
Allowed: []string{"WRITE", "READ"},
},
},
},
},
},
{
name: "Unauthorized",
statusUsers: http.StatusUnauthorized,
showUsers: []byte(`{}`),
args: args{
ctx: context.Background(),
},
wantErr: true,
},
{
name: "Permission error",
statusUsers: http.StatusOK,
showUsers: []byte(`{"results":[{"series":[{"columns":["user","admin"],"values":[["admin",true],["docbrown",true],["reader",false]]}]}]}`),
statusGrants: http.StatusBadRequest,
showGrants: []byte(`{}`),
args: args{
ctx: context.Background(),
},
wantErr: true,
},
}
for _, tt := range tests {
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
if path := r.URL.Path; path != "/query" {
t.Error("Expected the path to contain `/query` but was", path)
}
query := r.URL.Query().Get("q")
if strings.Contains(query, "GRANTS") {
rw.WriteHeader(tt.statusGrants)
rw.Write(tt.showGrants)
} else if strings.Contains(query, "USERS") {
rw.WriteHeader(tt.statusUsers)
rw.Write(tt.showUsers)
}
}))
u, _ := url.Parse(ts.URL)
c := &Client{
URL: u,
Logger: log.New(log.DebugLevel),
}
defer ts.Close()
got, err := c.All(tt.args.ctx)
if (err != nil) != tt.wantErr {
t.Errorf("%q. Client.All() error = %v, wantErr %v", tt.name, err, tt.wantErr)
continue
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("%q. Client.All() = %v, want %v", tt.name, got, tt.want)
}
}
}
func TestClient_Update(t *testing.T) {
type args struct {
ctx context.Context
u *chronograf.User
}
tests := []struct {
name string
statusUsers int
showUsers []byte
statusGrants int
showGrants []byte
statusRevoke int
revoke []byte
statusGrant int
grant []byte
args args
want []string
wantErr bool
}{
{
name: "Revoke all permissions",
statusUsers: http.StatusOK,
showUsers: []byte(`{"results":[{"series":[{"columns":["user","admin"],"values":[["admin",true],["docbrown",true],["reader",false]]}]}]}`),
statusGrants: http.StatusOK,
showGrants: []byte(`{"results":[{"series":[{"columns":["database","privilege"],"values":[["mydb","ALL PRIVILEGES"]]}]}]}`),
statusRevoke: http.StatusOK,
revoke: []byte(`{"results":[]}`),
args: args{
ctx: context.Background(),
u: &chronograf.User{
Name: "docbrown",
},
},
want: []string{
`SHOW USERS`,
`SHOW GRANTS FOR "docbrown"`,
`REVOKE ALL PRIVILEGES FROM "docbrown"`,
`REVOKE ALL ON "mydb" FROM "docbrown"`,
},
},
{
name: "Grant all permissions",
statusUsers: http.StatusOK,
showUsers: []byte(`{"results":[{"series":[{"columns":["user","admin"],"values":[["admin",true],["docbrown",true],["reader",false]]}]}]}`),
statusGrants: http.StatusOK,
showGrants: []byte(`{"results":[{"series":[{"columns":["database","privilege"],"values":[["mydb","ALL PRIVILEGES"]]}]}]}`),
statusRevoke: http.StatusOK,
revoke: []byte(`{"results":[]}`),
statusGrant: http.StatusOK,
grant: []byte(`{"results":[]}`),
args: args{
ctx: context.Background(),
u: &chronograf.User{
Name: "docbrown",
Permissions: chronograf.Permissions{
{
Scope: "all",
Allowed: []string{"WRITE", "READ"},
},
{
Scope: "database",
Name: "mydb",
Allowed: []string{"WRITE", "READ"},
},
},
},
},
want: []string{
`SHOW USERS`,
`SHOW GRANTS FOR "docbrown"`,
`GRANT ALL PRIVILEGES TO "docbrown"`,
`GRANT ALL ON "mydb" TO "docbrown"`,
},
},
{
name: "Revoke some add some",
statusUsers: http.StatusOK,
showUsers: []byte(`{"results":[{"series":[{"columns":["user","admin"],"values":[["admin",true],["docbrown",true],["reader",false]]}]}]}`),
statusGrants: http.StatusOK,
showGrants: []byte(`{"results":[{"series":[{"columns":["database","privilege"],"values":[["mydb","ALL PRIVILEGES"]]}]}]}`),
statusRevoke: http.StatusOK,
revoke: []byte(`{"results":[]}`),
statusGrant: http.StatusOK,
grant: []byte(`{"results":[]}`),
args: args{
ctx: context.Background(),
u: &chronograf.User{
Name: "docbrown",
Permissions: chronograf.Permissions{
{
Scope: "all",
Allowed: []string{},
},
{
Scope: "database",
Name: "mydb",
Allowed: []string{"WRITE"},
},
{
Scope: "database",
Name: "newdb",
Allowed: []string{"WRITE", "READ"},
},
},
},
},
want: []string{
`SHOW USERS`,
`SHOW GRANTS FOR "docbrown"`,
`GRANT WRITE ON "mydb" TO "docbrown"`,
`GRANT ALL ON "newdb" TO "docbrown"`,
`REVOKE ALL PRIVILEGES FROM "docbrown"`,
},
},
{
name: "Fail users",
statusUsers: http.StatusBadRequest,
showUsers: []byte(`{"results":[{"series":[{"columns":["user","admin"],"values":[["admin",true],["docbrown",true],["reader",false]]}]}]}`),
statusGrants: http.StatusOK,
showGrants: []byte(`{"results":[{"series":[{"columns":["database","privilege"],"values":[["mydb","ALL PRIVILEGES"]]}]}]}`),
statusRevoke: http.StatusOK,
revoke: []byte(`{"results":[]}`),
statusGrant: http.StatusOK,
grant: []byte(`{"results":[]}`),
args: args{
ctx: context.Background(),
u: &chronograf.User{
Name: "docbrown",
},
},
wantErr: true,
want: []string{
`SHOW USERS`,
},
},
{
name: "fail grants",
statusUsers: http.StatusOK,
showUsers: []byte(`{"results":[{"series":[{"columns":["user","admin"],"values":[["admin",true],["docbrown",true],["reader",false]]}]}]}`),
statusGrants: http.StatusOK,
showGrants: []byte(`{"results":[{"series":[{"columns":["database","privilege"],"values":[["mydb","ALL PRIVILEGES"]]}]}]}`),
statusRevoke: http.StatusOK,
revoke: []byte(`{"results":[]}`),
statusGrant: http.StatusBadRequest,
grant: []byte(`{"results":[]}`),
wantErr: true,
args: args{
ctx: context.Background(),
u: &chronograf.User{
Name: "docbrown",
Permissions: chronograf.Permissions{
{
Scope: "all",
Allowed: []string{},
},
{
Scope: "database",
Name: "mydb",
Allowed: []string{"WRITE"},
},
{
Scope: "database",
Name: "newdb",
Allowed: []string{"WRITE", "READ"},
},
},
},
},
want: []string{
`SHOW USERS`,
`SHOW GRANTS FOR "docbrown"`,
`GRANT WRITE ON "mydb" TO "docbrown"`,
},
},
{
name: "fail revoke",
statusUsers: http.StatusOK,
showUsers: []byte(`{"results":[{"series":[{"columns":["user","admin"],"values":[["admin",true],["docbrown",true],["reader",false]]}]}]}`),
statusGrants: http.StatusOK,
showGrants: []byte(`{"results":[{"series":[{"columns":["database","privilege"],"values":[["mydb","ALL PRIVILEGES"]]}]}]}`),
statusRevoke: http.StatusBadRequest,
revoke: []byte(`{"results":[]}`),
statusGrant: http.StatusOK,
grant: []byte(`{"results":[]}`),
wantErr: true,
args: args{
ctx: context.Background(),
u: &chronograf.User{
Name: "docbrown",
Permissions: chronograf.Permissions{
{
Scope: "all",
Allowed: []string{},
},
{
Scope: "database",
Name: "mydb",
Allowed: []string{"WRITE"},
},
{
Scope: "database",
Name: "newdb",
Allowed: []string{"WRITE", "READ"},
},
},
},
},
want: []string{
`SHOW USERS`,
`SHOW GRANTS FOR "docbrown"`,
`GRANT WRITE ON "mydb" TO "docbrown"`,
`GRANT ALL ON "newdb" TO "docbrown"`,
`REVOKE ALL PRIVILEGES FROM "docbrown"`,
},
},
}
for _, tt := range tests {
queries := []string{}
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
if path := r.URL.Path; path != "/query" {
t.Error("Expected the path to contain `/query` but was", path)
}
query := r.URL.Query().Get("q")
if strings.Contains(query, "GRANTS") {
rw.WriteHeader(tt.statusGrants)
rw.Write(tt.showGrants)
} else if strings.Contains(query, "USERS") {
rw.WriteHeader(tt.statusUsers)
rw.Write(tt.showUsers)
} else if strings.Contains(query, "REVOKE") {
rw.WriteHeader(tt.statusRevoke)
rw.Write(tt.revoke)
} else if strings.Contains(query, "GRANT") {
rw.WriteHeader(tt.statusGrant)
rw.Write(tt.grant)
}
queries = append(queries, query)
}))
u, _ := url.Parse(ts.URL)
c := &Client{
URL: u,
Logger: log.New(log.DebugLevel),
}
defer ts.Close()
if err := c.Update(tt.args.ctx, tt.args.u); (err != nil) != tt.wantErr {
t.Errorf("%q. Client.Update() error = %v, wantErr %v", tt.name, err, tt.wantErr)
}
if !reflect.DeepEqual(queries, tt.want) {
t.Errorf("%q. Client.Update() = %v, want %v", tt.name, queries, tt.want)
}
}
}
/*
*/