// Get gets a client from the data store. func Get(clientname string) (*Client, util.Gerror) { var client *Client var err error if config.UsingDB() { client, err = getClientSQL(clientname) if err != nil { var gerr util.Gerror if err != sql.ErrNoRows { gerr = util.Errorf(err.Error()) gerr.SetStatus(http.StatusInternalServerError) } else { gerr = util.Errorf("Client %s not found", clientname) gerr.SetStatus(http.StatusNotFound) } return nil, gerr } } else { ds := datastore.New() c, found := ds.Get("client", clientname) if !found { gerr := util.Errorf("Client %s not found", clientname) gerr.SetStatus(http.StatusNotFound) return nil, gerr } if c != nil { client = c.(*Client) } } return client, nil }
// Get a user. func Get(name string) (*User, util.Gerror) { var user *User if config.UsingDB() { var err error user, err = getUserSQL(name) if err != nil { var gerr util.Gerror if err != sql.ErrNoRows { gerr = util.Errorf(err.Error()) gerr.SetStatus(http.StatusInternalServerError) } else { gerr = util.Errorf("Client %s not found", name) gerr.SetStatus(http.StatusNotFound) } return nil, gerr } } else { ds := datastore.New() u, found := ds.Get("user", name) if !found { err := util.Errorf("User %s not found", name) return nil, err } if u != nil { user = u.(*User) } } return user, nil }
// Get a data bag. func Get(dbName string) (*DataBag, util.Gerror) { var dataBag *DataBag var err error if config.UsingDB() { dataBag, err = getDataBagSQL(dbName) if err != nil { var gerr util.Gerror if err == sql.ErrNoRows { gerr = util.Errorf("Cannot load data bag %s", dbName) gerr.SetStatus(http.StatusNotFound) } else { gerr = util.Errorf(err.Error()) gerr.SetStatus(http.StatusInternalServerError) } return nil, gerr } } else { ds := datastore.New() d, found := ds.Get("data_bag", dbName) if !found { err := util.Errorf("Cannot load data bag %s", dbName) err.SetStatus(http.StatusNotFound) return nil, err } if d != nil { dataBag = d.(*DataBag) for _, v := range dataBag.DataBagItems { z := datastore.WalkMapForNil(v.RawData) v.RawData = z.(map[string]interface{}) } } } return dataBag, nil }
// New creates an empty data bag, and kicks off adding it to the index. func New(name string) (*DataBag, util.Gerror) { var found bool var err util.Gerror if err = validateDataBagName(name, false); err != nil { return nil, err } if config.UsingDB() { var cerr error found, cerr = checkForDataBagSQL(datastore.Dbh, name) if cerr != nil { err = util.Errorf(cerr.Error()) err.SetStatus(http.StatusInternalServerError) return nil, err } } else { ds := datastore.New() _, found = ds.Get("data_bag", name) } if found { err = util.Errorf("Data bag %s already exists", name) err.SetStatus(http.StatusConflict) return nil, err } dbiMap := make(map[string]*DataBagItem) dataBag := &DataBag{ Name: name, DataBagItems: dbiMap, } indexer.CreateNewCollection(name) return dataBag, nil }
// UpdateFromJSON updates a user from a JSON object, carrying out a bunch of // validations inside. func (u *User) UpdateFromJSON(jsonUser map[string]interface{}) util.Gerror { userName, nerr := util.ValidateAsString(jsonUser["name"]) if nerr != nil { return nerr } if u.Username != userName { err := util.Errorf("User name %s and %s from JSON do not match", u.Username, userName) return err } /* Validations. */ /* Invalid top level elements */ validElements := []string{"username", "name", "org_name", "public_key", "private_key", "admin", "password", "email", "salt"} ValidElem: for k := range jsonUser { for _, i := range validElements { if k == i { continue ValidElem } } err := util.Errorf("Invalid key %s in request body", k) return err } var verr util.Gerror // Check the password first. If it's bad, bail before touching anything // else. if passwd, ok := jsonUser["password"]; ok { passwd, verr = util.ValidateAsString(passwd) if verr != nil { return verr } if passwd != "" { verr = u.SetPasswd(passwd.(string)) if verr != nil { return verr } } } if adminVal, ok := jsonUser["admin"]; ok { var ab bool if ab, verr = util.ValidateAsBool(adminVal); verr != nil { // NOTE: may need to tweak this error message depending // if this is a user or a client verr = util.Errorf("Field 'admin' invalid") return verr } else if u.Admin && !ab { if u.isLastAdmin() { verr = util.Errorf("Cannot remove admin status from the last admin") verr.SetStatus(http.StatusForbidden) return verr } } u.Admin = ab } return nil }
// New creates a new API user. func New(name string) (*User, util.Gerror) { var found bool var err util.Gerror if config.UsingDB() { var uerr error found, uerr = checkForUserSQL(datastore.Dbh, name) if uerr != nil { err = util.Errorf(uerr.Error()) err.SetStatus(http.StatusInternalServerError) return nil, err } } else { ds := datastore.New() _, found = ds.Get("user", name) } if found { err := util.Errorf("User '%s' already exists", name) err.SetStatus(http.StatusConflict) return nil, err } if err := validateUserName(name); err != nil { return nil, err } salt, saltErr := chefcrypto.GenerateSalt() if saltErr != nil { err := util.Errorf(saltErr.Error()) return nil, err } user := &User{ Username: name, Name: name, Admin: false, Email: "", pubKey: "", salt: salt, } return user, nil }
// Get an environment. func Get(envName string) (*ChefEnvironment, util.Gerror) { if envName == "_default" { return defaultEnvironment(), nil } var env *ChefEnvironment var found bool if config.UsingDB() { var err error env, err = getEnvironmentSQL(envName) if err != nil { var gerr util.Gerror if err != sql.ErrNoRows { gerr = util.CastErr(err) gerr.SetStatus(http.StatusInternalServerError) return nil, gerr } found = false } else { found = true } } else { ds := datastore.New() var e interface{} e, found = ds.Get("env", envName) if e != nil { env = e.(*ChefEnvironment) } } if !found { err := util.Errorf("Cannot load environment %s", envName) err.SetStatus(http.StatusNotFound) return nil, err } return env, nil }
// New creates a new client. func New(clientname string) (*Client, util.Gerror) { var found bool var err util.Gerror if config.UsingDB() { var cerr error found, cerr = checkForClientSQL(datastore.Dbh, clientname) if cerr != nil { err := util.Errorf(err.Error()) err.SetStatus(http.StatusInternalServerError) return nil, err } } else { ds := datastore.New() _, found = ds.Get("client", clientname) } if found { err = util.Errorf("Client already exists") err.SetStatus(http.StatusConflict) return nil, err } if err := validateClientName(clientname); err != nil { return nil, err } client := &Client{ Name: clientname, NodeName: clientname, ChefType: "client", JSONClass: "Chef::ApiClient", Validator: false, Orgname: "", pubKey: "", Admin: false, Certificate: "", } return client, nil }
// UpdateFromJSON updates a client/user from a json object. Does a bunch of // validations inside rather than in the handler. func (c *Client) UpdateFromJSON(jsonActor map[string]interface{}) util.Gerror { actorName, nerr := util.ValidateAsString(jsonActor["name"]) if nerr != nil { return nerr } if c.Name != actorName { err := util.Errorf("Client name %s and %s from JSON do not match", c.Name, actorName) return err } /* Validations. */ /* Invalid top level elements */ validElements := []string{"name", "json_class", "chef_type", "validator", "org_name", "orgname", "public_key", "private_key", "admin", "certificate", "password", "node_name"} ValidElem: for k := range jsonActor { for _, i := range validElements { if k == i { continue ValidElem } } err := util.Errorf("Invalid key %s in request body", k) return err } var verr util.Gerror jsonActor["json_class"], verr = util.ValidateAsFieldString(jsonActor["json_class"]) if verr != nil { if verr.Error() == "Field 'name' nil" { jsonActor["json_class"] = c.JSONClass } else { return verr } } else { if jsonActor["json_class"].(string) != "Chef::ApiClient" { verr = util.Errorf("Field 'json_class' invalid") return verr } } jsonActor["chef_type"], verr = util.ValidateAsFieldString(jsonActor["chef_type"]) if verr != nil { if verr.Error() == "Field 'name' nil" { jsonActor["chef_type"] = c.ChefType } else { return verr } } else { if jsonActor["chef_type"].(string) != "client" { verr = util.Errorf("Field 'chef_type' invalid") return verr } } var ab, vb bool if adminVal, ok := jsonActor["admin"]; ok { if ab, verr = util.ValidateAsBool(adminVal); verr != nil { // NOTE: may need to tweak this error message depending // if this is a user or a client verr = util.Errorf("Field 'admin' invalid") return verr } else if c.Admin && !ab { if c.isLastAdmin() { verr = util.Errorf("Cannot remove admin status from the last admin") verr.SetStatus(http.StatusForbidden) return verr } } } if validatorVal, ok := jsonActor["validator"]; ok { if vb, verr = util.ValidateAsBool(validatorVal); verr != nil { return verr } } if ab && vb { verr = util.Errorf("Client can be either an admin or a validator, but not both.") verr.SetStatus(http.StatusBadRequest) return verr } c.Admin = ab c.Validator = vb c.ChefType = jsonActor["chef_type"].(string) c.JSONClass = jsonActor["json_class"].(string) return nil }