package handler import ( "context" "database/sql" "encoding/json" "errors" "fmt" "mocksnow/server/models" "net/http" "strconv" "strings" ) // GetIncident responds to the link generated in the response to a New Snow func (h *Handler) GetIncident(w http.ResponseWriter, r *http.Request) { h.Logger.Debug("GetIncident Request received", "method", r.Method, "url", r.URL, "path", r.URL.Path, "query", r.URL.Query()) ctx := r.Context() path := r.URL.Path // Expected format: /api/now/table/incident/{id} parts := strings.Split(path, "/") h.Logger.Debug("Request path", "parts", parts) // Parse and write query parameters query := r.URL.Query() if len(query) == 0 { h.Logger.Debug("No query parameters.") } else { //fmt.Fprintln(w, "Query parameters:") for key, values := range query { for _, value := range values { h.Logger.Debug("Query Paramater", "key", key, "value", value) } } } if len(parts) == 6 && strings.HasPrefix(path, "/api/now/table/incident/") { // Handle the specific 'number' query parameter number := query.Get("number") active := query.Get("active") if number != "" { h.Logger.Debug("GetIncident called for specific incident number", "number", number) b, err := h.getSingleIncident(number, ctx) if err != nil { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) json.NewEncoder(w).Encode(map[string]string{ "status": "ERROR", "message": fmt.Sprintf("%s", err), }) return } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) fmt.Fprintf(w, string(b)) return // Query record from database and return that } else if active == "true" { // Return list of all incidents h.Logger.Debug("GetIncident called for list all incidents") responseList := make([]models.SingleIncidentResponse, 0) incList, err := h.Database.Queries().ListIncidents(ctx) if err != nil { if errors.Is(err, sql.ErrNoRows) { h.Logger.Debug("No incidents found") w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) fmt.Fprintf(w, "{\"result\": [{}]}") return } else { h.Logger.Error("", "error", err) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) json.NewEncoder(w).Encode(map[string]string{ "status": "ERROR", "message": fmt.Sprintf("Unable to query database for all incidents: '%s'", err), }) return } } wknList, err := h.Database.Queries().ListWorkNotes(ctx) if err != nil { if errors.Is(err, sql.ErrNoRows) { h.Logger.Debug("No incident worknotes found") } else { h.Logger.Error("", "error", err) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) json.NewEncoder(w).Encode(map[string]string{ "status": "ERROR", "message": fmt.Sprintf("Unable to query database for incident worknotes: '%s'", err), }) return } } // convert incList into json output for _, inc := range incList { var wkn []string // get worknotes for this incident for _, note := range wknList { if note.IncidentNumber == inc.IncidentNumber.String { wkn = append(wkn, note.Note.String) } } // transform inc to SingleIncidentResponse r := models.SingleIncidentResponse{ Number: inc.IncidentNumber.String, SysID: inc.SysID.String, IncidentState: strconv.FormatInt(inc.State.Int64, 10), State: strconv.FormatInt(inc.State.Int64, 10), Impact: strconv.FormatInt(inc.Impact.Int64, 10), Urgency: strconv.FormatInt(inc.Urgency.Int64, 10), ShortDescription: inc.ShortDescription.String, AssignedTo: inc.AssignedTo.String, Category: inc.Category.String, Subcategory: inc.SubCategory.String, CommentsAndWorkNotes: strings.Join(wkn, "\n\n"), // TODO } // add to responseList h.Logger.Debug("Adding incident to active inc response list", "incident", r) responseList = append(responseList, r) } // marshal struct into json and return wrappedList := models.MultipleIncidentResponse{ Result: responseList, } prettyPrint(wrappedList) b, err := json.Marshal(wrappedList) if err != nil { h.Logger.Error("Unable to convert database records into json", "error", err) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) json.NewEncoder(w).Encode(map[string]string{ "status": "ERROR", "message": fmt.Sprintf("Unable to convert database records into json: '%s'", err), }) return } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) fmt.Fprintf(w, string(b)) return } else { // Requested a single incident id := parts[5] // Extract {id} h.Logger.Debug("GetIncident called for specific incident", "id", id) b, err := h.getSingleIncident(id, ctx) if err != nil { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) json.NewEncoder(w).Encode(map[string]string{ "status": "ERROR", "message": fmt.Sprintf("%s", err), }) return } w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) fmt.Fprintf(w, string(b)) return } } else if strings.HasPrefix(path, "/api/now/table/incident") { h.Logger.Debug("GetIncident called for list of incidents") w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) fmt.Fprintf(w, "{\"result\": [{}]}") } // TODO - provide an incident list if necessary } func (h *Handler) getSingleIncident(number string, ctx context.Context) ([]byte, error) { var b []byte var wkn []string incResult, err := h.Database.Queries().GetIncident(ctx, nullStr(number)) if err != nil { if errors.Is(err, sql.ErrNoRows) { h.Logger.Debug("No incident record found", "number", number) } else { h.Logger.Error("Unable to query database for incident number", "number", number, "error", err) return b, err } } wknotes, err := h.Database.Queries().GetIncidentWorkNotes(ctx, number) if err != nil { if errors.Is(err, sql.ErrNoRows) { h.Logger.Debug("No incident worknotes found", "number", number) } else { h.Logger.Error("Unable to query database for incident worknotes", "number", number, "error", err) return b, err } } for _, note := range wknotes { wkn = append(wkn, note.Note.String) } // convert from database resposne to expected json format r := models.SingleIncidentResponse{ Number: incResult.IncidentNumber.String, SysID: incResult.SysID.String, IncidentState: strconv.FormatInt(incResult.State.Int64, 10), State: strconv.FormatInt(incResult.State.Int64, 10), Impact: strconv.FormatInt(incResult.Impact.Int64, 10), Urgency: strconv.FormatInt(incResult.Urgency.Int64, 10), ShortDescription: incResult.ShortDescription.String, AssignedTo: incResult.AssignedTo.String, Category: incResult.Category.String, Subcategory: incResult.SubCategory.String, CommentsAndWorkNotes: strings.Join(wkn, "\n\n"), // TODO } wrappedList := models.MultipleIncidentResponse{ Result: []models.SingleIncidentResponse{r}, } prettyPrint(wrappedList) b, err = json.Marshal(wrappedList) if err != nil { h.Logger.Error("Unable to convert database record into json", "error", err) return b, err } return b, nil }