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 b99eda5  Service Categories tenancy cross referencing DS tenancy 
(#5146)
b99eda5 is described below

commit b99eda51b03505f48d67aadf481d16470455a7f4
Author: mattjackson220 <[email protected]>
AuthorDate: Tue Oct 27 16:09:39 2020 -0600

    Service Categories tenancy cross referencing DS tenancy (#5146)
    
    * Service Categories tenancy cross referencing DS tenancy
    
    * update per comment
---
 .../deliveryservice/deliveryservices.go            | 44 ++++++++++++++++++++++
 .../servicecategory/servicecategories.go           | 31 +++++++++++++--
 traffic_ops/traffic_ops_golang/tenant/tenancy.go   | 35 +++++++++++++++--
 .../FormDeliveryServiceController.js               |  2 +-
 4 files changed, 105 insertions(+), 7 deletions(-)

diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go 
b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
index 5bd05fd..fe7a665 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
@@ -194,6 +194,28 @@ func CreateV30(w http.ResponseWriter, r *http.Request) {
                return
        }
 
+       if ds.ServiceCategory != nil {
+               serviceCategoryTenantId, exists, err := 
tenant.GetServiceCategoryTenantIDByNameTx(inf.Tx.Tx, *ds.ServiceCategory)
+               if err != nil {
+                       api.HandleErr(w, r, inf.Tx.Tx, 
http.StatusInternalServerError, nil, errors.New("getting service category 
tenancy"))
+                       return
+               }
+               if !exists {
+                       api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, 
errors.New("service category "+*ds.ServiceCategory+" does not exist"), nil)
+                       return
+               }
+
+               ok, err := tenant.CrossReferenceTenancy(inf.Tx.Tx, 
serviceCategoryTenantId, *ds.TenantID)
+               if err != nil {
+                       api.HandleErr(w, r, inf.Tx.Tx, 
http.StatusInternalServerError, nil, errors.New("cross referencing service 
category tenancy with delivery service"))
+                       return
+               }
+               if !ok {
+                       api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, 
errors.New("delivery service tenant does not have access to this service 
category"), nil)
+                       return
+               }
+       }
+
        res, status, userErr, sysErr := createV30(w, r, inf, ds)
        if userErr != nil || sysErr != nil {
                api.HandleErr(w, r, inf.Tx.Tx, status, userErr, sysErr)
@@ -607,6 +629,28 @@ func UpdateV30(w http.ResponseWriter, r *http.Request) {
        }
        ds.ID = &id
 
+       if ds.ServiceCategory != nil {
+               serviceCategoryTenantId, exists, err := 
tenant.GetServiceCategoryTenantIDByNameTx(inf.Tx.Tx, *ds.ServiceCategory)
+               if err != nil {
+                       api.HandleErr(w, r, inf.Tx.Tx, 
http.StatusInternalServerError, nil, errors.New("getting service category 
tenancy"))
+                       return
+               }
+               if !exists {
+                       api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, 
errors.New("service category "+*ds.ServiceCategory+" does not exist"), nil)
+                       return
+               }
+
+               ok, err := tenant.CrossReferenceTenancy(inf.Tx.Tx, 
serviceCategoryTenantId, *ds.TenantID)
+               if err != nil {
+                       api.HandleErr(w, r, inf.Tx.Tx, 
http.StatusInternalServerError, nil, errors.New("cross referencing service 
category tenancy with delivery service"))
+                       return
+               }
+               if !ok {
+                       api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, 
errors.New("delivery service tenant does not have access to this service 
category"), nil)
+                       return
+               }
+       }
+
        res, status, userErr, sysErr := updateV30(w, r, inf, &ds)
        if userErr != nil || sysErr != nil {
                api.HandleErr(w, r, inf.Tx.Tx, status, userErr, sysErr)
diff --git 
a/traffic_ops/traffic_ops_golang/servicecategory/servicecategories.go 
b/traffic_ops/traffic_ops_golang/servicecategory/servicecategories.go
index d585aee..41ef03f 100644
--- a/traffic_ops/traffic_ops_golang/servicecategory/servicecategories.go
+++ b/traffic_ops/traffic_ops_golang/servicecategory/servicecategories.go
@@ -136,12 +136,37 @@ func (serviceCategory *TOServiceCategory) Read(h 
http.Header, useIMS bool) ([]in
 
        filteredServiceCategories := []interface{}{}
        for _, sc := range serviceCategories {
-               sc1 := sc.(*tc.ServiceCategory)
-               if checkTenancy(sc1, tenantIDs) {
-                       filteredServiceCategories = 
append(filteredServiceCategories, sc1)
+               scToCheck := sc.(*tc.ServiceCategory)
+               if checkTenancy(scToCheck, tenantIDs) {
+                       filteredServiceCategories = 
append(filteredServiceCategories, scToCheck)
                }
        }
 
+       dsIdParam := serviceCategory.APIInfo().Params["dsId"]
+
+       if dsIdParam != "" {
+               dsId, err := strconv.Atoi(dsIdParam)
+               if err != nil {
+                       return nil, errors.New("dsId query param must be an 
int"), nil, http.StatusBadRequest, nil
+               }
+               dsTenantId, _, err := 
tenant.GetDSTenantIDByIDTx(serviceCategory.APIInfo().Tx.Tx, dsId)
+
+               dsAllowedTenants, err := 
tenant.GetUserTenantIDListTx(serviceCategory.APIInfo().Tx.Tx, *dsTenantId)
+               if err != nil {
+                       return nil, nil, errors.New("getting tenant list for 
user: " + err.Error()), http.StatusInternalServerError, nil
+               }
+
+               filteredSCByDS := []interface{}{}
+               for _, sc := range filteredServiceCategories {
+                       scToCheck := sc.(*tc.ServiceCategory)
+                       if checkTenancy(scToCheck, dsAllowedTenants) {
+                               filteredSCByDS = append(filteredSCByDS, 
scToCheck)
+                       }
+               }
+
+               return filteredSCByDS, nil, nil, errCode, maxTime
+       }
+
        return filteredServiceCategories, nil, nil, errCode, maxTime
 }
 
diff --git a/traffic_ops/traffic_ops_golang/tenant/tenancy.go 
b/traffic_ops/traffic_ops_golang/tenant/tenancy.go
index c40643c..e7827da 100644
--- a/traffic_ops/traffic_ops_golang/tenant/tenancy.go
+++ b/traffic_ops/traffic_ops_golang/tenant/tenancy.go
@@ -83,7 +83,7 @@ func Check(user *auth.CurrentUser, XMLID string, tx *sql.Tx) 
(error, error, int)
 // a system error, and an HTTP error code. If both the user and system error 
are nil, the error
 // code should be ignored.
 func CheckID(tx *sql.Tx, user *auth.CurrentUser, dsID int) (error, error, int) 
{
-       dsTenantID, ok, err := getDSTenantIDByIDTx(tx, dsID)
+       dsTenantID, ok, err := GetDSTenantIDByIDTx(tx, dsID)
        if err != nil {
                return nil, errors.New("checking tenant: " + err.Error()), 
http.StatusInternalServerError
        }
@@ -214,10 +214,10 @@ FETCH FIRST 1 ROW ONLY;
        }
 }
 
-// getDSTenantIDByIDTx returns the tenant ID, whether the delivery service 
exists, and any error.
+// GetDSTenantIDByIDTx returns the tenant ID, whether the delivery service 
exists, and any error.
 // Note the id may be nil, even if true is returned, if the delivery service 
exists but its tenant_id field is null.
 // TODO move somewhere generic
-func getDSTenantIDByIDTx(tx *sql.Tx, id int) (*int, bool, error) {
+func GetDSTenantIDByIDTx(tx *sql.Tx, id int) (*int, bool, error) {
        tenantID := (*int)(nil)
        if err := tx.QueryRow(`SELECT tenant_id FROM deliveryservice where id = 
$1`, id).Scan(&tenantID); err != nil {
                if err == sql.ErrNoRows {
@@ -227,3 +227,32 @@ func getDSTenantIDByIDTx(tx *sql.Tx, id int) (*int, bool, 
error) {
        }
        return tenantID, true, nil
 }
+
+// GetServiceCategoryTenantIDByNameTx returns the tenant ID, whether the 
service category exists, and any error.
+func GetServiceCategoryTenantIDByNameTx(tx *sql.Tx, name string) (int, bool, 
error) {
+       var tenantID int
+       if err := tx.QueryRow(`SELECT tenant_id FROM service_category where 
name = $1`, name).Scan(&tenantID); err != nil {
+               if err == sql.ErrNoRows {
+                       return 0, false, nil
+               }
+               return 0, false, fmt.Errorf("querying tenant ID for service 
category name '%v': %v", name, err)
+       }
+       return tenantID, true, nil
+}
+
+// CrossReferenceTenancy returns whether the tenantId is within the tenancy 
tree hierarchy of the tenantIdToReference
+// and any error.
+func CrossReferenceTenancy(tx *sql.Tx, tenantId int, tenantIdToReference int) 
(bool, error) {
+       allowedTenants, err := GetUserTenantIDListTx(tx, tenantIdToReference)
+       if err != nil {
+               return false, errors.New("getting tenant list: " + err.Error())
+       }
+
+       for _, tenantID := range allowedTenants {
+               if tenantID == tenantId {
+                       return true, nil
+               }
+       }
+       return false, nil
+
+}
diff --git 
a/traffic_portal/app/src/common/modules/form/deliveryService/FormDeliveryServiceController.js
 
b/traffic_portal/app/src/common/modules/form/deliveryService/FormDeliveryServiceController.js
index be36235..07f487a 100644
--- 
a/traffic_portal/app/src/common/modules/form/deliveryService/FormDeliveryServiceController.js
+++ 
b/traffic_portal/app/src/common/modules/form/deliveryService/FormDeliveryServiceController.js
@@ -47,7 +47,7 @@ var FormDeliveryServiceController = function(deliveryService, 
dsCurrent, origin,
     };
 
     var getServiceCategories = function() {
-        serviceCategoryService.getServiceCategories()
+        serviceCategoryService.getServiceCategories({dsId: deliveryService.id 
})
             .then(function(result) {
                 $scope.serviceCategories = result;
             });

Reply via email to