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() }) } }