rawlinp commented on a change in pull request #4015: Rewrite /federations to Go 
- POST/PUT/DELETE
URL: https://github.com/apache/trafficcontrol/pull/4015#discussion_r340187114
 
 

 ##########
 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 {
+                       inserted = append(inserted, ip)
+                       if _, err := 
tx.Exec(associateFederationWithResolverQuery, fedID, id); err != nil {
+                               return nil, err
+                       }
+               }
+
+       }
+
+       return inserted, nil
+}
+
+// RemoveFederationResolverMappingsForCurrentUser is the handler for a DELETE 
request to /federations
+// Confusingly, it does not delete a federation, but is instead used to remove 
an association
+// between all federation resolvers and all federations assigned to the 
authenticated user.
+func RemoveFederationResolverMappingsForCurrentUser(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()
+
+       ips, userErr, sysErr, errCode := 
removeFederationResolverMappingsForCurrentUser(tx, inf.User)
+       if userErr != nil || sysErr != nil {
+               api.HandleErr(w, r, tx, errCode, userErr, sysErr)
+               return
+       }
+
+       // I'm not sure if I necessarily agree with treating this as a client 
error, but it's what Perl did.
+       if len(ips) < 1 {
+               errCode = http.StatusConflict
+               userErr = fmt.Errorf("No federation resolvers to delete for 
user %s", inf.User.UserName)
+               api.HandleErr(w, r, tx, errCode, userErr, nil)
+               return
+       }
+
+       ipList := fmt.Sprintf("[ %s ]", strings.Join(ips, ", "))
+       msg := fmt.Sprintf("%s successfully deleted all federation resolvers: 
%s", inf.User.UserName, ipList)
+       changelogMsg := fmt.Sprintf("USER: %s, ID: %d, ACTION: %s", 
inf.User.UserName, inf.User.ID, msg)
+       api.CreateChangeLogRawTx(api.ApiChange, changelogMsg, inf.User, tx)
+
+       if inf.Version.Minor <= 3 {
 
 Review comment:
   ditto the previous comment

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

Reply via email to