You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@trafficcontrol.apache.org by GitBox <gi...@apache.org> on 2018/03/01 20:33:45 UTC

[GitHub] dewrich closed pull request #1947: TO golang API -- add validations to phys_locations

dewrich closed pull request #1947: TO golang API -- add validations to phys_locations
URL: https://github.com/apache/incubator-trafficcontrol/pull/1947
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/lib/go-tc/physlocations.go b/lib/go-tc/physlocations.go
index 4d506b842a..594296918f 100644
--- a/lib/go-tc/physlocations.go
+++ b/lib/go-tc/physlocations.go
@@ -19,25 +19,21 @@ package tc
  * under the License.
  */
 
-type PhysLocationsResponse struct {
-	Response []PhysLocation `json:"response"`
-}
-
 type PhysLocation struct {
-	Address     string `json:"address" db:"address"`
-	City        string `json:"city" db:"city"`
-	Comments    string `json:"comments" db:"comments"`
-	Email       string `json:"email" db:"email"`
-	ID          int    `json:"id" db:"id"`
-	LastUpdated Time   `json:"lastUpdated" db:"last_updated"`
-	Name        string `json:"name" db:"name"`
-	Phone       string `json:"phone" db:"phone"`
-	POC         string `json:"poc" db:"poc"`
-	RegionID    int    `json:"regionId" db:"region"`
-	RegionName  string `json:"region" db:"region_name"`
-	ShortName   string `json:"shortName" db:"short_name"`
-	State       string `json:"state" db:"state"`
-	Zip         string `json:"zip" db:"zip"`
+	Address     string    `json:"address" db:"address"`
+	City        string    `json:"city" db:"city"`
+	Comments    string    `json:"comments" db:"comments"`
+	Email       string    `json:"email" db:"email"`
+	ID          int       `json:"id" db:"id"`
+	LastUpdated TimeNoMod `json:"lastUpdated" db:"last_updated"`
+	Name        string    `json:"name" db:"name"`
+	Phone       string    `json:"phone" db:"phone"`
+	POC         string    `json:"poc" db:"poc"`
+	RegionID    int       `json:"regionId" db:"region"`
+	RegionName  string    `json:"region" db:"region_name"`
+	ShortName   string    `json:"shortName" db:"short_name"`
+	State       string    `json:"state" db:"state"`
+	Zip         string    `json:"zip" db:"zip"`
 }
 
 // PhysLocationNullable - a struct version that allows for all fields to be null
@@ -45,18 +41,18 @@ type PhysLocationNullable struct {
 	//
 	// NOTE: the db: struct tags are used for testing to map to their equivalent database column (if there is one)
 	//
-	Address     *string `json:"address" db:"address"`
-	City        *string `json:"city" db:"city"`
-	Comments    *string `json:"comments" db:"comments"`
-	Email       *string `json:"email" db:"email"`
-	ID          *int    `json:"id" db:"id"`
-	LastUpdated Time    `json:"lastUpdated" db:"last_updated"`
-	Name        *string `json:"name" db:"name"`
-	Phone       *string `json:"phone" db:"phone"`
-	POC         *string `json:"poc" db:"poc"`
-	RegionID    *int    `json:"regionId" db:"region"`
-	RegionName  *string `json:"region" db:"region_name"`
-	ShortName   *string `json:"shortName" db:"short_name"`
-	State       *string `json:"state" db:"state"`
-	Zip         *string `json:"zip" db:"zip"`
+	Address     *string   `json:"address" db:"address"`
+	City        *string   `json:"city" db:"city"`
+	Comments    *string   `json:"comments" db:"comments"`
+	Email       *string   `json:"email" db:"email"`
+	ID          *int      `json:"id" db:"id"`
+	LastUpdated TimeNoMod `json:"lastUpdated" db:"last_updated"`
+	Name        *string   `json:"name" db:"name"`
+	Phone       *string   `json:"phone" db:"phone"`
+	POC         *string   `json:"poc" db:"poc"`
+	RegionID    *int      `json:"regionId" db:"region"`
+	RegionName  *string   `json:"region" db:"region_name"`
+	ShortName   *string   `json:"shortName" db:"short_name"`
+	State       *string   `json:"state" db:"state"`
+	Zip         *string   `json:"zip" db:"zip"`
 }
diff --git a/traffic_ops/traffic_ops_golang/physlocation/phys_locations.go b/traffic_ops/traffic_ops_golang/physlocation/phys_locations.go
index 7632343fcb..451fd92491 100644
--- a/traffic_ops/traffic_ops_golang/physlocation/phys_locations.go
+++ b/traffic_ops/traffic_ops_golang/physlocation/phys_locations.go
@@ -29,6 +29,8 @@ import (
 	"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/api"
 	"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/auth"
 	"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
+	"github.com/apache/incubator-trafficcontrol/traffic_ops/traffic_ops_golang/tovalidate"
+	validation "github.com/go-ozzo/ozzo-validation"
 	"github.com/jmoiron/sqlx"
 	"github.com/lib/pq"
 )
