func RedoTaskHandler(prototype Task, w http.ResponseWriter, r *http.Request) { if !ctfeutil.UserHasEditRights(r) { skutil.ReportError(w, r, fmt.Errorf("Must have google or chromium account to redo tasks"), "") return } w.Header().Set("Content-Type", "application/json") vars := struct{ Id int64 }{} if err := json.NewDecoder(r.Body).Decode(&vars); err != nil { skutil.ReportError(w, r, err, "Failed to parse redo request") return } defer skutil.Close(r.Body) rowQuery := fmt.Sprintf("SELECT * FROM %s WHERE id = ? AND ts_completed IS NOT NULL", prototype.TableName()) binds := []interface{}{vars.Id} data, err := prototype.Select(rowQuery, binds...) if err != nil { skutil.ReportError(w, r, err, "Unable to find requested task.") return } tasks := AsTaskSlice(data) if len(tasks) != 1 { skutil.ReportError(w, r, err, "Unable to find requested task.") return } addTaskVars := tasks[0].GetPopulatedAddTaskVars() // Replace the username with the new requester. addTaskVars.GetAddTaskCommonVars().Username = login.LoggedInAs(r) if _, err := AddTask(addTaskVars); err != nil { skutil.ReportError(w, r, err, "Could not redo the task.") return } }
func AddTaskHandler(w http.ResponseWriter, r *http.Request, task AddTaskVars) { if !ctfeutil.UserHasEditRights(r) { skutil.ReportError(w, r, fmt.Errorf("Must have google or chromium account to add tasks"), "") return } if task.IsAdminTask() && !ctfeutil.UserHasAdminRights(r) { skutil.ReportError(w, r, fmt.Errorf("Must be admin to add admin tasks; contact rmistry@"), "") return } w.Header().Set("Content-Type", "application/json") if err := json.NewDecoder(r.Body).Decode(&task); err != nil { skutil.ReportError(w, r, err, fmt.Sprintf("Failed to add %T task", task)) return } defer skutil.Close(r.Body) task.GetAddTaskCommonVars().Username = login.LoggedInAs(r) task.GetAddTaskCommonVars().TsAdded = ctutil.GetCurrentTs() if len(task.GetAddTaskCommonVars().Username) > 255 { skutil.ReportError(w, r, fmt.Errorf("Username is too long, limit 255 bytes"), "") return } if _, err := AddTask(task); err != nil { skutil.ReportError(w, r, err, fmt.Sprintf("Failed to insert %T task", task)) return } }
func DeleteTaskHandler(prototype Task, w http.ResponseWriter, r *http.Request) { if !ctfeutil.UserHasEditRights(r) { skutil.ReportError(w, r, fmt.Errorf("Must have google or chromium account to delete tasks"), "") return } w.Header().Set("Content-Type", "application/json") vars := struct{ Id int64 }{} if err := json.NewDecoder(r.Body).Decode(&vars); err != nil { skutil.ReportError(w, r, err, "Failed to parse delete request") return } defer skutil.Close(r.Body) requireUsernameMatch := !ctfeutil.UserHasAdminRights(r) username := login.LoggedInAs(r) // Put all conditions in delete request; only if the delete fails, do a select to determine the cause. deleteQuery := fmt.Sprintf("DELETE FROM %s WHERE id = ? AND (ts_started IS NULL OR ts_completed IS NOT NULL)", prototype.TableName()) binds := []interface{}{vars.Id} if requireUsernameMatch { deleteQuery += " AND username = ?" binds = append(binds, username) } result, err := db.DB.Exec(deleteQuery, binds...) if err != nil { skutil.ReportError(w, r, err, "Failed to delete") return } // Check result to ensure that the row was deleted. if rowsDeleted, _ := result.RowsAffected(); rowsDeleted == 1 { glog.Infof("%s task with ID %d deleted by %s", prototype.GetTaskName(), vars.Id, username) return } // The code below determines the reason that no rows were deleted. rowQuery := fmt.Sprintf("SELECT * FROM %s WHERE id = ?", prototype.TableName()) data, err := prototype.Select(rowQuery, vars.Id) if err != nil { skutil.ReportError(w, r, err, "Unable to validate request.") return } tasks := AsTaskSlice(data) if len(tasks) != 1 { // Row already deleted; return success. return } if ok, err := canDeleteTask(tasks[0], r); !ok { skutil.ReportError(w, r, err, "") } else { skutil.ReportError(w, r, fmt.Errorf("Failed to delete; reason unknown"), "") return } }