influxdb/integrations/server_test.go

2967 lines
68 KiB
Go

package integrations
// This was intentionally added under the integrations package and not the integrations test package
// so that changes in other parts of the code base that may have an effect on these test will not
// compile until they are fixed.
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"testing"
"time"
"github.com/influxdata/chronograf"
"github.com/influxdata/chronograf/bolt"
"github.com/influxdata/chronograf/log"
"github.com/influxdata/chronograf/oauth2"
"github.com/influxdata/chronograf/roles"
"github.com/influxdata/chronograf/server"
)
func TestServer(t *testing.T) {
type fields struct {
Organizations []chronograf.Organization
Mappings []chronograf.Mapping
Users []chronograf.User
Sources []chronograf.Source
Servers []chronograf.Server
Layouts []chronograf.Layout
Dashboards []chronograf.Dashboard
Config *chronograf.Config
}
type args struct {
server *server.Server
method string
path string
payload interface{} // Expects this to be a json serializable struct
principal oauth2.Principal
}
type wants struct {
statusCode int
contentType string
body string
}
tests := []struct {
name string
subName string
fields fields
args args
wants wants
}{
{
name: "GET /sources/5000",
subName: "Get specific source; including Canned source",
fields: fields{
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
{
Name: "viewer",
Organization: "howdy", // from canned testdata
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/sources/5000",
principal: oauth2.Principal{
Organization: "howdy",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"id": "5000",
"name": "Influx 1",
"type": "influx-enterprise",
"username": "user1",
"url": "http://localhost:8086",
"metaUrl": "http://metaurl.com",
"default": true,
"telegraf": "telegraf",
"organization": "howdy",
"links": {
"self": "/chronograf/v1/sources/5000",
"kapacitors": "/chronograf/v1/sources/5000/kapacitors",
"proxy": "/chronograf/v1/sources/5000/proxy",
"queries": "/chronograf/v1/sources/5000/queries",
"write": "/chronograf/v1/sources/5000/write",
"permissions": "/chronograf/v1/sources/5000/permissions",
"users": "/chronograf/v1/sources/5000/users",
"roles": "/chronograf/v1/sources/5000/roles",
"databases": "/chronograf/v1/sources/5000/dbs",
"annotations": "/chronograf/v1/sources/5000/annotations"
}
}
`,
},
},
{
name: "GET /sources/5000/kapacitors/5000",
subName: "Get specific kapacitors; including Canned kapacitors",
fields: fields{
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
{
Name: "viewer",
Organization: "howdy", // from canned testdata
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/sources/5000/kapacitors/5000",
principal: oauth2.Principal{
Organization: "howdy",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"id": "5000",
"name": "Kapa 1",
"url": "http://localhost:9092",
"active": true,
"links": {
"proxy": "/chronograf/v1/sources/5000/kapacitors/5000/proxy",
"self": "/chronograf/v1/sources/5000/kapacitors/5000",
"rules": "/chronograf/v1/sources/5000/kapacitors/5000/rules",
"tasks": "/chronograf/v1/sources/5000/kapacitors/5000/proxy?path=/kapacitor/v1/tasks",
"ping": "/chronograf/v1/sources/5000/kapacitors/5000/proxy?path=/kapacitor/v1/ping"
}
}
`,
},
},
{
name: "GET /sources/5000/kapacitors",
subName: "Get all kapacitors; including Canned kapacitors",
fields: fields{
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
{
Name: "viewer",
Organization: "howdy", // from canned testdata
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/sources/5000/kapacitors",
principal: oauth2.Principal{
Organization: "howdy",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"kapacitors": [
{
"id": "5000",
"name": "Kapa 1",
"url": "http://localhost:9092",
"active": true,
"links": {
"proxy": "/chronograf/v1/sources/5000/kapacitors/5000/proxy",
"self": "/chronograf/v1/sources/5000/kapacitors/5000",
"rules": "/chronograf/v1/sources/5000/kapacitors/5000/rules",
"tasks": "/chronograf/v1/sources/5000/kapacitors/5000/proxy?path=/kapacitor/v1/tasks",
"ping": "/chronograf/v1/sources/5000/kapacitors/5000/proxy?path=/kapacitor/v1/ping"
}
}
]
}
`,
},
},
{
name: "GET /sources",
subName: "Get all sources; including Canned sources",
fields: fields{
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
{
Name: "viewer",
Organization: "howdy", // from canned testdata
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/sources",
principal: oauth2.Principal{
Organization: "howdy",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"sources": [
{
"id": "5000",
"name": "Influx 1",
"type": "influx-enterprise",
"username": "user1",
"url": "http://localhost:8086",
"metaUrl": "http://metaurl.com",
"default": true,
"telegraf": "telegraf",
"organization": "howdy",
"links": {
"self": "/chronograf/v1/sources/5000",
"kapacitors": "/chronograf/v1/sources/5000/kapacitors",
"proxy": "/chronograf/v1/sources/5000/proxy",
"queries": "/chronograf/v1/sources/5000/queries",
"write": "/chronograf/v1/sources/5000/write",
"permissions": "/chronograf/v1/sources/5000/permissions",
"users": "/chronograf/v1/sources/5000/users",
"roles": "/chronograf/v1/sources/5000/roles",
"databases": "/chronograf/v1/sources/5000/dbs",
"annotations": "/chronograf/v1/sources/5000/annotations"
}
}
]
}
`,
},
},
{
name: "GET /organizations",
subName: "Get all organizations; including Canned organization",
fields: fields{
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/organizations",
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"links": {
"self": "/chronograf/v1/organizations"
},
"organizations": [
{
"links": {
"self": "/chronograf/v1/organizations/default"
},
"id": "default",
"name": "Default",
"defaultRole": "member"
},
{
"links": {
"self": "/chronograf/v1/organizations/howdy"
},
"id": "howdy",
"name": "An Organization",
"defaultRole": "viewer"
}
]
}`,
},
},
{
name: "GET /organizations/howdy",
subName: "Get specific organizations; Canned organization",
fields: fields{
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/organizations/howdy",
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"links": {
"self": "/chronograf/v1/organizations/howdy"
},
"id": "howdy",
"name": "An Organization",
"defaultRole": "viewer"
}`,
},
},
{
name: "GET /dashboards/1000",
subName: "Get specific in the howdy organization; Using Canned testdata",
fields: fields{
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "howdy",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/dashboards/1000",
principal: oauth2.Principal{
Organization: "howdy",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"id": 1000,
"cells": [
{
"i": "8f61c619-dd9b-4761-8aa8-577f27247093",
"x": 0,
"y": 0,
"w": 11,
"h": 5,
"name": "Untitled Cell",
"queries": [
{
"query": "SELECT mean(\"value\") AS \"mean_value\" FROM \"telegraf\".\"autogen\".\"cpg\" WHERE time > :dashboardTime: GROUP BY :interval: FILL(null)",
"queryConfig": {
"database": "telegraf",
"measurement": "cpg",
"retentionPolicy": "autogen",
"fields": [
{
"value": "mean",
"type": "func",
"alias": "mean_value",
"args": [
{
"value": "value",
"type": "field",
"alias": ""
}
]
}
],
"tags": {},
"groupBy": {
"time": "auto",
"tags": []
},
"areTagsAccepted": false,
"fill": "null",
"rawText": null,
"range": null,
"shifts": null
},
"source": "/chronograf/v1/sources/2"
}
],
"axes": {
"x": {
"bounds": [],
"label": "",
"prefix": "",
"suffix": "",
"base": "10",
"scale": "linear"
},
"y": {
"bounds": [],
"label": "",
"prefix": "",
"suffix": "",
"base": "10",
"scale": "linear"
},
"y2": {
"bounds": [],
"label": "",
"prefix": "",
"suffix": "",
"base": "10",
"scale": "linear"
}
},
"type": "line",
"colors": [
{
"id": "0",
"type": "min",
"hex": "#00C9FF",
"name": "laser",
"value": "0"
},
{
"id": "1",
"type": "max",
"hex": "#9394FF",
"name": "comet",
"value": "100"
}
],
"legend":{
"type": "static",
"orientation": "bottom"
},
"links": {
"self": "/chronograf/v1/dashboards/1000/cells/8f61c619-dd9b-4761-8aa8-577f27247093"
}
}
],
"templates": [
{
"tempVar": ":dbs:",
"values": [
{
"value": "_internal",
"type": "database",
"selected": true
},
{
"value": "telegraf",
"type": "database",
"selected": false
},
{
"value": "tensorflowdb",
"type": "database",
"selected": false
},
{
"value": "pushgateway",
"type": "database",
"selected": false
},
{
"value": "node_exporter",
"type": "database",
"selected": false
},
{
"value": "mydb",
"type": "database",
"selected": false
},
{
"value": "tiny",
"type": "database",
"selected": false
},
{
"value": "blah",
"type": "database",
"selected": false
},
{
"value": "test",
"type": "database",
"selected": false
},
{
"value": "chronograf",
"type": "database",
"selected": false
},
{
"value": "db_name",
"type": "database",
"selected": false
},
{
"value": "demo",
"type": "database",
"selected": false
},
{
"value": "eeg",
"type": "database",
"selected": false
},
{
"value": "solaredge",
"type": "database",
"selected": false
},
{
"value": "zipkin",
"type": "database",
"selected": false
}
],
"id": "e7e498bf-5869-4874-9071-24628a2cda63",
"type": "databases",
"label": "",
"query": {
"influxql": "SHOW DATABASES",
"measurement": "",
"tagKey": "",
"fieldKey": ""
},
"links": {
"self": "/chronograf/v1/dashboards/1000/templates/e7e498bf-5869-4874-9071-24628a2cda63"
}
}
],
"name": "Name This Dashboard",
"organization": "howdy",
"links": {
"self": "/chronograf/v1/dashboards/1000",
"cells": "/chronograf/v1/dashboards/1000/cells",
"templates": "/chronograf/v1/dashboards/1000/templates"
}
}`,
},
},
{
name: "GET /dashboards",
subName: "Get all dashboards in the howdy organization; Using Canned testdata",
fields: fields{
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
{
Name: "admin",
Organization: "howdy",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/dashboards",
principal: oauth2.Principal{
Organization: "howdy",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"dashboards": [
{
"id": 1000,
"cells": [
{
"i": "8f61c619-dd9b-4761-8aa8-577f27247093",
"x": 0,
"y": 0,
"w": 11,
"h": 5,
"name": "Untitled Cell",
"queries": [
{
"query": "SELECT mean(\"value\") AS \"mean_value\" FROM \"telegraf\".\"autogen\".\"cpg\" WHERE time > :dashboardTime: GROUP BY :interval: FILL(null)",
"queryConfig": {
"database": "telegraf",
"measurement": "cpg",
"retentionPolicy": "autogen",
"fields": [
{
"value": "mean",
"type": "func",
"alias": "mean_value",
"args": [
{
"value": "value",
"type": "field",
"alias": ""
}
]
}
],
"tags": {},
"groupBy": {
"time": "auto",
"tags": []
},
"areTagsAccepted": false,
"fill": "null",
"rawText": null,
"range": null,
"shifts": null
},
"source": "/chronograf/v1/sources/2"
}
],
"axes": {
"x": {
"bounds": [],
"label": "",
"prefix": "",
"suffix": "",
"base": "10",
"scale": "linear"
},
"y": {
"bounds": [],
"label": "",
"prefix": "",
"suffix": "",
"base": "10",
"scale": "linear"
},
"y2": {
"bounds": [],
"label": "",
"prefix": "",
"suffix": "",
"base": "10",
"scale": "linear"
}
},
"type": "line",
"colors": [
{
"id": "0",
"type": "min",
"hex": "#00C9FF",
"name": "laser",
"value": "0"
},
{
"id": "1",
"type": "max",
"hex": "#9394FF",
"name": "comet",
"value": "100"
}
],
"legend":{
"type": "static",
"orientation": "bottom"
},
"links": {
"self": "/chronograf/v1/dashboards/1000/cells/8f61c619-dd9b-4761-8aa8-577f27247093"
}
}
],
"templates": [
{
"tempVar": ":dbs:",
"values": [
{
"value": "_internal",
"type": "database",
"selected": true
},
{
"value": "telegraf",
"type": "database",
"selected": false
},
{
"value": "tensorflowdb",
"type": "database",
"selected": false
},
{
"value": "pushgateway",
"type": "database",
"selected": false
},
{
"value": "node_exporter",
"type": "database",
"selected": false
},
{
"value": "mydb",
"type": "database",
"selected": false
},
{
"value": "tiny",
"type": "database",
"selected": false
},
{
"value": "blah",
"type": "database",
"selected": false
},
{
"value": "test",
"type": "database",
"selected": false
},
{
"value": "chronograf",
"type": "database",
"selected": false
},
{
"value": "db_name",
"type": "database",
"selected": false
},
{
"value": "demo",
"type": "database",
"selected": false
},
{
"value": "eeg",
"type": "database",
"selected": false
},
{
"value": "solaredge",
"type": "database",
"selected": false
},
{
"value": "zipkin",
"type": "database",
"selected": false
}
],
"id": "e7e498bf-5869-4874-9071-24628a2cda63",
"type": "databases",
"label": "",
"query": {
"influxql": "SHOW DATABASES",
"measurement": "",
"tagKey": "",
"fieldKey": ""
},
"links": {
"self": "/chronograf/v1/dashboards/1000/templates/e7e498bf-5869-4874-9071-24628a2cda63"
}
}
],
"name": "Name This Dashboard",
"organization": "howdy",
"links": {
"self": "/chronograf/v1/dashboards/1000",
"cells": "/chronograf/v1/dashboards/1000/cells",
"templates": "/chronograf/v1/dashboards/1000/templates"
}
}
]
}`,
},
},
{
name: "GET /users",
subName: "User Not Found in the Default Organization",
fields: fields{
Users: []chronograf.User{},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/organizations/default/users",
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 403,
body: `{"code":403,"message":"User is not authorized"}`,
},
},
{
name: "GET /users",
subName: "Single User in the Default Organization as SuperAdmin",
fields: fields{
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/organizations/default/users",
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"links": {
"self": "/chronograf/v1/organizations/default/users"
},
"users": [
{
"links": {
"self": "/chronograf/v1/organizations/default/users/1"
},
"id": "1",
"name": "billibob",
"provider": "github",
"scheme": "oauth2",
"superAdmin": true,
"roles": [
{
"name": "admin",
"organization": "default"
}
]
}
]
}`,
},
},
{
name: "GET /users",
subName: "Two users in two organizations; user making request is as SuperAdmin with out raw query param",
fields: fields{
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
{
ID: 2, // This is artificial, but should be reflective of the users actual ID
Name: "billietta",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "cool",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/organizations/default/users",
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"links": {
"self": "/chronograf/v1/organizations/default/users"
},
"users": [
{
"links": {
"self": "/chronograf/v1/organizations/default/users/1"
},
"id": "1",
"name": "billibob",
"provider": "github",
"scheme": "oauth2",
"superAdmin": true,
"roles": [
{
"name": "admin",
"organization": "default"
}
]
}
]
}
`,
},
},
{
name: "POST /users",
subName: "User making request is as SuperAdmin with raw query param; being created has wildcard role",
fields: fields{
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
payload: &chronograf.User{
Name: "user",
Provider: "provider",
Scheme: "oauth2",
Roles: []chronograf.Role{
{
Name: "*",
Organization: "default",
},
},
},
method: "POST",
path: "/chronograf/v1/users",
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 201,
body: `
{
"links": {
"self": "/chronograf/v1/users/2"
},
"id": "2",
"name": "user",
"provider": "provider",
"scheme": "oauth2",
"superAdmin": false,
"roles": [
{
"name": "member",
"organization": "default"
}
]
}
`,
},
},
{
name: "POST /users",
subName: "User making request is as SuperAdmin with raw query param; being created has no roles",
fields: fields{
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
payload: &chronograf.User{
Name: "user",
Provider: "provider",
Scheme: "oauth2",
Roles: []chronograf.Role{},
},
method: "POST",
path: "/chronograf/v1/users",
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 201,
body: `
{
"links": {
"self": "/chronograf/v1/users/2"
},
"id": "2",
"name": "user",
"provider": "provider",
"scheme": "oauth2",
"superAdmin": false,
"roles": []
}
`,
},
},
{
name: "GET /users",
subName: "Two users in two organizations; user making request is as SuperAdmin with raw query param",
fields: fields{
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "cool",
DefaultRole: roles.ViewerRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
{
ID: 2, // This is artificial, but should be reflective of the users actual ID
Name: "billietta",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "1",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/users",
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"links": {
"self": "/chronograf/v1/users"
},
"users": [
{
"links": {
"self": "/chronograf/v1/users/1"
},
"id": "1",
"name": "billibob",
"provider": "github",
"scheme": "oauth2",
"superAdmin": true,
"roles": [
{
"name": "admin",
"organization": "default"
}
]
},
{
"links": {
"self": "/chronograf/v1/users/2"
},
"id": "2",
"name": "billietta",
"provider": "github",
"scheme": "oauth2",
"superAdmin": true,
"roles": [
{
"name": "admin",
"organization": "1"
}
]
}
]
}
`,
},
},
{
name: "GET /users",
subName: "Two users in two organizations; user making request is as not SuperAdmin with raw query param",
fields: fields{
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "cool",
DefaultRole: roles.ViewerRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
{
ID: 2, // This is artificial, but should be reflective of the users actual ID
Name: "billietta",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: false,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
{
Name: "admin",
Organization: "1",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/users",
principal: oauth2.Principal{
Organization: "default",
Subject: "billieta",
Issuer: "github",
},
},
wants: wants{
statusCode: 403,
body: `
{
"code": 403,
"message": "User is not authorized"
}
`,
},
},
{
name: "POST /users",
subName: "Create a New User with SuperAdmin status; SuperAdminNewUsers is true (the default case); User on Principal is a SuperAdmin",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: true,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "POST",
path: "/chronograf/v1/organizations/default/users",
payload: &chronograf.User{
Name: "user",
Provider: "provider",
Scheme: "oauth2",
Roles: []chronograf.Role{
{
Name: roles.EditorRoleName,
Organization: "default",
},
},
},
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 201,
body: `
{
"links": {
"self": "/chronograf/v1/organizations/default/users/2"
},
"id": "2",
"name": "user",
"provider": "provider",
"scheme": "oauth2",
"superAdmin": true,
"roles": [
{
"name": "editor",
"organization": "default"
}
]
}`,
},
},
{
name: "POST /users",
subName: "Create a New User with SuperAdmin status; SuperAdminNewUsers is false; User on Principal is a SuperAdmin",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: false,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "POST",
path: "/chronograf/v1/organizations/default/users",
payload: &chronograf.User{
Name: "user",
Provider: "provider",
Scheme: "oauth2",
Roles: []chronograf.Role{
{
Name: roles.EditorRoleName,
Organization: "default",
},
},
},
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 201,
body: `
{
"links": {
"self": "/chronograf/v1/organizations/default/users/2"
},
"id": "2",
"name": "user",
"provider": "provider",
"scheme": "oauth2",
"superAdmin": false,
"roles": [
{
"name": "editor",
"organization": "default"
}
]
}`,
},
},
{
name: "POST /users",
subName: "Create a New User with SuperAdmin status; SuperAdminNewUsers is false; User on Principal is Admin, but not a SuperAdmin",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: false,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: false,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "POST",
path: "/chronograf/v1/organizations/default/users",
payload: &chronograf.User{
Name: "user",
Provider: "provider",
Scheme: "oauth2",
Roles: []chronograf.Role{
{
Name: roles.EditorRoleName,
Organization: "default",
},
},
},
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 201,
body: `
{
"links": {
"self": "/chronograf/v1/organizations/default/users/2"
},
"id": "2",
"name": "user",
"provider": "provider",
"scheme": "oauth2",
"superAdmin": false,
"roles": [
{
"name": "editor",
"organization": "default"
}
]
}`,
},
},
{
name: "POST /users",
subName: "Create a New User with SuperAdmin status; SuperAdminNewUsers is true; User on Principal is Admin, but not a SuperAdmin",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: true,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: false,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "POST",
path: "/chronograf/v1/organizations/default/users",
payload: &chronograf.User{
Name: "user",
Provider: "provider",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: roles.EditorRoleName,
Organization: "default",
},
},
},
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 401,
body: `
{
"code": 401,
"message": "User does not have authorization required to set SuperAdmin status. See https://github.com/influxdata/chronograf/issues/2601 for more information."
}`,
},
},
{
name: "POST /users",
subName: "Create a New User with in multiple organizations; User on Principal is a SuperAdmin with raw query param",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: true,
},
},
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "cool",
DefaultRole: roles.ViewerRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "POST",
path: "/chronograf/v1/users",
payload: &chronograf.User{
Name: "user",
Provider: "provider",
Scheme: "oauth2",
Roles: []chronograf.Role{
{
Name: roles.EditorRoleName,
Organization: "default",
},
{
Name: roles.EditorRoleName,
Organization: "1",
},
},
},
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 201,
body: `
{
"links": {
"self": "/chronograf/v1/users/2"
},
"id": "2",
"name": "user",
"provider": "provider",
"scheme": "oauth2",
"superAdmin": true,
"roles": [
{
"name": "editor",
"organization": "default"
},
{
"name": "editor",
"organization": "1"
}
]
}`,
},
},
{
name: "PATCH /users",
subName: "Update user to have no roles",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: true,
},
},
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "cool",
DefaultRole: roles.ViewerRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "PATCH",
path: "/chronograf/v1/users/1",
payload: map[string]interface{}{
"name": "billibob",
"provider": "github",
"scheme": "oauth2",
"superAdmin": true,
"roles": []chronograf.Role{},
},
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"links": {
"self": "/chronograf/v1/users/1"
},
"id": "1",
"name": "billibob",
"provider": "github",
"scheme": "oauth2",
"superAdmin": true,
"roles": [
]
}`,
},
},
{
name: "PATCH /users",
subName: "Update user roles with wildcard",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: true,
},
},
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "cool",
DefaultRole: roles.ViewerRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "PATCH",
path: "/chronograf/v1/users/1",
payload: &chronograf.User{
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: roles.AdminRoleName,
Organization: "default",
},
{
Name: roles.WildcardRoleName,
Organization: "1",
},
},
},
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"links": {
"self": "/chronograf/v1/users/1"
},
"id": "1",
"name": "billibob",
"provider": "github",
"scheme": "oauth2",
"superAdmin": true,
"roles": [
{
"name": "admin",
"organization": "default"
},
{
"name": "viewer",
"organization": "1"
}
]
}`,
},
},
{
name: "PATCH /users/1",
subName: "SuperAdmin modifying their own status",
fields: fields{
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "PATCH",
path: "/chronograf/v1/organizations/default/users/1",
payload: map[string]interface{}{
"id": "1",
"superAdmin": false,
"roles": []interface{}{
map[string]interface{}{
"name": "admin",
"organization": "default",
},
},
},
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: http.StatusUnauthorized,
body: `
{
"code": 401,
"message": "user cannot modify their own SuperAdmin status"
}
`,
},
},
{
name: "GET /organization/default/users",
subName: "Organization not set explicitly on principal",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: false,
},
},
Organizations: []chronograf.Organization{},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/organizations/default/users",
principal: oauth2.Principal{
Organization: "",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"links": {
"self": "/chronograf/v1/organizations/default/users"
},
"users": [
{
"links": {
"self": "/chronograf/v1/organizations/default/users/1"
},
"id": "1",
"name": "billibob",
"provider": "github",
"scheme": "oauth2",
"superAdmin": true,
"roles": [
{
"name": "admin",
"organization": "default"
}
]
}
]
}
`,
},
},
{
name: "PUT /me",
subName: "Change SuperAdmins current organization to org they dont belong to",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: false,
},
},
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "Sweet",
DefaultRole: roles.ViewerRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "PUT",
path: "/chronograf/v1/me",
payload: map[string]string{
"organization": "1",
},
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"id": "1",
"name": "billibob",
"roles": [
{
"name": "admin",
"organization": "default"
},
{
"name": "viewer",
"organization": "1"
}
],
"provider": "github",
"scheme": "oauth2",
"superAdmin": true,
"links": {
"self": "/chronograf/v1/organizations/1/users/1"
},
"organizations": [
{
"id": "1",
"name": "Sweet",
"defaultRole": "viewer"
},
{
"id": "default",
"name": "Default",
"defaultRole": "member"
}
],
"currentOrganization": {
"id": "1",
"name": "Sweet",
"defaultRole": "viewer"
}
}`,
},
},
{
name: "PUT /me",
subName: "Change Admin current organization to org they dont belong to",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: false,
},
},
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "Sweet",
DefaultRole: roles.ViewerRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: false,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "PUT",
path: "/chronograf/v1/me",
payload: map[string]string{
"organization": "1",
},
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 403,
body: `
{
"code": 403,
"message": "user not found"
}`,
},
},
{
name: "GET /me",
subName: "New user hits me for the first time",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: false,
},
},
Mappings: []chronograf.Mapping{
{
ID: "1",
Organization: "1",
Provider: "*",
Scheme: "*",
ProviderOrganization: "influxdata",
},
{
ID: "1",
Organization: "1",
Provider: "*",
Scheme: "*",
ProviderOrganization: "*",
},
{
ID: "2",
Organization: "2",
Provider: "github",
Scheme: "*",
ProviderOrganization: "*",
},
{
ID: "3",
Organization: "3",
Provider: "auth0",
Scheme: "ldap",
ProviderOrganization: "*",
},
},
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "Sweet",
DefaultRole: roles.ViewerRoleName,
},
{
ID: "2",
Name: "What",
DefaultRole: roles.EditorRoleName,
},
{
ID: "3",
Name: "Okay",
DefaultRole: roles.AdminRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/me",
principal: oauth2.Principal{
Subject: "billietta",
Issuer: "github",
Group: "influxdata,idk,mimi",
},
},
wants: wants{
statusCode: 200,
body: `
{
"id": "2",
"name": "billietta",
"roles": [
{
"name": "viewer",
"organization": "1"
},
{
"name": "editor",
"organization": "2"
},
{
"name": "member",
"organization": "default"
}
],
"provider": "github",
"scheme": "oauth2",
"links": {
"self": "/chronograf/v1/organizations/default/users/2"
},
"organizations": [
{
"id": "1",
"name": "Sweet",
"defaultRole": "viewer"
},
{
"id": "2",
"name": "What",
"defaultRole": "editor"
},
{
"id": "default",
"name": "Default",
"defaultRole": "member"
}
],
"currentOrganization": {
"id": "default",
"name": "Default",
"defaultRole": "member"
}
}
`,
},
},
{
name: "GET /mappings",
subName: "get all mappings",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: false,
},
},
Mappings: []chronograf.Mapping{
{
ID: "1",
Organization: "1",
Provider: "*",
Scheme: "*",
ProviderOrganization: "influxdata",
},
{
ID: "1",
Organization: "1",
Provider: "*",
Scheme: "*",
ProviderOrganization: "*",
},
{
ID: "2",
Organization: "2",
Provider: "github",
Scheme: "*",
ProviderOrganization: "*",
},
{
ID: "3",
Organization: "3",
Provider: "auth0",
Scheme: "ldap",
ProviderOrganization: "*",
},
},
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "Sweet",
DefaultRole: roles.ViewerRoleName,
},
{
ID: "2",
Name: "What",
DefaultRole: roles.EditorRoleName,
},
{
ID: "3",
Name: "Okay",
DefaultRole: roles.AdminRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/mappings",
principal: oauth2.Principal{
Subject: "billibob",
Issuer: "github",
Group: "influxdata,idk,mimi",
},
},
wants: wants{
statusCode: 200,
body: `
{
"links": {
"self": "/chronograf/v1/mappings"
},
"mappings": [
{
"links": {
"self": "/chronograf/v1/mappings/1"
},
"id": "1",
"organizationId": "1",
"provider": "*",
"scheme": "*",
"providerOrganization": "influxdata"
},
{
"links": {
"self": "/chronograf/v1/mappings/2"
},
"id": "2",
"organizationId": "1",
"provider": "*",
"scheme": "*",
"providerOrganization": "*"
},
{
"links": {
"self": "/chronograf/v1/mappings/3"
},
"id": "3",
"organizationId": "2",
"provider": "github",
"scheme": "*",
"providerOrganization": "*"
},
{
"links": {
"self": "/chronograf/v1/mappings/4"
},
"id": "4",
"organizationId": "3",
"provider": "auth0",
"scheme": "ldap",
"providerOrganization": "*"
},
{
"links": {
"self": "/chronograf/v1/mappings/default"
},
"id": "default",
"organizationId": "default",
"provider": "*",
"scheme": "*",
"providerOrganization": "*"
}
]
}
`,
},
},
{
name: "GET /mappings",
subName: "get all mappings - user is not super admin",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: false,
},
},
Mappings: []chronograf.Mapping{
{
ID: "1",
Organization: "1",
Provider: "*",
Scheme: "*",
ProviderOrganization: "influxdata",
},
{
ID: "1",
Organization: "1",
Provider: "*",
Scheme: "*",
ProviderOrganization: "*",
},
{
ID: "2",
Organization: "2",
Provider: "github",
Scheme: "*",
ProviderOrganization: "*",
},
{
ID: "3",
Organization: "3",
Provider: "auth0",
Scheme: "ldap",
ProviderOrganization: "*",
},
},
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "Sweet",
DefaultRole: roles.ViewerRoleName,
},
{
ID: "2",
Name: "What",
DefaultRole: roles.EditorRoleName,
},
{
ID: "3",
Name: "Okay",
DefaultRole: roles.AdminRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: false,
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/mappings",
principal: oauth2.Principal{
Subject: "billibob",
Issuer: "github",
Group: "influxdata,idk,mimi",
},
},
wants: wants{
statusCode: 403,
body: `
{
"code": 403,
"message": "User is not authorized"
}
`,
},
},
{
name: "POST /mappings",
subName: "create new mapping",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: false,
},
},
Mappings: []chronograf.Mapping{},
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "Sweet",
DefaultRole: roles.ViewerRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "POST",
path: "/chronograf/v1/mappings",
payload: &chronograf.Mapping{
ID: "1",
Organization: "1",
Provider: "*",
Scheme: "*",
ProviderOrganization: "influxdata",
},
principal: oauth2.Principal{
Subject: "billibob",
Issuer: "github",
Group: "influxdata,idk,mimi",
},
},
wants: wants{
statusCode: 201,
body: `
{
"links": {
"self": "/chronograf/v1/mappings/1"
},
"id": "1",
"organizationId": "1",
"provider": "*",
"scheme": "*",
"providerOrganization": "influxdata"
}
`,
},
},
{
name: "PUT /mappings",
subName: "update new mapping",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: false,
},
},
Mappings: []chronograf.Mapping{
chronograf.Mapping{
ID: "1",
Organization: "1",
Provider: "*",
Scheme: "*",
ProviderOrganization: "influxdata",
},
},
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "Sweet",
DefaultRole: roles.ViewerRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "PUT",
path: "/chronograf/v1/mappings/1",
payload: &chronograf.Mapping{
ID: "1",
Organization: "1",
Provider: "*",
Scheme: "*",
ProviderOrganization: "*",
},
principal: oauth2.Principal{
Subject: "billibob",
Issuer: "github",
Group: "influxdata,idk,mimi",
},
},
wants: wants{
statusCode: 200,
body: `
{
"links": {
"self": "/chronograf/v1/mappings/1"
},
"id": "1",
"organizationId": "1",
"provider": "*",
"scheme": "*",
"providerOrganization": "*"
}
`,
},
},
{
name: "GET /",
subName: "signed into default org",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: true,
},
},
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "cool",
DefaultRole: roles.ViewerRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: true,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/",
principal: oauth2.Principal{
Organization: "default",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"layouts": "/chronograf/v1/layouts",
"users": "/chronograf/v1/organizations/default/users",
"allUsers": "/chronograf/v1/users",
"organizations": "/chronograf/v1/organizations",
"mappings": "/chronograf/v1/mappings",
"sources": "/chronograf/v1/sources",
"me": "/chronograf/v1/me",
"environment": "/chronograf/v1/env",
"dashboards": "/chronograf/v1/dashboards",
"config": {
"self": "/chronograf/v1/config",
"auth": "/chronograf/v1/config/auth"
},
"auth": [
{
"name": "github",
"label": "Github",
"login": "/oauth/github/login",
"logout": "/oauth/github/logout",
"callback": "/oauth/github/callback"
}
],
"logout": "/oauth/logout",
"external": {
"statusFeed": ""
}
}
`,
},
},
{
name: "GET /",
subName: "signed into org 1",
fields: fields{
Config: &chronograf.Config{
Auth: chronograf.AuthConfig{
SuperAdminNewUsers: true,
},
},
Organizations: []chronograf.Organization{
{
ID: "1",
Name: "cool",
DefaultRole: roles.ViewerRoleName,
},
},
Users: []chronograf.User{
{
ID: 1, // This is artificial, but should be reflective of the users actual ID
Name: "billibob",
Provider: "github",
Scheme: "oauth2",
SuperAdmin: false,
Roles: []chronograf.Role{
{
Name: "admin",
Organization: "default",
},
{
Name: "member",
Organization: "1",
},
},
},
},
},
args: args{
server: &server.Server{
GithubClientID: "not empty",
GithubClientSecret: "not empty",
},
method: "GET",
path: "/chronograf/v1/",
principal: oauth2.Principal{
Organization: "1",
Subject: "billibob",
Issuer: "github",
},
},
wants: wants{
statusCode: 200,
body: `
{
"layouts": "/chronograf/v1/layouts",
"users": "/chronograf/v1/organizations/1/users",
"allUsers": "/chronograf/v1/users",
"organizations": "/chronograf/v1/organizations",
"mappings": "/chronograf/v1/mappings",
"sources": "/chronograf/v1/sources",
"me": "/chronograf/v1/me",
"environment": "/chronograf/v1/env",
"dashboards": "/chronograf/v1/dashboards",
"config": {
"self": "/chronograf/v1/config",
"auth": "/chronograf/v1/config/auth"
},
"auth": [
{
"name": "github",
"label": "Github",
"login": "/oauth/github/login",
"logout": "/oauth/github/logout",
"callback": "/oauth/github/callback"
}
],
"logout": "/oauth/logout",
"external": {
"statusFeed": ""
}
}
`,
},
},
}
for _, tt := range tests {
testName := fmt.Sprintf("%s: %s", tt.name, tt.subName)
t.Run(testName, func(t *testing.T) {
ctx := context.TODO()
// Create Test Server
host, port := hostAndPort()
tt.args.server.Host = host
tt.args.server.Port = port
// Use testdata directory for the canned data
tt.args.server.CannedPath = "testdata"
tt.args.server.ResourcesPath = "testdata"
// This is so that we can use staticly generate jwts
tt.args.server.TokenSecret = "secret"
boltFile := newBoltFile()
tt.args.server.BoltPath = boltFile
// Prepopulate BoltDB Database for Server
boltdb := bolt.NewClient()
boltdb.Path = boltFile
logger := log.New(log.ParseLevel("debug"))
build := chronograf.BuildInfo{
Version: "pre-1.4.0.0",
Commit: "",
}
_ = boltdb.Open(ctx, logger, build)
if tt.fields.Config != nil {
if err := boltdb.ConfigStore.Update(ctx, tt.fields.Config); err != nil {
t.Fatalf("failed to update global application config %v", err)
return
}
}
// Populate Organizations
for i, mapping := range tt.fields.Mappings {
o, err := boltdb.MappingsStore.Add(ctx, &mapping)
if err != nil {
t.Fatalf("failed to add mapping: %v", err)
return
}
tt.fields.Mappings[i] = *o
}
// Populate Organizations
for i, organization := range tt.fields.Organizations {
o, err := boltdb.OrganizationsStore.Add(ctx, &organization)
if err != nil {
t.Fatalf("failed to add organization: %v", err)
return
}
tt.fields.Organizations[i] = *o
}
// Populate Users
for i, user := range tt.fields.Users {
u, err := boltdb.UsersStore.Add(ctx, &user)
if err != nil {
t.Fatalf("failed to add user: %v", err)
return
}
tt.fields.Users[i] = *u
}
// Populate Sources
for i, source := range tt.fields.Sources {
s, err := boltdb.SourcesStore.Add(ctx, source)
if err != nil {
t.Fatalf("failed to add source: %v", err)
return
}
tt.fields.Sources[i] = s
}
// Populate Servers
for i, server := range tt.fields.Servers {
s, err := boltdb.ServersStore.Add(ctx, server)
if err != nil {
t.Fatalf("failed to add server: %v", err)
return
}
tt.fields.Servers[i] = s
}
// Populate Layouts
for i, layout := range tt.fields.Layouts {
l, err := boltdb.LayoutsStore.Add(ctx, layout)
if err != nil {
t.Fatalf("failed to add layout: %v", err)
return
}
tt.fields.Layouts[i] = l
}
// Populate Dashboards
for i, dashboard := range tt.fields.Dashboards {
d, err := boltdb.DashboardsStore.Add(ctx, dashboard)
if err != nil {
t.Fatalf("failed to add dashboard: %v", err)
return
}
tt.fields.Dashboards[i] = d
}
_ = boltdb.Close()
go tt.args.server.Serve(ctx)
serverURL := fmt.Sprintf("http://%v:%v%v", host, port, tt.args.path)
// Wait for the server to come online
timeout := time.Now().Add(5 * time.Second)
for {
_, err := http.Get(serverURL + "/swagger.json")
if err == nil {
break
}
if time.Now().After(timeout) {
t.Fatalf("failed to start server")
return
}
}
// Set the Expiry time on the principal
tt.args.principal.IssuedAt = time.Now()
tt.args.principal.ExpiresAt = time.Now().Add(10 * time.Second)
// Construct HTTP Request
buf, _ := json.Marshal(tt.args.payload)
reqBody := ioutil.NopCloser(bytes.NewReader(buf))
req, _ := http.NewRequest(tt.args.method, serverURL, reqBody)
token, _ := oauth2.NewJWT(tt.args.server.TokenSecret).Create(ctx, tt.args.principal)
req.AddCookie(&http.Cookie{
Name: "session",
Value: string(token),
HttpOnly: true,
Path: "/",
})
// Make actual http request
resp, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("failed to make httprequest: %v", err)
return
}
content := resp.Header.Get("Content-Type")
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode != tt.wants.statusCode {
t.Errorf(
"%s %s Status Code = %v, want %v",
tt.args.method,
tt.args.path,
resp.StatusCode,
tt.wants.statusCode,
)
}
if tt.wants.contentType != "" && content != tt.wants.contentType {
t.Errorf(
"%s %s Content Type = %v, want %v",
tt.args.method,
tt.args.path,
content,
tt.wants.contentType,
)
}
if eq, err := jsonEqual(tt.wants.body, string(body)); err != nil || !eq {
t.Errorf(
"%s %s Body = %v, want %v",
tt.args.method,
tt.args.path,
string(body),
tt.wants.body,
)
}
tt.args.server.Listener.Close()
})
}
}