func (api *Api) GetAllEnvCaps(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } //session := Session{} var errl error = nil //if session,errl = api.CheckLogin( login, guid ); errl != nil { if _, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) qs := r.URL.Query() // Query string - map[string][]string envcaps := []EnvCap{} if len(qs["code"]) > 0 { srch := qs["code"][0] mutex.Lock() api.db.Order("code").Find(&envcaps, "code = ?", srch) mutex.Unlock() } else { mutex.Lock() err := api.db.Order("Code").Find(&envcaps) mutex.Unlock() if err.Error != nil { if !err.RecordNotFound() { rest.Error(w, err.Error.Error(), 500) return } } } // Create a slice of maps from users struct // to selectively copy database fields for display u := make([]map[string]interface{}, len(envcaps)) for i := range envcaps { u[i] = make(map[string]interface{}) u[i]["Id"] = envcaps[i].Id u[i]["Code"] = envcaps[i].Code u[i]["Desc"] = envcaps[i].Desc } // Too much noise //api.LogActivity( session.Id, "Sent list of users" ) w.WriteJson(&u) }
func (api *Api) Logout(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") session := Session{} var errl error = nil if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 400) return } mutex.Lock() if err := api.db.Delete(&session).Error; err != nil { rest.Error(w, err.Error(), 400) mutex.Unlock() return } mutex.Unlock() logit("User '" + login + "' logged out") api.LogActivity(session.Id, "User '"+login+"' logged out") w.WriteJson("Success") }
func (api *Api) AddPerm(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already permData := Perm{} if err := r.DecodeJsonPayload(&permData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if permData.UserId == 0 { rest.Error(w, "Incorrect data format received.", 400) return } perm := Perm{} mutex.Lock() if !api.db.Find(&perm, "env_id = ? and user_id = ?", permData.EnvId, permData.UserId).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Add perm mutex.Lock() if err := api.db.Save(&permData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() text := fmt.Sprintf("Added new environment permission. PermID = '%d'.", permData.Id) api.LogActivity(session.Id, text) w.WriteJson(permData) }
func (api *Api) AddEnvCap(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already EnvCapData := EnvCap{} if err := r.DecodeJsonPayload(&EnvCapData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if len(EnvCapData.Code) == 0 || len(EnvCapData.Desc) == 0 { rest.Error(w, "A required field is empty.", 400) return } EnvCap := EnvCap{} mutex.Lock() if !api.db.Find(&EnvCap, "code = ?", EnvCapData.Code).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Add EnvCap mutex.Lock() if err := api.db.Save(&EnvCapData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() text := fmt.Sprintf("Added new EnvCap, '%s'.", EnvCapData.Code) api.LogActivity(session.Id, text) w.WriteJson(EnvCapData) }
func (api *Api) AddRepo(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already repoData := Repo{} if err := r.DecodeJsonPayload(&repoData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if len(repoData.Url) == 0 { rest.Error(w, "Incorrect data format received.", 400) return } repo := Repo{} mutex.Lock() if !api.db.Find(&repo, "Url = ?", repoData.Url). RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Add repo mutex.Lock() if err := api.db.Save(&repoData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, "Added new repo '"+repoData.Url+"'.") w.WriteJson(repoData) }
func (api *Api) AddOutputLine(w rest.ResponseWriter, r *rest.Request) { login := r.PathParam("login") guid := r.PathParam("GUID") // Admin is not allowed if login == "admin" { rest.Error(w, "Not allowed", 400) return } // Check credentials //session := Session{} var errl error if _, errl = api.CheckLoginNoExpiry(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } //defer api.TouchSession( guid ) outputLineData := OutputLine{} if err := r.DecodeJsonPayload(&outputLineData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if outputLineData.JobId == 0 { rest.Error(w, "Incorrect data format received.", 400) return } // Add OutputLine mutex.Lock() if err := api.db.Save(&outputLineData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() //text := "" //fmt.Sprintf( text,"%d",outputLineData.JobId ) //api.LogActivity( session.Id, "Started outputLine logging for job '"+ // text+"'." ) w.WriteJson("Success") }
func (api *Api) DeleteEnv(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Delete id := 0 if id, errl = strconv.Atoi(r.PathParam("id")); errl != nil { rest.Error(w, "Invalid id.", 400) return } env := Env{} mutex.Lock() if api.db.First(&env, id).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record not found.", 400) return } mutex.Unlock() mutex.Lock() if err := api.db.Delete(&env).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() dc := Dc{} mutex.Lock() api.db.First(&dc, env.DcId) mutex.Unlock() text := fmt.Sprintf("Deleted environment '%s->%s'.", dc.SysName, env.SysName) api.LogActivity(session.Id, text) w.WriteJson("Success") }
func (api *Api) DeletePlugin(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Delete id := 0 if id, errl = strconv.Atoi(r.PathParam("id")); errl != nil { rest.Error(w, "Invalid id.", 400) return } plugin := Plugin{} mutex.Lock() if api.db.First(&plugin, id).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record not found.", 400) return } mutex.Unlock() mutex.Lock() if err := api.db.Delete(&plugin).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } if err := api.db.Where("plugin_id = ?", plugin.Id). Delete(File{}).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, "Deleted plugin '"+plugin.Name+"'.") w.WriteJson("Success") }
func (api *Api) DeleteJob(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login == "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Delete id := 0 if id, errl = strconv.Atoi(r.PathParam("id")); errl != nil { rest.Error(w, "Invalid id.", 400) return } job := Job{} mutex.Lock() if api.db.First(&job, id).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record not found.", 400) return } mutex.Unlock() mutex.Lock() if err := api.db.Delete(&job).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, fmt.Sprintf("Deleted job %d.", job.Id)) w.WriteJson(&job) }
func (api *Api) DeleteOutputLine(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Admin is not allowed if login == "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Delete id := 0 if id, errl = strconv.Atoi(r.PathParam("id")); errl != nil { rest.Error(w, "Invalid id.", 400) return } outputline := OutputLine{} mutex.Lock() if err := api.db.Where("job_id = ?", id).Delete(&outputline).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, fmt.Sprintf("Deleted outputlines for job %d.", id)) w.WriteJson("Success") }
// AddUser processes "POST /users" queries. // func (api *Api) AddUser(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already userData := User{} if err := r.DecodeJsonPayload(&userData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if len(userData.Login) == 0 { rest.Error(w, "Incorrect data format received.", 400) return } user := User{} mutex.Lock() if !api.db.Find(&user, "login = ?", userData.Login).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Add user if len(userData.Passhash) == 0 { rest.Error(w, "Empty password not allowed.", 400) return } c := &Crypt{} c.Pass = []byte(userData.Passhash) c.Crypt() userData.Passhash = string(c.Hash) mutex.Lock() if err := api.db.Save(&userData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, "Added new user '"+userData.Login+"'.") w.WriteJson(userData) }
func (api *Api) GetAllScripts(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Anyone can read the list of scripts /* if login != "admin" { rest.Error(w, "Not allowed", 400) return }*/ //session := Session{} var errl error = nil //if session,errl = api.CheckLogin( login, guid ); errl != nil { if _, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) scripts := []Script{} qs := r.URL.Query() // Query string - map[string][]string if len(qs["id"]) > 0 { srch := qs["id"][0] mutex.Lock() api.db.Order("id").Find(&scripts, "id = ?", srch) mutex.Unlock() /* if api.db.Order("id"). Find(&scripts, "id = ?", srch).RecordNotFound() { rest.Error(w, "No results.", 400) return } */ } else if len(qs["name"]) > 0 { srch := qs["name"][0] mutex.Lock() api.db.Order("name").Find(&scripts, "name = ?", srch) mutex.Unlock() /* if api.db.Order("name"). Find(&scripts, "name = ?", srch).RecordNotFound() { rest.Error(w, "No results.", 400) return } */ } else { // No results is not an error mutex.Lock() err := api.db.Order("id").Find(&scripts) mutex.Unlock() if err.Error != nil { if !err.RecordNotFound() { rest.Error(w, err.Error.Error(), 500) return } } } // Create a slice of maps from users struct // to selectively copy database fields for display u := make([]map[string]interface{}, len(scripts)) for i := range scripts { u[i] = make(map[string]interface{}) u[i]["Id"] = scripts[i].Id u[i]["Name"] = scripts[i].Name u[i]["Desc"] = scripts[i].Desc // 'Source' doesn't go through Unmarshall so // is output as base64, good. Use nosource to // exclude this field. if len(qs["nosource"]) == 0 { u[i]["Source"] = scripts[i].Source } u[i]["Type"] = scripts[i].Type } // Too much noise //api.LogActivity( session.Id, "Sent list of users" ) w.WriteJson(&u) }
func (api *Api) UpdateScript(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Ensure user exists id := r.PathParam("id") // Check that the id string is a number if _, err := strconv.Atoi(id); err != nil { rest.Error(w, "Invalid id.", 400) return } // Load data from db, then ... script := Script{} mutex.Lock() if api.db.Find(&script, id).RecordNotFound() { mutex.Unlock() //rest.Error(w, err.Error(), 400) rest.Error(w, "Record not found.", 400) return } mutex.Unlock() // ... overwrite any sent fields if err := r.DecodeJsonPayload(&script); err != nil { //rest.Error(w, err.Error(), 400) rest.Error(w, "Invalid data format received.", 400) return } script_srch := Script{} mutex.Lock() if !api.db.Find(&script_srch, "name = ? and id != ?", script.Name, script.Id).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Work out type: // Write to disk then use unix 'file -b' (brief) if len(script.Source) > 0 { if err := ioutil.WriteFile(os.TempDir()+"/obdi_scriptcheck", script.Source, 0644); err != nil { script.Type = "Write file failed. Type of script unknown. (" + err.Error() + ")" } else { runCmd := exec.Command("file", "-b", os.TempDir()+"/obdi_scriptcheck") output, err := runCmd.Output() if err != nil { script.Type = "Unix 'file' failed. Type of script unknown." + " (" + err.Error() + ")" } else { script.Type = string(output) } } } // Force the use of the path id over an id in the payload Id, _ := strconv.Atoi(id) script.Id = int64(Id) mutex.Lock() if err := api.db.Save(&script).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, "Updated data centre details for '"+script.Name+"'.") w.WriteJson(script) }
func (api *Api) AddScript(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already scriptData := Script{} if err := r.DecodeJsonPayload(&scriptData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if len(scriptData.Source) == 0 { rest.Error(w, "Incorrect data format received.", 400) return } script := Script{} mutex.Lock() if !api.db.Find(&script, "name = ?", scriptData.Name).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Work out type: // Write to disk then use unix 'file -b' (brief) if err := ioutil.WriteFile(os.TempDir()+"/obdi_scriptcheck", scriptData.Source, 0644); err != nil { scriptData.Type = "Unknown type of script" } else { runCmd := exec.Command("file", "-b", os.TempDir()+"/obdi_scriptcheck") output, err := runCmd.Output() if err != nil { scriptData.Type = "Unknown type of script" } else { scriptData.Type = string(output) } } // Add script mutex.Lock() if err := api.db.Save(&scriptData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() // Try to start the script text := fmt.Sprintf("Added new script, %s.", scriptData.Name) api.LogActivity(session.Id, text) scriptData.Source = []byte{} w.WriteJson(scriptData) }
func (api *Api) KillJob(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login == "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Delete id := 0 if id, errl = strconv.Atoi(r.PathParam("id")); errl != nil { rest.Error(w, "Invalid id.", 400) return } job := Job{} mutex.Lock() if api.db.First(&job, id).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record not found.", 400) return } mutex.Unlock() env := Env{} mutex.Lock() api.db.Model(&job).Related(&env) mutex.Unlock() if env.WorkerUrl == "" || env.WorkerKey == "" { txt := "WorkerUrl or WorkerKey not set for the target environment" rest.Error(w, txt, 400) return } type Jobkill struct { JobID int64 Key string } data := Jobkill{ JobID: job.Id, Key: env.WorkerKey, } // Encode jsondata, err := json.Marshal(data) if err != nil { txt := fmt.Sprintf( "Error sending kill command to worker, JSON Encode:", err.Error()) rest.Error(w, txt, 400) return } // POST to worker resp, err := DELETE(jsondata, env.WorkerUrl, "jobs") if err != nil { txt := "Could not send kill command to worker. ('" + err.Error() + "')" rest.Error(w, txt, 400) return } defer resp.Body.Close() if resp.StatusCode != 200 { var body []byte if b, err := ioutil.ReadAll(resp.Body); err != nil { txt := fmt.Sprintf("Error reading Body ('%s').", err.Error()) rest.Error(w, txt, 400) return } else { body = b } type myErr struct { Error string } errstr := myErr{} if err := json.Unmarshal(body, &errstr); err != nil { txt := fmt.Sprintf("Error decoding JSON ('%s')"+ ". Check the Worker URL.", err.Error()) rest.Error(w, txt, 400) return } txt := "Sending Kill failed. Worker said: '" + errstr.Error + "'" rest.Error(w, txt, 400) return } api.LogActivity(session.Id, fmt.Sprintf("Killed job %d.", job.Id)) w.WriteJson(&job) }
func (api *Api) GetAllFiles(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Anyone can view files /* if login != "admin" { rest.Error(w, "Not allowed", 400) return } */ //session := Session{} var errl error = nil //if session,errl = api.CheckLogin( login, guid ); errl != nil { if _, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) files := []File{} qs := r.URL.Query() // Query string - map[string][]string if len(qs["name"]) > 0 && len(qs["plugin_id"]) > 0 { srch1 := qs["name"][0] srch2 := qs["plugin_id"][0] mutex.Lock() api.db.Order("name").Find(&files, "name = ? and plugin_id = ?", srch1, srch2) mutex.Unlock() /* if api.db.Order("name"). Find(&files, "name = ?", srch).RecordNotFound() { rest.Error(w, "No results.", 400) return } */ } else if len(qs["name"]) > 0 { srch := qs["name"][0] mutex.Lock() api.db.Order("name").Find(&files, "name = ?", srch) mutex.Unlock() /* if api.db.Order("name"). Find(&files, "name = ?", srch).RecordNotFound() { rest.Error(w, "No results.", 400) return } */ } else { // No results is not an error mutex.Lock() err := api.db.Order("name").Find(&files) mutex.Unlock() if err.Error != nil { if !err.RecordNotFound() { rest.Error(w, err.Error.Error(), 500) return } } } // Create a slice of maps from users struct // to selectively copy database fields for display u := make([]map[string]interface{}, len(files)) for i := range files { u[i] = make(map[string]interface{}) u[i]["Id"] = files[i].Id u[i]["Name"] = files[i].Name u[i]["Desc"] = files[i].Desc u[i]["Url"] = files[i].Url u[i]["Type"] = files[i].Type u[i]["PluginId"] = files[i].PluginId plugin := Plugin{} mutex.Lock() api.db.Model(&files[i]).Related(&plugin) mutex.Unlock() u[i]["PluginName"] = plugin.Name } // Too much noise //api.LogActivity( session.Id, "Sent list of users" ) w.WriteJson(&u) }
func (api *Api) UpdateEnvCap(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Ensure user exists id := r.PathParam("id") // Check that the id string is a number if _, err := strconv.Atoi(id); err != nil { rest.Error(w, "Invalid id.", 400) return } // Load data from db, then ... EnvCap := EnvCap{} mutex.Lock() if api.db.Find(&EnvCap, id).RecordNotFound() { mutex.Unlock() //rest.Error(w, err.Error(), 400) rest.Error(w, "Record not found.", 400) return } mutex.Unlock() // ... overwrite any sent fields if err := r.DecodeJsonPayload(&EnvCap); err != nil { //rest.Error(w, err.Error(), 400) rest.Error(w, "Invalid data format received.", 400) return } // Force the use of the path id over an id in the payload Id, _ := strconv.Atoi(id) EnvCap.Id = int64(Id) mutex.Lock() if err := api.db.Save(&EnvCap).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() text := fmt.Sprintf("Updated EnvCap, '%s'.", EnvCap.Code) api.LogActivity(session.Id, text) w.WriteJson("Success") }
func (api *Api) GetAllPlugins(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Anyone can view plugins /* if login != "admin" { rest.Error(w, "Not allowed", 400) return } */ //session := Session{} var errl error = nil //if session,errl = api.CheckLogin( login, guid ); errl != nil { if _, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) plugins := []Plugin{} qs := r.URL.Query() // Query string - map[string][]string if len(qs["name"]) > 0 { srch := qs["name"][0] mutex.Lock() api.db.Order("name").Find(&plugins, "name = ?", srch) mutex.Unlock() /* if api.db.Order("name"). Find(&plugins, "name = ?", srch).RecordNotFound() { rest.Error(w, "No results.", 400) return } */ } else { // No results is not an error mutex.Lock() err := api.db.Order("name").Find(&plugins) mutex.Unlock() if err.Error != nil { if !err.RecordNotFound() { rest.Error(w, err.Error.Error(), 500) return } } } // Create a slice of maps from users struct // to selectively copy database fields for display u := make([]map[string]interface{}, len(plugins)) for i := range plugins { u[i] = make(map[string]interface{}) u[i]["Id"] = plugins[i].Id u[i]["Name"] = plugins[i].Name u[i]["Desc"] = plugins[i].Desc u[i]["Parent"] = plugins[i].Parent u[i]["HasView"] = plugins[i].HasView u[i]["CreatedAt"] = plugins[i].CreatedAt // UpdatedAt doesn't get updated 'cos we use Save // //u[i]["UpdatedAt"] = plugins[i].CreatedAt } // Too much noise //api.LogActivity( session.Id, "Sent list of users" ) w.WriteJson(&u) }
func (api *Api) UpdateJob(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Admin is not allowed if login == "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Ensure user exists id := r.PathParam("id") // Check that the id string is a number if _, err := strconv.Atoi(id); err != nil { rest.Error(w, "Invalid id.", 400) return } // Load data from db, then ... job := Job{} mutex.Lock() if api.db.Find(&job, id).RecordNotFound() { mutex.Unlock() //rest.Error(w, err.Error(), 400) rest.Error(w, "Job ID not found.", 400) return } mutex.Unlock() // ... overwrite any sent fields if err := r.DecodeJsonPayload(&job); err != nil { //rest.Error(w, err.Error(), 400) rest.Error(w, "Invalid data format received.", 400) return } // Force the use of the path id over an id in the payload Id, _ := strconv.Atoi(id) job.Id = int64(Id) mutex.Lock() if err := api.db.Save(&job).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, fmt.Sprintf("Updated job details for jobId %d.", job.Id)) w.WriteJson(job) }
func (api *Api) UpdatePlugin(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Ensure user exists id := r.PathParam("id") // Check that the id string is a number if _, err := strconv.Atoi(id); err != nil { rest.Error(w, "Invalid id.", 400) return } // Load data from db, then ... plugin := Plugin{} mutex.Lock() if api.db.Find(&plugin, id).RecordNotFound() { mutex.Unlock() //rest.Error(w, err.Error(), 400) rest.Error(w, "Record not found.", 400) return } mutex.Unlock() // ... overwrite any sent fields if err := r.DecodeJsonPayload(&plugin); err != nil { //rest.Error(w, err.Error(), 400) rest.Error(w, "Invalid data format received.", 400) return } // Force the use of the path id over an id in the payload Id, _ := strconv.Atoi(id) plugin.Id = int64(Id) // Make sure parent exists pluginSrch := Plugin{} mutex.Lock() if len(plugin.Parent) > 0 && api.db.Find(&pluginSrch, "name = ?", plugin.Parent).RecordNotFound() { mutex.Unlock() rest.Error(w, "Parent not found.", 400) return } mutex.Unlock() if pluginSrch.Id == plugin.Id { rest.Error(w, "Cannot be a parent of itself.", 400) return } mutex.Lock() if err := api.db.Save(&plugin).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, "Updated plugin details for '"+plugin.Name+"'.") w.WriteJson("Success") }
func (api *Api) AddPlugin(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already pluginData := Plugin{} if err := r.DecodeJsonPayload(&pluginData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if len(pluginData.Name) == 0 { rest.Error(w, "Incorrect data format received.", 400) return } plugin := Plugin{} mutex.Lock() if !api.db.Find(&plugin, "name = ?", pluginData.Name). RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Make sure parent exists mutex.Lock() if len(pluginData.Parent) > 0 && api.db.Find(&plugin, "name = ?", pluginData.Parent).RecordNotFound() { mutex.Unlock() rest.Error(w, "Parent not found.", 400) return } mutex.Unlock() // Add plugin mutex.Lock() if err := api.db.Save(&pluginData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, "Added new plugin '"+pluginData.Name+"'.") w.WriteJson(pluginData) }
func (api *Api) AddDcCapMap(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already dcCapMapData := DcCapMap{} if err := r.DecodeJsonPayload(&dcCapMapData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if dcCapMapData.DcId == 0 || dcCapMapData.DcCapId == 0 { rest.Error(w, "A required field is empty.", 400) return } dcCapMap := DcCapMap{} mutex.Lock() if !api.db.Find(&dcCapMap, "dc_id = ? and dc_cap_id = ?", dcCapMapData.DcId, dcCapMapData.DcCapId).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Check that DcId and DcCapId exist dc := Dc{} mutex.Lock() if api.db.Find(&dc, dcCapMapData.DcId).RecordNotFound() { mutex.Unlock() rest.Error(w, "Invalid data centre id.", 400) return } mutex.Unlock() dcCap := DcCap{} mutex.Lock() if api.db.Find(&dcCap, dcCapMapData.DcCapId).RecordNotFound() { mutex.Unlock() rest.Error(w, "Invalid data centre capability id.", 400) return } mutex.Unlock() // Add DcCapMap mutex.Lock() if err := api.db.Save(&dcCapMapData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() text := fmt.Sprintf("Added new DcCapMap, '%d'.", dcCapMapData.Id) api.LogActivity(session.Id, text) w.WriteJson(dcCapMapData) }
func (api *Api) GetAllEnvs(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Anyone can view envs //session := Session{} var errl error = nil //if session,errl = api.CheckLogin( login, guid ); errl != nil { if _, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) envs := []Env{} qs := r.URL.Query() // Query string - map[string][]string if login == "admin" { if len(qs["sys_name"]) > 0 { srch := qs["sys_name"][0] if len(qs["dc_id"]) > 0 { dcid := qs["dc_id"][0] mutex.Lock() api.db.Order("sys_name").Find(&envs, "sys_name = ? and dc_id = ?", srch, dcid) mutex.Unlock() } else { mutex.Lock() api.db.Order("sys_name").Find(&envs, "sys_name = ?", srch) mutex.Unlock() } /* if api.db.Order("sys_name"). Find(&envs, "sys_name = ?", srch).RecordNotFound() { rest.Error(w, "No results.", 400) return } */ } else { mutex.Lock() err := api.db.Order("dc_id,sys_name").Find(&envs) mutex.Unlock() if err.Error != nil { if !err.RecordNotFound() { rest.Error(w, err.Error.Error(), 500) return } } } } else { //Not admin // Only return readable/writeable envs for the current user additional_where := "" if len(qs["env_id"]) > 0 { additional_where = "AND envs.id = " + qs["env_id"][0] } if len(qs["writeable"]) > 0 { // only writeable envs mutex.Lock() api.db.Where("envs.id in (SELECT perms.env_id from perms "+ "LEFT JOIN users on users.id=perms.user_id "+ "WHERE users.login=? and perms.writeable=1) "+ additional_where, login).Find(&envs) mutex.Unlock() } else { // readable or writeable envs mutex.Lock() api.db.Where("envs.id in (SELECT perms.env_id from perms "+ "LEFT JOIN users on users.id=perms.user_id "+ "WHERE users.login=? and perms.enabled=1) "+ additional_where, login).Find(&envs) mutex.Unlock() } } // Create a slice of maps from users struct // to selectively copy database fields for display u := make([]map[string]interface{}, len(envs)) for i := range envs { u[i] = make(map[string]interface{}) u[i]["Id"] = envs[i].Id u[i]["DispName"] = envs[i].DispName u[i]["SysName"] = envs[i].SysName //u[i]["WorkerIp"] = envs[i].WorkerIp //u[i]["WorkerPort"] = envs[i].WorkerPort u[i]["WorkerUrl"] = envs[i].WorkerUrl if login == "admin" { u[i]["WorkerKey"] = envs[i].WorkerKey } u[i]["CreatedAt"] = envs[i].CreatedAt dc := Dc{} mutex.Lock() api.db.Model(&envs[i]).Related(&dc) mutex.Unlock() u[i]["DcSysName"] = dc.SysName u[i]["DcDispName"] = dc.DispName u[i]["DcId"] = dc.Id } // Too much noise //api.LogActivity( session.Id, "Sent list of users" ) w.WriteJson(&u) }
// UpdateUser processes "PUT /users" queries. // func (api *Api) UpdateUser(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Ensure user exists id := r.PathParam("id") // Check that the id string is a number if _, err := strconv.Atoi(id); err != nil { rest.Error(w, "Invalid id.", 400) return } // Load data from db, then ... user := User{} mutex.Lock() if api.db.Find(&user, id).RecordNotFound() { mutex.Unlock() //rest.Error(w, err.Error(), 400) rest.Error(w, "Record not found.", 400) return } mutex.Unlock() // FIXME: DecodeJsonPayload(&somethingelse) then // merge with 'user' manually. This will remove // the 'password can't begin with $' limitation. // ... overwrite any sent fields if err := r.DecodeJsonPayload(&user); err != nil { //rest.Error(w, err.Error(), 400) rest.Error(w, "Invalid data format received.", 400) return } // Add user if !strings.HasPrefix(user.Passhash, "$") { c := &Crypt{} c.Pass = []byte(user.Passhash) c.Crypt() user.Passhash = string(c.Hash) } // Force the use of the path id over an id in the payload Id, _ := strconv.Atoi(id) user.Id = int64(Id) mutex.Lock() if err := api.db.Save(&user).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, "Updated user details for '"+user.Login+"'.") w.WriteJson(user) }
// GetAllUsers processes "GET /users" queries. // func (api *Api) GetAllUsers(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } //session := Session{} var errl error = nil //if session,errl = api.CheckLogin( login, guid ); errl != nil { if _, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) users := []User{} qs := r.URL.Query() // map[string][]string if len(qs["login"]) > 0 { srch := qs["login"][0] mutex.Lock() if api.db.Order("login"). Find(&users, "login = ?", srch).RecordNotFound() { mutex.Unlock() rest.Error(w, "No results.", 400) return } mutex.Unlock() } else { mutex.Lock() if api.db.Order("login").Find(&users).RecordNotFound() { mutex.Unlock() rest.Error(w, "Empty Table.", 400) return } mutex.Unlock() } // Create a slice of maps from users struct // to selectively copy database fields for display u := make([]map[string]interface{}, len(users)) for i := range users { u[i] = make(map[string]interface{}) u[i]["Id"] = users[i].Id u[i]["Login"] = users[i].Login u[i]["Forename"] = users[i].Forename u[i]["Surname"] = users[i].Surname u[i]["Enabled"] = users[i].Enabled u[i]["CreatedAt"] = users[i].CreatedAt u[i]["Email"] = users[i].Email } // Too much noise //api.LogActivity( session.Id, "Sent list of users" ) w.WriteJson(&u) }
func (api *Api) GetAllOutputLines(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Admin is not allowed if login == "admin" { rest.Error(w, "Not allowed", 400) return } //session := Session{} var errl error = nil //if session,errl = api.CheckLogin( login, guid ); errl != nil { if _, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) outputlines := []OutputLine{} qs := r.URL.Query() // Query string - map[string][]string if len(qs["job_id"]) > 0 { srch := qs["job_id"][0] if len(qs["top"]) > 0 { mutex.Lock() api.db.Order("serial").Limit(qs["top"][0]).Find(&outputlines, "job_id = ?", srch) mutex.Unlock() } else if len(qs["bottom"]) > 0 { mutex.Lock() // TODO last X lines but *in* order api.db.Order("serial desc").Limit(qs["bottom"][0]). Find(&outputlines, "job_id = ?", srch) mutex.Unlock() } else { mutex.Lock() api.db.Order("serial").Find(&outputlines, "job_id = ?", srch) mutex.Unlock() } } else { mutex.Lock() err := api.db.Order("serial").Find(&outputlines) mutex.Unlock() if err.Error != nil { if !err.RecordNotFound() { rest.Error(w, err.Error.Error(), 500) return } } } // Create a slice of maps from users struct // to selectively copy database fields for display u := make([]map[string]interface{}, len(outputlines)) for i := range outputlines { u[i] = make(map[string]interface{}) u[i]["Id"] = outputlines[i].Id u[i]["Serial"] = outputlines[i].Serial u[i]["JobId"] = outputlines[i].JobId u[i]["Text"] = outputlines[i].Text } // Too much noise //api.LogActivity( session.Id, "Sent list of users" ) w.WriteJson(&u) }
func (api *Api) GetAllJobs(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Admin is NOT allowed if login == "admin" { rest.Error(w, "Not allowed", 400) return } //session := Session{} var errl error = nil //if session,errl = api.CheckLogin( login, guid ); errl != nil { if _, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) jobs := []Job{} qs := r.URL.Query() // Query string - map[string][]string if len(qs["job_id"]) > 0 { srch := qs["job_id"][0] mutex.Lock() api.db.Order("id desc").Find(&jobs, "id = ?", srch) mutex.Unlock() /* if api.db.Order("id"). Find(&jobs, "id = ?", srch).RecordNotFound() { rest.Error(w, "No results.", 400) return } */ } else { // No results is not an error mutex.Lock() err := api.db.Order("id desc").Limit(200).Find(&jobs) mutex.Unlock() if err.Error != nil { if !err.RecordNotFound() { rest.Error(w, err.Error.Error(), 500) return } } } // Create a slice of maps from users struct // to selectively copy database fields for display u := make([]map[string]interface{}, len(jobs)) for i := range jobs { u[i] = make(map[string]interface{}) u[i]["Id"] = jobs[i].Id u[i]["ScriptId"] = jobs[i].ScriptId u[i]["UserLogin"] = jobs[i].UserLogin u[i]["Args"] = jobs[i].Args u[i]["EnvVars"] = jobs[i].EnvVars u[i]["Status"] = jobs[i].Status u[i]["StatusReason"] = jobs[i].StatusReason u[i]["StatusPercent"] = jobs[i].StatusPercent u[i]["CreatedAt"] = jobs[i].CreatedAt u[i]["UpdatedAt"] = jobs[i].UpdatedAt u[i]["Type"] = jobs[i].Type //u[i]["WorkerIp"] = jobs[i].WorkerIp //u[i]["WorkerPort"] = jobs[i].WorkerPort u[i]["EnvId"] = jobs[i].EnvId env := Env{} mutex.Lock() api.db.Model(&jobs[i]).Related(&env) mutex.Unlock() u[i]["EnvSysName"] = env.SysName u[i]["EnvDispName"] = env.DispName u[i]["WorkerUrl"] = env.WorkerUrl dc := Dc{} mutex.Lock() api.db.Model(&env).Related(&dc) mutex.Unlock() u[i]["DcId"] = dc.Id u[i]["DcSysName"] = dc.SysName u[i]["DcDispName"] = dc.DispName script := Script{} mutex.Lock() api.db.Model(&jobs[i]).Related(&script) mutex.Unlock() u[i]["ScriptName"] = script.Name u[i]["ScriptDesc"] = script.Desc u[i]["ScriptType"] = script.Type } // Too much noise //api.LogActivity( session.Id, "Sent list of users" ) w.WriteJson(&u) }
func (api *Api) AddJob(w rest.ResponseWriter, r *rest.Request) { // This function will return successfully in all cases, after // the sanity checks. Errors are saved in to the job here, or by // the worker. // // TODO: Delete jobs (and output_lines) over N days old here // logit(fmt.Sprintf("Connection from %s", r.RemoteAddr)) // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Admin is not allowed if login == "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already jobData := Job{} if err := r.DecodeJsonPayload(&jobData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if jobData.ScriptId == 0 { rest.Error(w, "Incorrect data format received.", 400) return } jobData.UserLogin = login // Sanity checks if jobData.ScriptId == 0 { txt := "Script ID must be specified" rest.Error(w, txt, 400) return } if jobData.EnvId == 0 { txt := "Environment ID must be specified" rest.Error(w, txt, 400) return } // Add job to DB saveJob := func() { mutex.Lock() if err := api.db.Save(&jobData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() } saveJob() // Get the associated environment data env := Env{} mutex.Lock() api.db.Model(&jobData).Related(&env) mutex.Unlock() // We need WorkerUrl and WorkerKey if env.WorkerUrl == "" || env.WorkerKey == "" { txt := "WorkerUrl or WorkerKey not set for this environment" jobData.Status = STATUS_ERROR jobData.StatusReason = txt saveJob() w.WriteJson(jobData) return } // Send the job to the worker script := Script{} saveJob() mutex.Lock() if err := api.db.Find(&script, jobData.ScriptId); err.Error != nil { mutex.Unlock() txt := fmt.Sprintf("Script ID %d not found ('%s')", jobData.ScriptId, err.Error.Error()) jobData.Status = STATUS_ERROR jobData.StatusReason = txt saveJob() w.WriteJson(jobData) //rest.Error(w, txt, 400) return } mutex.Unlock() // Jobsend definition type Jobsend struct { ScriptSource []byte ScriptName string Args string EnvVars string //NotifURL string JobID int64 Key string Type int64 // 1 - user job, 2 - system job } // Jobsend data data := Jobsend{ ScriptSource: script.Source, ScriptName: script.Name, JobID: jobData.Id, Key: env.WorkerKey, Args: jobData.Args, EnvVars: jobData.EnvVars, Type: jobData.Type, } // Encode jsondata, err := json.Marshal(data) if err != nil { txt := fmt.Sprintf("Error sending job to worker, JSON Encode:", err.Error()) jobData.Status = STATUS_ERROR jobData.StatusReason = txt saveJob() w.WriteJson(jobData) //rest.Error(w, txt, 400) return } // POST to worker resp, err := POST(jsondata, env.WorkerUrl, "jobs") //fmt.Printf("%+v", jsondata) if err != nil { txt := "Could not send job to worker. ('" + err.Error() + "')" jobData.Status = STATUS_ERROR jobData.StatusReason = txt saveJob() w.WriteJson(jobData) //rest.Error(w, txt, 400) return } defer resp.Body.Close() text := fmt.Sprintf("Added new job, %d.", jobData.Id) api.LogActivity(session.Id, text) w.WriteJson(jobData) }
func (api *Api) GenericPutEndpoint(w rest.ResponseWriter, r *rest.Request) { // Reserve the tcp plugin port now iport := api.Port() port := strconv.FormatInt(iport, 10) defer api.DecrementPort(iport) // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Admin is not allowed if login == "admin" { rest.Error(w, "Not allowed", 400) return } var errl error = nil if _, errl = api.CheckLogin(login, guid); errl != nil { logit(errl.Error()) rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // If the plugin isn't available try to compile it endpoint := r.PathParam("endpoint") subitem := r.PathParam("subitem") pluginFile := path.Join(config.GoPluginDir, endpoint, subitem) if err := api.CompilePlugin(w, pluginFile, endpoint, subitem); err != nil { return } // Run the Go plugin var reply []byte var err error if reply, err = api.RunPluginUsingRPC(w, r, pluginFile, port, "PUT"); err != nil { return // Just return full error was written in RunPluginUsingRPC } // Decode arbitrary JSON. Pull out the mandatory PluginReturn // and PluginError fields - all plugins send at least these. var generic interface{} json.Unmarshal(reply, &generic) genericReply := generic.(map[string]interface{}) var pluginReturn int64 var pluginError string for k, v := range genericReply { if k == "PluginReturn" { pluginReturn = int64(v.(float64)) } if k == "PluginError" { pluginError = v.(string) } } // Return, 0 - success, 1 - error if pluginReturn == 1 { txt := fmt.Sprintf("Plugin returned error. %s", pluginError) rest.Error(w, txt, 400) logit(txt) return } // Response is already json encoded so send it raw w.(http.ResponseWriter).Write(reply) // Too much noise //api.LogActivity( session.Id, "Sent list of users" ) }
func (api *Api) AddEnv(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already envData := Env{} if err := r.DecodeJsonPayload(&envData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if len(envData.SysName) == 0 { rest.Error(w, "Incorrect data format received.", 400) return } env := Env{} mutex.Lock() if !api.db.Find(&env, "sys_name = ? and dc_id = ?", envData.SysName, envData.DcId).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Add env mutex.Lock() if err := api.db.Save(&envData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() dc := Dc{} mutex.Lock() api.db.First(&dc, envData.DcId) mutex.Unlock() text := fmt.Sprintf("Added new environment '%s->%s'.", dc.SysName, envData.SysName) api.LogActivity(session.Id, text) w.WriteJson(envData) }