Add get of all users for a data source

pull/10616/head
Chris Goller 2017-02-17 15:13:51 -06:00
parent 3fac8f2707
commit b304ac256e
7 changed files with 132 additions and 31 deletions

View File

@ -120,3 +120,25 @@ func (s *UsersStore) Update(ctx context.Context, usr *chronograf.User) error {
return nil return nil
} }
// All returns all users
func (s *UsersStore) All(ctx context.Context) ([]chronograf.User, error) {
var users []chronograf.User
if err := s.client.db.View(func(tx *bolt.Tx) error {
if err := tx.Bucket(UsersBucket).ForEach(func(k, v []byte) error {
var user chronograf.User
if err := internal.UnmarshalUser(v, &user); err != nil {
return err
}
users = append(users, user)
return nil
}); err != nil {
return err
}
return nil
}); err != nil {
return nil, err
}
return users, nil
}

View File

@ -229,6 +229,8 @@ type User struct {
// UsersStore is the Storage and retrieval of authentication information // UsersStore is the Storage and retrieval of authentication information
type UsersStore interface { type UsersStore interface {
// All lists all users from the UsersStore
All(context.Context) ([]User, error)
// Create a new User in the UsersStore // Create a new User in the UsersStore
Add(context.Context, *User) (*User, error) Add(context.Context, *User) (*User, error)
// Delete the User from the UsersStore // Delete the User from the UsersStore

View File

@ -24,6 +24,7 @@ type Client struct {
CreateUser(ctx context.Context, name, passwd string) error CreateUser(ctx context.Context, name, passwd string) error
DeleteUser(ctx context.Context, name string) error DeleteUser(ctx context.Context, name string) error
ChangePassword(ctx context.Context, name, passwd string) error ChangePassword(ctx context.Context, name, passwd string) error
Users(ctx context.Context, name *string) (*Users, error)
} }
Logger chronograf.Logger Logger chronograf.Logger

View File

@ -39,16 +39,23 @@ func (cc *ControlClient) ShowCluster(context.Context) (*enterprise.Cluster, erro
func (cc *ControlClient) User(ctx context.Context, name string) (*enterprise.User, error) { func (cc *ControlClient) User(ctx context.Context, name string) (*enterprise.User, error) {
return nil, nil return nil, nil
} }
func (cc *ControlClient) CreateUser(ctx context.Context, name, passwd string) error { func (cc *ControlClient) CreateUser(ctx context.Context, name, passwd string) error {
return nil return nil
} }
func (cc *ControlClient) DeleteUser(ctx context.Context, name string) error { func (cc *ControlClient) DeleteUser(ctx context.Context, name string) error {
return nil return nil
} }
func (cc *ControlClient) ChangePassword(ctx context.Context, name, passwd string) error { func (cc *ControlClient) ChangePassword(ctx context.Context, name, passwd string) error {
return nil return nil
} }
func (cc *ControlClient) Users(ctx context.Context, name *string) (*enterprise.Users, error) {
return nil, nil
}
type TimeSeries struct { type TimeSeries struct {
URLs []string URLs []string
Response Response Response Response

View File

@ -35,3 +35,19 @@ func (c *Client) Update(ctx context.Context, u *chronograf.User) error {
// TODO: Update permissions // TODO: Update permissions
return c.Ctrl.ChangePassword(ctx, u.Name, u.Passwd) return c.Ctrl.ChangePassword(ctx, u.Name, u.Passwd)
} }
// All is all users in influx
func (c *Client) All(ctx context.Context) ([]chronograf.User, error) {
all, err := c.Ctrl.Users(ctx, nil)
if err != nil {
return nil, err
}
res := make([]chronograf.User, len(all.Users))
for i, user := range all.Users {
res[i] = chronograf.User{
Name: user.Name,
}
}
return res, nil
}

View File

@ -6,10 +6,10 @@ import (
"github.com/influxdata/chronograf" "github.com/influxdata/chronograf"
) )
// Create a new User in Influx Enterprise // Create a new User in InfluxDB
func (c *Client) Add(context.Context, *chronograf.User) (*chronograf.User, error) { return nil, nil } func (c *Client) Add(context.Context, *chronograf.User) (*chronograf.User, error) { return nil, nil }
// Delete the User from Influx Enterprise // Delete the User from InfluxDB
func (c *Client) Delete(context.Context, *chronograf.User) error { return nil } func (c *Client) Delete(context.Context, *chronograf.User) error { return nil }
// Get retrieves a user if name exists. // Get retrieves a user if name exists.
@ -19,3 +19,6 @@ func (c *Client) Get(ctx context.Context, name string) (*chronograf.User, error)
// Update the user's permissions or roles // Update the user's permissions or roles
func (c *Client) Update(context.Context, *chronograf.User) error { return nil } func (c *Client) Update(context.Context, *chronograf.User) error { return nil }
// All is all users in influx
func (c *Client) All(context.Context) ([]chronograf.User, error) { return nil, nil }

View File

@ -1,6 +1,7 @@
package server package server
import ( import (
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
@ -48,21 +49,8 @@ type sourceUserLinks struct {
// NewSourceUser adds user to source // NewSourceUser adds user to source
func (h *Service) NewSourceUser(w http.ResponseWriter, r *http.Request) { func (h *Service) NewSourceUser(w http.ResponseWriter, r *http.Request) {
srcID, err := paramID("id", r)
if err != nil {
Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger)
return
}
ctx := r.Context()
src, err := h.SourcesStore.Get(ctx, srcID)
if err != nil {
notFound(w, srcID, h.Logger)
return
}
var req newSourceUserRequest var req newSourceUserRequest
if err = json.NewDecoder(r.Body).Decode(&req); err != nil { if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
invalidJSON(w, h.Logger) invalidJSON(w, h.Logger)
return return
} }
@ -71,13 +59,13 @@ func (h *Service) NewSourceUser(w http.ResponseWriter, r *http.Request) {
return return
} }
if err = h.TimeSeries.Connect(ctx, &src); err != nil { ctx := r.Context()
msg := fmt.Sprintf("Unable to connect to source %d", srcID)
Error(w, http.StatusBadRequest, msg, h.Logger) srcID, store, err := h.sourceUsersStore(ctx, w, r)
if err != nil {
return return
} }
store := h.TimeSeries.Users(ctx)
user := &chronograf.User{ user := &chronograf.User{
Name: req.Username, Name: req.Username,
Passwd: req.Password, Passwd: req.Password,
@ -93,31 +81,93 @@ func (h *Service) NewSourceUser(w http.ResponseWriter, r *http.Request) {
encodeJSON(w, http.StatusCreated, su, h.Logger) encodeJSON(w, http.StatusCreated, su, h.Logger)
} }
// SourceUserID retrieves a user with ID from store. type sourceUsers struct {
func (h *Service) SourceUserID(w http.ResponseWriter, r *http.Request) { Users []sourceUser `json:"users"`
srcID, err := paramID("id", r) }
// SourceUsers retrieves all users from source.
func (h *Service) SourceUsers(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
srcID, store, err := h.sourceUsersStore(ctx, w, r)
if err != nil { if err != nil {
Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger)
return return
} }
users, err := store.All(ctx)
if err != nil {
Error(w, http.StatusBadRequest, err.Error(), h.Logger)
return
}
su := []sourceUser{}
for _, u := range users {
su = append(su, NewSourceUser(srcID, u.Name))
}
res := sourceUsers{
Users: su,
}
encodeJSON(w, http.StatusOK, res, h.Logger)
}
// SourceUserID retrieves a user with ID from store.
func (h *Service) SourceUserID(w http.ResponseWriter, r *http.Request) {
ctx := r.Context() ctx := r.Context()
uid := httprouter.GetParamFromContext(ctx, "uid")
srcID, store, err := h.sourceUsersStore(ctx, w, r)
if err != nil {
return
}
u, err := store.Get(ctx, uid)
if err != nil {
Error(w, http.StatusBadRequest, err.Error(), h.Logger)
return
}
res := NewSourceUser(srcID, u.Name)
encodeJSON(w, http.StatusOK, res, h.Logger)
}
func (h *Service) RemoveSourceUser(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
uid := httprouter.GetParamFromContext(ctx, "uid")
_, store, err := h.sourceUsersStore(ctx, w, r)
if err != nil {
return
}
if err := store.Delete(ctx, &chronograf.User{Name: uid}); err != nil {
Error(w, http.StatusBadRequest, err.Error(), h.Logger)
return
}
w.WriteHeader(http.StatusNoContent)
}
func (h *Service) sourceUsersStore(ctx context.Context, w http.ResponseWriter, r *http.Request) (int, chronograf.UsersStore, error) {
srcID, err := paramID("id", r)
if err != nil {
Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger)
return 0, nil, err
}
src, err := h.SourcesStore.Get(ctx, srcID) src, err := h.SourcesStore.Get(ctx, srcID)
if err != nil { if err != nil {
notFound(w, srcID, h.Logger) notFound(w, srcID, h.Logger)
return return 0, nil, err
} }
if err = h.TimeSeries.Connect(ctx, &src); err != nil { if err = h.TimeSeries.Connect(ctx, &src); err != nil {
msg := fmt.Sprintf("Unable to connect to source %d", srcID) msg := fmt.Sprintf("Unable to connect to source %d", srcID)
Error(w, http.StatusBadRequest, msg, h.Logger) Error(w, http.StatusBadRequest, msg, h.Logger)
return return 0, nil, err
} }
uid := httprouter.GetParamFromContext(ctx, "uid")
store := h.TimeSeries.Users(ctx) store := h.TimeSeries.Users(ctx)
u, err := store.Get(ctx, uid) return srcID, store, nil
res := NewSourceUser(srcID, u.Name)
encodeJSON(w, http.StatusOK, res, h.Logger)
} }