This is an automated email from the ASF dual-hosted git repository.

rshah pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new b2ca0f2c78 Update timestamp for Delivery service Request Comment to 
match RFC3339 format (#7570)
b2ca0f2c78 is described below

commit b2ca0f2c78f282886b9ef49513ca296aac4fe35f
Author: Srijeet Chatterjee <[email protected]>
AuthorDate: Fri Jun 23 10:19:29 2023 -0600

    Update timestamp for Delivery service Request Comment to match RFC3339 
format (#7570)
    
    * wip
    
    * add remaining methods
    
    * Add changelog, fix formatting
    
    * code review comments
    
    * add nano
---
 CHANGELOG.md                                       |   1 +
 .../api/v5/deliveryservice_request_comments.rst    |  14 +-
 lib/go-tc/deliveryservice_request_comments.go      |  31 +++
 .../v5/deliveryservice_request_comments_test.go    |  10 +-
 traffic_ops/testing/api/v5/traffic_control_test.go |   2 +-
 .../deliveryservice/request/comment/comments.go    | 259 +++++++++++++++++++++
 traffic_ops/traffic_ops_golang/routing/routes.go   |   8 +-
 .../v5-client/deliveryservice_request_comments.go  |   8 +-
 8 files changed, 312 insertions(+), 21 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2e578712b8..a207fe4dd2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -57,6 +57,7 @@ The format is based on [Keep a 
Changelog](http://keepachangelog.com/en/1.0.0/).
 - [#7469](https://github.com/apache/trafficcontrol/pull/7469) *Traffic Ops* 
Changed logic to not report empty or missing cookies into TO error.log.
 
 ### Fixed
+- [#7570](https://github.com/apache/trafficcontrol/pull/7570) *Traffic Ops* 
Fixes `deliveryservice_request_comments` v5 apis to respond with `RFC3339` 
date/time Format.
 - [#7312](https://github.com/apache/trafficcontrol/issues/7312) *Docs* 
Changing docs for CDN locks for DELETE response structure v4 and v5. 
 - [#7572](https://github.com/apache/trafficcontrol/pull/7572) *Traffic Ops* 
Fixes Delivery Service Requests V5 apis docs with RFC3339 date/time Format
 - [#7539](https://github.com/apache/trafficcontrol/pull/7539) *Traffic 
Monitor* Use stats_over_http timestamp to calculate bandwidth for TM's health. 
diff --git a/docs/source/api/v5/deliveryservice_request_comments.rst 
b/docs/source/api/v5/deliveryservice_request_comments.rst
index d546ecbcc1..f06d2c0ef0 100644
--- a/docs/source/api/v5/deliveryservice_request_comments.rst
+++ b/docs/source/api/v5/deliveryservice_request_comments.rst
@@ -61,7 +61,7 @@ Response Structure
 :authorId:                      The integral, unique identifier of the user 
who created the comment.
 :deliveryServiceRequestId:      The integral, unique identifier of the 
:term:`Delivery Service Request` that the comment was posted on.
 :id:                            The integral, unique identifier of the 
:term:`DSR` comment.
-:lastUpdated:                   The date and time at which the user was last 
modified, in :ref:`non-rfc-datetime`
+:lastUpdated:                   The date and time at which the user was last 
modified, in :rfc:`3339`
 :value:                         The text of the comment that was posted.
 :xmlId:                         This is the ``xmlId`` value that you provided 
in the request.
 
@@ -88,7 +88,7 @@ Response Structure
                                "author": "admin",
                                "deliveryServiceRequestId": 2,
                                "id": 3,
-                               "lastUpdated": "2020-02-24 19:59:46+00",
+                               "lastUpdated": 
"2020-02-24T19:59:46.682939-06:00",
                                "value": "Changing to a different origin for 
now.",
                                "xmlId": "demo1"
                        },
@@ -97,7 +97,7 @@ Response Structure
                                "author": "admin",
                                "deliveryServiceRequestId": 2,
                                "id": 4,
-                               "lastUpdated": "2020-02-24 19:59:55+00",
+                               "lastUpdated": 
"2020-02-24T19:59:55.782431-06:00",
                                "value": "Using HTTPS.",
                                "xmlId": "demo1"
                        }
@@ -141,7 +141,7 @@ Response Structure
 :authorId:                      The integral, unique identifier of the user 
who created the comment.
 :deliveryServiceRequestId:      The integral, unique identifier of the 
:term:`Delivery Service Request` that the comment was posted on.
 :id:                            The integral, unique identifier of the 
:term:`DSR` comment.
-:lastUpdated:                   The date and time at which the user was last 
modified, in :ref:`non-rfc-datetime`
+:lastUpdated:                   The date and time at which the user was last 
modified, in :rfc:`3339`
 :value:                         The text of the comment that was posted.
 :xmlId:                         This is the ``xmlId`` value that you provided 
in the request.
 
@@ -173,7 +173,7 @@ Response Structure
                        "author": null,
                        "deliveryServiceRequestId": 2,
                        "id": 6,
-                       "lastUpdated": "2020-02-24 20:02:20+00",
+                       "lastUpdated": "2020-02-24T20:02:20.583524-06:00",
                        "value": "Does anyone have time to review my delivery 
service request?",
                        "xmlId": null
                }
@@ -226,7 +226,7 @@ Response Structure
 :authorId:                      The integral, unique identifier of the user 
who created the comment.
 :deliveryServiceRequestId:      The integral, unique identifier of the 
:term:`Delivery Service Request` that the comment was posted on.
 :id:                            The integral, unique identifier of the 
:term:`DSR` comment.
-:lastUpdated:                   The date and time at which the user was last 
modified, in :ref:`non-rfc-datetime`
+:lastUpdated:                   The date and time at which the user was last 
modified, in :rfc:`3339`
 :value:                         The text of the comment that was posted.
 :xmlId:                         This is the ``xmlId`` value that you provided 
in the request.
 
@@ -258,7 +258,7 @@ Response Structure
                        "author": null,
                        "deliveryServiceRequestId": 2,
                        "id": 6,
-                       "lastUpdated": "2020-02-24 20:05:46+00",
+                       "lastUpdated": "2020-02-24T20:05:46.124229-06:00",
                        "value": "Update: We no longer need this, feel free to 
reject.\n\nDoes anyone have time to review my delivery service request?",
                        "xmlId": null
                }
diff --git a/lib/go-tc/deliveryservice_request_comments.go 
b/lib/go-tc/deliveryservice_request_comments.go
index dce1f77434..02314b8e07 100644
--- a/lib/go-tc/deliveryservice_request_comments.go
+++ b/lib/go-tc/deliveryservice_request_comments.go
@@ -19,6 +19,37 @@ package tc
  * under the License.
  */
 
+import (
+       "time"
+)
+
+// DeliveryServiceRequestCommentV5 is a Delivery Service Request Comment as it 
appears in version 5 of the
+// Traffic Ops API - it always points to the highest minor version in APIv5.
+type DeliveryServiceRequestCommentV5 DeliveryServiceRequestCommentV50
+
+// DeliveryServiceRequestCommentV50 is a struct containing the fields for a 
delivery
+// service request comment, for API version 5.0.
+type DeliveryServiceRequestCommentV50 struct {
+       AuthorID                 IDNoMod   `json:"authorId" db:"author_id"`
+       Author                   string    `json:"author"`
+       DeliveryServiceRequestID int       `json:"deliveryServiceRequestId" 
db:"deliveryservice_request_id"`
+       ID                       int       `json:"id" db:"id"`
+       LastUpdated              time.Time `json:"lastUpdated" 
db:"last_updated"`
+       Value                    string    `json:"value" db:"value"`
+       XMLID                    string    `json:"xmlId" db:"xml_id"`
+}
+
+// DeliveryServiceRequestCommentsResponseV5 is a Delivery Service Request 
Comment Response as it appears in version 5
+// of the Traffic Ops API - it always points to the highest minor version in 
APIv5.
+type DeliveryServiceRequestCommentsResponseV5 
DeliveryServiceRequestCommentsResponseV50
+
+// DeliveryServiceRequestCommentsResponseV50 is a list of
+// DeliveryServiceRequestCommentsV5 as a response, for API version 5.0.
+type DeliveryServiceRequestCommentsResponseV50 struct {
+       Response []DeliveryServiceRequestCommentV5 `json:"response"`
+       Alerts
+}
+
 // DeliveryServiceRequestCommentsResponse is a list of
 // DeliveryServiceRequestComments as a response.
 type DeliveryServiceRequestCommentsResponse struct {
diff --git 
a/traffic_ops/testing/api/v5/deliveryservice_request_comments_test.go 
b/traffic_ops/testing/api/v5/deliveryservice_request_comments_test.go
index 1b3c8ead37..94d49c8b71 100644
--- a/traffic_ops/testing/api/v5/deliveryservice_request_comments_test.go
+++ b/traffic_ops/testing/api/v5/deliveryservice_request_comments_test.go
@@ -38,7 +38,7 @@ func TestDeliveryServiceRequestComments(t *testing.T) {
                currentTimeRFC := currentTime.Format(time.RFC1123)
                tomorrow := currentTime.AddDate(0, 0, 1).Format(time.RFC1123)
 
-               methodTests := utils.TestCase[client.Session, 
client.RequestOptions, tc.DeliveryServiceRequestComment]{
+               methodTests := utils.TestCase[client.Session, 
client.RequestOptions, tc.DeliveryServiceRequestCommentV5]{
                        "GET": {
                                "NOT MODIFIED when NO CHANGES made": {
                                        ClientSession: TOSession,
@@ -68,7 +68,7 @@ func TestDeliveryServiceRequestComments(t *testing.T) {
                                "OK when VALID request": {
                                        EndpointID:    GetDSRequestCommentId(t, 
"admin"),
                                        ClientSession: TOSession,
-                                       RequestBody: 
tc.DeliveryServiceRequestComment{
+                                       RequestBody: 
tc.DeliveryServiceRequestCommentV5{
                                                DeliveryServiceRequestID: 
GetDSRequestId(t, "test-ds1")(),
                                                Value:                    
"updated comment",
                                        },
@@ -78,13 +78,13 @@ func TestDeliveryServiceRequestComments(t *testing.T) {
                                        EndpointID:    GetDSRequestCommentId(t, 
"admin"),
                                        ClientSession: TOSession,
                                        RequestOpts:   
client.RequestOptions{Header: http.Header{rfc.IfUnmodifiedSince: 
{currentTimeRFC}}},
-                                       RequestBody:   
tc.DeliveryServiceRequestComment{},
+                                       RequestBody:   
tc.DeliveryServiceRequestCommentV5{},
                                        Expectations:  
utils.CkRequest(utils.HasError(), 
utils.HasStatus(http.StatusPreconditionFailed)),
                                },
                                "PRECONDITION FAILED when updating with IFMATCH 
ETAG Header": {
                                        EndpointID:    GetDSRequestCommentId(t, 
"admin"),
                                        ClientSession: TOSession,
-                                       RequestBody:   
tc.DeliveryServiceRequestComment{},
+                                       RequestBody:   
tc.DeliveryServiceRequestCommentV5{},
                                        RequestOpts:   
client.RequestOptions{Header: http.Header{rfc.IfMatch: 
{rfc.ETag(currentTime)}}},
                                        Expectations:  
utils.CkRequest(utils.HasError(), 
utils.HasStatus(http.StatusPreconditionFailed)),
                                },
@@ -147,7 +147,7 @@ func GetDSRequestId(t *testing.T, xmlId string) func() int {
 func validateSortedDSRequestComments() utils.CkReqFunc {
        return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, _ 
tc.Alerts, err error) {
                var sortedList []string
-               dsReqComments := resp.([]tc.DeliveryServiceRequestComment)
+               dsReqComments := resp.([]tc.DeliveryServiceRequestCommentV5)
 
                for _, comment := range dsReqComments {
                        sortedList = append(sortedList, comment.XMLID)
diff --git a/traffic_ops/testing/api/v5/traffic_control_test.go 
b/traffic_ops/testing/api/v5/traffic_control_test.go
index 5fd0eea97f..d9df3d0bad 100644
--- a/traffic_ops/testing/api/v5/traffic_control_test.go
+++ b/traffic_ops/testing/api/v5/traffic_control_test.go
@@ -29,7 +29,7 @@ type TrafficControl struct {
        Coordinates                                       []tc.CoordinateV5     
                  `json:"coordinates"`
        DeliveryServicesRegexes                           
[]tc.DeliveryServiceRegexesTest         `json:"deliveryServicesRegexes"`
        DeliveryServiceRequests                           
[]tc.DeliveryServiceRequestV5           `json:"deliveryServiceRequests"`
-       DeliveryServiceRequestComments                    
[]tc.DeliveryServiceRequestComment      `json:"deliveryServiceRequestComments"`
+       DeliveryServiceRequestComments                    
[]tc.DeliveryServiceRequestCommentV5    `json:"deliveryServiceRequestComments"`
        DeliveryServices                                  
[]tc.DeliveryServiceV5                  `json:"deliveryservices"`
        DeliveryServicesRequiredCapabilities              
[]tc.DeliveryServicesRequiredCapability 
`json:"deliveryservicesRequiredCapabilities"`
        DeliveryServiceServerAssignments                  
[]tc.DeliveryServiceServers             
`json:"deliveryServiceServerAssignments"`
diff --git 
a/traffic_ops/traffic_ops_golang/deliveryservice/request/comment/comments.go 
b/traffic_ops/traffic_ops_golang/deliveryservice/request/comment/comments.go
index 60414f342b..19d761cfdf 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/request/comment/comments.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/request/comment/comments.go
@@ -20,16 +20,20 @@ package comment
  */
 
 import (
+       "encoding/json"
        "errors"
+       "fmt"
        "net/http"
        "strconv"
        "time"
 
+       "github.com/apache/trafficcontrol/lib/go-log"
        "github.com/apache/trafficcontrol/lib/go-tc"
        "github.com/apache/trafficcontrol/lib/go-tc/tovalidate"
        "github.com/apache/trafficcontrol/lib/go-util"
        "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
        
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
+       
"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/util/ims"
 
        validation "github.com/go-ozzo/ozzo-validation"
 )
@@ -55,6 +59,15 @@ JOIN deliveryservice_request dsr ON 
dsrc.deliveryservice_request_id = dsr.id ` +
        select max(last_updated) as t from last_deleted l where 
l.table_name='deliveryservice_request_comment') as res`
 }
 
+func selectMaxLastUpdatedQuery(where, orderBy, pagination string) string {
+       return `SELECT max(t) from (
+               SELECT max(dsrc.last_updated) as t from 
deliveryservice_request_comment dsrc
+JOIN tm_user a ON dsrc.author_id = a.id
+JOIN deliveryservice_request dsr ON dsrc.deliveryservice_request_id = dsr.id ` 
+ where + orderBy + pagination +
+               ` UNION ALL
+       select max(last_updated) as t from last_deleted l where 
l.table_name='deliveryservice_request_comment') as res`
+}
+
 func (v *TODeliveryServiceRequestComment) NewReadObj() interface{} {
        return &tc.DeliveryServiceRequestCommentNullable{}
 }
@@ -186,3 +199,249 @@ WHERE id=:id RETURNING last_updated`
 func deleteQuery() string {
        return `DELETE FROM deliveryservice_request_comment WHERE id = :id`
 }
+
+// Get is used to read the DeliveryServiceRequestCommentV5 entities from the 
database.
+func Get(w http.ResponseWriter, r *http.Request) {
+       var maxTime time.Time
+       var runSecond bool
+       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()
+
+       api.DefaultSort(inf, "xmlId")
+       cols := map[string]dbhelpers.WhereColumnInfo{
+               "authorId":                 dbhelpers.WhereColumnInfo{Column: 
"dsrc.author_id"},
+               "author":                   dbhelpers.WhereColumnInfo{Column: 
"a.username"},
+               "deliveryServiceRequestId": dbhelpers.WhereColumnInfo{Column: 
"dsrc.deliveryservice_request_id"},
+               "id":                       dbhelpers.WhereColumnInfo{Column: 
"dsrc.id", Checker: api.IsInt},
+       }
+
+       where, orderBy, pagination, queryValues, errs := 
dbhelpers.BuildWhereAndOrderByAndPagination(inf.Params, cols)
+       if len(errs) > 0 {
+               errCode = http.StatusBadRequest
+               userErr = util.JoinErrs(errs)
+               api.HandleErr(w, r, tx, errCode, userErr, nil)
+               return
+       }
+
+       if inf.Config.UseIMS {
+               runSecond, maxTime = ims.TryIfModifiedSinceQuery(inf.Tx, 
r.Header, queryValues, selectMaxLastUpdatedQuery(where, orderBy, pagination))
+               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")
+       }
+
+       deliveryServiceRequestComments := []tc.DeliveryServiceRequestCommentV5{}
+       query := selectQuery() + where + orderBy + pagination
+       rows, err := inf.Tx.NamedQuery(query, queryValues)
+       if err != nil {
+               api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, 
errors.New("querying cdn locks: "+err.Error()))
+               return
+       }
+       defer rows.Close()
+
+       for rows.Next() {
+               var deliveryServiceRequestComment 
tc.DeliveryServiceRequestCommentV5
+               if err = rows.Scan(&deliveryServiceRequestComment.Author, 
&deliveryServiceRequestComment.AuthorID, 
&deliveryServiceRequestComment.DeliveryServiceRequestID, 
&deliveryServiceRequestComment.XMLID, &deliveryServiceRequestComment.ID, 
&deliveryServiceRequestComment.LastUpdated, 
&deliveryServiceRequestComment.Value); err != nil {
+                       api.HandleErr(w, r, tx, http.StatusInternalServerError, 
nil, errors.New("scanning delivery service request comments: "+err.Error()))
+                       return
+               }
+               deliveryServiceRequestComments = 
append(deliveryServiceRequestComments, deliveryServiceRequestComment)
+       }
+       api.WriteResp(w, r, deliveryServiceRequestComments)
+}
+
+// Validate is used to ensure that the DeliveryServiceRequestCommentV5 struct 
passed in to the function is valid.
+func Validate(dsrc tc.DeliveryServiceRequestCommentV5) error {
+       errs := validation.Errors{
+               "deliveryServiceRequestId": 
validation.Validate(dsrc.DeliveryServiceRequestID, validation.NotNil),
+               "value":                    validation.Validate(dsrc.Value, 
validation.NotNil),
+       }
+       return util.JoinErrs(tovalidate.ToErrors(errs))
+}
+
+// Update is used to modify an existing DeliveryServiceRequestCommentV5 in the 
database.
+func Update(w http.ResponseWriter, r *http.Request) {
+       var deliveryServiceRequestComment tc.DeliveryServiceRequestCommentV5
+
+       inf, userErr, sysErr, errCode := api.NewInfo(r, []string{"id"}, 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 err := 
json.NewDecoder(r.Body).Decode(&deliveryServiceRequestComment); err != nil {
+               api.HandleErr(w, r, tx, http.StatusBadRequest, err, nil)
+               return
+       }
+
+       if err := Validate(deliveryServiceRequestComment); err != nil {
+               api.HandleErr(w, r, tx, http.StatusBadRequest, err, nil)
+               return
+       }
+
+       var current tc.DeliveryServiceRequestCommentV5
+       err := inf.Tx.QueryRowx(selectQuery() + `WHERE dsrc.id=` + 
inf.Params["id"]).StructScan(&current)
+       if err != nil {
+               api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, 
errors.New("scanning deliveryservice_request_comment: "+err.Error()))
+               return
+       }
+
+       userID := tc.IDNoMod(inf.User.ID)
+       if current.AuthorID != userID {
+               api.HandleErr(w, r, tx, http.StatusBadRequest, 
errors.New("comments can only be updated by the author"), nil)
+               return
+       }
+       deliveryServiceRequestComment.AuthorID = current.AuthorID
+       idParam := inf.Params["id"]
+       id, parseErr := strconv.Atoi(idParam)
+       if parseErr != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, 
errors.New("id must be an integer"), nil)
+               return
+       }
+       deliveryServiceRequestComment.ID = id
+       userErr, sysErr, sc := api.CheckIfUnModified(r.Header, inf.Tx, id, 
"deliveryservice_request_comment")
+       if userErr != nil || sysErr != nil {
+               api.HandleErr(w, r, tx, sc, userErr, sysErr)
+               return
+       }
+
+       rows, err := inf.Tx.NamedQuery(updateQuery(), 
deliveryServiceRequestComment)
+       if err != nil {
+               userErr, sysErr, sc := api.ParseDBError(err)
+               api.HandleErr(w, r, tx, sc, userErr, sysErr)
+               return
+       }
+       defer rows.Close()
+
+       if !rows.Next() {
+               api.HandleErr(w, r, tx, http.StatusNotFound, errors.New("no 
deliveryservice_request_comment 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 deliveryservice_request_comment insert: 
"+err.Error()))
+               return
+       }
+       deliveryServiceRequestComment.LastUpdated = time.Now()
+
+       if rows.Next() {
+               api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, 
errors.New("deliveryservice_request_comment update affected too many rows: >1"))
+               return
+       }
+
+       alerts := tc.CreateAlerts(tc.SuccessLevel, 
"deliveryservice_request_comment was updated.")
+       api.WriteAlertsObj(w, r, http.StatusOK, alerts, 
deliveryServiceRequestComment)
+       changeLogMsg := fmt.Sprintf("DELIVERYSERVICE_REQUEST_COMMENT: %d, ID: 
%d, ACTION: Updated deliveryservice_request_comment", 
deliveryServiceRequestComment.ID, deliveryServiceRequestComment.ID)
+       api.CreateChangeLogRawTx(api.ApiChange, changeLogMsg, inf.User, tx)
+}
+
+// Create is used to add a new DeliveryServiceRequestCommentV5 to the database.
+func Create(w http.ResponseWriter, r *http.Request) {
+       var deliveryServiceRequestComment tc.DeliveryServiceRequestCommentV5
+
+       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 err := 
json.NewDecoder(r.Body).Decode(&deliveryServiceRequestComment); err != nil {
+               api.HandleErr(w, r, tx, http.StatusBadRequest, err, nil)
+               return
+       }
+
+       if err := Validate(deliveryServiceRequestComment); err != nil {
+               api.HandleErr(w, r, tx, http.StatusBadRequest, err, nil)
+               return
+       }
+
+       au := tc.IDNoMod(inf.User.ID)
+       deliveryServiceRequestComment.AuthorID = au
+
+       resultRows, err := inf.Tx.NamedQuery(insertQuery(), 
deliveryServiceRequestComment)
+       if err != nil {
+               userErr, sysErr, errCode := api.ParseDBError(err)
+               api.HandleErr(w, r, tx, errCode, userErr, sysErr)
+               return
+       }
+       defer resultRows.Close()
+
+       rowsAffected := 0
+       for resultRows.Next() {
+               rowsAffected++
+               if err := resultRows.Scan(&deliveryServiceRequestComment.ID, 
&deliveryServiceRequestComment.LastUpdated); err != nil {
+                       api.HandleErr(w, r, tx, http.StatusInternalServerError, 
nil, errors.New("deliveryservice_request_comment create: scanning comment: 
"+err.Error()))
+                       return
+               }
+       }
+       if rowsAffected == 0 {
+               api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, 
errors.New("deliveryservice_request_comment create: comment couldn't be 
created"))
+               return
+       } else if rowsAffected > 1 {
+               api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, 
errors.New("deliveryservice_request_comment create: comment couldn't be 
created: too many ids returned from insert"))
+               return
+       }
+
+       alerts := tc.CreateAlerts(tc.SuccessLevel, 
"deliveryservice_request_comment was created.")
+       api.WriteAlertsObj(w, r, http.StatusOK, alerts, 
deliveryServiceRequestComment)
+       changeLogMsg := fmt.Sprintf("DELIVERYSERVICE_REQUEST_COMMENT: %d, ID: 
%d, ACTION: Created deliveryservice_request_comment", 
deliveryServiceRequestComment.ID, deliveryServiceRequestComment.ID)
+       api.CreateChangeLogRawTx(api.ApiChange, changeLogMsg, inf.User, tx)
+}
+
+// Delete is used to remove an existing DeliveryServiceRequestCommentV5 from 
the database.
+func Delete(w http.ResponseWriter, r *http.Request) {
+       inf, userErr, sysErr, errCode := api.NewInfo(r, []string{"id"}, nil)
+       if userErr != nil || sysErr != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
+               return
+       }
+       defer inf.Close()
+
+       tx := inf.Tx.Tx
+
+       idParam := inf.Params["id"]
+       id, parseErr := strconv.Atoi(idParam)
+       if parseErr != nil {
+               api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, 
errors.New("id must be an integer "+parseErr.Error()), nil)
+               return
+       }
+
+       var current tc.DeliveryServiceRequestCommentV5
+       err := inf.Tx.QueryRowx(selectQuery() + `WHERE dsrc.id=` + 
idParam).StructScan(&current)
+       if err != nil {
+               api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, 
errors.New("scanning deliveryservice_request_comment: "+err.Error()))
+               return
+       }
+
+       if userID := tc.IDNoMod(inf.User.ID); current.AuthorID != userID {
+               api.HandleErr(w, r, tx, http.StatusBadRequest, 
errors.New("comments can only be deleted by the author"), nil)
+               return
+       }
+
+       rows, err := inf.Tx.NamedQuery(deleteQuery(), current)
+       if err != nil {
+               api.HandleErr(w, r, tx, http.StatusInternalServerError, nil, 
fmt.Errorf("deleting deliveryservice_request_comment: %w", err))
+               return
+       }
+       rows.Close()
+       alerts := tc.CreateAlerts(tc.SuccessLevel, 
"deliveryservice_request_comment was deleted.")
+       api.WriteAlerts(w, r, http.StatusOK, alerts)
+       changeLogMsg := fmt.Sprintf("DELIVERYSERVICE_REQUEST_COMMENT: %d, 
ACTION: Deleted Deliveryservice_request_comment", id)
+       api.CreateChangeLogRawTx(api.ApiChange, changeLogMsg, inf.User, tx)
+}
diff --git a/traffic_ops/traffic_ops_golang/routing/routes.go 
b/traffic_ops/traffic_ops_golang/routing/routes.go
index 618002e4a6..90c6b53358 100644
--- a/traffic_ops/traffic_ops_golang/routing/routes.go
+++ b/traffic_ops/traffic_ops_golang/routing/routes.go
@@ -385,10 +385,10 @@ func Routes(d ServerData) ([]Route, http.Handler, error) {
                {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodPut, Path: `deliveryservice_requests/{id}/status$`, Handler: 
dsrequest.PutStatus, RequiredPrivLevel: auth.PrivLevelPortal, 
RequiredPermissions: []string{"DS-REQUEST:UPDATE", "DS-REQUEST:READ"}, 
Authenticated: Authenticated, Middlewares: nil, ID: 46841509931},
 
                //Delivery service request comment: CRUD
-               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodGet, Path: `deliveryservice_request_comments/?$`, Handler: 
api.ReadHandler(&comment.TODeliveryServiceRequestComment{}), RequiredPrivLevel: 
auth.PrivLevelReadOnly, RequiredPermissions: []string{"DS-REQUEST:READ", 
"DELIVERY-SERVICE:READ", "USER:READ"}, Authenticated: Authenticated, 
Middlewares: nil, ID: 403265073731},
-               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodPut, Path: `deliveryservice_request_comments/?$`, Handler: 
api.UpdateHandler(&comment.TODeliveryServiceRequestComment{}), 
RequiredPrivLevel: auth.PrivLevelPortal, RequiredPermissions: 
[]string{"DS-REQUEST:UPDATE", "DELIVERY-SERVICE:READ", "USER:READ"}, 
Authenticated: Authenticated, Middlewares: nil, ID: 46048784731},
-               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodPost, Path: `deliveryservice_request_comments/?$`, Handler: 
api.CreateHandler(&comment.TODeliveryServiceRequestComment{}), 
RequiredPrivLevel: auth.PrivLevelPortal, RequiredPermissions: 
[]string{"DS-REQUEST:UPDATE", "DELIVERY-SERVICE:READ", "USER:READ"}, 
Authenticated: Authenticated, Middlewares: nil, ID: 42722767231},
-               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodDelete, Path: `deliveryservice_request_comments/?$`, Handler: 
api.DeleteHandler(&comment.TODeliveryServiceRequestComment{}), 
RequiredPrivLevel: auth.PrivLevelPortal, RequiredPermissions: 
[]string{"DS-REQUEST:UPDATE", "DELIVERY-SERVICE:READ", "USER:READ"}, 
Authenticated: Authenticated, Middlewares: nil, ID: 49950466831},
+               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodGet, Path: `deliveryservice_request_comments/?$`, Handler: 
comment.Get, RequiredPrivLevel: auth.PrivLevelReadOnly, RequiredPermissions: 
[]string{"DS-REQUEST:READ", "DELIVERY-SERVICE:READ", "USER:READ"}, 
Authenticated: Authenticated, Middlewares: nil, ID: 403265073731},
+               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodPut, Path: `deliveryservice_request_comments/?$`, Handler: 
comment.Update, RequiredPrivLevel: auth.PrivLevelPortal, RequiredPermissions: 
[]string{"DS-REQUEST:UPDATE", "DELIVERY-SERVICE:READ", "USER:READ"}, 
Authenticated: Authenticated, Middlewares: nil, ID: 46048784731},
+               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodPost, Path: `deliveryservice_request_comments/?$`, Handler: 
comment.Create, RequiredPrivLevel: auth.PrivLevelPortal, RequiredPermissions: 
[]string{"DS-REQUEST:UPDATE", "DELIVERY-SERVICE:READ", "USER:READ"}, 
Authenticated: Authenticated, Middlewares: nil, ID: 42722767231},
+               {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodDelete, Path: `deliveryservice_request_comments/?$`, Handler: 
comment.Delete, RequiredPrivLevel: auth.PrivLevelPortal, RequiredPermissions: 
[]string{"DS-REQUEST:UPDATE", "DELIVERY-SERVICE:READ", "USER:READ"}, 
Authenticated: Authenticated, Middlewares: nil, ID: 49950466831},
 
                //Delivery service uri signing keys: CRUD
                {Version: api.Version{Major: 5, Minor: 0}, Method: 
http.MethodGet, Path: `deliveryservices/{xmlID}/urisignkeys$`, Handler: 
urisigning.GetURIsignkeysHandler, RequiredPrivLevel: auth.PrivLevelAdmin, 
RequiredPermissions: []string{"DS-SECURITY-KEY:READ"}, Authenticated: 
Authenticated, Middlewares: nil, ID: 429307855831},
diff --git a/traffic_ops/v5-client/deliveryservice_request_comments.go 
b/traffic_ops/v5-client/deliveryservice_request_comments.go
index e7d8f945ae..d089d32bbe 100644
--- a/traffic_ops/v5-client/deliveryservice_request_comments.go
+++ b/traffic_ops/v5-client/deliveryservice_request_comments.go
@@ -29,7 +29,7 @@ const apiDeliveryServiceRequestComments = 
"/deliveryservice_request_comments"
 
 // CreateDeliveryServiceRequestComment creates the given Delivery Service
 // Request comment.
-func (to *Session) CreateDeliveryServiceRequestComment(comment 
tc.DeliveryServiceRequestComment, opts RequestOptions) (tc.Alerts, 
toclientlib.ReqInf, error) {
+func (to *Session) CreateDeliveryServiceRequestComment(comment 
tc.DeliveryServiceRequestCommentV5, opts RequestOptions) (tc.Alerts, 
toclientlib.ReqInf, error) {
        var alerts tc.Alerts
        reqInf, err := to.post(apiDeliveryServiceRequestComments, opts, 
comment, &alerts)
        return alerts, reqInf, err
@@ -37,7 +37,7 @@ func (to *Session) 
CreateDeliveryServiceRequestComment(comment tc.DeliveryServic
 
 // UpdateDeliveryServiceRequestComment replaces the Delivery Service Request
 // comment identified by 'id' with the one provided.
-func (to *Session) UpdateDeliveryServiceRequestComment(id int, comment 
tc.DeliveryServiceRequestComment, opts RequestOptions) (tc.Alerts, 
toclientlib.ReqInf, error) {
+func (to *Session) UpdateDeliveryServiceRequestComment(id int, comment 
tc.DeliveryServiceRequestCommentV5, opts RequestOptions) (tc.Alerts, 
toclientlib.ReqInf, error) {
        if opts.QueryParameters == nil {
                opts.QueryParameters = url.Values{}
        }
@@ -49,8 +49,8 @@ func (to *Session) UpdateDeliveryServiceRequestComment(id 
int, comment tc.Delive
 
 // GetDeliveryServiceRequestComments retrieves all comments on all Delivery
 // Service Requests.
-func (to *Session) GetDeliveryServiceRequestComments(opts RequestOptions) 
(tc.DeliveryServiceRequestCommentsResponse, toclientlib.ReqInf, error) {
-       var data tc.DeliveryServiceRequestCommentsResponse
+func (to *Session) GetDeliveryServiceRequestComments(opts RequestOptions) 
(tc.DeliveryServiceRequestCommentsResponseV5, toclientlib.ReqInf, error) {
+       var data tc.DeliveryServiceRequestCommentsResponseV5
        reqInf, err := to.get(apiDeliveryServiceRequestComments, opts, &data)
        return data, reqInf, err
 }

Reply via email to