2017-10-09 21:16:24 +00:00
package server
2017-02-22 03:36:23 +00:00
import (
2017-03-10 19:24:48 +00:00
"bytes"
2017-02-22 03:36:23 +00:00
"context"
2017-10-09 21:16:24 +00:00
"encoding/json"
2017-02-22 03:36:23 +00:00
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
2017-03-10 19:24:48 +00:00
"github.com/bouk/httprouter"
2019-01-08 00:37:16 +00:00
"github.com/influxdata/influxdb/chronograf"
"github.com/influxdata/influxdb/chronograf/mocks"
"github.com/influxdata/influxdb/chronograf/roles"
2017-02-22 03:36:23 +00:00
)
2017-10-09 21:16:24 +00:00
func TestService_UserID ( t * testing . T ) {
2017-02-22 03:36:23 +00:00
type fields struct {
2017-10-09 21:16:24 +00:00
UsersStore chronograf . UsersStore
Logger chronograf . Logger
2017-02-22 03:36:23 +00:00
}
type args struct {
w * httptest . ResponseRecorder
r * http . Request
}
tests := [ ] struct {
name string
fields fields
args args
2017-10-09 21:16:24 +00:00
id string
2017-02-22 03:36:23 +00:00
wantStatus int
wantContentType string
wantBody string
} {
{
2017-10-09 21:16:24 +00:00
name : "Get Single Chronograf User" ,
2017-02-22 03:36:23 +00:00
args : args {
w : httptest . NewRecorder ( ) ,
2017-03-10 19:24:48 +00:00
r : httptest . NewRequest (
2017-10-09 21:16:24 +00:00
"GET" ,
"http://any.url" , // can be any valid URL as we are bypassing mux
nil ,
) ,
2017-03-10 19:24:48 +00:00
} ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2017-10-09 21:16:24 +00:00
UsersStore : & mocks . UsersStore {
2017-10-18 18:17:42 +00:00
GetF : func ( ctx context . Context , q chronograf . UserQuery ) ( * chronograf . User , error ) {
switch * q . ID {
case 1337 :
2017-10-09 21:16:24 +00:00
return & chronograf . User {
ID : 1337 ,
Name : "billysteve" ,
2017-10-24 23:17:59 +00:00
Provider : "google" ,
Scheme : "oauth2" ,
2017-10-13 00:42:30 +00:00
Roles : [ ] chronograf . Role {
2017-11-03 20:32:05 +00:00
roles . ViewerRole ,
2017-10-13 00:42:30 +00:00
} ,
2017-10-09 21:16:24 +00:00
} , nil
default :
2018-11-21 14:22:35 +00:00
return nil , fmt . Errorf ( "user with ID %d not found" , * q . ID )
2017-03-10 19:24:48 +00:00
}
} ,
} ,
} ,
2017-10-09 21:16:24 +00:00
id : "1337" ,
wantStatus : http . StatusOK ,
2017-03-10 19:24:48 +00:00
wantContentType : "application/json" ,
2017-11-01 13:12:19 +00:00
wantBody : ` { "id":"1337","superAdmin":false,"name":"billysteve","provider":"google","scheme":"oauth2","links": { "self":"/chronograf/v1/users/1337"},"roles":[ { "name":"viewer"}]} ` ,
2017-03-10 19:24:48 +00:00
} ,
}
2017-10-09 21:16:24 +00:00
2017-03-10 19:24:48 +00:00
for _ , tt := range tests {
2017-10-09 21:16:24 +00:00
t . Run ( tt . name , func ( t * testing . T ) {
s := & Service {
2017-10-31 20:41:17 +00:00
Store : & mocks . Store {
UsersStore : tt . fields . UsersStore ,
} ,
Logger : tt . fields . Logger ,
2017-10-09 21:16:24 +00:00
}
2017-03-10 19:24:48 +00:00
2017-10-09 21:16:24 +00:00
tt . args . r = tt . args . r . WithContext ( httprouter . WithParams (
context . Background ( ) ,
httprouter . Params {
{
Key : "id" ,
Value : tt . id ,
} ,
} ) )
2017-03-10 19:24:48 +00:00
2017-10-09 21:16:24 +00:00
s . UserID ( tt . args . w , tt . args . r )
2017-03-10 19:24:48 +00:00
2017-10-09 21:16:24 +00:00
resp := tt . args . w . Result ( )
content := resp . Header . Get ( "Content-Type" )
body , _ := ioutil . ReadAll ( resp . Body )
2017-03-10 19:24:48 +00:00
2017-10-09 21:16:24 +00:00
if resp . StatusCode != tt . wantStatus {
t . Errorf ( "%q. UserID() = %v, want %v" , tt . name , resp . StatusCode , tt . wantStatus )
}
if tt . wantContentType != "" && content != tt . wantContentType {
t . Errorf ( "%q. UserID() = %v, want %v" , tt . name , content , tt . wantContentType )
}
if eq , _ := jsonEqual ( string ( body ) , tt . wantBody ) ; tt . wantBody != "" && ! eq {
t . Errorf ( "%q. UserID() = \n***%v***\n,\nwant\n***%v***" , tt . name , string ( body ) , tt . wantBody )
}
} )
2017-03-10 19:24:48 +00:00
}
}
2017-10-09 21:16:24 +00:00
func TestService_NewUser ( t * testing . T ) {
2017-03-10 19:24:48 +00:00
type fields struct {
2018-01-12 17:27:55 +00:00
UsersStore chronograf . UsersStore
OrganizationsStore chronograf . OrganizationsStore
ConfigStore chronograf . ConfigStore
Logger chronograf . Logger
2017-03-10 19:24:48 +00:00
}
type args struct {
2017-11-09 14:18:13 +00:00
w * httptest . ResponseRecorder
r * http . Request
user * userRequest
userKeyUser * chronograf . User
2017-03-10 19:24:48 +00:00
}
tests := [ ] struct {
name string
fields fields
args args
wantStatus int
wantContentType string
wantBody string
} {
{
2017-10-09 21:16:24 +00:00
name : "Create a new Chronograf User" ,
2017-03-10 19:24:48 +00:00
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
2017-10-09 21:16:24 +00:00
"POST" ,
"http://any.url" ,
nil ,
) ,
2017-10-13 19:34:30 +00:00
user : & userRequest {
2017-10-09 21:16:24 +00:00
Name : "bob" ,
2017-10-24 23:17:59 +00:00
Provider : "github" ,
Scheme : "oauth2" ,
2017-03-10 19:24:48 +00:00
} ,
2017-02-24 05:26:09 +00:00
} ,
2017-02-22 03:36:23 +00:00
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2017-12-14 19:11:51 +00:00
ConfigStore : & mocks . ConfigStore {
Config : & chronograf . Config {
Auth : chronograf . AuthConfig {
SuperAdminNewUsers : false ,
} ,
} ,
} ,
2017-10-09 21:16:24 +00:00
UsersStore : & mocks . UsersStore {
AddF : func ( ctx context . Context , user * chronograf . User ) ( * chronograf . User , error ) {
return & chronograf . User {
ID : 1338 ,
Name : "bob" ,
2017-10-24 23:17:59 +00:00
Provider : "github" ,
Scheme : "oauth2" ,
2017-10-13 19:34:30 +00:00
Roles : [ ] chronograf . Role { } ,
2017-03-10 19:24:48 +00:00
} , nil
} ,
} ,
2017-02-24 05:26:09 +00:00
} ,
2017-10-09 21:16:24 +00:00
wantStatus : http . StatusCreated ,
2017-02-22 03:36:23 +00:00
wantContentType : "application/json" ,
2017-11-01 13:12:19 +00:00
wantBody : ` { "id":"1338","superAdmin":false,"name":"bob","provider":"github","scheme":"oauth2","roles":[],"links": { "self":"/chronograf/v1/users/1338"}} ` ,
2017-02-22 03:36:23 +00:00
} ,
2017-11-03 16:06:18 +00:00
{
name : "Create a new Chronograf User with multiple roles" ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"POST" ,
"http://any.url" ,
nil ,
) ,
user : & userRequest {
Name : "bob" ,
Provider : "github" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
{
2017-11-06 16:31:44 +00:00
Name : roles . AdminRoleName ,
2017-11-22 20:03:15 +00:00
Organization : "1" ,
2017-11-03 16:06:18 +00:00
} ,
{
2017-11-06 16:31:44 +00:00
Name : roles . ViewerRoleName ,
2017-11-22 20:03:15 +00:00
Organization : "2" ,
2017-11-03 16:06:18 +00:00
} ,
} ,
} ,
} ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2017-12-14 19:11:51 +00:00
ConfigStore : & mocks . ConfigStore {
Config : & chronograf . Config {
Auth : chronograf . AuthConfig {
SuperAdminNewUsers : false ,
} ,
} ,
} ,
2018-01-12 17:27:55 +00:00
OrganizationsStore : & mocks . OrganizationsStore {
GetF : func ( ctx context . Context , q chronograf . OrganizationQuery ) ( * chronograf . Organization , error ) {
switch * q . ID {
case "1" :
return & chronograf . Organization {
ID : "1" ,
Name : "org" ,
DefaultRole : roles . ViewerRoleName ,
} , nil
case "2" :
return & chronograf . Organization {
ID : "2" ,
Name : "another" ,
DefaultRole : roles . MemberRoleName ,
} , nil
}
return nil , fmt . Errorf ( "org not found" )
} ,
} ,
2017-11-03 16:06:18 +00:00
UsersStore : & mocks . UsersStore {
AddF : func ( ctx context . Context , user * chronograf . User ) ( * chronograf . User , error ) {
return & chronograf . User {
ID : 1338 ,
Name : "bob" ,
Provider : "github" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
{
2017-11-06 16:31:44 +00:00
Name : roles . AdminRoleName ,
2017-11-22 20:03:15 +00:00
Organization : "1" ,
2017-11-03 16:06:18 +00:00
} ,
{
2017-11-06 16:31:44 +00:00
Name : roles . ViewerRoleName ,
2017-11-22 20:03:15 +00:00
Organization : "2" ,
2017-11-03 16:06:18 +00:00
} ,
} ,
} , nil
} ,
} ,
} ,
wantStatus : http . StatusCreated ,
wantContentType : "application/json" ,
2017-11-22 20:03:15 +00:00
wantBody : ` { "id":"1338","superAdmin":false,"name":"bob","provider":"github","scheme":"oauth2","roles":[ { "name":"admin","organization":"1"}, { "name":"viewer","organization":"2"}],"links": { "self":"/chronograf/v1/users/1338"}} ` ,
2017-11-03 16:06:18 +00:00
} ,
{
name : "Create a new Chronograf User with multiple roles same org" ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"POST" ,
"http://any.url" ,
nil ,
) ,
user : & userRequest {
Name : "bob" ,
Provider : "github" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
{
2017-11-06 16:31:44 +00:00
Name : roles . AdminRoleName ,
2017-11-22 20:03:15 +00:00
Organization : "1" ,
2017-11-03 16:06:18 +00:00
} ,
{
2017-11-06 16:31:44 +00:00
Name : roles . ViewerRoleName ,
2017-11-22 20:03:15 +00:00
Organization : "1" ,
2017-11-03 16:06:18 +00:00
} ,
} ,
} ,
} ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2017-12-14 19:11:51 +00:00
ConfigStore : & mocks . ConfigStore {
Config : & chronograf . Config {
Auth : chronograf . AuthConfig {
SuperAdminNewUsers : false ,
} ,
} ,
} ,
2017-11-03 16:06:18 +00:00
UsersStore : & mocks . UsersStore {
AddF : func ( ctx context . Context , user * chronograf . User ) ( * chronograf . User , error ) {
return & chronograf . User {
ID : 1338 ,
Name : "bob" ,
Provider : "github" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
{
2017-11-06 16:31:44 +00:00
Name : roles . AdminRoleName ,
2017-11-22 20:03:15 +00:00
Organization : "1" ,
2017-11-03 16:06:18 +00:00
} ,
{
2017-11-06 16:31:44 +00:00
Name : roles . ViewerRoleName ,
2017-11-22 20:03:15 +00:00
Organization : "1" ,
2017-11-03 16:06:18 +00:00
} ,
} ,
} , nil
} ,
} ,
} ,
wantStatus : http . StatusUnprocessableEntity ,
wantContentType : "application/json" ,
2017-11-22 20:03:15 +00:00
wantBody : ` { "code":422,"message":"duplicate organization \"1\" in roles"} ` ,
2017-11-03 16:06:18 +00:00
} ,
2017-11-03 16:51:33 +00:00
{
name : "Create a new SuperAdmin User - Not as superadmin" ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"POST" ,
"http://any.url" ,
nil ,
) ,
user : & userRequest {
Name : "bob" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : true ,
} ,
2017-11-09 14:18:13 +00:00
userKeyUser : & chronograf . User {
ID : 0 ,
Name : "coolUser" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : false ,
} ,
2017-11-03 16:51:33 +00:00
} ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2017-12-14 19:11:51 +00:00
ConfigStore : & mocks . ConfigStore {
Config : & chronograf . Config {
Auth : chronograf . AuthConfig {
SuperAdminNewUsers : false ,
} ,
} ,
} ,
2017-11-03 16:51:33 +00:00
UsersStore : & mocks . UsersStore {
AddF : func ( ctx context . Context , user * chronograf . User ) ( * chronograf . User , error ) {
return & chronograf . User {
ID : 1338 ,
Name : "bob" ,
Provider : "github" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role { } ,
} , nil
} ,
} ,
} ,
wantStatus : http . StatusUnauthorized ,
wantContentType : "application/json" ,
2019-01-08 00:37:16 +00:00
wantBody : ` { "code":401,"message":"user does not have authorization required to set SuperAdmin status. See https://github.com/influxdata/influxdb/chronograf/issues/2601 for more information"} ` ,
2017-11-03 16:51:33 +00:00
} ,
{
name : "Create a new SuperAdmin User - as superadmin" ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"POST" ,
"http://any.url" ,
nil ,
) ,
user : & userRequest {
Name : "bob" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : true ,
} ,
2017-11-09 14:18:13 +00:00
userKeyUser : & chronograf . User {
ID : 0 ,
Name : "coolUser" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : true ,
} ,
2017-11-03 16:51:33 +00:00
} ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2017-12-14 19:11:51 +00:00
ConfigStore : & mocks . ConfigStore {
Config : & chronograf . Config {
Auth : chronograf . AuthConfig {
SuperAdminNewUsers : false ,
} ,
} ,
} ,
2017-11-03 16:51:33 +00:00
UsersStore : & mocks . UsersStore {
AddF : func ( ctx context . Context , user * chronograf . User ) ( * chronograf . User , error ) {
return & chronograf . User {
2017-11-06 19:17:27 +00:00
ID : 1338 ,
Name : "bob" ,
Provider : "github" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role { } ,
SuperAdmin : true ,
2017-11-03 16:51:33 +00:00
} , nil
} ,
} ,
} ,
wantStatus : http . StatusCreated ,
wantContentType : "application/json" ,
2017-11-06 19:17:27 +00:00
wantBody : ` { "id":"1338","superAdmin":true,"name":"bob","provider":"github","scheme":"oauth2","roles":[],"links": { "self":"/chronograf/v1/users/1338"}} ` ,
2017-11-03 16:51:33 +00:00
} ,
2017-12-14 19:11:51 +00:00
{
name : "Create a new User with SuperAdminNewUsers: true in ConfigStore" ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"POST" ,
"http://any.url" ,
nil ,
) ,
user : & userRequest {
Name : "bob" ,
Provider : "github" ,
Scheme : "oauth2" ,
} ,
userKeyUser : & chronograf . User {
ID : 0 ,
Name : "coolUser" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : true ,
} ,
} ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2017-12-14 19:11:51 +00:00
ConfigStore : & mocks . ConfigStore {
Config : & chronograf . Config {
Auth : chronograf . AuthConfig {
SuperAdminNewUsers : true ,
} ,
} ,
} ,
UsersStore : & mocks . UsersStore {
AddF : func ( ctx context . Context , user * chronograf . User ) ( * chronograf . User , error ) {
user . ID = 1338
return user , nil
} ,
} ,
} ,
wantStatus : http . StatusCreated ,
wantContentType : "application/json" ,
wantBody : ` { "id":"1338","superAdmin":true,"name":"bob","provider":"github","scheme":"oauth2","roles":[],"links": { "self":"/chronograf/v1/users/1338"}} ` ,
} ,
2018-01-12 17:27:55 +00:00
{
name : "Create a new Chronograf User with multiple roles with wildcard default role" ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"POST" ,
"http://any.url" ,
nil ,
) ,
user : & userRequest {
Name : "bob" ,
Provider : "github" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
{
Name : roles . AdminRoleName ,
Organization : "1" ,
} ,
{
Name : roles . WildcardRoleName ,
Organization : "2" ,
} ,
} ,
} ,
} ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2018-01-12 17:27:55 +00:00
ConfigStore : & mocks . ConfigStore {
Config : & chronograf . Config {
Auth : chronograf . AuthConfig {
SuperAdminNewUsers : false ,
} ,
} ,
} ,
OrganizationsStore : & mocks . OrganizationsStore {
GetF : func ( ctx context . Context , q chronograf . OrganizationQuery ) ( * chronograf . Organization , error ) {
switch * q . ID {
case "1" :
return & chronograf . Organization {
ID : "1" ,
Name : "org" ,
DefaultRole : roles . ViewerRoleName ,
} , nil
case "2" :
return & chronograf . Organization {
ID : "2" ,
Name : "another" ,
DefaultRole : roles . MemberRoleName ,
} , nil
}
return nil , fmt . Errorf ( "org not found" )
} ,
} ,
UsersStore : & mocks . UsersStore {
AddF : func ( ctx context . Context , user * chronograf . User ) ( * chronograf . User , error ) {
return & chronograf . User {
ID : 1338 ,
Name : "bob" ,
Provider : "github" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
{
Name : roles . AdminRoleName ,
Organization : "1" ,
} ,
{
Name : roles . MemberRoleName ,
Organization : "2" ,
} ,
} ,
} , nil
} ,
} ,
} ,
wantStatus : http . StatusCreated ,
wantContentType : "application/json" ,
wantBody : ` { "id":"1338","superAdmin":false,"name":"bob","provider":"github","scheme":"oauth2","roles":[ { "name":"admin","organization":"1"}, { "name":"member","organization":"2"}],"links": { "self":"/chronograf/v1/users/1338"}} ` ,
} ,
2017-03-10 19:24:48 +00:00
}
2017-10-09 21:16:24 +00:00
2017-03-10 19:24:48 +00:00
for _ , tt := range tests {
2017-10-09 21:16:24 +00:00
t . Run ( tt . name , func ( t * testing . T ) {
s := & Service {
2017-10-31 20:41:17 +00:00
Store : & mocks . Store {
2018-01-12 17:27:55 +00:00
UsersStore : tt . fields . UsersStore ,
ConfigStore : tt . fields . ConfigStore ,
OrganizationsStore : tt . fields . OrganizationsStore ,
2017-10-31 20:41:17 +00:00
} ,
Logger : tt . fields . Logger ,
2017-10-09 21:16:24 +00:00
}
buf , _ := json . Marshal ( tt . args . user )
tt . args . r . Body = ioutil . NopCloser ( bytes . NewReader ( buf ) )
2017-11-03 16:51:33 +00:00
ctx := tt . args . r . Context ( )
2017-11-09 14:18:13 +00:00
if tt . args . userKeyUser != nil {
2017-11-10 16:18:06 +00:00
ctx = context . WithValue ( ctx , UserContextKey , tt . args . userKeyUser )
2017-11-03 16:51:33 +00:00
}
tt . args . r = tt . args . r . WithContext ( ctx )
2017-10-09 21:16:24 +00:00
s . NewUser ( tt . args . w , tt . args . r )
2017-03-10 19:24:48 +00:00
2017-10-09 21:16:24 +00:00
resp := tt . args . w . Result ( )
content := resp . Header . Get ( "Content-Type" )
body , _ := ioutil . ReadAll ( resp . Body )
2017-03-10 19:24:48 +00:00
2017-10-09 21:16:24 +00:00
if resp . StatusCode != tt . wantStatus {
t . Errorf ( "%q. UserID() = %v, want %v" , tt . name , resp . StatusCode , tt . wantStatus )
}
if tt . wantContentType != "" && content != tt . wantContentType {
t . Errorf ( "%q. UserID() = %v, want %v" , tt . name , content , tt . wantContentType )
}
if eq , _ := jsonEqual ( string ( body ) , tt . wantBody ) ; tt . wantBody != "" && ! eq {
t . Errorf ( "%q. UserID() = \n***%v***\n,\nwant\n***%v***" , tt . name , string ( body ) , tt . wantBody )
}
} )
2017-03-10 19:24:48 +00:00
}
}
2017-10-09 21:16:24 +00:00
func TestService_RemoveUser ( t * testing . T ) {
2017-03-10 19:24:48 +00:00
type fields struct {
2017-10-09 21:16:24 +00:00
UsersStore chronograf . UsersStore
Logger chronograf . Logger
2017-03-10 19:24:48 +00:00
}
type args struct {
2017-10-09 21:16:24 +00:00
w * httptest . ResponseRecorder
r * http . Request
2017-11-09 14:37:15 +00:00
user * chronograf . User
id string
2017-03-10 19:24:48 +00:00
}
tests := [ ] struct {
2017-10-09 21:16:24 +00:00
name string
fields fields
args args
wantStatus int
2017-11-09 14:37:15 +00:00
wantBody string
2017-03-10 19:24:48 +00:00
} {
2017-02-22 03:36:23 +00:00
{
2017-10-09 21:16:24 +00:00
name : "Delete a Chronograf User" ,
2017-02-22 03:36:23 +00:00
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2017-10-09 21:16:24 +00:00
UsersStore : & mocks . UsersStore {
2017-10-18 18:17:42 +00:00
GetF : func ( ctx context . Context , q chronograf . UserQuery ) ( * chronograf . User , error ) {
switch * q . ID {
case 1339 :
2017-10-09 21:16:24 +00:00
return & chronograf . User {
ID : 1339 ,
Name : "helena" ,
2017-10-24 23:17:59 +00:00
Provider : "heroku" ,
Scheme : "oauth2" ,
2017-10-09 21:16:24 +00:00
} , nil
default :
2018-11-21 14:22:35 +00:00
return nil , fmt . Errorf ( "user with ID %d not found" , * q . ID )
2017-03-10 19:24:48 +00:00
}
} ,
2017-10-09 21:16:24 +00:00
DeleteF : func ( ctx context . Context , user * chronograf . User ) error {
2017-03-10 19:24:48 +00:00
return nil
} ,
} ,
} ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
2017-10-09 21:16:24 +00:00
"DELETE" ,
"http://any.url" ,
nil ,
) ,
2017-11-09 14:37:15 +00:00
user : & chronograf . User {
ID : 1338 ,
2017-10-09 21:16:24 +00:00
Name : "helena" ,
2017-10-24 23:17:59 +00:00
Provider : "heroku" ,
Scheme : "oauth2" ,
2017-03-10 19:24:48 +00:00
} ,
2017-11-09 14:37:15 +00:00
id : "1339" ,
2017-02-24 05:26:09 +00:00
} ,
2017-03-10 19:24:48 +00:00
wantStatus : http . StatusNoContent ,
2017-02-22 03:36:23 +00:00
} ,
2017-11-09 14:37:15 +00:00
{
name : "Deleting yourself" ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2017-11-09 14:37:15 +00:00
UsersStore : & mocks . UsersStore {
GetF : func ( ctx context . Context , q chronograf . UserQuery ) ( * chronograf . User , error ) {
switch * q . ID {
case 1339 :
return & chronograf . User {
ID : 1339 ,
Name : "helena" ,
Provider : "heroku" ,
Scheme : "oauth2" ,
} , nil
default :
2018-11-21 14:22:35 +00:00
return nil , fmt . Errorf ( "user with ID %d not found" , * q . ID )
2017-11-09 14:37:15 +00:00
}
} ,
DeleteF : func ( ctx context . Context , user * chronograf . User ) error {
return nil
} ,
} ,
} ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"DELETE" ,
"http://any.url" ,
nil ,
) ,
user : & chronograf . User {
ID : 1339 ,
Name : "helena" ,
Provider : "heroku" ,
Scheme : "oauth2" ,
} ,
id : "1339" ,
} ,
2018-02-07 14:46:08 +00:00
wantStatus : http . StatusNoContent ,
wantBody : ` ` ,
2017-11-09 14:37:15 +00:00
} ,
2017-02-22 03:36:23 +00:00
}
for _ , tt := range tests {
2017-10-09 21:16:24 +00:00
t . Run ( tt . name , func ( t * testing . T ) {
s := & Service {
2017-10-31 20:41:17 +00:00
Store : & mocks . Store {
UsersStore : tt . fields . UsersStore ,
} ,
Logger : tt . fields . Logger ,
2017-10-09 21:16:24 +00:00
}
tt . args . r = tt . args . r . WithContext ( httprouter . WithParams (
context . Background ( ) ,
httprouter . Params {
{
Key : "id" ,
2017-11-09 14:37:15 +00:00
Value : tt . args . id ,
2017-10-09 21:16:24 +00:00
} ,
2017-03-10 19:24:48 +00:00
} ,
2017-10-09 21:16:24 +00:00
) )
2017-02-22 03:36:23 +00:00
2017-11-09 14:37:15 +00:00
if tt . args . user != nil {
ctx := tt . args . r . Context ( )
2017-11-10 16:18:06 +00:00
ctx = context . WithValue ( ctx , UserContextKey , tt . args . user )
2017-11-09 14:37:15 +00:00
tt . args . r = tt . args . r . WithContext ( ctx )
}
2017-10-09 21:16:24 +00:00
s . RemoveUser ( tt . args . w , tt . args . r )
resp := tt . args . w . Result ( )
2017-11-09 14:37:15 +00:00
body , _ := ioutil . ReadAll ( resp . Body )
2017-10-09 21:16:24 +00:00
if resp . StatusCode != tt . wantStatus {
t . Errorf ( "%q. RemoveUser() = %v, want %v" , tt . name , resp . StatusCode , tt . wantStatus )
}
2017-11-09 14:37:15 +00:00
if tt . wantStatus == http . StatusNoContent {
return
}
if eq , _ := jsonEqual ( string ( body ) , tt . wantBody ) ; ! eq {
t . Errorf ( "%q. RemoveUser() = %v, want %v" , tt . name , string ( body ) , tt . wantBody )
}
2017-10-09 21:16:24 +00:00
} )
2017-03-10 19:24:48 +00:00
}
}
2017-02-22 03:36:23 +00:00
2017-10-09 21:16:24 +00:00
func TestService_UpdateUser ( t * testing . T ) {
2017-03-10 19:24:48 +00:00
type fields struct {
2018-01-12 17:27:55 +00:00
UsersStore chronograf . UsersStore
OrganizationsStore chronograf . OrganizationsStore
Logger chronograf . Logger
2017-03-10 19:24:48 +00:00
}
type args struct {
2017-11-09 14:18:13 +00:00
w * httptest . ResponseRecorder
r * http . Request
user * userRequest
userKeyUser * chronograf . User
2017-03-10 19:24:48 +00:00
}
tests := [ ] struct {
name string
fields fields
args args
2017-10-09 21:16:24 +00:00
id string
2017-03-10 19:24:48 +00:00
wantStatus int
wantContentType string
wantBody string
} {
2018-01-12 17:37:30 +00:00
{
name : "Update a Chronograf user - no roles" ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2018-01-12 17:37:30 +00:00
UsersStore : & mocks . UsersStore {
UpdateF : func ( ctx context . Context , user * chronograf . User ) error {
return nil
} ,
GetF : func ( ctx context . Context , q chronograf . UserQuery ) ( * chronograf . User , error ) {
switch * q . ID {
case 1336 :
return & chronograf . User {
ID : 1336 ,
Name : "bobbetta" ,
Provider : "github" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
{
Name : roles . EditorRoleName ,
Organization : "1" ,
} ,
} ,
} , nil
default :
2018-11-21 14:22:35 +00:00
return nil , fmt . Errorf ( "user with ID %d not found" , * q . ID )
2018-01-12 17:37:30 +00:00
}
} ,
} ,
} ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"PATCH" ,
"http://any.url" ,
nil ,
) ,
userKeyUser : & chronograf . User {
ID : 0 ,
Name : "coolUser" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : false ,
} ,
user : & userRequest {
ID : 1336 ,
Roles : [ ] chronograf . Role { } ,
} ,
} ,
id : "1336" ,
wantStatus : http . StatusOK ,
wantContentType : "application/json" ,
wantBody : ` { "id":"1336","superAdmin":false,"name":"bobbetta","provider":"github","scheme":"oauth2","links": { "self":"/chronograf/v1/users/1336"},"roles":[]} ` ,
} ,
2017-03-10 19:24:48 +00:00
{
2017-10-09 21:16:24 +00:00
name : "Update a Chronograf user" ,
2017-03-10 19:24:48 +00:00
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2018-01-12 17:27:55 +00:00
OrganizationsStore : & mocks . OrganizationsStore {
GetF : func ( ctx context . Context , q chronograf . OrganizationQuery ) ( * chronograf . Organization , error ) {
switch * q . ID {
case "1" :
return & chronograf . Organization {
ID : "1" ,
Name : "org" ,
DefaultRole : roles . ViewerRoleName ,
} , nil
}
return nil , fmt . Errorf ( "org not found" )
} ,
} ,
2017-10-09 21:16:24 +00:00
UsersStore : & mocks . UsersStore {
UpdateF : func ( ctx context . Context , user * chronograf . User ) error {
2017-03-10 19:24:48 +00:00
return nil
} ,
2017-10-18 18:17:42 +00:00
GetF : func ( ctx context . Context , q chronograf . UserQuery ) ( * chronograf . User , error ) {
switch * q . ID {
case 1336 :
2017-10-09 21:16:24 +00:00
return & chronograf . User {
ID : 1336 ,
2017-10-24 21:20:24 +00:00
Name : "bobbetta" ,
2017-10-24 23:17:59 +00:00
Provider : "github" ,
Scheme : "oauth2" ,
2017-10-13 00:42:30 +00:00
Roles : [ ] chronograf . Role {
2017-11-22 19:49:44 +00:00
{
Name : roles . EditorRoleName ,
Organization : "1" ,
} ,
2017-10-13 00:42:30 +00:00
} ,
2017-10-09 21:16:24 +00:00
} , nil
default :
2018-11-21 14:22:35 +00:00
return nil , fmt . Errorf ( "user with ID %d not found" , * q . ID )
2017-03-10 19:24:48 +00:00
}
} ,
} ,
} ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
2017-10-09 21:16:24 +00:00
"PATCH" ,
"http://any.url" ,
nil ,
) ,
2017-12-20 23:17:08 +00:00
userKeyUser : & chronograf . User {
ID : 0 ,
Name : "coolUser" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : false ,
} ,
2017-10-13 19:34:30 +00:00
user : & userRequest {
2017-10-24 21:20:24 +00:00
ID : 1336 ,
2017-10-16 23:26:08 +00:00
Roles : [ ] chronograf . Role {
2017-11-22 19:49:44 +00:00
{
Name : roles . AdminRoleName ,
Organization : "1" ,
} ,
2017-10-13 00:42:30 +00:00
} ,
2017-03-10 19:24:48 +00:00
} ,
} ,
2017-10-09 21:16:24 +00:00
id : "1336" ,
2017-03-10 19:24:48 +00:00
wantStatus : http . StatusOK ,
wantContentType : "application/json" ,
2017-11-22 19:49:44 +00:00
wantBody : ` { "id":"1336","superAdmin":false,"name":"bobbetta","provider":"github","scheme":"oauth2","links": { "self":"/chronograf/v1/users/1336"},"roles":[ { "name":"admin","organization":"1"}]} ` ,
2017-10-10 18:40:33 +00:00
} ,
2017-11-03 16:06:18 +00:00
{
name : "Update a Chronograf user roles different orgs" ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2018-01-12 17:27:55 +00:00
OrganizationsStore : & mocks . OrganizationsStore {
GetF : func ( ctx context . Context , q chronograf . OrganizationQuery ) ( * chronograf . Organization , error ) {
switch * q . ID {
case "1" :
return & chronograf . Organization {
ID : "1" ,
Name : "org" ,
DefaultRole : roles . ViewerRoleName ,
} , nil
case "2" :
return & chronograf . Organization {
ID : "2" ,
Name : "another" ,
DefaultRole : roles . ViewerRoleName ,
} , nil
}
return nil , fmt . Errorf ( "org not found" )
} ,
} ,
2017-11-03 16:06:18 +00:00
UsersStore : & mocks . UsersStore {
UpdateF : func ( ctx context . Context , user * chronograf . User ) error {
return nil
} ,
GetF : func ( ctx context . Context , q chronograf . UserQuery ) ( * chronograf . User , error ) {
switch * q . ID {
case 1336 :
return & chronograf . User {
ID : 1336 ,
Name : "bobbetta" ,
Provider : "github" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
2017-11-06 16:31:44 +00:00
roles . EditorRole ,
2017-11-03 16:06:18 +00:00
} ,
} , nil
default :
2018-11-21 14:22:35 +00:00
return nil , fmt . Errorf ( "user with ID %d not found" , * q . ID )
2017-11-03 16:06:18 +00:00
}
} ,
} ,
} ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"PATCH" ,
"http://any.url" ,
nil ,
) ,
2017-12-20 23:17:08 +00:00
userKeyUser : & chronograf . User {
ID : 0 ,
Name : "coolUser" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : false ,
} ,
2017-11-03 16:06:18 +00:00
user : & userRequest {
ID : 1336 ,
Roles : [ ] chronograf . Role {
{
2017-11-06 16:31:44 +00:00
Name : roles . AdminRoleName ,
2017-11-22 19:49:44 +00:00
Organization : "1" ,
2017-11-03 16:06:18 +00:00
} ,
{
2017-11-06 16:31:44 +00:00
Name : roles . ViewerRoleName ,
2017-11-22 19:49:44 +00:00
Organization : "2" ,
2017-11-03 16:06:18 +00:00
} ,
} ,
} ,
} ,
id : "1336" ,
wantStatus : http . StatusOK ,
wantContentType : "application/json" ,
2017-11-22 19:49:44 +00:00
wantBody : ` { "id":"1336","superAdmin":false,"name":"bobbetta","provider":"github","scheme":"oauth2","links": { "self":"/chronograf/v1/users/1336"},"roles":[ { "name":"admin","organization":"1"}, { "name":"viewer","organization":"2"}]} ` ,
2017-11-03 16:06:18 +00:00
} ,
{
name : "Update a Chronograf user roles same org" ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2017-11-03 16:06:18 +00:00
UsersStore : & mocks . UsersStore {
UpdateF : func ( ctx context . Context , user * chronograf . User ) error {
return nil
} ,
GetF : func ( ctx context . Context , q chronograf . UserQuery ) ( * chronograf . User , error ) {
switch * q . ID {
case 1336 :
return & chronograf . User {
ID : 1336 ,
Name : "bobbetta" ,
Provider : "github" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
2017-11-06 16:31:44 +00:00
roles . EditorRole ,
2017-11-03 16:06:18 +00:00
} ,
} , nil
default :
2018-11-21 14:22:35 +00:00
return nil , fmt . Errorf ( "user with ID %d not found" , * q . ID )
2017-11-03 16:06:18 +00:00
}
} ,
} ,
} ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"PATCH" ,
"http://any.url" ,
nil ,
) ,
user : & userRequest {
ID : 1336 ,
Roles : [ ] chronograf . Role {
{
2017-11-06 16:31:44 +00:00
Name : roles . AdminRoleName ,
2017-11-22 19:49:44 +00:00
Organization : "1" ,
2017-11-03 16:06:18 +00:00
} ,
{
2017-11-06 16:31:44 +00:00
Name : roles . ViewerRoleName ,
2017-11-22 19:49:44 +00:00
Organization : "1" ,
2017-11-03 16:06:18 +00:00
} ,
} ,
} ,
} ,
id : "1336" ,
wantStatus : http . StatusUnprocessableEntity ,
wantContentType : "application/json" ,
2017-11-22 19:49:44 +00:00
wantBody : ` { "code":422,"message":"duplicate organization \"1\" in roles"} ` ,
2017-11-03 16:06:18 +00:00
} ,
2017-12-20 23:17:08 +00:00
{
name : "SuperAdmin modifying their own SuperAdmin Status - user missing from context" ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2018-01-12 17:27:55 +00:00
OrganizationsStore : & mocks . OrganizationsStore {
GetF : func ( ctx context . Context , q chronograf . OrganizationQuery ) ( * chronograf . Organization , error ) {
switch * q . ID {
case "1" :
return & chronograf . Organization {
ID : "1" ,
Name : "org" ,
DefaultRole : roles . ViewerRoleName ,
} , nil
}
return nil , fmt . Errorf ( "org not found" )
} ,
} ,
2017-12-20 23:17:08 +00:00
UsersStore : & mocks . UsersStore {
UpdateF : func ( ctx context . Context , user * chronograf . User ) error {
return nil
} ,
GetF : func ( ctx context . Context , q chronograf . UserQuery ) ( * chronograf . User , error ) {
switch * q . ID {
case 1336 :
return & chronograf . User {
ID : 1336 ,
Name : "bobbetta" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : true ,
Roles : [ ] chronograf . Role {
{
Name : roles . EditorRoleName ,
Organization : "1" ,
} ,
} ,
} , nil
default :
2018-11-21 14:22:35 +00:00
return nil , fmt . Errorf ( "user with ID %d not found" , * q . ID )
2017-12-20 23:17:08 +00:00
}
} ,
} ,
} ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"PATCH" ,
"http://any.url" ,
nil ,
) ,
user : & userRequest {
ID : 1336 ,
SuperAdmin : false ,
Roles : [ ] chronograf . Role {
{
Name : roles . AdminRoleName ,
Organization : "1" ,
} ,
} ,
} ,
} ,
id : "1336" ,
wantStatus : http . StatusInternalServerError ,
wantContentType : "application/json" ,
wantBody : ` { "code":500,"message":"failed to retrieve user from context"} ` ,
} ,
{
name : "SuperAdmin modifying their own SuperAdmin Status" ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2018-01-12 17:27:55 +00:00
OrganizationsStore : & mocks . OrganizationsStore {
GetF : func ( ctx context . Context , q chronograf . OrganizationQuery ) ( * chronograf . Organization , error ) {
switch * q . ID {
case "1" :
return & chronograf . Organization {
ID : "1" ,
Name : "org" ,
DefaultRole : roles . ViewerRoleName ,
} , nil
}
return nil , fmt . Errorf ( "org not found" )
} ,
} ,
2017-12-20 23:17:08 +00:00
UsersStore : & mocks . UsersStore {
UpdateF : func ( ctx context . Context , user * chronograf . User ) error {
return nil
} ,
GetF : func ( ctx context . Context , q chronograf . UserQuery ) ( * chronograf . User , error ) {
switch * q . ID {
case 1336 :
return & chronograf . User {
ID : 1336 ,
Name : "bobbetta" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : true ,
Roles : [ ] chronograf . Role {
{
Name : roles . EditorRoleName ,
Organization : "1" ,
} ,
} ,
} , nil
default :
2018-11-21 14:22:35 +00:00
return nil , fmt . Errorf ( "user with ID %d not found" , * q . ID )
2017-12-20 23:17:08 +00:00
}
} ,
} ,
} ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"PATCH" ,
"http://any.url" ,
nil ,
) ,
user : & userRequest {
ID : 1336 ,
SuperAdmin : false ,
Roles : [ ] chronograf . Role {
{
Name : roles . AdminRoleName ,
Organization : "1" ,
} ,
} ,
} ,
userKeyUser : & chronograf . User {
ID : 1336 ,
Name : "coolUser" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : true ,
} ,
} ,
id : "1336" ,
wantStatus : http . StatusUnauthorized ,
wantContentType : "application/json" ,
wantBody : ` { "code":401,"message":"user cannot modify their own SuperAdmin status"} ` ,
} ,
2017-12-04 21:53:30 +00:00
{
name : "Update a SuperAdmin's Roles - without super admin context" ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2018-01-12 17:27:55 +00:00
OrganizationsStore : & mocks . OrganizationsStore {
GetF : func ( ctx context . Context , q chronograf . OrganizationQuery ) ( * chronograf . Organization , error ) {
switch * q . ID {
case "1" :
return & chronograf . Organization {
ID : "1" ,
Name : "org" ,
DefaultRole : roles . ViewerRoleName ,
} , nil
}
return nil , fmt . Errorf ( "org not found" )
} ,
} ,
2017-12-04 21:53:30 +00:00
UsersStore : & mocks . UsersStore {
UpdateF : func ( ctx context . Context , user * chronograf . User ) error {
return nil
} ,
GetF : func ( ctx context . Context , q chronograf . UserQuery ) ( * chronograf . User , error ) {
switch * q . ID {
case 1336 :
return & chronograf . User {
ID : 1336 ,
Name : "bobbetta" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : true ,
Roles : [ ] chronograf . Role {
{
Name : roles . EditorRoleName ,
Organization : "1" ,
} ,
} ,
} , nil
default :
2018-11-21 14:22:35 +00:00
return nil , fmt . Errorf ( "user with ID %d not found" , * q . ID )
2017-12-04 21:53:30 +00:00
}
} ,
} ,
} ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"PATCH" ,
"http://any.url" ,
nil ,
) ,
user : & userRequest {
ID : 1336 ,
SuperAdmin : true ,
Roles : [ ] chronograf . Role {
{
Name : roles . AdminRoleName ,
Organization : "1" ,
} ,
} ,
} ,
userKeyUser : & chronograf . User {
ID : 0 ,
Name : "coolUser" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : false ,
} ,
} ,
id : "1336" ,
wantStatus : http . StatusOK ,
wantContentType : "application/json" ,
wantBody : ` { "links": { "self":"/chronograf/v1/users/1336"},"id":"1336","name":"bobbetta","provider":"github","scheme":"oauth2","superAdmin":true,"roles":[ { "name":"admin","organization":"1"}]} ` ,
} ,
2017-11-03 16:51:33 +00:00
{
name : "Update a Chronograf user to super admin - without super admin context" ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2018-01-12 17:27:55 +00:00
OrganizationsStore : & mocks . OrganizationsStore {
GetF : func ( ctx context . Context , q chronograf . OrganizationQuery ) ( * chronograf . Organization , error ) {
switch * q . ID {
case "1" :
return & chronograf . Organization {
ID : "1" ,
Name : "org" ,
DefaultRole : roles . ViewerRoleName ,
} , nil
}
return nil , fmt . Errorf ( "org not found" )
} ,
} ,
2017-11-03 16:51:33 +00:00
UsersStore : & mocks . UsersStore {
UpdateF : func ( ctx context . Context , user * chronograf . User ) error {
return nil
} ,
GetF : func ( ctx context . Context , q chronograf . UserQuery ) ( * chronograf . User , error ) {
switch * q . ID {
case 1336 :
return & chronograf . User {
ID : 1336 ,
Name : "bobbetta" ,
Provider : "github" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
2017-11-06 16:31:44 +00:00
roles . EditorRole ,
2017-11-03 16:51:33 +00:00
} ,
} , nil
default :
2018-11-21 14:22:35 +00:00
return nil , fmt . Errorf ( "user with ID %d not found" , * q . ID )
2017-11-03 16:51:33 +00:00
}
} ,
} ,
} ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"PATCH" ,
"http://any.url" ,
nil ,
) ,
user : & userRequest {
ID : 1336 ,
SuperAdmin : true ,
Roles : [ ] chronograf . Role {
2017-11-22 19:49:44 +00:00
{
Name : roles . AdminRoleName ,
Organization : "1" ,
} ,
2017-11-03 16:51:33 +00:00
} ,
} ,
2017-11-09 14:18:13 +00:00
userKeyUser : & chronograf . User {
ID : 0 ,
Name : "coolUser" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : false ,
} ,
2017-11-03 16:51:33 +00:00
} ,
id : "1336" ,
wantStatus : http . StatusUnauthorized ,
wantContentType : "application/json" ,
2019-01-08 00:37:16 +00:00
wantBody : ` { "code":401,"message":"user does not have authorization required to set SuperAdmin status. See https://github.com/influxdata/influxdb/chronograf/issues/2601 for more information"} ` ,
2017-11-03 16:51:33 +00:00
} ,
{
name : "Update a Chronograf user to super admin - with super admin context" ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2018-01-12 17:27:55 +00:00
OrganizationsStore : & mocks . OrganizationsStore {
GetF : func ( ctx context . Context , q chronograf . OrganizationQuery ) ( * chronograf . Organization , error ) {
switch * q . ID {
case "1" :
return & chronograf . Organization {
ID : "1" ,
Name : "org" ,
DefaultRole : roles . ViewerRoleName ,
} , nil
}
return nil , fmt . Errorf ( "org not found" )
} ,
} ,
2017-11-03 16:51:33 +00:00
UsersStore : & mocks . UsersStore {
UpdateF : func ( ctx context . Context , user * chronograf . User ) error {
return nil
} ,
GetF : func ( ctx context . Context , q chronograf . UserQuery ) ( * chronograf . User , error ) {
switch * q . ID {
case 1336 :
return & chronograf . User {
ID : 1336 ,
Name : "bobbetta" ,
Provider : "github" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
2017-11-06 16:31:44 +00:00
roles . EditorRole ,
2017-11-03 16:51:33 +00:00
} ,
} , nil
default :
2018-11-21 14:22:35 +00:00
return nil , fmt . Errorf ( "user with ID %d not found" , * q . ID )
2017-11-03 16:51:33 +00:00
}
} ,
} ,
} ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"PATCH" ,
"http://any.url" ,
nil ,
) ,
user : & userRequest {
ID : 1336 ,
SuperAdmin : true ,
Roles : [ ] chronograf . Role {
2017-11-22 19:49:44 +00:00
{
Name : roles . AdminRoleName ,
Organization : "1" ,
} ,
2017-11-03 16:51:33 +00:00
} ,
} ,
2017-11-09 14:18:13 +00:00
userKeyUser : & chronograf . User {
ID : 0 ,
Name : "coolUser" ,
Provider : "github" ,
Scheme : "oauth2" ,
SuperAdmin : true ,
} ,
2017-11-03 16:51:33 +00:00
} ,
id : "1336" ,
wantStatus : http . StatusOK ,
wantContentType : "application/json" ,
2017-11-22 19:49:44 +00:00
wantBody : ` { "id":"1336","superAdmin":true,"name":"bobbetta","provider":"github","scheme":"oauth2","links": { "self":"/chronograf/v1/users/1336"},"roles":[ { "name":"admin","organization":"1"}]} ` ,
2017-11-03 16:51:33 +00:00
} ,
2017-03-10 19:24:48 +00:00
}
for _ , tt := range tests {
2017-10-09 21:16:24 +00:00
t . Run ( tt . name , func ( t * testing . T ) {
s := & Service {
2017-10-31 20:41:17 +00:00
Store : & mocks . Store {
2018-01-12 17:27:55 +00:00
UsersStore : tt . fields . UsersStore ,
OrganizationsStore : tt . fields . OrganizationsStore ,
2017-10-31 20:41:17 +00:00
} ,
Logger : tt . fields . Logger ,
2017-10-09 21:16:24 +00:00
}
tt . args . r = tt . args . r . WithContext ( httprouter . WithParams ( context . Background ( ) ,
httprouter . Params {
{
Key : "id" ,
Value : tt . id ,
} ,
} ) )
buf , _ := json . Marshal ( tt . args . user )
tt . args . r . Body = ioutil . NopCloser ( bytes . NewReader ( buf ) )
2017-02-22 03:36:23 +00:00
2017-11-03 16:51:33 +00:00
ctx := tt . args . r . Context ( )
2017-11-09 14:18:13 +00:00
if tt . args . userKeyUser != nil {
2017-11-10 16:18:06 +00:00
ctx = context . WithValue ( ctx , UserContextKey , tt . args . userKeyUser )
2017-11-03 16:51:33 +00:00
}
tt . args . r = tt . args . r . WithContext ( ctx )
2017-10-09 21:16:24 +00:00
s . UpdateUser ( tt . args . w , tt . args . r )
resp := tt . args . w . Result ( )
content := resp . Header . Get ( "Content-Type" )
body , _ := ioutil . ReadAll ( resp . Body )
if resp . StatusCode != tt . wantStatus {
t . Errorf ( "%q. UpdateUser() = %v, want %v" , tt . name , resp . StatusCode , tt . wantStatus )
}
if tt . wantContentType != "" && content != tt . wantContentType {
t . Errorf ( "%q. UpdateUser() = %v, want %v" , tt . name , content , tt . wantContentType )
}
if eq , _ := jsonEqual ( string ( body ) , tt . wantBody ) ; tt . wantBody != "" && ! eq {
2017-10-24 21:20:24 +00:00
t . Errorf ( "%q. UpdateUser()\ngot:%v\n,\nwant:%v" , tt . name , string ( body ) , tt . wantBody )
2017-10-09 21:16:24 +00:00
}
} )
}
}
2017-10-09 22:03:50 +00:00
func TestService_Users ( t * testing . T ) {
type fields struct {
UsersStore chronograf . UsersStore
Logger chronograf . Logger
}
type args struct {
w * httptest . ResponseRecorder
r * http . Request
}
tests := [ ] struct {
name string
fields fields
args args
wantStatus int
wantContentType string
wantBody string
} {
{
name : "Get all Chronograf users" ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2017-10-09 22:03:50 +00:00
UsersStore : & mocks . UsersStore {
AllF : func ( ctx context . Context ) ( [ ] chronograf . User , error ) {
return [ ] chronograf . User {
{
ID : 1337 ,
Name : "billysteve" ,
2017-10-24 23:17:59 +00:00
Provider : "google" ,
Scheme : "oauth2" ,
2017-10-13 00:42:30 +00:00
Roles : [ ] chronograf . Role {
2017-11-03 20:32:05 +00:00
roles . EditorRole ,
2017-10-13 00:42:30 +00:00
} ,
2017-10-09 22:03:50 +00:00
} ,
{
ID : 1338 ,
Name : "bobbettastuhvetta" ,
2017-10-24 23:17:59 +00:00
Provider : "auth0" ,
Scheme : "oauth2" ,
2017-10-09 22:03:50 +00:00
} ,
} , nil
} ,
} ,
} ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"GET" ,
"http://any.url" , // can be any valid URL as we are bypassing mux
nil ,
) ,
} ,
wantStatus : http . StatusOK ,
wantContentType : "application/json" ,
2017-11-01 13:12:19 +00:00
wantBody : ` { "users":[ { "id":"1337","superAdmin":false,"name":"billysteve","provider":"google","scheme":"oauth2","roles":[ { "name":"editor"}],"links": { "self":"/chronograf/v1/users/1337"}}, { "id":"1338","superAdmin":false,"name":"bobbettastuhvetta","provider":"auth0","scheme":"oauth2","roles":[],"links": { "self":"/chronograf/v1/users/1338"}}],"links": { "self":"/chronograf/v1/users"}} ` ,
2017-10-09 22:03:50 +00:00
} ,
2017-10-09 22:19:46 +00:00
{
name : "Get all Chronograf users, ensuring order of users in response" ,
fields : fields {
2018-11-16 16:45:00 +00:00
Logger : & chronograf . NoopLogger { } ,
2017-10-09 22:19:46 +00:00
UsersStore : & mocks . UsersStore {
AllF : func ( ctx context . Context ) ( [ ] chronograf . User , error ) {
return [ ] chronograf . User {
{
ID : 1338 ,
Name : "bobbettastuhvetta" ,
2017-10-24 23:17:59 +00:00
Provider : "auth0" ,
Scheme : "oauth2" ,
2017-10-09 22:19:46 +00:00
} ,
{
ID : 1337 ,
Name : "billysteve" ,
2017-10-24 23:17:59 +00:00
Provider : "google" ,
Scheme : "oauth2" ,
2017-10-13 00:42:30 +00:00
Roles : [ ] chronograf . Role {
2017-11-03 20:32:05 +00:00
roles . EditorRole ,
2017-10-13 00:42:30 +00:00
} ,
2017-10-09 22:19:46 +00:00
} ,
} , nil
} ,
} ,
} ,
args : args {
w : httptest . NewRecorder ( ) ,
r : httptest . NewRequest (
"GET" ,
"http://any.url" , // can be any valid URL as we are bypassing mux
nil ,
) ,
} ,
wantStatus : http . StatusOK ,
wantContentType : "application/json" ,
2017-11-01 13:12:19 +00:00
wantBody : ` { "users":[ { "id":"1337","superAdmin":false,"name":"billysteve","provider":"google","scheme":"oauth2","roles":[ { "name":"editor"}],"links": { "self":"/chronograf/v1/users/1337"}}, { "id":"1338","superAdmin":false,"name":"bobbettastuhvetta","provider":"auth0","scheme":"oauth2","roles":[],"links": { "self":"/chronograf/v1/users/1338"}}],"links": { "self":"/chronograf/v1/users"}} ` ,
2017-10-09 22:19:46 +00:00
} ,
2017-10-09 22:03:50 +00:00
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
s := & Service {
2017-10-31 20:41:17 +00:00
Store : & mocks . Store {
UsersStore : tt . fields . UsersStore ,
} ,
Logger : tt . fields . Logger ,
2017-10-09 22:03:50 +00:00
}
s . Users ( tt . args . w , tt . args . r )
resp := tt . args . w . Result ( )
content := resp . Header . Get ( "Content-Type" )
body , _ := ioutil . ReadAll ( resp . Body )
if resp . StatusCode != tt . wantStatus {
t . Errorf ( "%q. Users() = %v, want %v" , tt . name , resp . StatusCode , tt . wantStatus )
}
if tt . wantContentType != "" && content != tt . wantContentType {
t . Errorf ( "%q. Users() = %v, want %v" , tt . name , content , tt . wantContentType )
}
if eq , _ := jsonEqual ( string ( body ) , tt . wantBody ) ; tt . wantBody != "" && ! eq {
t . Errorf ( "%q. Users() = \n***%v***\n,\nwant\n***%v***" , tt . name , string ( body ) , tt . wantBody )
}
} )
}
}
2017-10-16 19:28:15 +00:00
func TestUserRequest_ValidCreate ( t * testing . T ) {
type args struct {
u * userRequest
}
tests := [ ] struct {
name string
args args
wantErr bool
err error
} {
{
name : "Valid" ,
args : args {
u : & userRequest {
ID : 1337 ,
Name : "billietta" ,
2017-10-24 23:17:59 +00:00
Provider : "auth0" ,
Scheme : "oauth2" ,
2017-10-16 23:26:08 +00:00
Roles : [ ] chronograf . Role {
2017-11-22 19:49:44 +00:00
{
Name : roles . EditorRoleName ,
Organization : "1" ,
} ,
2017-10-16 23:26:08 +00:00
} ,
2017-10-16 19:28:15 +00:00
} ,
} ,
wantErr : false ,
err : nil ,
} ,
{
name : "Invalid – Name missing" ,
args : args {
u : & userRequest {
ID : 1337 ,
2017-10-24 23:17:59 +00:00
Provider : "auth0" ,
Scheme : "oauth2" ,
2017-10-16 23:26:08 +00:00
Roles : [ ] chronograf . Role {
2017-11-22 19:49:44 +00:00
{
Name : roles . EditorRoleName ,
Organization : "1" ,
} ,
2017-10-16 23:26:08 +00:00
} ,
2017-10-16 19:28:15 +00:00
} ,
} ,
wantErr : true ,
2018-11-21 14:22:35 +00:00
err : fmt . Errorf ( "name required on Chronograf User request body" ) ,
2017-10-16 19:28:15 +00:00
} ,
{
name : "Invalid – Provider missing" ,
args : args {
u : & userRequest {
ID : 1337 ,
Name : "billietta" ,
2017-10-24 23:17:59 +00:00
Scheme : "oauth2" ,
2017-10-16 23:26:08 +00:00
Roles : [ ] chronograf . Role {
2017-11-22 19:49:44 +00:00
{
Name : roles . EditorRoleName ,
Organization : "1" ,
} ,
2017-10-16 23:26:08 +00:00
} ,
2017-10-16 19:28:15 +00:00
} ,
} ,
wantErr : true ,
2018-11-21 14:22:35 +00:00
err : fmt . Errorf ( "provider required on Chronograf User request body" ) ,
2017-10-16 19:28:15 +00:00
} ,
{
name : "Invalid – Scheme missing" ,
args : args {
u : & userRequest {
ID : 1337 ,
Name : "billietta" ,
2017-10-24 23:17:59 +00:00
Provider : "auth0" ,
2017-10-16 23:26:08 +00:00
Roles : [ ] chronograf . Role {
2017-11-22 19:49:44 +00:00
{
Name : roles . EditorRoleName ,
Organization : "1" ,
} ,
2017-10-16 23:26:08 +00:00
} ,
2017-10-16 19:28:15 +00:00
} ,
} ,
wantErr : true ,
2018-11-21 14:22:35 +00:00
err : fmt . Errorf ( "scheme required on Chronograf User request body" ) ,
2017-10-16 19:28:15 +00:00
} ,
{
2017-11-22 19:49:44 +00:00
name : "Invalid roles - bad role name" ,
2017-10-16 19:28:15 +00:00
args : args {
u : & userRequest {
ID : 1337 ,
Name : "billietta" ,
2017-10-24 23:17:59 +00:00
Provider : "auth0" ,
Scheme : "oauth2" ,
2017-10-16 23:26:08 +00:00
Roles : [ ] chronograf . Role {
{
2017-11-22 19:49:44 +00:00
Name : "BilliettaSpecialRole" ,
Organization : "1" ,
2017-10-16 23:26:08 +00:00
} ,
} ,
2017-10-16 19:28:15 +00:00
} ,
} ,
wantErr : true ,
2018-11-21 14:22:35 +00:00
err : fmt . Errorf ( "unknown role BilliettaSpecialRole. Valid roles are 'member', 'viewer', 'editor', 'admin', and '*'" ) ,
2017-10-16 19:28:15 +00:00
} ,
2017-11-22 19:49:44 +00:00
{
name : "Invalid roles - missing organization" ,
args : args {
u : & userRequest {
ID : 1337 ,
Name : "billietta" ,
Provider : "auth0" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
{
Name : roles . EditorRoleName ,
} ,
} ,
} ,
} ,
wantErr : true ,
err : fmt . Errorf ( "no organization was provided" ) ,
} ,
2017-10-16 19:28:15 +00:00
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
err := tt . args . u . ValidCreate ( )
if tt . wantErr {
if err == nil || err . Error ( ) != tt . err . Error ( ) {
t . Errorf ( "%q. ValidCreate(): wantErr %v,\nwant %v,\ngot %v" , tt . name , tt . wantErr , tt . err , err )
}
} else {
if err != nil {
t . Errorf ( "%q. ValidCreate(): wantErr %v,\nwant %v,\ngot %v" , tt . name , tt . wantErr , tt . err , err )
}
}
} )
}
}
func TestUserRequest_ValidUpdate ( t * testing . T ) {
type args struct {
u * userRequest
}
tests := [ ] struct {
name string
args args
wantErr bool
err error
} {
{
name : "Valid" ,
args : args {
u : & userRequest {
2017-10-24 21:20:24 +00:00
ID : 1337 ,
2017-10-16 23:26:08 +00:00
Roles : [ ] chronograf . Role {
2017-11-22 19:49:44 +00:00
{
Name : roles . EditorRoleName ,
Organization : "1" ,
} ,
2017-10-16 23:26:08 +00:00
} ,
2017-10-16 19:28:15 +00:00
} ,
} ,
wantErr : false ,
err : nil ,
} ,
{
2017-10-24 21:20:24 +00:00
name : "Invalid – roles missing" ,
args : args {
u : & userRequest { } ,
} ,
wantErr : true ,
2018-11-21 14:22:35 +00:00
err : fmt . Errorf ( "no Roles to update" ) ,
2017-10-24 21:20:24 +00:00
} ,
{
2017-11-22 20:20:48 +00:00
name : "Invalid - bad role name" ,
2017-10-24 21:20:24 +00:00
args : args {
u : & userRequest {
2017-11-22 20:20:48 +00:00
ID : 1337 ,
Name : "billietta" ,
Provider : "auth0" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
{
Name : "BillietaSpecialOrg" ,
Organization : "0" ,
} ,
} ,
2017-10-24 21:20:24 +00:00
} ,
} ,
wantErr : true ,
2018-11-21 14:22:35 +00:00
err : fmt . Errorf ( "unknown role BillietaSpecialOrg. Valid roles are 'member', 'viewer', 'editor', 'admin', and '*'" ) ,
2018-01-12 17:37:30 +00:00
} ,
{
name : "Valid – roles empty" ,
args : args {
u : & userRequest {
ID : 1337 ,
Name : "billietta" ,
Provider : "auth0" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role { } ,
} ,
} ,
wantErr : false ,
} ,
{
name : "Invalid - bad role name" ,
args : args {
u : & userRequest {
ID : 1337 ,
Name : "billietta" ,
Provider : "auth0" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
{
Name : "BillietaSpecialOrg" ,
Organization : "0" ,
} ,
} ,
} ,
} ,
wantErr : true ,
2018-11-21 14:22:35 +00:00
err : fmt . Errorf ( "unknown role BillietaSpecialOrg. Valid roles are 'member', 'viewer', 'editor', 'admin', and '*'" ) ,
2017-10-24 21:20:24 +00:00
} ,
{
2017-11-22 20:20:48 +00:00
name : "Invalid - duplicate organization" ,
2017-10-24 21:20:24 +00:00
args : args {
u : & userRequest {
2017-11-22 20:20:48 +00:00
ID : 1337 ,
Name : "billietta" ,
Provider : "auth0" ,
Scheme : "oauth2" ,
Roles : [ ] chronograf . Role {
{
Name : roles . AdminRoleName ,
Organization : "0" ,
} ,
{
Name : roles . ViewerRoleName ,
Organization : "0" ,
} ,
} ,
2017-10-24 21:20:24 +00:00
} ,
} ,
wantErr : true ,
2017-11-22 20:20:48 +00:00
err : fmt . Errorf ( "duplicate organization \"0\" in roles" ) ,
2017-10-16 19:28:15 +00:00
} ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
err := tt . args . u . ValidUpdate ( )
if tt . wantErr {
if err == nil || err . Error ( ) != tt . err . Error ( ) {
2017-10-24 21:20:24 +00:00
t . Errorf ( "%q. ValidUpdate(): wantErr %v,\nwant %v,\ngot %v" , tt . name , tt . wantErr , tt . err , err )
2017-10-16 19:28:15 +00:00
}
} else {
if err != nil {
2017-10-24 21:20:24 +00:00
t . Errorf ( "%q. ValidUpdate(): wantErr %v,\nwant %v,\ngot %v" , tt . name , tt . wantErr , tt . err , err )
2017-10-16 19:28:15 +00:00
}
}
} )
}
}