diff --git a/influx/users.go b/influx/users.go index 5f1514a0a..d264dc2ea 100644 --- a/influx/users.go +++ b/influx/users.go @@ -160,8 +160,12 @@ func (r *showResults) Permissions() chronograf.Permissions { } else if priv, ok := v[1].(string); !ok { continue } else { + if priv == "ALL PRIVILEGES" { + priv = "ALL" + } c := chronograf.Permission{ Name: db, + Scope: chronograf.DBScope, Allowed: []string{priv}, } res = append(res, c) diff --git a/server/admin.go b/server/admin.go index 124ab2192..22dda9ea9 100644 --- a/server/admin.go +++ b/server/admin.go @@ -11,13 +11,13 @@ import ( "github.com/influxdata/chronograf" ) -type newSourceUserRequest struct { +type sourceUserRequest struct { Username string `json:"username,omitempty"` // Username for new account Password string `json:"password,omitempty"` // Password for new account Permissions chronograf.Permissions `json:"permissions,omitempty"` // Optional permissions } -func (r *newSourceUserRequest) Valid() error { +func (r *sourceUserRequest) ValidCreate() error { if r.Username == "" { return fmt.Errorf("Username required") } @@ -27,6 +27,17 @@ func (r *newSourceUserRequest) Valid() error { return nil } +func (r *sourceUserRequest) ValidUpdate() error { + if r.Username == "" { + return fmt.Errorf("Username required") + } + + if r.Password == "" && len(r.Permissions) == 0 { + return fmt.Errorf("No fields to update") + } + return nil +} + type sourceUser struct { Username string `json:"username,omitempty"` // Username for new account Permissions chronograf.Permissions `json:"permissions,omitempty"` // Account's permissions @@ -52,12 +63,12 @@ type sourceUserLinks struct { // NewSourceUser adds user to source func (h *Service) NewSourceUser(w http.ResponseWriter, r *http.Request) { - var req newSourceUserRequest + var req sourceUserRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { invalidJSON(w, h.Logger) return } - if err := req.Valid(); err != nil { + if err := req.ValidCreate(); err != nil { invalidData(w, err, h.Logger) return } @@ -152,6 +163,40 @@ func (h *Service) RemoveSourceUser(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) } +func (h *Service) UpdateSourceUser(w http.ResponseWriter, r *http.Request) { + var req sourceUserRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + invalidJSON(w, h.Logger) + return + } + if err := req.ValidUpdate(); err != nil { + invalidData(w, err, h.Logger) + return + } + + ctx := r.Context() + uid := httprouter.GetParamFromContext(ctx, "uid") + srcID, store, err := h.sourceUsersStore(ctx, w, r) + if err != nil { + return + } + + user := &chronograf.User{ + Name: uid, + Passwd: req.Password, + Permissions: req.Permissions, + } + + if err := store.Update(ctx, user); err != nil { + Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) + } + + su := NewSourceUser(srcID, user.Name, user.Permissions) + w.Header().Add("Location", su.Links.Self) + encodeJSON(w, http.StatusCreated, su, h.Logger) + +} + 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 { diff --git a/server/mux.go b/server/mux.go index bd7fab17f..b1c14410e 100644 --- a/server/mux.go +++ b/server/mux.go @@ -69,6 +69,14 @@ func NewMux(opts MuxOpts, service Service) http.Handler { // Source Proxy to Influx router.POST("/chronograf/v1/sources/:id/proxy", service.Influx) + // Users associated with the data source + router.GET("/chronograf/v1/sources/:id/users", service.SourceUsers) + router.POST("/chronograf/v1/sources/:id/users", service.NewSourceUser) + + router.GET("/chronograf/v1/sources/:id/users/:uid", service.SourceUserID) + router.DELETE("/chronograf/v1/sources/:id/users/:uid", service.RemoveSourceUser) + router.PATCH("/chronograf/v1/sources/:id/users/:uid", service.UpdateSourceUser) + // Kapacitor router.GET("/chronograf/v1/sources/:id/kapacitors", service.Kapacitors) router.POST("/chronograf/v1/sources/:id/kapacitors", service.NewKapacitor)