mhoppa commented on a change in pull request #4015: Rewrite /federations to Go - POST/PUT/DELETE URL: https://github.com/apache/trafficcontrol/pull/4015#discussion_r339808566
########## File path: traffic_ops/traffic_ops_golang/federations/federations.go ########## @@ -167,3 +206,296 @@ ORDER BY } return feds, nil } + +// AddFederationResorverMappingsForCurrentUser is the handler for a POST request to /federations. +// Confusingly, it does not create a federation, but is instead used to manipulate the resolvers +// used by one or more particular Delivery Services for one or more particular Federations. +func AddFederationResolverMappingsForCurrentUser(w http.ResponseWriter, r *http.Request) { + inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil) + tx := inf.Tx.Tx + if userErr != nil || sysErr != nil { + api.HandleErr(w, r, tx, errCode, userErr, sysErr) + return + } + defer inf.Close() + + mappings, userErr, sysErr := getMappingsFromRequestBody(*inf.Version, r.Body) + if userErr != nil || sysErr != nil { + api.HandleErr(w, r, tx, http.StatusBadRequest, userErr, sysErr) + return + } + + if err := mappings.Validate(tx); err != nil { + errCode = http.StatusBadRequest + userErr = fmt.Errorf("validating request: %v", err) + api.HandleErr(w, r, tx, errCode, userErr, nil) + return + } + + userErr, sysErr, errCode = addFederationResolverMappingsForCurrentUser(inf.User, tx, mappings) + if userErr != nil || sysErr != nil { + api.HandleErr(w, r, tx, errCode, userErr, sysErr) + return + } + + msg := fmt.Sprintf("%s successfully created federation resolvers.", inf.User.UserName) + if inf.Version.Minor <= 3 { + api.WriteResp(w, r, msg) + } else { + api.WriteRespAlertObj(w, r, tc.SuccessLevel, msg, msg) + } +} + +// handles the main logic of the POST handler, separated out for convenience +func addFederationResolverMappingsForCurrentUser(u *auth.CurrentUser, tx *sql.Tx, mappings []tc.DeliveryServiceFederationResolverMapping) (error, error, int) { + for _, fed := range mappings { + dsTenant, ok, err := dbhelpers.GetDSTenantIDFromXMLID(tx, fed.DeliveryService) + if err != nil { + return nil, err, http.StatusInternalServerError + } else if !ok { + return fmt.Errorf("'%s' - no such Delivery Service", fed.DeliveryService), nil, http.StatusConflict + } + + if ok, err = tenant.IsResourceAuthorizedToUserTx(dsTenant, u, tx); err != nil { + err = fmt.Errorf("Checking user #%d tenancy permissions on DS '%s' (tenant #%d)", u.ID, fed.DeliveryService, dsTenant) + return nil, err, http.StatusInternalServerError + } else if !ok { + userErr := fmt.Errorf("'%s' - no such Delivery Service", fed.DeliveryService) + sysErr := fmt.Errorf("User '%s' requested unauthorized federation resolver mapping modification on the '%s' Delivery Service", u.UserName, fed.DeliveryService) + return userErr, sysErr, http.StatusConflict + } + + fedID, ok, err := dbhelpers.GetFederationIDForUserIDByXMLID(tx, u.ID, fed.DeliveryService) + if err != nil { + return nil, fmt.Errorf("Getting Federation ID: %v", err), http.StatusInternalServerError + } else if !ok { + err = fmt.Errorf("No federation(s) found for user %s on delivery service '%s'.", u.UserName, fed.DeliveryService) + return err, nil, http.StatusConflict + } + + inserted, err := addFederationResolverMappingsToFederation(fed.Mappings, fed.DeliveryService, fedID, tx) + if err != nil { + err = fmt.Errorf("Adding federation resolver mapping(s) to federation: %v", err) + return nil, err, http.StatusInternalServerError + } + + changelogMsg := "FEDERATION DELIVERY SERVICE: %s, ID: %d, ACTION: User %s successfully added federation resolvers [ %s ]" + changelogMsg = fmt.Sprintf(changelogMsg, fed.DeliveryService, fedID, u.UserName, inserted) + api.CreateChangeLogRawTx(api.ApiChange, changelogMsg, u, tx) + } + return nil, nil, http.StatusOK +} + +// adds federation resolver mappings for a particular delivery service to a given federation, creating said resolvers if +// they don't already exist. +func addFederationResolverMappingsToFederation(res tc.ResolverMapping, xmlid string, fed uint, tx *sql.Tx) (string, error) { + var resp string + if len(res.Resolve4) > 0 { + inserted, err := addFederationResolver(res.Resolve4, tc.FederationResolverType4, fed, tx) + if err != nil { + return "", err + } + resp = strings.Join(inserted, ", ") + } + if len(res.Resolve6) > 0 { + inserted, err := addFederationResolver(res.Resolve6, tc.FederationResolverType6, fed, tx) + if err != nil { + return "", err + } + resp += strings.Join(inserted, ", ") + } + return resp, nil +} + +// adds federation resolvers of a specific type to the given federation +func addFederationResolver(res []string, t tc.FederationResolverType, fedID uint, tx *sql.Tx) ([]string, error) { + inserted := []string{} + for _, r := range res { + var ip string + var id uint + if err := tx.QueryRow(insertResolverQuery, r, t).Scan(&ip, &id); err != nil && err != sql.ErrNoRows { + return nil, err + } + if ip != "" && id > 0 { Review comment: what would it mean if the ip is equal to "" and the id less than zero? Would that ever happen do we need to check for it? ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services