@@ -70,12 +72,19 @@ func (pl *TOPhysLocation) SetID(i int) {
 }
 
 func (pl *TOPhysLocation) Validate(db *sqlx.DB) []error {
-	errs := []error{}
-	name := pl.Name
-	if name != nil && len(*name) < 1 {
-		errs = append(errs, errors.New(`PhysLocation 'name' is required.`))
+	errs := validation.Errors{
+		"address":   validation.Validate(pl.Address, validation.Required),
+		"city":      validation.Validate(pl.City, validation.Required),
+		"name":      validation.Validate(pl.Name, validation.Required),
+		"regionId":  validation.Validate(pl.RegionID, validation.Required, validation.Min(0)),
+		"shortName": validation.Validate(pl.ShortName, validation.Required),
+		"state":     validation.Validate(pl.State, validation.Required),
+		"zip":       validation.Validate(pl.Zip, validation.Required),
 	}
-	return errs
+	if errs != nil {
+		return tovalidate.ToErrors(errs)
+	}
+	return nil
 }
 
 func (pl *TOPhysLocation) Read(db *sqlx.DB, parameters map[string]string, user auth.CurrentUser) ([]interface{}, []error, tc.ApiErrorType) {
@@ -177,7 +186,7 @@ func (pl *TOPhysLocation) Update(db *sqlx.DB, user auth.CurrentUser) (error, tc.
 	}
 	defer resultRows.Close()
 
-	var lastUpdated tc.Time
+	var lastUpdated tc.TimeNoMod
 	rowsAffected := 0
 	for resultRows.Next() {
 		rowsAffected++
@@ -242,7 +251,7 @@ func (pl *TOPhysLocation) Create(db *sqlx.DB, user auth.CurrentUser) (error, tc.
 	defer resultRows.Close()
 
 	var id int
-	var lastUpdated tc.Time
+	var lastUpdated tc.TimeNoMod
 	rowsAffected := 0
 	for resultRows.Next() {
 		rowsAffected++
diff --git a/traffic_ops/traffic_ops_golang/physlocation/phys_locations_test.go b/traffic_ops/traffic_ops_golang/physlocation/phys_locations_test.go
index ff61e435ba..dd16bcf72a 100644
--- a/traffic_ops/traffic_ops_golang/physlocation/phys_locations_test.go
+++ b/traffic_ops/traffic_ops_golang/physlocation/phys_locations_test.go
@@ -20,6 +20,8 @@ package physlocation
  */
 
 import (
+	"errors"
+	"reflect"
 	"testing"
 	"time"
 
@@ -39,7 +41,7 @@ func getTestPhysLocations() []tc.PhysLocation {
 		City:        "Denver",
 		Email:       "d.t@gmail.com",
 		ID:          1,
-		LastUpdated: tc.Time{Time: time.Now()},
+		LastUpdated: tc.TimeNoMod{Time: time.Now()},
 		Name:        "physLocation1",
 		Phone:       "303-210-0000",
 		POC:         "Dennis Thompson",
@@ -124,3 +126,21 @@ func TestInterfaces(t *testing.T) {
 		t.Errorf("PhysLocation must be Identifier")
 	}
 }
+
+func TestValidate(t *testing.T) {
+	p := TOPhysLocation{}
+	errs := test.SortErrors(p.Validate(nil))
+	expected := test.SortErrors([]error{
+		errors.New("'state' cannot be blank"),
+		errors.New("'zip' cannot be blank"),
+		errors.New("'address' cannot be blank"),
+		errors.New("'city' cannot be blank"),
+		errors.New("'name' cannot be blank"),
+		errors.New("'regionId' cannot be blank"),
+		errors.New("'shortName' cannot be blank"),
+	})
+
+	if !reflect.DeepEqual(expected, errs) {
+		t.Errorf("expected %++v,  got %++v", expected, errs)
+	}
+}
diff --git a/traffic_ops/traffic_ops_golang/test/helpers.go b/traffic_ops/traffic_ops_golang/test/helpers.go
index b550fabf0f..4b6ef9c479 100644
--- a/traffic_ops/traffic_ops_golang/test/helpers.go
+++ b/traffic_ops/traffic_ops_golang/test/helpers.go
@@ -21,6 +21,7 @@ package test
 
 import (
 	"reflect"
+	"sort"
 	"strings"
 )
 
@@ -40,3 +41,22 @@ func ColsFromStructByTag(tagName string, thing interface{}) []string {
 	}
 	return cols
 }
+
+// sortableErrors provides ordering a list of errors for easier comparison with an expected list
+type sortableErrors []error
+
+func (s sortableErrors) Len() int {
+	return len(s)
+}
+func (s sortableErrors) Swap(i, j int) {
+	s[i], s[j] = s[j], s[i]
+}
+func (s sortableErrors) Less(i, j int) bool {
+	return s[i].Error() < s[j].Error()
+}
+
+// SortErrors sorts the list of errors lexically
+func SortErrors(p []error) []error {
+	sort.Sort(sortableErrors(p))
+	return p
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services