github-code-scanning[bot] commented on code in PR #7740:
URL: https://github.com/apache/trafficcontrol/pull/7740#discussion_r1302168804


##########
traffic_ops/traffic_ops_golang/staticdnsentry/staticdnsentry.go:
##########
@@ -260,3 +265,380 @@
 WHERE id=:id`
        return query
 }
+
+// Validate validates a statisDNSEntry entity and makes sure that all the 
supplied fields are valid.
+func Validate(staticDNSEntry tc.StaticDNSEntryV5, tx *sql.Tx) (error, error) {
+       typeStr, err := tc.ValidateTypeID(tx, staticDNSEntry.TypeID, 
"staticdnsentry")
+       if err != nil {
+               return err, nil
+       }
+
+       var addressErr, ttlErr error
+       switch typeStr {
+       case "A_RECORD":
+               addressErr = validation.Validate(staticDNSEntry.Address, 
validation.Required, is.IPv4)
+       case "AAAA_RECORD":
+               addressErr = validation.Validate(staticDNSEntry.Address, 
validation.Required, is.IPv6)
+       case "CNAME_RECORD":
+               addressErr = validation.Validate(staticDNSEntry.Address, 
validation.Required, is.DNSName)
+               address := *staticDNSEntry.Address
+               if addressErr == nil {
+                       lastChar := address[len(address)-1:]
+                       if lastChar != "." {
+                               addressErr = fmt.Errorf("for type: CNAME_RECORD 
must have a trailing period")
+                       }
+               }
+       default:
+               addressErr = validation.Validate(staticDNSEntry.Address, 
validation.Required)
+       }
+
+       if staticDNSEntry.TTL != nil {
+               if *staticDNSEntry.TTL == 0 {
+                       ttlErr = validation.Validate(staticDNSEntry.TTL, 
is.Digit)
+               }
+       } else {
+               ttlErr = validation.Validate(staticDNSEntry.TTL, 
validation.Required)
+       }
+
+       errs := validation.Errors{
+               "host":              validation.Validate(staticDNSEntry.Host, 
validation.Required, is.DNSName),
+               "address":           addressErr,
+               "deliveryserviceId": 
validation.Validate(staticDNSEntry.DeliveryServiceID, validation.Required),
+               "ttl":               ttlErr,
+               "typeId":            validation.Validate(staticDNSEntry.TypeID, 
validation.Required),
+       }
+       return util.JoinErrs(tovalidate.ToErrors(errs)), nil
+}
+
+// Update will modify an existing StaticDNSEntry entity in the database, for 
api v5.0.
+func Update(w http.ResponseWriter, r *http.Request) {
+       inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+       if userErr != nil || sysErr != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+               return
+       }
+       defer inf.Close()
+
+       tx := inf.Tx.Tx
+
+       defer r.Body.Close()
+       var staticDNSEntry tc.StaticDNSEntryV5
+
+       if err := json.NewDecoder(r.Body).Decode(&staticDNSEntry); err != nil {
+               api.HandleErr(w, r, nil, http.StatusInternalServerError, nil, 
err)
+               return
+       }
+
+       userErr, sysErr = Validate(staticDNSEntry, tx)
+       if userErr != nil || sysErr != nil {
+               code := http.StatusBadRequest
+               if sysErr != nil {
+                       code = http.StatusInternalServerError
+               }
+               api.HandleErr(w, r, tx, code, userErr, sysErr)
+               return
+       }
+
+       var cdnName tc.CDNName
+       if id, ok := inf.Params["id"]; !ok {
+               api.HandleErr(w, r, tx, http.StatusBadRequest, 
errors.New("missing key: id"), nil)
+               return
+       } else {
+               idNum, err := strconv.Atoi(id)
+               if err != nil {
+                       api.HandleErr(w, r, tx, http.StatusBadRequest, 
errors.New("couldn't convert ID into a numeric value: "+err.Error()), nil)
+                       return
+               }
+               staticDNSEntry.ID = &idNum
+               if staticDNSEntry.DeliveryServiceID != nil {
+                       _, cdnName, _, err = 
dbhelpers.GetDSNameAndCDNFromID(tx, *staticDNSEntry.DeliveryServiceID)
+                       if err != nil {
+                               api.HandleErr(w, r, tx, 
http.StatusInternalServerError, nil, err)
+                               return
+                       }
+                       userErr, sysErr, errCode := 
dbhelpers.CheckIfCurrentUserCanModifyCDN(tx, string(cdnName), inf.User.UserName)
+                       if userErr != nil || sysErr != nil {
+                               api.HandleErr(w, r, inf.Tx.Tx, errCode, 
userErr, sysErr)
+                               return
+                       }
+               }
+
+               existingLastUpdated, found, err := api.GetLastUpdated(inf.Tx, 
idNum, "staticdnsentry")
+               if err == nil && found == false {
+                       api.HandleErr(w, r, tx, http.StatusNotFound, 
errors.New("no staticDNSEntry found with this id"), nil)
+                       return
+               }
+               if err != nil {
+                       api.HandleErr(w, r, tx, http.StatusNotFound, nil, err)
+                       return
+               }
+               if !api.IsUnmodified(r.Header, *existingLastUpdated) {
+                       api.HandleErr(w, r, tx, http.StatusPreconditionFailed, 
api.ResourceModifiedError, nil)
+                       return
+               }
+
+               rows, err := inf.Tx.NamedQuery(updateQuery(), staticDNSEntry)
+               if err != nil {
+                       userErr, sysErr, errCode = api.ParseDBError(err)
+                       api.HandleErr(w, r, tx, errCode, userErr, sysErr)
+                       return
+               }
+               defer rows.Close()
+
+               if !rows.Next() {
+                       api.HandleErr(w, r, tx, http.StatusNotFound, 
errors.New("no staticDNSEntry found with this id"), nil)
+                       return
+               }
+               lastUpdated := time.Time{}
+               if err := rows.Scan(&lastUpdated); err != nil {
+                       api.HandleErr(w, r, tx, http.StatusInternalServerError, 
nil, errors.New("scanning lastUpdated from staticDNSEntry insert: 
"+err.Error()))
+                       return
+               }
+               staticDNSEntry.LastUpdated = &lastUpdated
+               if rows.Next() {
+                       api.HandleErr(w, r, tx, http.StatusInternalServerError, 
nil, errors.New("staticDNSEntry update affected too many rows: >1"))
+                       return
+               }
+
+               alerts := tc.CreateAlerts(tc.SuccessLevel, "staticDNSEntry was 
updated.")
+               api.WriteAlertsObj(w, r, http.StatusOK, alerts, staticDNSEntry)
+               changeLogMsg := fmt.Sprintf("STATICDNSENTRY: %s, ID: %d, 
ACTION: Updated staticDNSEntry", *staticDNSEntry.Host, *staticDNSEntry.ID)
+               api.CreateChangeLogRawTx(api.ApiChange, changeLogMsg, inf.User, 
tx)
+               return
+       }
+}
+
+// Create will add a new StaticDNSEntry entity into the database, for api v5.0.
+func Create(w http.ResponseWriter, r *http.Request) {
+       inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+       if userErr != nil || sysErr != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+               return
+       }
+       defer inf.Close()
+
+       tx := inf.Tx.Tx
+
+       defer r.Body.Close()
+       var staticDNSEntry tc.StaticDNSEntryV5
+
+       if err := json.NewDecoder(r.Body).Decode(&staticDNSEntry); err != nil {
+               api.HandleErr(w, r, nil, http.StatusInternalServerError, nil, 
err)
+               return
+       }
+
+       userErr, sysErr = Validate(staticDNSEntry, tx)
+       if userErr != nil || sysErr != nil {
+               code := http.StatusBadRequest
+               if sysErr != nil {
+                       code = http.StatusInternalServerError
+               }
+               api.HandleErr(w, r, tx, code, userErr, sysErr)
+               return
+       }
+
+       var cdnName tc.CDNName
+       var err error
+       if staticDNSEntry.DeliveryServiceID != nil {
+               _, cdnName, _, err = dbhelpers.GetDSNameAndCDNFromID(tx, 
*staticDNSEntry.DeliveryServiceID)
+               if err != nil {
+                       api.HandleErr(w, r, tx, http.StatusInternalServerError, 
nil, err)
+                       return
+               }
+               userErr, sysErr, errCode := 
dbhelpers.CheckIfCurrentUserCanModifyCDN(tx, string(cdnName), inf.User.UserName)
+               if userErr != nil || sysErr != nil {
+                       api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+                       return
+               }
+       }
+
+       resultRows, err := inf.Tx.NamedQuery(insertQuery(), staticDNSEntry)
+       if err != nil {
+               userErr, sysErr, errCode = api.ParseDBError(err)
+               api.HandleErr(w, r, tx, errCode, userErr, sysErr)
+               return
+       }
+       defer resultRows.Close()
+
+       var id int
+       lastUpdated := time.Time{}
+       rowsAffected := 0
+       for resultRows.Next() {
+               rowsAffected++
+               if err := resultRows.Scan(&id, &lastUpdated); err != nil {
+                       api.HandleErr(w, r, tx, http.StatusInternalServerError, 
nil, errors.New("staticDNSEntry create scanning: "+err.Error()))
+                       return
+               }
+       }
+
+       if rowsAffected == 0 {
+               api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, 
errors.New("staticDNSEntry create: no staticDNSEntry was inserted, no id was 
returned"))
+               return
+       } else if rowsAffected > 1 {
+               api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, 
errors.New("too many ids returned from staticDNSEntry insert"))
+               return
+       }
+       staticDNSEntry.ID = &id
+       staticDNSEntry.LastUpdated = &lastUpdated
+
+       alerts := tc.CreateAlerts(tc.SuccessLevel, "staticDNSEntry was 
created.")
+       api.WriteAlertsObj(w, r, http.StatusOK, alerts, staticDNSEntry)
+       changeLogMsg := fmt.Sprintf("STATICDNSENTRY: %s, ID: %d, ACTION: 
Created staticDNSEntry", *staticDNSEntry.Host, *staticDNSEntry.ID)
+       api.CreateChangeLogRawTx(api.ApiChange, changeLogMsg, inf.User, tx)
+       return
+}
+
+// Delete removes a staticDNSEntry from the database, for api v5.0.
+func Delete(w http.ResponseWriter, r *http.Request) {
+       inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+       if userErr != nil || sysErr != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+               return
+       }
+       defer inf.Close()
+
+       tx := inf.Tx.Tx
+       if id, ok := inf.Params["id"]; !ok {
+               api.HandleErr(w, r, tx, http.StatusBadRequest, 
errors.New("missing key: id"), nil)
+               return
+       } else {
+               idNum, err := strconv.Atoi(id)
+               if err != nil {
+                       api.HandleErr(w, r, tx, http.StatusBadRequest, 
errors.New("couldn't convert ID into a numeric value: "+err.Error()), nil)
+                       return
+               }
+               staticDNSEntry := tc.StaticDNSEntryV5{
+                       ID: &idNum,
+               }
+               var cdnName tc.CDNName
+               var dsID int
+               if staticDNSEntry.DeliveryServiceID != nil {
+                       dsID = *staticDNSEntry.DeliveryServiceID
+               } else if staticDNSEntry.ID != nil {
+                       dsID, err = dbhelpers.GetDSIDFromStaticDNSEntry(tx, 
*staticDNSEntry.ID)
+                       if err != nil {
+                               api.HandleErr(w, r, tx, 
http.StatusInternalServerError, nil, errors.New("couldn't get DS ID from static 
dns entry ID: "+err.Error()))
+                               return
+                       }
+               }
+               _, cdnName, _, err = dbhelpers.GetDSNameAndCDNFromID(tx, dsID)
+               if err != nil {
+                       api.HandleErr(w, r, tx, http.StatusInternalServerError, 
nil, err)
+                       return
+               }
+               userErr, sysErr, errCode := 
dbhelpers.CheckIfCurrentUserCanModifyCDN(tx, string(cdnName), inf.User.UserName)
+               if userErr != nil || sysErr != nil {
+                       api.HandleErr(w, r, tx, errCode, userErr, sysErr)
+                       return
+               }
+               result, err := inf.Tx.NamedExec(deleteQuery(), staticDNSEntry)
+               if err != nil {
+                       userErr, sysErr, errCode = api.ParseDBError(err)
+                       api.HandleErr(w, r, tx, errCode, userErr, sysErr)
+                       return
+               }
+
+               if rowsAffected, err := result.RowsAffected(); err != nil {
+                       api.HandleErr(w, r, tx, http.StatusInternalServerError, 
nil, errors.New("deleting staticDNSEntry: getting rows affected: "+err.Error()))
+                       return
+               } else if rowsAffected < 1 {
+                       api.HandleErr(w, r, tx, http.StatusBadRequest, 
errors.New("no staticDNSEntry with that key found"), nil)
+                       return
+               } else if rowsAffected > 1 {
+                       api.HandleErr(w, r, tx, http.StatusInternalServerError, 
nil, fmt.Errorf("staticDNSEntry delete affected too many rows: %d", 
rowsAffected))
+                       return
+               }
+               log.Debugf("changelog for delete on staticDNSEntry")
+
+               alerts := tc.CreateAlerts(tc.SuccessLevel, "staticDNSEntry was 
deleted.")
+               api.WriteAlerts(w, r, http.StatusOK, alerts)
+               changeLogMsg := fmt.Sprintf("STATICDNSENTRY: %d, ID: %d, 
ACTION: Deleted staticDNSEntry", *staticDNSEntry.ID, *staticDNSEntry.ID)
+               api.CreateChangeLogRawTx(api.ApiChange, changeLogMsg, inf.User, 
tx)
+               return
+       }
+}
+
+// Get : function to read the staticDNSEntries, for api version 5.0.
+func Get(w http.ResponseWriter, r *http.Request) {
+       inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
+       if userErr != nil || sysErr != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+               return
+       }
+       defer inf.Close()
+
+       api.DefaultSort(inf, "host")
+       useIMS := false
+       config, e := api.GetConfig(r.Context())
+       if e == nil && config != nil {
+               useIMS = config.UseIMS
+       } else {
+               log.Warnf("Couldn't get config %v", e)
+       }
+
+       var maxTime time.Time
+       var runSecond bool
+
+       scList := make([]tc.StaticDNSEntryV5, 0)
+
+       tx := inf.Tx
+
+       where, orderBy, pagination, queryValues, errs := 
dbhelpers.BuildWhereAndOrderByAndPagination(inf.Params, 
map[string]dbhelpers.WhereColumnInfo{
+               "address":           dbhelpers.WhereColumnInfo{Column: 
"sde.address"},
+               "cachegroup":        dbhelpers.WhereColumnInfo{Column: 
"cg.name"},
+               "cachegroupId":      dbhelpers.WhereColumnInfo{Column: "cg.id"},
+               "deliveryservice":   dbhelpers.WhereColumnInfo{Column: 
"ds.xml_id"},
+               "deliveryserviceId": dbhelpers.WhereColumnInfo{Column: 
"sde.deliveryservice"},
+               "host":              dbhelpers.WhereColumnInfo{Column: 
"sde.host"},
+               "id":                dbhelpers.WhereColumnInfo{Column: 
"sde.id"},
+               "ttl":               dbhelpers.WhereColumnInfo{Column: 
"sde.ttl"},
+               "type":              dbhelpers.WhereColumnInfo{Column: 
"tp.name"},
+               "typeId":            dbhelpers.WhereColumnInfo{Column: "tp.id"},
+       })
+       if len(errs) > 0 {
+               api.HandleErr(w, r, tx.Tx, http.StatusBadRequest, nil, 
util.JoinErrs(errs))
+               return
+       }
+       if useIMS {
+               runSecond, maxTime = ims.TryIfModifiedSinceQuery(inf.Tx, 
r.Header, queryValues, selectMaxLastUpdatedQuery(where))
+               if !runSecond {
+                       log.Debugln("IMS HIT")
+                       api.AddLastModifiedHdr(w, maxTime)
+                       w.WriteHeader(http.StatusNotModified)
+                       return
+               }
+               log.Debugln("IMS MISS")
+       } else {
+               log.Debugln("Non IMS request")
+       }
+
+       // Case where we need to run the second query
+       query := selectQuery() + where + orderBy + pagination
+       rows, err := tx.NamedQuery(query, queryValues)

Review Comment:
   ## Database query built from user-controlled sources
   
   This query depends on a [user-provided value](1).
   
   [Show more 
details](https://github.com/apache/trafficcontrol/security/code-scanning/304)



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

To unsubscribe, e-mail: issues-unsubscr...@trafficcontrol.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to