func createHandlerHelper()

in traffic_ops/traffic_ops_golang/api/shared_handlers.go [492:626]


func createHandlerHelper(creator Creator, errHandler errWriterFunc, successHandler createSuccessWriterFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		inf, userErr, sysErr, errCode := NewInfo(r, nil, nil)
		if userErr != nil || sysErr != nil {
			errHandler(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
			return
		}
		defer inf.Close()

		interfacePtr := reflect.ValueOf(creator)
		if interfacePtr.Kind() != reflect.Ptr {
			errHandler(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("reflect: can only indirect from a pointer"))
			return
		}
		objectType := reflect.Indirect(interfacePtr).Type()
		obj := reflect.New(objectType).Interface().(Creator)
		obj.SetInfo(inf)

		if c, ok := obj.(MultipleCreator); ok && c.AllowMultipleCreates() {
			data, err := ioutil.ReadAll(r.Body)
			if err != nil {
				errHandler(w, r, inf.Tx.Tx, http.StatusBadRequest, err, nil)
				return
			}

			if len(data) == 0 {
				HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("no request body supplied"), nil)
				return
			}

			objSlice, err := parseMultipleCreates(data, objectType, inf)
			if err != nil {
				errHandler(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, err)
				return
			}

			for _, objElemInt := range objSlice {
				objElem := reflect.ValueOf(objElemInt).Interface().(Creator)

				userErr, sysErr = objElem.Validate()
				if userErr != nil || sysErr != nil {
					code := http.StatusBadRequest
					if sysErr != nil {
						code = http.StatusInternalServerError
					}
					errHandler(w, r, inf.Tx.Tx, code, userErr, sysErr)
					return
				}

				if t, ok := objElem.(Tenantable); ok {
					authorized, err := t.IsTenantAuthorized(inf.User)
					if err != nil {
						errHandler(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("checking tenant authorized: "+err.Error()))
						return
					}
					if !authorized {
						errHandler(w, r, inf.Tx.Tx, http.StatusForbidden, errors.New("not authorized on this tenant"), nil)
						return
					}
				}

				userErr, sysErr, errCode = objElem.Create()
				if userErr != nil || sysErr != nil {
					errHandler(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
					return
				}

				if err = CreateChangeLog(ApiChange, Created, objElem, inf.User, inf.Tx.Tx); err != nil {
					errHandler(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("inserting changelog: %w", err))
					return
				}
			}
			if len(objSlice) == 0 {
				WriteRespAlert(w, r, tc.SuccessLevel, "No objects were provided in request.")
				return
			}
			var (
				responseObj interface{}
				message     string
			)
			if len(objSlice) == 1 {
				responseObj = objSlice[0]
				message = objSlice[0].GetType() + " was created."
			} else {
				message = objSlice[0].GetType() + "s were created."
			}
			alerts := tc.CreateAlerts(tc.SuccessLevel, message)
			if _, hasAlerts := objSlice[0].(AlertsResponse); hasAlerts {
				for _, objElem := range objSlice {
					alerts.AddAlerts(objElem.(AlertsResponse).GetAlerts())
				}
			}
			successHandler(w, r, http.StatusOK, alerts, responseObj)

		} else {
			userErr, sysErr := decodeAndValidateRequestBody(r, obj)
			if userErr != nil || sysErr != nil {
				code := http.StatusBadRequest
				if sysErr != nil {
					code = http.StatusInternalServerError
				}
				errHandler(w, r, inf.Tx.Tx, code, userErr, sysErr)
				return
			}

			if t, ok := obj.(Tenantable); ok {
				authorized, err := t.IsTenantAuthorized(inf.User)
				if err != nil {
					errHandler(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("checking tenant authorized: "+err.Error()))
					return
				}
				if !authorized {
					errHandler(w, r, inf.Tx.Tx, http.StatusForbidden, errors.New("not authorized on this tenant"), nil)
					return
				}
			}

			userErr, sysErr, errCode = obj.Create()
			if userErr != nil || sysErr != nil {
				errHandler(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
				return
			}

			if err := CreateChangeLog(ApiChange, Created, obj, inf.User, inf.Tx.Tx); err != nil {
				errHandler(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, fmt.Errorf("inserting changelog: %w", err))
				return
			}
			alerts := tc.CreateAlerts(tc.SuccessLevel, obj.GetType()+" was created.")
			if alertsObj, hasAlerts := obj.(AlertsResponse); hasAlerts {
				alerts.AddAlerts(alertsObj.GetAlerts())
			}
			successHandler(w, r, http.StatusOK, alerts, obj)
		}
	}
}