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)
}
}
}