func PutStatus()

in traffic_ops/traffic_ops_golang/deliveryservice/request/status.go [104:242]


func PutStatus(w http.ResponseWriter, r *http.Request) {
	inf, userErr, sysErr, errCode := api.NewInfo(r, []string{"id"}, []string{"id"})
	tx := inf.Tx.Tx
	if userErr != nil || sysErr != nil {
		api.HandleErr(w, r, tx, errCode, userErr, sysErr)
		return
	}
	defer inf.Close()

	// Middleware should've already handled this, so idk why this is a pointer at all tbh
	if inf.Version == nil {
		middleware.NotImplementedHandler().ServeHTTP(w, r)
		return
	}

	if inf.User == nil {
		sysErr = errors.New("got api info with no user")
		api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, sysErr)
		return
	}

	var req tc.StatusChangeRequest
	if err := api.Parse(r.Body, tx, &req); err != nil {
		api.HandleErr(w, r, tx, http.StatusBadRequest, err, nil)
		return
	}

	dsrID := inf.IntParams["id"]

	var dsr tc.DeliveryServiceRequestV5
	if err := inf.Tx.QueryRowx(selectQuery+"WHERE r.id=$1", dsrID).StructScan(&dsr); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			errCode = http.StatusNotFound
			userErr = fmt.Errorf("no such Delivery Service Request: %d", dsrID)
			sysErr = nil
		} else {
			errCode = http.StatusInternalServerError
			userErr = nil
			sysErr = fmt.Errorf("looking for DSR: %w", err)
		}
		api.HandleErr(w, r, tx, errCode, userErr, sysErr)
		return
	}
	dsr.SetXMLID()

	if err := dsr.Status.ValidTransition(req.Status); err != nil {
		api.HandleErr(w, r, tx, http.StatusBadRequest, err, nil)
		return
	}

	authorized, err := isTenantAuthorized(dsr, inf)
	if err != nil {
		api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, err)
		return
	}
	if !authorized {
		api.HandleErr(w, r, tx, http.StatusForbidden, errors.New("not authorized on this tenant"), nil)
		return
	}

	dsr.LastEditedBy = inf.User.UserName
	dsr.LastEditedByID = new(int)
	*dsr.LastEditedByID = inf.User.ID

	// store the current original DS if the DSR is being closed
	// (and isn't a "create" request)
	if dsr.IsOpen() && req.Status != tc.RequestStatusDraft && req.Status != tc.RequestStatusSubmitted && dsr.ChangeType != tc.DSRChangeTypeCreate {
		if dsr.ChangeType == tc.DSRChangeTypeUpdate && dsr.Requested != nil && dsr.Requested.ID != nil {
			errCode, userErr, sysErr = getOriginals([]int{*dsr.Requested.ID}, inf.Tx, map[int][]*tc.DeliveryServiceRequestV5{*dsr.Requested.ID: {&dsr}})
			if userErr != nil || sysErr != nil {
				api.HandleErr(w, r, tx, errCode, userErr, sysErr)
				return
			}
			if dsr.Original == nil {
				sysErr = fmt.Errorf("failed to build original from dsr #%d that was to be closed; requested ID: %d", dsrID, *dsr.Requested.ID)
			}
		} else if dsr.ChangeType == tc.DSRChangeTypeDelete && dsr.Original != nil && dsr.Original.ID != nil {
			errCode, userErr, sysErr = getOriginals([]int{*dsr.Original.ID}, inf.Tx, map[int][]*tc.DeliveryServiceRequestV5{*dsr.Original.ID: {&dsr}})
			if userErr != nil || sysErr != nil {
				api.HandleErr(w, r, tx, errCode, userErr, sysErr)
				return
			}
			if dsr.Original == nil {
				sysErr = fmt.Errorf("failed to build original from dsr #%d that was to be closed; original ID: %d", dsrID, *dsr.Original.ID)
			}
		}

		if sysErr != nil {
			api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, sysErr)
			return
		}

		err := tx.QueryRow(updateStatusAndOriginalQuery, dsr.Original, req.Status, dsr.LastEditedByID, dsrID).Scan(&dsr.LastUpdated)
		if err != nil {
			sysErr = fmt.Errorf("updating original for dsr #%d: %w", dsrID, err)
			api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, sysErr)
			return
		}
	} else if err := tx.QueryRow(updateStatusQuery, req.Status, dsr.LastEditedByID, *dsr.ID).Scan(&dsr.LastUpdated); err == nil {
		if dsr.IsOpen() && dsr.ChangeType != tc.DSRChangeTypeCreate {
			query := deliveryservice.SelectDeliveryServicesQuery + " WHERE ds.xml_id = :xmlid"
			original, userErr, sysErr, errCode := deliveryservice.GetDeliveryServices(query, map[string]interface{}{"xmlid": dsr.XMLID}, inf.Tx)
			if userErr != nil || sysErr != nil {
				api.HandleErr(w, r, tx, errCode, userErr, sysErr)
				return
			}
			if len(original) != 1 {
				api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, fmt.Errorf("expected exactly one DS with XMLID '%s', found: %d", dsr.XMLID, len(original)))
				return
			}
			dsr.Original = new(tc.DeliveryServiceV5)
			*dsr.Original = original[0].DS
		}
	} else {
		userErr, sysErr, errCode = api.ParseDBError(err)
		api.HandleErr(w, r, tx, errCode, userErr, sysErr)
		return
	}

	message := fmt.Sprintf("Changed status of '%s' Delivery Service Request from '%s' to '%s'", dsr.XMLID, dsr.Status, req.Status)
	dsr.Status = req.Status

	var resp interface{}
	if inf.Version.Major >= 5 {
		resp = dsr
	} else if inf.Version.Major >= 4 {
		if inf.Version.Minor >= 1 {
			resp = dsr.Downgrade()
		} else {
			resp = dsr.Downgrade().Downgrade()
		}
	} else {
		resp = dsr.Downgrade().Downgrade().Downgrade()
	}

	api.WriteRespAlertObj(w, r, tc.SuccessLevel, message, resp)
	message = fmt.Sprintf("Delivery Service Request: %d, ID: %d, ACTION: %s deliveryservice_request, keys: {id:%d }", *dsr.ID, *dsr.ID, message, *dsr.ID)
	inf.CreateChangeLog(message)
}