This is an automated email from the ASF dual-hosted git repository.
ocket8888 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 4a6f1e6 Add sort by privilege level to TO and use it in TP (#3682)
4a6f1e6 is described below
commit 4a6f1e62b8fdb4d9fed59ce006e5c6eb9ed07228
Author: Alex Luckerman <[email protected]>
AuthorDate: Wed Aug 7 15:41:25 2019 -0600
Add sort by privilege level to TO and use it in TP (#3682)
* Add sort by priv_level to TO and use in TP
* Add support for sorting roles by priv_level
* Change TP to request roles ordered by priv_level
* Add support to TO Go to order by descending order
* Change TP to request roles in descending order
* Change TO sort direction parameter
* Require valid orderby before applying sortOrder
* Make requested PR changes
* Fix comment and raise API version to 1.4
* Update CHANGELOG.md
* Fix roles sortBy TO API test
* Fix Go comment
* Remove db-admin binary
---
CHANGELOG.md | 1 +
traffic_ops/client/role.go | 36 +++++++++++++++++-----
traffic_ops/testing/api/v14/roles_test.go | 33 +++++++++++++++++++-
.../traffic_ops_golang/dbhelpers/db_helpers.go | 12 +++++++-
traffic_ops/traffic_ops_golang/role/roles.go | 6 ++--
.../app/src/modules/private/roles/list/index.js | 2 +-
6 files changed, 76 insertions(+), 14 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ce9f36a..3b51a6f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -38,6 +38,7 @@ The format is based on [Keep a
Changelog](http://keepachangelog.com/en/1.0.0/).
- Added /#!/sso page to Traffic Portal to catch redirects back from OAuth
provider and POST token into the API.
- In Traffic Portal, server table columns can now be rearranged and their
visibility toggled on/off as desired by the user. Hidden table columns are
excluded from the table search. These settings are persisted in the browser.
- Added pagination support to some Traffic Ops endpoints via three new query
parameters, limit and offset/page
+- Traffic Ops now supports a "sortOrder" query parameter on some endpoints to
return API responses in descending order
### Changed
- Traffic Router, added TLS certificate validation on certificates imported
from Traffic Ops
diff --git a/traffic_ops/client/role.go b/traffic_ops/client/role.go
index 5e0c185..5e415ab 100644
--- a/traffic_ops/client/role.go
+++ b/traffic_ops/client/role.go
@@ -26,7 +26,7 @@ import (
)
const (
- API_v13_ROLES = "/api/1.3/roles"
+ API_v14_ROLES = "/api/1.4/roles"
)
// Create a Role
@@ -38,7 +38,7 @@ func (to *Session) CreateRole(region tc.Role) (tc.Alerts,
ReqInf, int, error) {
if err != nil {
return tc.Alerts{}, reqInf, 0, err
}
- resp, remoteAddr, errClient := to.rawRequest(http.MethodPost,
API_v13_ROLES, reqBody)
+ resp, remoteAddr, errClient := to.rawRequest(http.MethodPost,
API_v14_ROLES, reqBody)
if resp != nil {
defer resp.Body.Close()
var alerts tc.Alerts
@@ -59,7 +59,7 @@ func (to *Session) UpdateRoleByID(id int, region tc.Role)
(tc.Alerts, ReqInf, in
if err != nil {
return tc.Alerts{}, reqInf, 0, err
}
- route := fmt.Sprintf("%s/?id=%d", API_v13_ROLES, id)
+ route := fmt.Sprintf("%s/?id=%d", API_v14_ROLES, id)
resp, remoteAddr, errClient := to.rawRequest(http.MethodPut, route,
reqBody)
if resp != nil {
defer resp.Body.Close()
@@ -74,7 +74,7 @@ func (to *Session) UpdateRoleByID(id int, region tc.Role)
(tc.Alerts, ReqInf, in
// Returns a list of roles
func (to *Session) GetRoles() ([]tc.Role, ReqInf, int, error) {
- resp, remoteAddr, errClient := to.rawRequest(http.MethodGet,
API_v13_ROLES, nil)
+ resp, remoteAddr, errClient := to.rawRequest(http.MethodGet,
API_v14_ROLES, nil)
reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr:
remoteAddr}
if resp != nil {
defer resp.Body.Close()
@@ -90,7 +90,7 @@ func (to *Session) GetRoles() ([]tc.Role, ReqInf, int, error)
{
// GET a Role by the Role id
func (to *Session) GetRoleByID(id int) ([]tc.Role, ReqInf, int, error) {
- route := fmt.Sprintf("%s/?id=%d", API_v13_ROLES, id)
+ route := fmt.Sprintf("%s/?id=%d", API_v14_ROLES, id)
resp, remoteAddr, errClient := to.rawRequest(http.MethodGet, route, nil)
reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr:
remoteAddr}
if resp != nil {
@@ -107,8 +107,28 @@ func (to *Session) GetRoleByID(id int) ([]tc.Role, ReqInf,
int, error) {
// GET a Role by the Role name
func (to *Session) GetRoleByName(name string) ([]tc.Role, ReqInf, int, error) {
- url := fmt.Sprintf("%s?name=%s", API_v13_ROLES, url.QueryEscape(name))
- resp, remoteAddr, errClient := to.rawRequest(http.MethodGet, url, nil)
+ route := fmt.Sprintf("%s?name=%s", API_v14_ROLES, url.QueryEscape(name))
+ resp, remoteAddr, errClient := to.rawRequest(http.MethodGet, route, nil)
+ reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr:
remoteAddr}
+ if resp != nil {
+ defer resp.Body.Close()
+
+ var data tc.RolesResponse
+ if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
+ return data.Response, reqInf, resp.StatusCode, err
+ }
+ return data.Response, reqInf, resp.StatusCode, errClient
+ }
+ return []tc.Role{}, reqInf, 0, errClient
+}
+
+// GetRoleByQueryParams gets a Role by the Role query parameters
+func (to *Session) GetRoleByQueryParams(queryParams map[string]string)
([]tc.Role, ReqInf, int, error) {
+ route := fmt.Sprintf("%s?", API_v14_ROLES)
+ for param, val := range queryParams {
+ route += fmt.Sprintf("%s=%s&", url.QueryEscape(param),
url.QueryEscape(val))
+ }
+ resp, remoteAddr, errClient := to.rawRequest(http.MethodGet, route, nil)
reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr:
remoteAddr}
if resp != nil {
defer resp.Body.Close()
@@ -124,7 +144,7 @@ func (to *Session) GetRoleByName(name string) ([]tc.Role,
ReqInf, int, error) {
// DELETE a Role by ID
func (to *Session) DeleteRoleByID(id int) (tc.Alerts, ReqInf, int, error) {
- route := fmt.Sprintf("%s/?id=%d", API_v13_ROLES, id)
+ route := fmt.Sprintf("%s/?id=%d", API_v14_ROLES, id)
resp, remoteAddr, errClient := to.rawRequest(http.MethodDelete, route,
nil)
reqInf := ReqInf{CacheHitStatus: CacheHitStatusMiss, RemoteAddr:
remoteAddr}
if resp != nil {
diff --git a/traffic_ops/testing/api/v14/roles_test.go
b/traffic_ops/testing/api/v14/roles_test.go
index 0fd588b..e34c0ce 100644
--- a/traffic_ops/testing/api/v14/roles_test.go
+++ b/traffic_ops/testing/api/v14/roles_test.go
@@ -34,11 +34,12 @@ func TestRoles(t *testing.T) {
WithObjs(t, []TCObj{Parameters, Roles}, func() {
UpdateTestRoles(t)
GetTestRoles(t)
+ VerifyGetRolesOrder(t)
})
}
func CreateTestRoles(t *testing.T) {
- expectedAlerts := []tc.Alerts{tc.Alerts{[]tc.Alert{tc.Alert{"role was
created.", "success"}}}, tc.Alerts{[]tc.Alert{tc.Alert{"can not add
non-existent capabilities: [invalid-capability]", "error"}}}}
+ expectedAlerts := []tc.Alerts{tc.Alerts{[]tc.Alert{tc.Alert{"role was
created.", "success"}}}, tc.Alerts{[]tc.Alert{tc.Alert{"can not add
non-existent capabilities: [invalid-capability]", "error"}}},
tc.Alerts{[]tc.Alert{tc.Alert{"role was created.", "success"}}}}
for i, role := range testData.Roles {
var alerts tc.Alerts
alerts, _, status, err := TOSession.CreateRole(role)
@@ -105,6 +106,36 @@ func GetTestRoles(t *testing.T) {
}
+func VerifyGetRolesOrder(t *testing.T) {
+ params := map[string]string{
+ "orderby": "name",
+ "sortOrder": "desc",
+ }
+ descResp, _, status, err := TOSession.GetRoleByQueryParams(params)
+ log.Debugln("Status Code: ", status)
+ if err != nil {
+ t.Errorf("cannot GET Role by role: %v - %v\n", err, descResp)
+ }
+ params["sortOrder"] = "asc"
+ ascResp, _, status, err := TOSession.GetRoleByQueryParams(params)
+ log.Debugln("Status Code: ", status)
+ if err != nil {
+ t.Errorf("cannot GET Role by role: %v - %v\n", err, ascResp)
+ }
+
+ if reflect.DeepEqual(descResp, ascResp) {
+ t.Errorf("Role responses for descending and ascending are the
same: %v - %v\n", descResp, ascResp)
+ }
+
+ // reverse the descending-sorted response and compare it to the
ascending-sorted one
+ for start, end := 0, len(descResp)-1; start < end; start, end =
start+1, end-1 {
+ descResp[start], descResp[end] = descResp[end], descResp[start]
+ }
+ if !reflect.DeepEqual(descResp, ascResp) {
+ t.Errorf("Role responses are not equal after reversal: %v -
%v\n", descResp, ascResp)
+ }
+}
+
func DeleteTestRoles(t *testing.T) {
role := testData.Roles[roleGood]
diff --git a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
index dfd6cff..7fbb06d 100644
--- a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
+++ b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
@@ -63,8 +63,18 @@ func BuildWhereAndOrderByAndPagination(parameters
map[string]string, queryParams
if colInfo, ok := queryParamsToSQLCols[orderby]; ok {
log.Debugln("orderby column ", colInfo)
orderBy += " " + colInfo.Column
+
+ // if orderby is specified and valid, also check for
sortOrder
+ if sortOrder, exists := parameters["sortOrder"]; exists
{
+ log.Debugln("sortOrder: ", sortOrder)
+ if sortOrder == "desc" {
+ orderBy += " DESC"
+ } else if sortOrder != "asc" {
+ log.Debugln("sortOrder value must be
desc or asc. Invalid value provided: ", sortOrder)
+ }
+ }
} else {
- log.Debugln("Incorrect name for orderby: ", orderby)
+ log.Debugln("This column is not configured to support
orderby: ", orderby)
}
}
diff --git a/traffic_ops/traffic_ops_golang/role/roles.go
b/traffic_ops/traffic_ops_golang/role/roles.go
index 1f4b580..68621aa 100644
--- a/traffic_ops/traffic_ops_golang/role/roles.go
+++ b/traffic_ops/traffic_ops_golang/role/roles.go
@@ -50,9 +50,9 @@ func (v *TORole) NewReadObj() interface{} { return
&TORole{} }
func (v *TORole) SelectQuery() string { return selectQuery() }
func (v *TORole) ParamColumns() map[string]dbhelpers.WhereColumnInfo {
return map[string]dbhelpers.WhereColumnInfo{
- "name": dbhelpers.WhereColumnInfo{"name", nil},
- "id": dbhelpers.WhereColumnInfo{"id", api.IsInt},
- }
+ "name": dbhelpers.WhereColumnInfo{"name", nil},
+ "id": dbhelpers.WhereColumnInfo{"id", api.IsInt},
+ "privLevel": dbhelpers.WhereColumnInfo{"priv_level", api.IsInt}}
}
func (v *TORole) UpdateQuery() string { return updateQuery() }
func (v *TORole) DeleteQuery() string { return deleteQuery() }
diff --git a/traffic_portal/app/src/modules/private/roles/list/index.js
b/traffic_portal/app/src/modules/private/roles/list/index.js
index f991001..a85bde3 100644
--- a/traffic_portal/app/src/modules/private/roles/list/index.js
+++ b/traffic_portal/app/src/modules/private/roles/list/index.js
@@ -28,7 +28,7 @@ module.exports =
angular.module('trafficPortal.private.roles.list', [])
controller:
'TableRolesController',
resolve: {
roles:
function(roleService) {
- return
roleService.getRoles({ orderby: 'priv_level DESC' });
+ return
roleService.getRoles({ orderby: 'privLevel', sortOrder : 'desc' });
}
}
}