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
}
// 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
type UsersStore interface {
// All lists all users from the UsersStore
All(context.Context) ([]User, error)
// Create a new User in the UsersStore
Add(context.Context, *User) (*User, error)
// Delete the User from the UsersStore

View File

@ -24,6 +24,7 @@ type Client struct {
CreateUser(ctx context.Context, name, passwd string) error
DeleteUser(ctx context.Context, name string) error
ChangePassword(ctx context.Context, name, passwd string) error
Users(ctx context.Context, name *string) (*Users, error)
}
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) {
return nil, nil
}
func (cc *ControlClient) CreateUser(ctx context.Context, name, passwd string) error {
return nil
}
func (cc *ControlClient) DeleteUser(ctx context.Context, name string) error {
return nil
}
func (cc *ControlClient) ChangePassword(ctx context.Context, name, passwd string) error {
return nil
}
func (cc *ControlClient) Users(ctx context.Context, name *string) (*enterprise.Users, error) {
return nil, nil
}
type TimeSeries struct {
URLs []string
Response Response

View File

@ -35,3 +35,19 @@ func (c *Client) Update(ctx context.Context, u *chronograf.User) error {
// TODO: Update permissions
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"
)
// 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 }
// Delete the User from Influx Enterprise
// Delete the User from InfluxDB
func (c *Client) Delete(context.Context, *chronograf.User) error { return nil }
// 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
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
import (
"context"
"encoding/json"
"fmt"
"net/http"
@ -48,21 +49,8 @@ type sourceUserLinks struct {
// NewSourceUser adds user to source
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
if err = json.NewDecoder(r.Body).Decode(&req); err != nil {
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
invalidJSON(w, h.Logger)
return
}
@ -71,13 +59,13 @@ func (h *Service) NewSourceUser(w http.ResponseWriter, r *http.Request) {
return
}
if err = h.TimeSeries.Connect(ctx, &src); err != nil {
msg := fmt.Sprintf("Unable to connect to source %d", srcID)
Error(w, http.StatusBadRequest, msg, h.Logger)
ctx := r.Context()
srcID, store, err := h.sourceUsersStore(ctx, w, r)
if err != nil {
return
}
store := h.TimeSeries.Users(ctx)
user := &chronograf.User{
Name: req.Username,
Passwd: req.Password,
@ -93,31 +81,93 @@ func (h *Service) NewSourceUser(w http.ResponseWriter, r *http.Request) {
encodeJSON(w, http.StatusCreated, su, h.Logger)
}
// SourceUserID retrieves a user with ID from store.
func (h *Service) SourceUserID(w http.ResponseWriter, r *http.Request) {
srcID, err := paramID("id", r)
type sourceUsers struct {
Users []sourceUser `json:"users"`
}
// 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 {
Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger)
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()
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)
if err != nil {
notFound(w, srcID, h.Logger)
return
return 0, nil, err
}
if err = h.TimeSeries.Connect(ctx, &src); err != nil {
msg := fmt.Sprintf("Unable to connect to source %d", srcID)
Error(w, http.StatusBadRequest, msg, h.Logger)
return
return 0, nil, err
}
uid := httprouter.GetParamFromContext(ctx, "uid")
store := h.TimeSeries.Users(ctx)
u, err := store.Get(ctx, uid)
res := NewSourceUser(srcID, u.Name)
encodeJSON(w, http.StatusOK, res, h.Logger)
return srcID, store, nil
}