rob05c commented on a change in pull request #4942:
URL: https://github.com/apache/trafficcontrol/pull/4942#discussion_r468289446
##########
File path: traffic_ops/traffic_ops_golang/deliveryservice/request/requests.go
##########
@@ -383,6 +401,20 @@ func (req *deliveryServiceRequestAssignment) Update()
(error, error, int) {
req.DeliveryServiceRequestNullable =
current.DeliveryServiceRequestNullable
req.AssigneeID = assigneeID
+ err, existingLastUpdated := CheckIfExistsBeforeUpdate(req.ReqInfo.Tx,
*req.ID)
Review comment:
This whole block seems to be identical in a lot of places. Could it be
abstracted into something like `func IsUnmodified(tx *sql.Tx, id int, tableName
string, hdr http.Header) bool` ?
##########
File path: traffic_ops/traffic_ops_golang/user/user.go
##########
@@ -266,6 +286,20 @@ func (user *TOUser) Update() (error, error, int) {
}
}
+ err, existingLastUpdated := CheckIfExistsBeforeUpdate(user.ReqInfo.Tx,
*user.ID)
+ if err != nil {
+ return errors.New("no server found with this id"), nil,
http.StatusNotFound
+ }
+ _, iumsTime := rfc.GetETagOrIfUnmodifiedSinceTime(h)
+ existingEtag := rfc.ETag(existingLastUpdated.Time)
+
+ if h.Get(rfc.IfMatch) != "" && !strings.Contains(h.Get(rfc.IfMatch),
existingEtag) {
+ return errors.New("header preconditions dont match"), nil,
http.StatusPreconditionFailed
+ }
+ if iumsTime != nil && existingLastUpdated.UTC().After(iumsTime.UTC()) {
Review comment:
If the header was an `If-Unmodified-Since`, the `HTTP-Date` only has
second-precison. Which means, if we simply round or truncate when setting
`Last-Modified`, `If-Modified-Since` will always be true, and
`If-Unmodified-Since` will always be false.
But ETag has as much precision as we want to give it, and we definitely want
to keep that precision in the check.
It could be changed in your code here, to add a second if it's exactly
rounded to the second (and therefore an `IUS` not `IM`).
But I think the better solution is to leave your code here as it is, and fix
the place(s) that set `LastModified` to use
`lastModified.Truncate(time.Second).Add(time.Second)`
##########
File path: traffic_ops/traffic_ops_golang/origin/origins.go
##########
@@ -309,6 +309,7 @@ func (origin *TOOrigin) Update() (error, error, int) {
}
log.Debugf("about to run exec query: %s with origin: %++v",
updateQuery(), origin)
+ // ToDo : Srijeet change here
Review comment:
I assume an Unmodified check needs to go here?
##########
File path: traffic_ops/traffic_ops_golang/deliveryservice/request/requests.go
##########
@@ -226,7 +244,7 @@ func (req *TODeliveryServiceRequest) Update() (error,
error, int) {
userID := tc.IDNoMod(req.APIInfo().User.ID)
req.LastEditedByID = &userID
- return api.GenericUpdate(req)
+ return api.GenericUpdate(nil, req)
Review comment:
Why is this passing `nil`, and not the `http.Header`?
##########
File path: traffic_ops/traffic_ops_golang/cachegroup/cachegroups.go
##########
@@ -567,6 +582,22 @@ func (cg *TOCacheGroup) Update() (error, error, int) {
return nil, nil, http.StatusOK
}
+func CheckIfExistsBeforeUpdate(tx *sqlx.Tx, cgID int) (error, *tc.TimeNoMod) {
Review comment:
These functions look identical, except for the table in the select query.
Could they be refactored to use a common func, maybe something like
```
// GetLastUpdated returns the last updated time of the given ID in the given
table, whether the ID existed, and any error.
func GetLastUpdated(tx *sqlx.Tx, dbTable string, id int) (time.Time, bool,
error)
````
In the `api` package?
##########
File path: traffic_ops/traffic_ops_golang/deliveryservice/safe.go
##########
@@ -23,11 +23,10 @@ import (
"database/sql"
"fmt"
"github.com/apache/trafficcontrol/lib/go-log"
- "net/http"
-
"github.com/apache/trafficcontrol/lib/go-tc"
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
+ "net/http"
Review comment:
We try to separate imports with newlines for "standard library," "third
party", and "our own," just to make it a little easier to read. Would you mind
moving this up with the other standard library imports? Mind also moving
`lib/go-log` down with the other TC ones? (that one wasn't yours, but while
you're improving it, might as well do that one too).
##########
File path: traffic_ops/traffic_ops_golang/steeringtargets/steeringtargets.go
##########
@@ -244,6 +244,7 @@ func (st *TOSteeringTargetV11) Update() (error, error, int)
{
return userErr, sysErr, errCode
}
+ // ToDo : Srijeet change here
Review comment:
Need an Unmodified check here?
##########
File path: traffic_ops/traffic_ops_golang/server/servers_server_capability.go
##########
@@ -121,7 +121,7 @@ func (ssc TOServerServerCapability) Validate() error {
return util.JoinErrs(tovalidate.ToErrors(errs))
}
-func (ssc *TOServerServerCapability) Update() (error, error, int) {
+func (ssc *TOServerServerCapability) Update(h http.Header) (error, error, int)
{
Review comment:
I know you didn't create this function, but it can be deleted.
This is a legacy from when the "CRUDer" stuff required every func be
implemented. This endpoint doesn't have a PUT method, and the "CRUDer"
framework no longer requires all funcs, so it can just be deleted now.
##########
File path: traffic_ops/traffic_ops_golang/deliveryservice/request/requests.go
##########
@@ -383,6 +401,20 @@ func (req *deliveryServiceRequestAssignment) Update()
(error, error, int) {
req.DeliveryServiceRequestNullable =
current.DeliveryServiceRequestNullable
req.AssigneeID = assigneeID
+ err, existingLastUpdated := CheckIfExistsBeforeUpdate(req.ReqInfo.Tx,
*req.ID)
+ if err != nil {
+ return errors.New("no delivery service request found with this
id"), nil, http.StatusNotFound
+ }
+ _, iumsTime := rfc.GetETagOrIfUnmodifiedSinceTime(h)
+ existingEtag := rfc.ETag(existingLastUpdated.Time)
+
+ if h.Get(rfc.IfMatch) != "" && !strings.Contains(h.Get(rfc.IfMatch),
existingEtag) {
+ return errors.New("header preconditions dont match"), nil,
http.StatusPreconditionFailed
Review comment:
The text here doesn't have to match the code, and since it's a user
error, I think it's safe (from a security perspective) to let them know why
they're getting a 412. Could we make the message something more informative
like "resource was modified" ?
----------------------------------------------------------------
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:
[email protected]