Merge branch 'master' into feature/934-ew-users-pages
commit
07cb3244a6
|
@ -1,6 +1,7 @@
|
|||
## v1.2.0 [unreleased]
|
||||
|
||||
### Bug Fixes
|
||||
1. [#936](https://github.com/influxdata/chronograf/pull/936): Fix leaking sockets for InfluxQL queries
|
||||
|
||||
### Features
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
"id": "f3bec493-0bc1-49d5-a40a-a09bd5cfb700",
|
||||
"measurement": "consul_consul_fsm_register",
|
||||
"app": "consul_telemetry",
|
||||
"autoflow": true,
|
||||
"cells": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 4,
|
||||
"h": 4,
|
||||
"i": "9e14639d-b8d9-4245-8c45-862ed4383701",
|
||||
"name": "Consul Agent – Number of Go Routines",
|
||||
"queries": [
|
||||
{
|
||||
"query": "SELECT max(\"value\") AS \"Go Routines\" FROM \"consul_ip-172-31-6-247_runtime_num_goroutines\"",
|
||||
"groupbys": [
|
||||
],
|
||||
"wheres": [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 4,
|
||||
"h": 4,
|
||||
"i": "9e14639d-b8d9-4245-8c45-862ed4383702",
|
||||
"name": "Consul Agent – Runtime Alloc Bytes",
|
||||
"queries": [
|
||||
{
|
||||
"query": "SELECT max(\"value\") AS \"Runtime Alloc Bytes\" FROM \"consul_ip-172-31-6-247_runtime_alloc_bytes\"",
|
||||
"groupbys": [
|
||||
],
|
||||
"wheres": [
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 4,
|
||||
"h": 4,
|
||||
"i": "9e14639d-b8d9-4245-8c45-862ed4383703",
|
||||
"name": "Consul Agent – Heap Objects",
|
||||
"queries": [
|
||||
{
|
||||
"query": "SELECT max(\"value\") AS \"Heap Objects\" FROM \"consul_ip-172-31-6-247_runtime_heap_objects\"",
|
||||
"groupbys": [
|
||||
],
|
||||
"wheres": [
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"id": "350b780c-7d32-4b29-ac49-0d4e2c092943",
|
||||
"measurement": "consul_memberlist_msg_alive",
|
||||
"app": "consul_telemetry",
|
||||
"autoflow": true,
|
||||
"cells": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 4,
|
||||
"h": 4,
|
||||
"i": "bd62186a-f475-478b-bf02-8c4ab07eccd1",
|
||||
"name": "Consul – Number of Agents",
|
||||
"queries": [
|
||||
{
|
||||
"query": "SELECT min(\"value\") AS \"num_agents\" FROM \"consul_memberlist_msg_alive\"",
|
||||
"label": "count",
|
||||
"groupbys": [],
|
||||
"wheres": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"id": "b15aaf24-701a-4d9b-920c-9a407e91da71",
|
||||
"measurement": "consul_raft_state_candidate",
|
||||
"app": "consul_telemetry",
|
||||
"autoflow": true,
|
||||
"cells": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 4,
|
||||
"h": 4,
|
||||
"i": "5b2bddce-badb-4594-91fb-0486f62266e5",
|
||||
"name": "Consul – Leadership Election",
|
||||
"queries": [
|
||||
{
|
||||
"query": "SELECT max(\"value\") AS \"max_value\" FROM \"consul_raft_state_candidate\"",
|
||||
"label": "count",
|
||||
"groupbys": [],
|
||||
"wheres": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"id": "26809869-8df3-49ad-b2f0-b1e1c72f67b0",
|
||||
"measurement": "consul_consul_http_GET_v1_health_state__",
|
||||
"app": "consul_telemetry",
|
||||
"autoflow": true,
|
||||
"cells": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 4,
|
||||
"h": 4,
|
||||
"i": "dfb4c50f-547e-484a-944b-d6374ba2b4c0",
|
||||
"name": "Consul – HTTP Request Time (ms)",
|
||||
"queries": [
|
||||
{
|
||||
"query": "SELECT max(\"upper\") AS \"GET_health_state\" FROM \"consul_consul_http_GET_v1_health_state__\"",
|
||||
"label": "ms",
|
||||
"groupbys": [],
|
||||
"wheres": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"id": "34611ae0-7c3e-4697-8db0-371b16bef345",
|
||||
"measurement": "consul_raft_state_leader",
|
||||
"app": "consul_telemetry",
|
||||
"autoflow": true,
|
||||
"cells": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 4,
|
||||
"h": 4,
|
||||
"i": "ef8eeeb5-b408-46d6-8cfc-20c00c9d7239",
|
||||
"name": "Consul – Leadership Change",
|
||||
"queries": [
|
||||
{
|
||||
"query": "SELECT max(\"value\") as \"change\" FROM \"consul_raft_state_leader\"",
|
||||
"label": "count",
|
||||
"groupbys": [],
|
||||
"wheres": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"id": "ef4b596c-77de-41c5-bb5b-d5c9a69fa633",
|
||||
"measurement": "consul_serf_events",
|
||||
"app": "consul_telemetry",
|
||||
"autoflow": true,
|
||||
"cells": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 4,
|
||||
"h": 4,
|
||||
"i": "59df3d73-5fac-48cb-84f1-dbe9a1bb886c",
|
||||
"name": "Consul – Number of serf events",
|
||||
"queries": [
|
||||
{
|
||||
"query": "SELECT max(\"value\") AS \"serf_events\" FROM \"consul_serf_events\"",
|
||||
"label": "count",
|
||||
"groupbys": [],
|
||||
"wheres": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -275,6 +275,7 @@ type User struct {
|
|||
Name string `json:"name"`
|
||||
Passwd string `json:"password"`
|
||||
Permissions Permissions `json:"permissions,omitempty"`
|
||||
Roles []Role `json:"roles,omitempty"`
|
||||
}
|
||||
|
||||
// UsersStore is the Storage and retrieval of authentication information
|
||||
|
|
|
@ -24,6 +24,8 @@ type Ctrl interface {
|
|||
ChangePassword(ctx context.Context, name, passwd string) error
|
||||
SetUserPerms(ctx context.Context, name string, perms Permissions) error
|
||||
|
||||
UserRoles(ctx context.Context) (map[string]Roles, error)
|
||||
|
||||
Roles(ctx context.Context, name *string) (*Roles, error)
|
||||
Role(ctx context.Context, name string) (*Role, error)
|
||||
CreateRole(ctx context.Context, name string) error
|
||||
|
|
|
@ -155,6 +155,27 @@ func (m *MetaClient) SetUserPerms(ctx context.Context, name string, perms Permis
|
|||
return m.Post(ctx, "/user", a, nil)
|
||||
}
|
||||
|
||||
// UserRoles returns a map of users to all of their current roles
|
||||
func (m *MetaClient) UserRoles(ctx context.Context) (map[string]Roles, error) {
|
||||
res, err := m.Roles(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userRoles := make(map[string]Roles)
|
||||
for _, role := range res.Roles {
|
||||
for _, u := range role.Users {
|
||||
ur, ok := userRoles[u]
|
||||
if !ok {
|
||||
ur = Roles{}
|
||||
}
|
||||
ur.Roles = append(ur.Roles, role)
|
||||
userRoles[u] = ur
|
||||
}
|
||||
}
|
||||
return userRoles, nil
|
||||
}
|
||||
|
||||
// Roles gets all the roles. If name is not nil it filters for a single role
|
||||
func (m *MetaClient) Roles(ctx context.Context, name *string) (*Roles, error) {
|
||||
params := map[string]string{}
|
||||
|
|
|
@ -876,6 +876,110 @@ func TestMetaClient_Role(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestMetaClient_UserRoles(t *testing.T) {
|
||||
type fields struct {
|
||||
URL *url.URL
|
||||
client interface {
|
||||
Do(URL *url.URL, path, method string, params map[string]string, body io.Reader) (*http.Response, error)
|
||||
}
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
name *string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
want map[string]Roles
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Successful Show all roles",
|
||||
fields: fields{
|
||||
URL: &url.URL{
|
||||
Host: "twinpinesmall.net:8091",
|
||||
Scheme: "https",
|
||||
},
|
||||
client: NewMockClient(
|
||||
http.StatusOK,
|
||||
[]byte(`{"roles":[{"name":"timetravelers","users":["marty","docbrown"],"permissions":{"":["ViewAdmin","ViewChronograf"]}},{"name":"mcfly","users":["marty","george"],"permissions":{"":["ViewAdmin","ViewChronograf"]}}]}`),
|
||||
nil,
|
||||
nil,
|
||||
),
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
name: nil,
|
||||
},
|
||||
want: map[string]Roles{
|
||||
"marty": Roles{
|
||||
Roles: []Role{
|
||||
{
|
||||
Name: "timetravelers",
|
||||
Permissions: map[string][]string{
|
||||
"": []string{
|
||||
"ViewAdmin", "ViewChronograf",
|
||||
},
|
||||
},
|
||||
Users: []string{"marty", "docbrown"},
|
||||
},
|
||||
{
|
||||
Name: "mcfly",
|
||||
Permissions: map[string][]string{
|
||||
"": []string{
|
||||
"ViewAdmin", "ViewChronograf",
|
||||
},
|
||||
},
|
||||
Users: []string{"marty", "george"},
|
||||
},
|
||||
},
|
||||
},
|
||||
"docbrown": Roles{
|
||||
Roles: []Role{
|
||||
{
|
||||
Name: "timetravelers",
|
||||
Permissions: map[string][]string{
|
||||
"": []string{
|
||||
"ViewAdmin", "ViewChronograf",
|
||||
},
|
||||
},
|
||||
Users: []string{"marty", "docbrown"},
|
||||
},
|
||||
},
|
||||
},
|
||||
"george": Roles{
|
||||
Roles: []Role{
|
||||
{
|
||||
Name: "mcfly",
|
||||
Permissions: map[string][]string{
|
||||
"": []string{
|
||||
"ViewAdmin", "ViewChronograf",
|
||||
},
|
||||
},
|
||||
Users: []string{"marty", "george"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
m := &MetaClient{
|
||||
URL: tt.fields.URL,
|
||||
client: tt.fields.client,
|
||||
}
|
||||
got, err := m.UserRoles(tt.args.ctx)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("%q. MetaClient.UserRoles() error = %v, wantErr %v", tt.name, err, tt.wantErr)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("%q. MetaClient.UserRoles() = %v, want %v", tt.name, got, tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMetaClient_CreateRole(t *testing.T) {
|
||||
type fields struct {
|
||||
URL *url.URL
|
||||
|
|
|
@ -68,6 +68,10 @@ func (cc *ControlClient) Role(ctx context.Context, name string) (*enterprise.Rol
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func (ccm *ControlClient) UserRoles(ctx context.Context) (map[string]enterprise.Roles, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (ccm *ControlClient) Roles(ctx context.Context, name *string) (*enterprise.Roles, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
@ -85,9 +85,13 @@ func (c *RolesStore) All(ctx context.Context) ([]chronograf.Role, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
res := make([]chronograf.Role, len(all.Roles))
|
||||
for i, role := range all.Roles {
|
||||
return all.ToChronograf(), nil
|
||||
}
|
||||
|
||||
// ToChronograf converts enterprise roles to chronograf
|
||||
func (r *Roles) ToChronograf() []chronograf.Role {
|
||||
res := make([]chronograf.Role, len(r.Roles))
|
||||
for i, role := range r.Roles {
|
||||
users := make([]chronograf.User, len(role.Users))
|
||||
for i, user := range role.Users {
|
||||
users[i] = chronograf.User{
|
||||
|
@ -101,5 +105,5 @@ func (c *RolesStore) All(ctx context.Context) ([]chronograf.Role, error) {
|
|||
Users: users,
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package enterprise
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/influxdata/chronograf"
|
||||
)
|
||||
|
||||
func TestRoles_ToChronograf(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
roles []Role
|
||||
want []chronograf.Role
|
||||
}{
|
||||
{
|
||||
name: "empty roles",
|
||||
roles: []Role{},
|
||||
want: []chronograf.Role{},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &Roles{
|
||||
Roles: tt.roles,
|
||||
}
|
||||
if got := r.ToChronograf(); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Roles.ToChronograf() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -35,9 +35,23 @@ func (c *UserStore) Get(ctx context.Context, name string) (*chronograf.User, err
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ur, err := c.Ctrl.UserRoles(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
role := ur[name]
|
||||
cr := role.ToChronograf()
|
||||
// For now we are removing all users from a role being returned.
|
||||
for i, r := range cr {
|
||||
r.Users = []chronograf.User{}
|
||||
cr[i] = r
|
||||
}
|
||||
return &chronograf.User{
|
||||
Name: u.Name,
|
||||
Permissions: ToChronograf(u.Permissions),
|
||||
Roles: cr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -59,11 +73,25 @@ func (c *UserStore) All(ctx context.Context) ([]chronograf.User, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
ur, err := c.Ctrl.UserRoles(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := make([]chronograf.User, len(all.Users))
|
||||
for i, user := range all.Users {
|
||||
role := ur[user.Name]
|
||||
cr := role.ToChronograf()
|
||||
// For now we are removing all users from a role being returned.
|
||||
for i, r := range cr {
|
||||
r.Users = []chronograf.User{}
|
||||
cr[i] = r
|
||||
}
|
||||
|
||||
res[i] = chronograf.User{
|
||||
Name: user.Name,
|
||||
Permissions: ToChronograf(user.Permissions),
|
||||
Roles: cr,
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
|
|
|
@ -180,6 +180,9 @@ func TestClient_Get(t *testing.T) {
|
|||
},
|
||||
}, nil
|
||||
},
|
||||
userRoles: func(ctx context.Context) (map[string]enterprise.Roles, error) {
|
||||
return map[string]enterprise.Roles{}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
|
@ -194,6 +197,71 @@ func TestClient_Get(t *testing.T) {
|
|||
Allowed: chronograf.Allowances{"ViewChronograf", "ReadData", "WriteData"},
|
||||
},
|
||||
},
|
||||
Roles: []chronograf.Role{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Successful Get User with roles",
|
||||
fields: fields{
|
||||
Ctrl: &mockCtrl{
|
||||
user: func(ctx context.Context, name string) (*enterprise.User, error) {
|
||||
return &enterprise.User{
|
||||
Name: "marty",
|
||||
Password: "johnny be good",
|
||||
Permissions: map[string][]string{
|
||||
"": {
|
||||
"ViewChronograf",
|
||||
"ReadData",
|
||||
"WriteData",
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
userRoles: func(ctx context.Context) (map[string]enterprise.Roles, error) {
|
||||
return map[string]enterprise.Roles{
|
||||
"marty": enterprise.Roles{
|
||||
Roles: []enterprise.Role{
|
||||
{
|
||||
Name: "timetravels",
|
||||
Permissions: map[string][]string{
|
||||
"": {
|
||||
"ViewChronograf",
|
||||
"ReadData",
|
||||
"WriteData",
|
||||
},
|
||||
},
|
||||
Users: []string{"marty", "docbrown"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
name: "marty",
|
||||
},
|
||||
want: &chronograf.User{
|
||||
Name: "marty",
|
||||
Permissions: chronograf.Permissions{
|
||||
{
|
||||
Scope: chronograf.AllScope,
|
||||
Allowed: chronograf.Allowances{"ViewChronograf", "ReadData", "WriteData"},
|
||||
},
|
||||
},
|
||||
Roles: []chronograf.Role{
|
||||
{
|
||||
Name: "timetravels",
|
||||
Permissions: chronograf.Permissions{
|
||||
{
|
||||
Scope: chronograf.AllScope,
|
||||
Allowed: chronograf.Allowances{"ViewChronograf", "ReadData", "WriteData"},
|
||||
},
|
||||
},
|
||||
Users: []chronograf.User{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -372,6 +440,9 @@ func TestClient_All(t *testing.T) {
|
|||
},
|
||||
}, nil
|
||||
},
|
||||
userRoles: func(ctx context.Context) (map[string]enterprise.Roles, error) {
|
||||
return map[string]enterprise.Roles{}, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
|
@ -386,6 +457,7 @@ func TestClient_All(t *testing.T) {
|
|||
Allowed: chronograf.Allowances{"ViewChronograf", "ReadData", "WriteData"},
|
||||
},
|
||||
},
|
||||
Roles: []chronograf.Role{},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -499,6 +571,8 @@ type mockCtrl struct {
|
|||
users func(ctx context.Context, name *string) (*enterprise.Users, error)
|
||||
setUserPerms func(ctx context.Context, name string, perms enterprise.Permissions) error
|
||||
|
||||
userRoles func(ctx context.Context) (map[string]enterprise.Roles, error)
|
||||
|
||||
roles func(ctx context.Context, name *string) (*enterprise.Roles, error)
|
||||
role func(ctx context.Context, name string) (*enterprise.Role, error)
|
||||
createRole func(ctx context.Context, name string) error
|
||||
|
@ -510,25 +584,35 @@ type mockCtrl struct {
|
|||
func (m *mockCtrl) ShowCluster(ctx context.Context) (*enterprise.Cluster, error) {
|
||||
return m.showCluster(ctx)
|
||||
}
|
||||
|
||||
func (m *mockCtrl) User(ctx context.Context, name string) (*enterprise.User, error) {
|
||||
return m.user(ctx, name)
|
||||
}
|
||||
|
||||
func (m *mockCtrl) CreateUser(ctx context.Context, name, passwd string) error {
|
||||
return m.createUser(ctx, name, passwd)
|
||||
}
|
||||
|
||||
func (m *mockCtrl) DeleteUser(ctx context.Context, name string) error {
|
||||
return m.deleteUser(ctx, name)
|
||||
}
|
||||
|
||||
func (m *mockCtrl) ChangePassword(ctx context.Context, name, passwd string) error {
|
||||
return m.changePassword(ctx, name, passwd)
|
||||
}
|
||||
|
||||
func (m *mockCtrl) Users(ctx context.Context, name *string) (*enterprise.Users, error) {
|
||||
return m.users(ctx, name)
|
||||
}
|
||||
|
||||
func (m *mockCtrl) SetUserPerms(ctx context.Context, name string, perms enterprise.Permissions) error {
|
||||
return m.setUserPerms(ctx, name, perms)
|
||||
}
|
||||
|
||||
func (m *mockCtrl) UserRoles(ctx context.Context) (map[string]enterprise.Roles, error) {
|
||||
return m.userRoles(ctx)
|
||||
}
|
||||
|
||||
func (m *mockCtrl) Roles(ctx context.Context, name *string) (*enterprise.Roles, error) {
|
||||
return m.roles(ctx, name)
|
||||
}
|
||||
|
|
|
@ -13,6 +13,14 @@ import (
|
|||
|
||||
var _ chronograf.TimeSeries = &Client{}
|
||||
|
||||
// Shared transports for all clients to prevent leaking connections
|
||||
var (
|
||||
skipVerifyTransport = &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
defaultTransport = &http.Transport{}
|
||||
)
|
||||
|
||||
// Client is a device for retrieving time series data from an InfluxDB instance
|
||||
type Client struct {
|
||||
URL *url.URL
|
||||
|
@ -74,10 +82,9 @@ func (c *Client) query(u *url.URL, q chronograf.Query) (chronograf.Response, err
|
|||
|
||||
hc := &http.Client{}
|
||||
if c.InsecureSkipVerify {
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
hc.Transport = tr
|
||||
hc.Transport = skipVerifyTransport
|
||||
} else {
|
||||
hc.Transport = defaultTransport
|
||||
}
|
||||
resp, err := hc.Do(req)
|
||||
if err != nil {
|
||||
|
|
|
@ -52,6 +52,7 @@ func (r *sourceUserRequest) ValidUpdate() error {
|
|||
type sourceUser struct {
|
||||
Username string `json:"name,omitempty"` // Username for new account
|
||||
Permissions chronograf.Permissions `json:"permissions,omitempty"` // Account's permissions
|
||||
Roles []roleResponse `json:"roles,omitempty"` // Roles if source uses them
|
||||
Links selfLinks `json:"links"` // Links are URI locations related to user
|
||||
}
|
||||
|
||||
|
@ -128,11 +129,19 @@ func (h *Service) SourceUsers(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
su := []sourceUser{}
|
||||
for _, u := range users {
|
||||
su = append(su, sourceUser{
|
||||
res := sourceUser{
|
||||
Username: u.Name,
|
||||
Permissions: u.Permissions,
|
||||
Links: newSelfLinks(srcID, "users", u.Name),
|
||||
})
|
||||
}
|
||||
if len(u.Roles) > 0 {
|
||||
rr := make([]roleResponse, len(u.Roles))
|
||||
for i, role := range u.Roles {
|
||||
rr[i] = newRoleResponse(srcID, &role)
|
||||
}
|
||||
res.Roles = rr
|
||||
}
|
||||
su = append(su, res)
|
||||
}
|
||||
|
||||
res := sourceUsers{
|
||||
|
@ -163,6 +172,13 @@ func (h *Service) SourceUserID(w http.ResponseWriter, r *http.Request) {
|
|||
Permissions: u.Permissions,
|
||||
Links: newSelfLinks(srcID, "users", u.Name),
|
||||
}
|
||||
if len(u.Roles) > 0 {
|
||||
rr := make([]roleResponse, len(u.Roles))
|
||||
for i, role := range u.Roles {
|
||||
rr[i] = newRoleResponse(srcID, &role)
|
||||
}
|
||||
res.Roles = rr
|
||||
}
|
||||
encodeJSON(w, http.StatusOK, res, h.Logger)
|
||||
}
|
||||
|
||||
|
@ -346,7 +362,7 @@ func (r *sourceRoleRequest) ValidUpdate() error {
|
|||
}
|
||||
|
||||
type roleResponse struct {
|
||||
Users []sourceUser `json:"users"`
|
||||
Users []sourceUser `json:"users,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Permissions chronograf.Permissions `json:"permissions"`
|
||||
Links selfLinks `json:"links"`
|
||||
|
|
|
@ -2565,6 +2565,34 @@
|
|||
"$ref": "#/definitions/Role"
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"roles": [
|
||||
{
|
||||
"users": [
|
||||
{
|
||||
"name": "admin",
|
||||
"links": {
|
||||
"self": "/chronograf/v1/sources/3/users/admin"
|
||||
}
|
||||
}
|
||||
],
|
||||
"name": "timetravelers",
|
||||
"permissions": [
|
||||
{
|
||||
"scope": "database",
|
||||
"name": "telegraf",
|
||||
"allowed": [
|
||||
"ReadData",
|
||||
"WriteData"
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": {
|
||||
"self": "/chronograf/v1/sources/3/roles/timetravelers"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Role": {
|
||||
|
@ -2596,6 +2624,30 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"users": [
|
||||
{
|
||||
"name": "admin",
|
||||
"links": {
|
||||
"self": "/chronograf/v1/sources/3/users/admin"
|
||||
}
|
||||
}
|
||||
],
|
||||
"name": "timetravelers",
|
||||
"permissions": [
|
||||
{
|
||||
"scope": "database",
|
||||
"name": "telegraf",
|
||||
"allowed": [
|
||||
"ReadData",
|
||||
"WriteData"
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": {
|
||||
"self": "/chronograf/v1/sources/3/roles/timetravelers"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Users": {
|
||||
|
@ -2616,21 +2668,43 @@
|
|||
{
|
||||
"scope": "all",
|
||||
"allowed": [
|
||||
"ViewAdmin",
|
||||
"ViewChronograf",
|
||||
"ReadData"
|
||||
]
|
||||
},
|
||||
{
|
||||
"scope": "database",
|
||||
"name": "telegraf",
|
||||
"allowed": [
|
||||
"ViewChronograf",
|
||||
"ReadData"
|
||||
"CreateDatabase",
|
||||
"CreateUserAndRole",
|
||||
"DropDatabase",
|
||||
"DropData",
|
||||
"ReadData",
|
||||
"WriteData",
|
||||
"ManageShard",
|
||||
"ManageContinuousQuery",
|
||||
"ManageQuery",
|
||||
"ManageSubscription",
|
||||
"Monitor",
|
||||
"KapacitorAPI"
|
||||
]
|
||||
}
|
||||
],
|
||||
"roles": [
|
||||
{
|
||||
"name": "timetravelers",
|
||||
"permissions": [
|
||||
{
|
||||
"scope": "database",
|
||||
"name": "telegraf",
|
||||
"allowed": [
|
||||
"ReadData",
|
||||
"WriteData"
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": {
|
||||
"self": "/chronograf/v1/sources/3/roles/timetravelers"
|
||||
}
|
||||
}
|
||||
],
|
||||
"links": {
|
||||
"self": "/chronograf/v1/source/1/users/docbrown"
|
||||
"self": "/chronograf/v1/sources/3/users/docbrown"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -2669,21 +2743,43 @@
|
|||
{
|
||||
"scope": "all",
|
||||
"allowed": [
|
||||
"ViewAdmin",
|
||||
"ViewChronograf",
|
||||
"ReadData"
|
||||
]
|
||||
},
|
||||
{
|
||||
"scope": "database",
|
||||
"name": "telegraf",
|
||||
"allowed": [
|
||||
"ViewChronograf",
|
||||
"ReadData"
|
||||
"CreateDatabase",
|
||||
"CreateUserAndRole",
|
||||
"DropDatabase",
|
||||
"DropData",
|
||||
"ReadData",
|
||||
"WriteData",
|
||||
"ManageShard",
|
||||
"ManageContinuousQuery",
|
||||
"ManageQuery",
|
||||
"ManageSubscription",
|
||||
"Monitor",
|
||||
"KapacitorAPI"
|
||||
]
|
||||
}
|
||||
],
|
||||
"roles": [
|
||||
{
|
||||
"name": "timetravelers",
|
||||
"permissions": [
|
||||
{
|
||||
"scope": "database",
|
||||
"name": "telegraf",
|
||||
"allowed": [
|
||||
"ReadData",
|
||||
"WriteData"
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": {
|
||||
"self": "/chronograf/v1/sources/3/roles/timetravelers"
|
||||
}
|
||||
}
|
||||
],
|
||||
"links": {
|
||||
"self": "/chronograf/v1/source/1/users/docbrown"
|
||||
"self": "/chronograf/v1/sources/3/users/docbrown"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue