// user handling func userHandling(w http.ResponseWriter, r *http.Request) map[string]string { userResponse := make(map[string]string) opUser, oerr := actor.GetReqUser(r.Header.Get("X-OPS-USERID")) if oerr != nil { jsonErrorReport(w, r, oerr.Error(), oerr.Status()) return nil } switch r.Method { case "GET": userList := user.GetList() for _, k := range userList { /* Make sure it's a client and not a user. */ itemURL := fmt.Sprintf("/users/%s", k) userResponse[k] = util.CustomURL(itemURL) } case "POST": userData, jerr := parseObjJSON(r.Body) if jerr != nil { jsonErrorReport(w, r, jerr.Error(), http.StatusBadRequest) return nil } if averr := util.CheckAdminPlusValidator(userData); averr != nil { jsonErrorReport(w, r, averr.Error(), averr.Status()) return nil } if !opUser.IsAdmin() && !opUser.IsValidator() { jsonErrorReport(w, r, "You are not allowed to take this action.", http.StatusForbidden) return nil } else if !opUser.IsAdmin() && opUser.IsValidator() { if aerr := opUser.CheckPermEdit(userData, "admin"); aerr != nil { jsonErrorReport(w, r, aerr.Error(), aerr.Status()) return nil } if verr := opUser.CheckPermEdit(userData, "validator"); verr != nil { jsonErrorReport(w, r, verr.Error(), verr.Status()) return nil } } userName, sterr := util.ValidateAsString(userData["name"]) if sterr != nil || userName == "" { err := fmt.Errorf("Field 'name' missing") jsonErrorReport(w, r, err.Error(), http.StatusBadRequest) return nil } chefUser, err := user.NewFromJSON(userData) if err != nil { jsonErrorReport(w, r, err.Error(), err.Status()) return nil } if publicKey, pkok := userData["public_key"]; !pkok { var perr error if userResponse["private_key"], perr = chefUser.GenerateKeys(); perr != nil { jsonErrorReport(w, r, perr.Error(), http.StatusInternalServerError) return nil } } else { switch publicKey := publicKey.(type) { case string: if pkok, pkerr := user.ValidatePublicKey(publicKey); !pkok { jsonErrorReport(w, r, pkerr.Error(), pkerr.Status()) return nil } chefUser.SetPublicKey(publicKey) case nil: var perr error if userResponse["private_key"], perr = chefUser.GenerateKeys(); perr != nil { jsonErrorReport(w, r, perr.Error(), http.StatusInternalServerError) return nil } default: jsonErrorReport(w, r, "Bad public key", http.StatusBadRequest) return nil } } /* If we make it here, we want the public key in the * response. I think. */ userResponse["public_key"] = chefUser.PublicKey() chefUser.Save() if lerr := loginfo.LogEvent(opUser, chefUser, "create"); lerr != nil { jsonErrorReport(w, r, lerr.Error(), http.StatusInternalServerError) return nil } userResponse["uri"] = util.ObjURL(chefUser) w.WriteHeader(http.StatusCreated) default: jsonErrorReport(w, r, "Method not allowed for clients or users", http.StatusMethodNotAllowed) return nil } return userResponse }
func clientHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") path := splitPath(r.URL.Path) clientName := path[1] opUser, oerr := actor.GetReqUser(r.Header.Get("X-OPS-USERID")) if oerr != nil { jsonErrorReport(w, r, oerr.Error(), oerr.Status()) return } switch r.Method { case "DELETE": chefClient, gerr := client.Get(clientName) if gerr != nil { jsonErrorReport(w, r, gerr.Error(), gerr.Status()) return } if !opUser.IsAdmin() && !opUser.IsSelf(chefClient) { jsonErrorReport(w, r, "Deleting that client is forbidden", http.StatusForbidden) return } /* Docs were incorrect. It does want the body of the * deleted object. */ jsonClient := chefClient.ToJSON() /* Log the delete event before deleting the client, in * case the client is deleting itself. */ if lerr := loginfo.LogEvent(opUser, chefClient, "delete"); lerr != nil { jsonErrorReport(w, r, lerr.Error(), http.StatusInternalServerError) return } err := chefClient.Delete() if err != nil { jsonErrorReport(w, r, err.Error(), http.StatusForbidden) return } enc := json.NewEncoder(w) if err = enc.Encode(&jsonClient); err != nil { jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError) return } case "GET": chefClient, gerr := client.Get(clientName) if gerr != nil { jsonErrorReport(w, r, gerr.Error(), gerr.Status()) return } if !opUser.IsAdmin() && !opUser.IsSelf(chefClient) { jsonErrorReport(w, r, "You are not allowed to perform that action.", http.StatusForbidden) return } /* API docs are wrong here re: public_key vs. * certificate. Also orgname (at least w/ open source) * and clientname, and it wants chef_type and * json_class */ jsonClient := chefClient.ToJSON() enc := json.NewEncoder(w) if err := enc.Encode(&jsonClient); err != nil { jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError) return } case "PUT": clientData, jerr := parseObjJSON(r.Body) if jerr != nil { jsonErrorReport(w, r, jerr.Error(), http.StatusBadRequest) return } chefClient, err := client.Get(clientName) if err != nil { jsonErrorReport(w, r, err.Error(), http.StatusNotFound) return } /* Makes chef-pedant happy. I suppose it is, after all, * pedantic. */ if averr := util.CheckAdminPlusValidator(clientData); averr != nil { jsonErrorReport(w, r, averr.Error(), averr.Status()) return } if !opUser.IsAdmin() && !opUser.IsSelf(chefClient) { jsonErrorReport(w, r, "You are not allowed to perform that action.", http.StatusForbidden) return } if !opUser.IsAdmin() { var verr util.Gerror aerr := opUser.CheckPermEdit(clientData, "admin") if !opUser.IsValidator() { verr = opUser.CheckPermEdit(clientData, "validator") } if aerr != nil && verr != nil { jsonErrorReport(w, r, "Client can be either an admin or a validator, but not both.", http.StatusBadRequest) return } else if aerr != nil || verr != nil { if aerr == nil { aerr = verr } jsonErrorReport(w, r, aerr.Error(), aerr.Status()) return } } jsonName, sterr := util.ValidateAsString(clientData["name"]) if sterr != nil { jsonErrorReport(w, r, sterr.Error(), http.StatusBadRequest) return } /* If clientName and clientData["name"] aren't the * same, we're renaming. Check the new name doesn't * already exist. */ jsonClient := chefClient.ToJSON() if clientName != jsonName { if lerr := loginfo.LogEvent(opUser, chefClient, "modify"); lerr != nil { jsonErrorReport(w, r, lerr.Error(), http.StatusInternalServerError) return } err := chefClient.Rename(jsonName) if err != nil { jsonErrorReport(w, r, err.Error(), err.Status()) return } w.WriteHeader(http.StatusCreated) } if uerr := chefClient.UpdateFromJSON(clientData); uerr != nil { jsonErrorReport(w, r, uerr.Error(), uerr.Status()) return } if pk, pkfound := clientData["public_key"]; pkfound { switch pk := pk.(type) { case string: if pkok, pkerr := client.ValidatePublicKey(pk); !pkok { jsonErrorReport(w, r, pkerr.Error(), http.StatusBadRequest) return } chefClient.SetPublicKey(pk) jsonClient["public_key"] = pk case nil: //show_public_key = false default: jsonErrorReport(w, r, "Bad request", http.StatusBadRequest) return } } if p, pfound := clientData["private_key"]; pfound { switch p := p.(type) { case bool: if p { var cgerr error if jsonClient["private_key"], cgerr = chefClient.GenerateKeys(); cgerr != nil { jsonErrorReport(w, r, cgerr.Error(), http.StatusInternalServerError) return } // make sure the json // client gets the new // public key jsonClient["public_key"] = chefClient.PublicKey() } default: jsonErrorReport(w, r, "Bad request", http.StatusBadRequest) return } } chefClient.Save() if lerr := loginfo.LogEvent(opUser, chefClient, "modify"); lerr != nil { jsonErrorReport(w, r, lerr.Error(), http.StatusInternalServerError) return } enc := json.NewEncoder(w) if err := enc.Encode(&jsonClient); err != nil { jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError) return } default: jsonErrorReport(w, r, "Unrecognized method for client!", http.StatusMethodNotAllowed) } }