// GET: /user func (cr *UserController) ReadMany(cx *goweb.Context) { // Log Request and check for Auth LogRequest(cx.Request) u, err := AuthenticateRequest(cx.Request) if err != nil { if err.Error() == e.NoAuth || err.Error() == e.UnAuth { cx.RespondWithError(http.StatusUnauthorized) return } else { log.Error("Err@user_Read: " + err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } } if u.Admin { users := user.Users{} user.AdminGet(&users) if len(users) > 0 { cx.RespondWithData(users) return } else { cx.RespondWithNotFound() return } } else { cx.RespondWithError(http.StatusUnauthorized) return } }
// GET: /client/{id} func (cr *ClientController) Read(id string, cx *goweb.Context) { LogRequest(cx.Request) // Gather query params query := &Query{list: cx.Request.URL.Query()} if query.Has("heartbeat") { client, err := queueMgr.ClientHeartBeat(id) if err != nil { cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) } else { cx.RespondWithData(client.Id) } return } client, err := queueMgr.GetClient(id) if err != nil { if err.Error() == e.ClientNotFound { cx.RespondWithErrorMessage(e.ClientNotFound, http.StatusBadRequest) } else { Log.Error("Error in GET client:" + err.Error()) cx.RespondWithError(http.StatusBadRequest) } return } cx.RespondWithData(client) }
// DELETE: /job/{id} func (cr *JobController) Delete(id string, cx *goweb.Context) { LogRequest(cx.Request) if err := queueMgr.DeleteJob(id); err != nil { cx.RespondWithErrorMessage("fail to delete job: "+id, http.StatusBadRequest) return } cx.RespondWithData("job deleted: " + id) return }
// GET: /queue // get status from queue manager func (cr *QueueController) ReadMany(cx *goweb.Context) { LogRequest(cx.Request) // Gather query params // query := &Query{list: cx.Request.URL.Query()} msg := queueMgr.ShowStatus() cx.RespondWithData(msg) }
func ResourceDescription(cx *goweb.Context) { LogRequest(cx.Request) r := resource{ R: []string{"job", "work", "client", "queue"}, U: apiUrl(cx) + "/", D: siteUrl(cx) + "/", C: conf.ADMIN_EMAIL, I: "AWE", T: "AWE", } cx.WriteResponse(r, 200) }
func ResourceDescription(cx *goweb.Context) { LogRequest(cx.Request) r := resource{ R: []string{"node", "user"}, U: apiUrl(cx) + "/", D: siteUrl(cx) + "/", C: conf.ADMIN_EMAIL, I: "Shock", T: "Shock", } cx.WriteResponse(r, 200) }
// DELETE: /job?suspend func (cr *JobController) DeleteMany(cx *goweb.Context) { LogRequest(cx.Request) // Gather query params query := &Query{list: cx.Request.URL.Query()} if query.Has("suspend") { num := queueMgr.DeleteSuspendedJobs() cx.RespondWithData(fmt.Sprintf("deleted %d suspended jobs", num)) } else { cx.RespondWithError(http.StatusNotImplemented) } return }
func handleAuthError(err error, cx *goweb.Context) { switch err.Error() { case e.MongoDocNotFound: cx.RespondWithErrorMessage("Invalid username or password", http.StatusBadRequest) return // case e.InvalidAuth: // cx.RespondWithErrorMessage("Invalid Authorization header", http.StatusBadRequest) // return } Log.Error("Error at Auth: " + err.Error()) cx.RespondWithError(http.StatusInternalServerError) return }
func PreAuthRequest(cx *goweb.Context) { LogRequest(cx.Request) id := cx.PathParams["id"] if p, err := store.LoadPreAuth(id); err != nil { if err.Error() == e.MongoDocNotFound { cx.RespondWithNotFound() } else { cx.RespondWithError(http.StatusInternalServerError) log.Error("err:@preAuth load: " + err.Error()) } return } else { if node, err := store.LoadNodeUnauth(p.NodeId); err == nil { switch p.Type { case "download": filename := node.Id if fn, has := p.Options["filename"]; has { filename = fn } streamDownload(cx, node, filename) store.DeletePreAuth(id) return default: cx.RespondWithError(http.StatusInternalServerError) } } else { cx.RespondWithError(http.StatusInternalServerError) log.Error("err:@preAuth loadnode: " + err.Error()) } } return }
// PUT: /work/{id} -> status update func (cr *WorkController) Update(id string, cx *goweb.Context) { // Log Request and check for Auth LogRequest(cx.Request) // Gather query params query := &Query{list: cx.Request.URL.Query()} if query.Has("status") && query.Has("client") { //notify execution result: "done" or "fail" notice := core.Notice{WorkId: id, Status: query.Value("status"), ClientId: query.Value("client")} defer queueMgr.NotifyWorkStatus(notice) if query.Has("report") { // if "report" is specified in query, parse performance statistics _, files, err := ParseMultipartForm(cx.Request) if err != nil { Log.Error("err@workContoller_Update_ParseMultipartForm: " + err.Error()) cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) return } if _, ok := files["perf"]; !ok { Log.Error("err@workContoller_Update: no perf file uploaded") cx.RespondWithErrorMessage("no perf file uploaded", http.StatusBadRequest) return } if err := queueMgr.FinalizeWorkPerf(id, files["perf"].Path); err != nil { Log.Error("err@workContoller_Update_FinalizeWorkPerf: " + err.Error()) cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) return } } } cx.RespondWithData("ok") return }
// GET: /work/{id} // get a workunit by id, read-only func (cr *WorkController) Read(id string, cx *goweb.Context) { LogRequest(cx.Request) // Load workunit by id workunit, err := queueMgr.GetWorkById(id) if err != nil { if err.Error() != e.QueueEmpty { Log.Error("Err@work_Read:QueueMgr.GetWorkById(): " + err.Error()) } cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) return } // Base case respond with workunit in json cx.RespondWithData(workunit) return }
func ResourceDescription(cx *goweb.Context) { LogRequest(cx.Request) host := "" if strings.Contains(cx.Request.Host, ":") { split := strings.Split(cx.Request.Host, ":") host = split[0] } else { host = cx.Request.Host } r := resource{ R: []string{"job", "work", "client"}, U: "http://" + host + ":" + fmt.Sprint(conf.API_PORT) + "/", D: "http://" + host + ":" + fmt.Sprint(conf.SITE_PORT) + "/", C: conf.ADMIN_EMAIL, I: "AWE", T: "AWE", } cx.WriteResponse(r, 200) }
// GET: /client func (cr *ClientController) ReadMany(cx *goweb.Context) { LogRequest(cx.Request) clients := queueMgr.GetAllClients() if len(clients) == 0 { cx.RespondWithErrorMessage(e.ClientNotFound, http.StatusBadRequest) return } query := &Query{list: cx.Request.URL.Query()} filtered := []*core.Client{} if query.Has("busy") { for _, client := range clients { if len(client.Current_work) > 0 { filtered = append(filtered, client) } } } else { filtered = clients } cx.RespondWithData(filtered) }
func streamDownload(cx *goweb.Context, node *store.Node, filename string) { query := &Query{list: cx.Request.URL.Query()} nf, err := node.FileReader() if err != nil { // File not found or some sort of file read error. // Probably deserves more checking log.Error("err:@preAuth node.FileReader: " + err.Error()) cx.RespondWithError(http.StatusBadRequest) return } if query.Has("filename") { filename = query.Value("filename") } s := &streamer{rs: []store.SectionReader{nf}, ws: cx.ResponseWriter, contentType: "application/octet-stream", filename: filename, size: node.File.Size, filter: nil} err = s.stream() if err != nil { // causes "multiple response.WriteHeader calls" error but better than no response cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) log.Error("err:@preAuth: s.stream: " + err.Error()) } }
// POST: /client func (cr *ClientController) Create(cx *goweb.Context) { // Log Request and check for Auth LogRequest(cx.Request) // Parse uploaded form _, files, err := ParseMultipartForm(cx.Request) if err != nil { if err.Error() != "request Content-Type isn't multipart/form-data" { Log.Error("Error parsing form: " + err.Error()) cx.RespondWithError(http.StatusBadRequest) return } } client, err := queueMgr.RegisterNewClient(files) if err != nil { msg := "Error in registering new client:" + err.Error() Log.Error(msg) cx.RespondWithErrorMessage(msg, http.StatusBadRequest) return } //log event about client registration (CR) Log.Event(EVENT_CLIENT_REGISTRATION, "clientid="+client.Id+";name="+client.Name) cx.RespondWithData(client) return }
// PUT: /client/{id} -> status update func (cr *ClientController) Update(id string, cx *goweb.Context) { LogRequest(cx.Request) client, err := queueMgr.ClientHeartBeat(id) if err != nil { if err.Error() == e.ClientNotFound { cx.RespondWithErrorMessage(e.ClientNotFound, http.StatusBadRequest) } else { Log.Error("Error in handle client heartbeat:" + err.Error()) cx.RespondWithError(http.StatusBadRequest) } return } cx.RespondWithData(client) }
// GET: /work // checkout a workunit with earliest submission time // to-do: to support more options for workunit checkout func (cr *WorkController) ReadMany(cx *goweb.Context) { // Gather query params query := &Query{list: cx.Request.URL.Query()} if !query.Has("client") { //view workunits var workunits []*core.Workunit if query.Has("state") { workunits = queueMgr.ShowWorkunits(query.Value("state")) } else { workunits = queueMgr.ShowWorkunits("") } cx.RespondWithData(workunits) return } //checkout a workunit in FCFS order clientid := query.Value("client") workunits, err := queueMgr.CheckoutWorkunits("FCFS", clientid, 1) if err != nil { if err.Error() != e.QueueEmpty && err.Error() != e.NoEligibleWorkunitFound { Log.Error("Err@work_ReadMany:QueueMgr.GetWorkByFCFS(): " + err.Error()) } cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) return } //log access info only when the queue is not empty, save some log LogRequest(cx.Request) //log event about workunit checkout (WO) workids := []string{} for _, work := range workunits { workids = append(workids, work.Id) } Log.Event(EVENT_WORK_CHECKOUT, "workids="+strings.Join(workids, ","), "clientid="+clientid) // Base case respond with node in json cx.RespondWithData(workunits[0]) return }
// GET: /job/{id} func (cr *JobController) Read(id string, cx *goweb.Context) { LogRequest(cx.Request) // Load job by id job, err := core.LoadJob(id) if err != nil { if err.Error() == e.MongoDocNotFound { cx.RespondWithNotFound() return } else { // In theory the db connection could be lost between // checking user and load but seems unlikely. Log.Error("Err@job_Read:LoadJob: " + id + ":" + err.Error()) cx.RespondWithErrorMessage("job not found:"+id, http.StatusBadRequest) return } } // Base case respond with job in json cx.RespondWithData(job) return }
// DELETE: /node func (cr *Controller) DeleteMany(cx *goweb.Context) { request.Log(cx.Request) cx.RespondWithError(http.StatusNotImplemented) }
// Options: /node func (cr *Controller) Options(cx *goweb.Context) { request.Log(cx.Request) cx.RespondWithOK() return }
// PUT: /node func (cr *NodeController) UpdateMany(cx *goweb.Context) { LogRequest(cx.Request) cx.RespondWithError(http.StatusNotImplemented) }
// POST: /node func (cr *NodeController) Create(cx *goweb.Context) { // Log Request and check for Auth LogRequest(cx.Request) u, err := AuthenticateRequest(cx.Request) if err != nil && err.Error() != e.NoAuth { handleAuthError(err, cx) return } // Fake public user if u == nil { if conf.ANON_WRITE { u = &user.User{Uuid: ""} } else { cx.RespondWithErrorMessage(e.NoAuth, http.StatusUnauthorized) return } } // Parse uploaded form params, files, err := ParseMultipartForm(cx.Request) if err != nil { // If not multipart/form-data it will create an empty node. // TODO: create another request parser for non-multipart request // to handle this cleaner. if err.Error() == "request Content-Type isn't multipart/form-data" { node, err := store.CreateNodeUpload(u, params, files) if err != nil { log.Error("Error at create empty: " + err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } if node == nil { // Not sure how you could get an empty node with no error // Assume it's the user's fault cx.RespondWithError(http.StatusBadRequest) return } else { cx.RespondWithData(node) return } } else { // Some error other than request encoding. Theoretically // could be a lost db connection between user lookup and parsing. // Blame the user, Its probaby their fault anyway. log.Error("Error parsing form: " + err.Error()) cx.RespondWithError(http.StatusBadRequest) return } } // Create node node, err := store.CreateNodeUpload(u, params, files) if err != nil { log.Error("err " + err.Error()) cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) return } cx.RespondWithData(node) return }
// PUT: /node/{id} -> multipart-form func (cr *NodeController) Update(id string, cx *goweb.Context) { // Log Request and check for Auth LogRequest(cx.Request) u, err := AuthenticateRequest(cx.Request) if err != nil && err.Error() != e.NoAuth { handleAuthError(err, cx) return } // Gather query params query := &Query{list: cx.Request.URL.Query()} // Fake public user if u == nil { u = &user.User{Uuid: ""} } node, err := store.LoadNode(id, u.Uuid) if err != nil { if err.Error() == e.UnAuth { cx.RespondWithError(http.StatusUnauthorized) return } else if err.Error() == e.MongoDocNotFound { cx.RespondWithNotFound() return } else { // In theory the db connection could be lost between // checking user and load but seems unlikely. log.Error("Err@node_Update:LoadNode: " + err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } } if query.Has("index") { if !node.HasFile() { cx.RespondWithErrorMessage("node file empty", http.StatusBadRequest) return } if query.Value("index") == "bai" { //bam index is created by the command-line tool samtools if ext := node.FileExt(); ext == ".bam" { if err := CreateBamIndex(node.FilePath()); err != nil { cx.RespondWithErrorMessage("Error while creating bam index", http.StatusBadRequest) return } return } else { cx.RespondWithErrorMessage("Index type bai requires .bam file", http.StatusBadRequest) return } } newIndexer := indexer.Indexer(query.Value("index")) f, _ := os.Open(node.FilePath()) defer f.Close() idxer := newIndexer(f) err := idxer.Create() if err != nil { log.Error("err " + err.Error()) } err = idxer.Dump(node.IndexPath() + "/record") if err != nil { cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) return } else { cx.RespondWithOK() return } } else { params, files, err := ParseMultipartForm(cx.Request) if err != nil { log.Error("err " + err.Error()) cx.RespondWithError(http.StatusBadRequest) return } err = node.Update(params, files) if err != nil { errors := []string{e.FileImut, e.AttrImut, "parts cannot be less than 1"} for e := range errors { if err.Error() == errors[e] { cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) return } } log.Error("err " + err.Error()) cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) return } cx.RespondWithData(node) } return }
// Options: /node func (cr *NodeController) Options(cx *goweb.Context) { LogRequest(cx.Request) cx.RespondWithOK() return }
// GET: /node // To do: // - Iterate node queries func (cr *NodeController) ReadMany(cx *goweb.Context) { // Log Request and check for Auth LogRequest(cx.Request) u, err := AuthenticateRequest(cx.Request) if err != nil && err.Error() != e.NoAuth { handleAuthError(err, cx) return } // Gather query params query := &Query{list: cx.Request.URL.Query()} // Setup query and nodes objects q := bson.M{} nodes := store.Nodes{} if u != nil { // Admin sees all if !u.Admin { q["$or"] = []bson.M{bson.M{"acl.read": []string{}}, bson.M{"acl.read": u.Uuid}} } } else { if conf.ANON_READ { // select on only nodes with no read rights set q["acl.read"] = []string{} } else { cx.RespondWithErrorMessage(e.NoAuth, http.StatusUnauthorized) return } } // Gather params to make db query. Do not include the // following list. skip := map[string]int{"limit": 1, "skip": 1, "query": 1} if query.Has("query") { for key, val := range query.All() { _, s := skip[key] if !s { q[fmt.Sprintf("attributes.%s", key)] = val[0] } } } // Limit and skip. Set default if both are not specified if query.Has("limit") || query.Has("skip") { var lim, off int if query.Has("limit") { lim, _ = strconv.Atoi(query.Value("limit")) } else { lim = 100 } if query.Has("skip") { off, _ = strconv.Atoi(query.Value("skip")) } else { off = 0 } // Get nodes from db err := nodes.GetAllLimitOffset(q, lim, off) if err != nil { log.Error("err " + err.Error()) cx.RespondWithError(http.StatusBadRequest) return } } else { // Get nodes from db err := nodes.GetAll(q) if err != nil { log.Error("err " + err.Error()) cx.RespondWithError(http.StatusBadRequest) return } } cx.RespondWithData(nodes) return }
// GET: /node/{id} // ToDo: clean up this function. About to get unmanageable func (cr *NodeController) Read(id string, cx *goweb.Context) { // Log Request and check for Auth LogRequest(cx.Request) u, err := AuthenticateRequest(cx.Request) if err != nil && err.Error() != e.NoAuth { handleAuthError(err, cx) return } // Fake public user if u == nil { if conf.ANON_READ { u = &user.User{Uuid: ""} } else { cx.RespondWithErrorMessage(e.NoAuth, http.StatusUnauthorized) return } } // Gather query params query := &Query{list: cx.Request.URL.Query()} var fFunc filter.FilterFunc = nil if query.Has("filter") { if filter.Has(query.Value("filter")) { fFunc = filter.Filter(query.Value("filter")) } } // Load node and handle user unauthorized node, err := store.LoadNode(id, u.Uuid) if err != nil { if err.Error() == e.UnAuth { cx.RespondWithError(http.StatusUnauthorized) return } else if err.Error() == e.MongoDocNotFound { cx.RespondWithNotFound() return } else { // In theory the db connection could be lost between // checking user and load but seems unlikely. log.Error("Err@node_Read:LoadNode: " + err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } } // Switch though param flags // ?download=1 if query.Has("download") { if !node.HasFile() { cx.RespondWithErrorMessage("File not found", http.StatusBadRequest) return } //_, chunksize := // ?index=foo if query.Has("index") { //handling bam file if query.Value("index") == "bai" { s := &streamer{rs: []store.SectionReader{}, ws: cx.ResponseWriter, contentType: "application/octet-stream", filename: node.Id, size: node.File.Size, filter: fFunc} var region string if query.Has("region") { //retrieve alingments overlapped with specified region region = query.Value("region") } argv, err := ParseSamtoolsArgs(query) if err != nil { cx.RespondWithErrorMessage("Invaid args in query url", http.StatusBadRequest) return } err = s.stream_samtools(node.FilePath(), region, argv...) if err != nil { cx.RespondWithErrorMessage("error while involking samtools", http.StatusBadRequest) return } return } // if forgot ?part=N if !query.Has("part") { cx.RespondWithErrorMessage("Index parameter requires part parameter", http.StatusBadRequest) return } // open file r, err := node.FileReader() if err != nil { log.Error("Err@node_Read:Open: " + err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } // load index idx, err := node.Index(query.Value("index")) if err != nil { cx.RespondWithErrorMessage("Invalid index", http.StatusBadRequest) return } if idx.Type() == "virtual" { csize := int64(1048576) if query.Has("chunksize") { csize, err = strconv.ParseInt(query.Value("chunksize"), 10, 64) if err != nil { cx.RespondWithErrorMessage("Invalid chunksize", http.StatusBadRequest) return } } idx.Set(map[string]interface{}{"ChunkSize": csize}) } var size int64 = 0 s := &streamer{rs: []store.SectionReader{}, ws: cx.ResponseWriter, contentType: "application/octet-stream", filename: node.Id, filter: fFunc} for _, p := range query.List("part") { pos, length, err := idx.Part(p) if err != nil { cx.RespondWithErrorMessage("Invalid index part", http.StatusBadRequest) return } size += length s.rs = append(s.rs, io.NewSectionReader(r, pos, length)) } s.size = size err = s.stream() if err != nil { // causes "multiple response.WriteHeader calls" error but better than no response cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) log.Error("err: " + err.Error()) } } else { //!query.Has("index") nf, err := node.FileReader() if err != nil { // File not found or some sort of file read error. // Probably deserves more checking log.Error("err " + err.Error()) cx.RespondWithError(http.StatusBadRequest) return } s := &streamer{rs: []store.SectionReader{nf}, ws: cx.ResponseWriter, contentType: "application/octet-stream", filename: node.Id, size: node.File.Size, filter: fFunc} err = s.stream() if err != nil { // causes "multiple response.WriteHeader calls" error but better than no response cx.RespondWithErrorMessage(err.Error(), http.StatusBadRequest) log.Error("err " + err.Error()) } } return } else if query.Has("pipe") { cx.RespondWithError(http.StatusNotImplemented) } else if query.Has("list") { cx.RespondWithError(http.StatusNotImplemented) } else { // Base case respond with node in json cx.RespondWithData(node) } }
// DELETE: /node/{id} func (cr *NodeController) Delete(id string, cx *goweb.Context) { LogRequest(cx.Request) cx.RespondWithError(http.StatusNotImplemented) }
// GET: /user/{id} func (cr *UserController) Read(id string, cx *goweb.Context) { // Log Request and check for Auth LogRequest(cx.Request) u, err := AuthenticateRequest(cx.Request) if err != nil { if err.Error() == e.NoAuth || err.Error() == e.UnAuth { cx.RespondWithError(http.StatusUnauthorized) return } else { log.Error("Err@user_Read: " + err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } } // Any user can access their own user info. Only admins can // access other's info if u.Uuid == id { cx.RespondWithData(u) return } else if u.Admin { nu, err := user.FindByUuid(id) if err != nil { if err.Error() == e.MongoDocNotFound { cx.RespondWithNotFound() return } else { log.Error("Err@user_Read:Admin: " + err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } } cx.RespondWithData(nu) return } else { // Not sure how we could end up here but its probably the // user's fault cx.RespondWithError(http.StatusBadRequest) return } }
// POST: /user // To create a new user make a empty POST to /user with user:password // Basic Auth encoded in the header. Return new user object. func (cr *UserController) Create(cx *goweb.Context) { // Log Request LogRequest(cx.Request) if _, ok := cx.Request.Header["Authorization"]; !ok { cx.RespondWithError(http.StatusUnauthorized) return } header := cx.Request.Header.Get("Authorization") tmpAuthArray := strings.Split(header, " ") authValues, err := base64.URLEncoding.DecodeString(tmpAuthArray[1]) if err != nil { err = errors.New("Failed to decode encoded auth settings in http request.") cx.RespondWithError(http.StatusBadRequest) return } authValuesArray := strings.Split(string(authValues), ":") if conf.ANON_CREATEUSER == false && len(authValuesArray) != 4 { if len(authValuesArray) == 2 { cx.RespondWithErrorMessage(e.UnAuth, http.StatusUnauthorized) return } else { cx.RespondWithError(http.StatusBadRequest) return } } name := authValuesArray[0] passwd := authValuesArray[1] admin := false if len(authValuesArray) == 4 { if authValuesArray[2] != fmt.Sprint(conf.SECRET_KEY) { cx.RespondWithErrorMessage(e.UnAuth, http.StatusUnauthorized) return } else if authValuesArray[3] == "true" { admin = true } } u, err := user.New(name, passwd, admin) if err != nil { // Duplicate key check if e.MongoDupKeyRegex.MatchString(err.Error()) { log.Error("Err@user_Create: duplicate key error") cx.RespondWithErrorMessage("Username not available", http.StatusBadRequest) return } else { log.Error("Err@user_Create: " + err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } } cx.RespondWithData(u) return }
// DELETE: /node/{id} func (cr *NodeController) Delete(id string, cx *goweb.Context) { LogRequest(cx.Request) u, err := AuthenticateRequest(cx.Request) if err != nil && err.Error() != e.NoAuth { handleAuthError(err, cx) return } if u == nil { cx.RespondWithErrorMessage(e.NoAuth, http.StatusUnauthorized) return } // Load node and handle user unauthorized node, err := store.LoadNode(id, u.Uuid) if err != nil { if err.Error() == e.UnAuth { cx.RespondWithError(http.StatusUnauthorized) return } else if err.Error() == e.MongoDocNotFound { cx.RespondWithNotFound() return } else { // In theory the db connection could be lost between // checking user and load but seems unlikely. log.Error("Err@node_Read:Delete: " + err.Error()) cx.RespondWithError(http.StatusInternalServerError) return } } if err := node.Delete(); err == nil { cx.RespondWithOK() return } else { log.Error("Err@node_Delet:Delete: " + err.Error()) cx.RespondWithError(http.StatusInternalServerError) } return }