tenantutils - becoming stateless

Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/16eb2597
Tree: 
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/16eb2597
Diff: 
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/16eb2597

Branch: refs/heads/master
Commit: 16eb2597759ca265fba984f8caf1f0b0d8d1bd50
Parents: f5ca600
Author: nir-sopher <nirsop...@gmail.com>
Authored: Fri Jun 2 16:45:54 2017 +0300
Committer: Jeremy Mitchell <mitchell...@gmail.com>
Committed: Tue Jul 18 12:12:31 2017 -0600

----------------------------------------------------------------------
 traffic_ops/app/lib/API/Tenant.pm     |  44 +++++---
 traffic_ops/app/lib/UI/TenantUtils.pm | 171 +++++++++++++++--------------
 2 files changed, 119 insertions(+), 96 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/16eb2597/traffic_ops/app/lib/API/Tenant.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/app/lib/API/Tenant.pm 
b/traffic_ops/app/lib/API/Tenant.pm
index 4812439..e9b9cb5 100644
--- a/traffic_ops/app/lib/API/Tenant.pm
+++ b/traffic_ops/app/lib/API/Tenant.pm
@@ -36,18 +36,20 @@ sub index {
        my $self        = shift;        
        my $orderby = $self->param('orderby') || "name";
 
+       my $tenant_utils = UI::TenantUtils->new($self);
+       my $tenants_data = $tenant_utils->create_tenants_data_from_db($orderby);
+
        my @data = ();
-       my $tenantUtils = UI::TenantUtils->new($self);
-       my @tenants_list = $tenantUtils->get_hierarchic_tenants_list(undef, 
$orderby);
+       my @tenants_list = 
$tenant_utils->get_hierarchic_tenants_list($tenants_data, undef, $orderby);
        foreach my $row (@tenants_list) {
-               if ($tenantUtils->is_tenant_resource_readable($row->id)) {
+               if ($tenant_utils->is_tenant_resource_readable($tenants_data, 
$row->id)) {
                        push(
                                @data, {
                                        "id"           => $row->id,
                                        "name"         => $row->name,
                                        "active"       => \$row->active,
                                        "parentId"     => $row->parent_id,
-                                       "parentName"   => ( defined 
$row->parent_id ) ? $tenantUtils->get_tenant($row->parent_id)->name : undef,
+                                       "parentName"   => ( defined 
$row->parent_id ) ? $tenant_utils->get_tenant($tenants_data, 
$row->parent_id)->name : undef,
                                }
                        );
                }
@@ -60,18 +62,20 @@ sub show {
        my $self = shift;
        my $id   = $self->param('id');
 
+       my $tenant_utils = UI::TenantUtils->new($self);
+       my $tenants_data = $tenant_utils->create_tenants_data_from_db(undef);
+
        my @data = ();
-       my $tenantUtils = UI::TenantUtils->new($self);
        my $rs_data = $self->db->resultset("Tenant")->search( { 'me.id' => $id 
});
        while ( my $row = $rs_data->next ) {
-               if ($tenantUtils->is_tenant_resource_readable($row->id)) {
+               if ($tenant_utils->is_tenant_resource_readable($tenants_data, 
$row->id)) {
                        push(
                                @data, {
                                        "id"           => $row->id,
                                        "name"         => $row->name,
                                        "active"       => \$row->active,
                                        "parentId"     => $row->parent_id,
-                                       "parentName"   => ( defined 
$row->parent_id ) ? $tenantUtils->get_tenant($row->parent_id)->name : undef,
+                                       "parentName"   => ( defined 
$row->parent_id ) ? $tenant_utils->get_tenant($tenants_data, 
$row->parent_id)->name : undef,
                                }
                        );
                }
@@ -109,9 +113,10 @@ sub update {
                }       
        }       
 
-       my $tenantUtils = UI::TenantUtils->new($self);
+       my $tenant_utils = UI::TenantUtils->new($self);
+       my $tenants_data = $tenant_utils->create_tenants_data_from_db(undef);
 
-       if ( !defined( $params->{parentId}) && 
!$tenantUtils->is_root_tenant($id) ) {
+       if ( !defined( $params->{parentId}) && 
!$tenant_utils->is_root_tenant($tenants_data, $id) ) {
                # Cannot turn a simple tenant to a root tenant.
                # Practically there is no problem with doing so, but it is to 
risky to be done by mistake. 
                return $self->alert("Parent Id is required.");
@@ -123,7 +128,7 @@ sub update {
 
        my $is_active = $params->{active};
        
-       if ( !$params->{active} && $tenantUtils->is_root_tenant($id)) {
+       if ( !$params->{active} && $tenant_utils->is_root_tenant($tenants_data, 
$id)) {
                return $self->alert("Root tenant cannot be in-active.");
        }
 
@@ -134,11 +139,11 @@ sub update {
                $current_resource_tenancy = $id;
        }
        
-       if 
(!$tenantUtils->is_tenant_resource_writeable($current_resource_tenancy)) {
+       if (!$tenant_utils->is_tenant_resource_writeable($tenants_data, 
$current_resource_tenancy)) {
                return $self->alert("Current owning tenant is not under user's 
tenancy.");
        }
 
-       if (!$tenantUtils->is_tenant_resource_writeable($params->{parentId})) {
+       if (!$tenant_utils->is_tenant_resource_writeable($tenants_data, 
$params->{parentId})) {
                return $self->alert("Parent tenant to be set is not under 
user's tenancy.");
        }
 
@@ -150,6 +155,7 @@ sub update {
                parent_id => $params->{parentId}
        };
 
+       #$tenants_data is about to become outdated
        my $rs = $tenant->update($values);
        if ($rs) {
                my %idnames;
@@ -196,8 +202,10 @@ sub create {
                return $self->alert("Parent Id is required.");
        }
        
-       my $tenantUtils = UI::TenantUtils->new($self);
-       if (!$tenantUtils->is_tenant_resource_writeable($params->{parentId})) {
+       my $tenant_utils = UI::TenantUtils->new($self);
+       my $tenants_data = $tenant_utils->create_tenants_data_from_db(undef);
+       
+       if (!$tenant_utils->is_tenant_resource_writeable($tenants_data, 
$params->{parentId})) {
                return $self->alert("Parent tenant to be set is not under 
user's tenancy.");
        }
 
@@ -218,6 +226,7 @@ sub create {
                parent_id       => $params->{parentId}
        };
 
+       #$tenants_data is about to become outdated
        my $insert = $self->db->resultset('Tenant')->create($values);
        my $rs = $insert->insert();
        if ($rs) {
@@ -262,8 +271,10 @@ sub delete {
 
        my $parent_tenant = $tenant->parent_id;
        
-       my $tenantUtils = UI::TenantUtils->new($self);
-       if (!$tenantUtils->is_tenant_resource_writeable($parent_tenant)) {
+       my $tenant_utils = UI::TenantUtils->new($self);
+       my $tenants_data = $tenant_utils->create_tenants_data_from_db(undef);
+       
+       if (!$tenant_utils->is_tenant_resource_writeable($tenants_data, 
$parent_tenant)) {
                return $self->alert("Parent tenant is not under user's 
tenancy.");
        }
 
@@ -285,6 +296,7 @@ sub delete {
                return $self->alert("Tenant '$name' is assign with user(s): 
e.g. '$existing_user'. Please update these users and retry.");
        }
 
+       #$tenants_data is about to become outdated
        my $rs = $tenant->delete();
        if ($rs) {
                return $self->success_message("Tenant deleted.");

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/16eb2597/traffic_ops/app/lib/UI/TenantUtils.pm
----------------------------------------------------------------------
diff --git a/traffic_ops/app/lib/UI/TenantUtils.pm 
b/traffic_ops/app/lib/UI/TenantUtils.pm
index d2b1ea5..6b02f8e 100644
--- a/traffic_ops/app/lib/UI/TenantUtils.pm
+++ b/traffic_ops/app/lib/UI/TenantUtils.pm
@@ -15,53 +15,101 @@ package UI::TenantUtils;
 #
 #
 #
-use NetAddr::IP;
+
+
+#
+# This class provide utilities to examine different tenancy aspects, 
+# and specifically tenancy based access restrictions.
+#
+# The class itself is almost* stateless. However in order to reduce calls to 
DB, its
+# API allows the user to create the "DATA" object (using 
"create_tenants_data_from_db") 
+# and run utility functions over it.
+#
+# For now, until the current user tenant ID will come from the jwt, the 
current user tenant is taken from the DB.
+# In order to reduce the number of calls from the DB, the current user tenant 
is taken in the class creation
+#
+
 use Data::Dumper;
-use Switch;
 use UI::Utils;
 
 
 sub new {
        my $class = shift;
-       my $self  = {
-               context => shift,
-               user_tenant_id => -1,           
+       my $context = shift;
+       # For now, until the current user tenant ID will come from the jwt, the 
current user tenant is taken from the DB.
+       my $current_user_tenant = $context->db->resultset('TmUser')->search( { 
username => $context->current_user()->{username} } 
)->get_column('tenant_id')->single();
+       my $dbh = $context->db; 
+       my $self  = {           
+               dbh => $dbh,
+               # In order to reduce the number of calls from the DB, the 
current user tenant is taken in the class creation.
+               # the below parameters are held temporarily until the info is 
taken from the jwt
+               current_user_tenant => $current_user_tenant,
+               is_ldap => $context->is_ldap(),
+       };
+       bless $self, $class;
+       return $self;
+}
+
+sub create_tenants_data_from_db {
+       my $self = shift;
+       my $tenants_data = {
                tenants_dict => undef,
                root_tenants => undef,
                order_by => -1,
                ordered_by => undef,
        };
-       return bless $self, $class;
+       $tenants_data->{order_by} = shift || "name";#some default
+       
+       my $tenants_table = $self->{dbh}->resultset("Tenant")->search( undef, { 
order_by => $tenants_data->{order_by} });
+       
+       $tenants_data->{ordered_by} = ();
+       $tenants_data->{tenants_dict} = {};
+       while ( my $row = $tenants_table->next ) {
+               push (@{ $tenants_data->{ordered_by} }, $row->id);
+               $tenants_data->{tenants_dict}->{$row->id} = {
+                       row => $row,
+                       parent => $row->parent_id,
+                       children => (),
+               }
+       }
+       
+       $tenants_data->{root_tenants} = ();
+       foreach my $key (@{ $tenants_data->{ordered_by} }) {
+               my $value = $tenants_data->{tenants_dict}->{$key};
+               my $parent = $value->{parent};
+               if (!defined($parent))
+               {
+                       push @{ $tenants_data->{root_tenants} }, $key;
+               }
+               else{
+                       push @{ 
$tenants_data->{tenants_dict}->{$parent}{children} }, $key;
+               }
+       }
+       
+       return $tenants_data;
 }
 
-
 sub current_user_tenant {
        my $self = shift;
-       if ($self->{user_tenant_id} == -1) 
-       {
-               $self->{user_tenant_id} = 
$self->{context}->db->resultset('TmUser')->search( { username => 
$self->{context}->current_user()->{username} } 
)->get_column('tenant_id')->single();
-       }
-       return $self->{user_tenant_id};
+       return $self->{current_user_tenant};
 }
 
 sub get_tenant {
        my $self = shift;
+       my $tenants_data = shift;
        my $tenant_id = shift;  
        
-       $self->_init_tenants_if_needed(undef);
-
-       return $self->{tenants_dict}->{$tenant_id}{row};
+       return $tenants_data->{tenants_dict}->{$tenant_id}{row};
 }
 
 sub get_tenants_list {
        my $self = shift;
+       my $tenants_data = shift;
        my $order_by = shift;   
        
-       $self->_init_tenants_if_needed($order_by);
-
        my @result = ();
-       foreach my $tenant_id (@{ $self->{ordered_by} }) {
-               push @result, $self->{tenants_dict}->{$tenant_id}{row};
+       foreach my $tenant_id (@{ $tenants_data->{ordered_by} }) {
+               push @result, $tenants_data->{tenants_dict}->{$tenant_id}{row};
        }
 
        return @result; 
@@ -69,24 +117,23 @@ sub get_tenants_list {
 
 sub get_hierarchic_tenants_list {
        my $self = shift;
+       my $tenants_data = shift;
        my $tree_root = shift;  
        my $order_by = shift;   
        
-       $self->_init_tenants_if_needed($order_by);
-
        my @stack = ();
        if (defined($tree_root)){
                push (@stack, $tree_root);
        }
        else {
-               push (@stack, reverse(@{$self->{root_tenants}}));
+               push (@stack, reverse(@{$tenants_data->{root_tenants}}));
        }
 
        my @result = ();
        while (@stack) {
                my $tenant_id = pop @stack;
-               push (@result, $self->{tenants_dict}->{$tenant_id}{row});
-               push (@stack, 
reverse(@{$self->{tenants_dict}->{$tenant_id}{children}}));
+               push (@result, 
$tenants_data->{tenants_dict}->{$tenant_id}{row});
+               push (@stack, 
reverse(@{$tenants_data->{tenants_dict}->{$tenant_id}{children}}));
        }
                
        return @result; 
@@ -94,82 +141,47 @@ sub get_hierarchic_tenants_list {
 
 sub is_root_tenant {
        my $self = shift;
+       my $tenants_data = shift;
        my $tenant_id = shift;
        
        if (!defined($tenant_id)) {
                return 0;
        }
        
-       if (defined($self->{tenants_dict})) {
-               return !(defined($self->{tenants_dict}{$tenant_id}{parent}));
+       if (defined($tenants_data->{tenants_dict})) {
+               return 
!(defined($tenants_data->{tenants_dict}{$tenant_id}{parent}));
        }
-       return !defined($self->{context}->db->resultset('Tenant')->search( { id 
=> $tenant_id } )->get_column('parent_id')->single()); 
+       return !defined($self->{dbh}->resultset('Tenant')->search( { id => 
$tenant_id } )->get_column('parent_id')->single()); 
 }
 
 sub is_tenant_resource_readable {
-    my $self = shift;
-    my $resource_tenancy = shift;
+       my $self = shift;
+       my $tenants_data = shift;
+       my $resource_tenancy = shift;
     
-    return _is_resource_accessable ($self, $resource_tenancy, "r");
+       return $self->_is_resource_accessable ($tenants_data, 
$resource_tenancy, "r");
 }
 
 sub is_tenant_resource_writeable {
-    my $self = shift;
-    my $resource_tenancy = shift;
+       my $self = shift;
+       my $tenants_data = shift;
+       my $resource_tenancy = shift;
     
-    return _is_resource_accessable ($self, $resource_tenancy, "w");
+       return $self->_is_resource_accessable ($tenants_data, 
$resource_tenancy, "w");
 }
 
 
 
 ##############################################################
 
-sub _init_tenants {
-       my $self = shift;
-       $self->{order_by} = shift || "name";#some default
-       my $tenants_table = $self->{context}->db->resultset("Tenant")->search( 
undef, { order_by => $self->{order_by} });
-       
-       $self->{ordered_by} = ();
-       $self->{tenants_dict} = {};
-       while ( my $row = $tenants_table->next ) {
-               push (@{ $self->{ordered_by} }, $row->id);
-               $self->{tenants_dict}->{$row->id} = {
-                       row => $row,
-                       parent => $row->parent_id,
-                       children => (),
-               }
-       }
-       
-       $self->{root_tenants} = ();
-       foreach my $key (@{ $self->{ordered_by} }) {
-               my $value = $self->{tenants_dict}->{$key};
-               my $parent = $value->{parent};
-               if (!defined($parent))
-               {
-                       push @{ $self->{root_tenants} }, $key;
-               }
-               else{
-                       push @{ $self->{tenants_dict}->{$parent}{children} }, 
$key;
-               }
-       }
-}
-
-sub _init_tenants_if_needed {
-       my $self = shift;
-       my $order_by = shift;
-       if (($self->{order_by} == -1) || (defined($order_by) && $order_by != 
$self->{order_by})) {
-               ## first run to build the list OR (the order is important AND 
is not the current order)
-               $self->_init_tenants($order_by);
-       }
-}
-
-sub _max_tenancy_heirarchy {
+sub _tenancy_heirarchy_limit {
        my $self = shift;
        return 100;
 }
 
 sub _is_resource_accessable {
        my $self = shift;
+       my $tenants_data = shift;
        my $resource_tenant = shift;
        my $operation = shift;
 
@@ -178,7 +190,7 @@ sub _is_resource_accessable {
                return 1;
        }
 
-       if (&is_ldap($self->{context})) {
+       if ($self->{is_ldap}) {
                if ($operation eq "r") {
                        #ldap user, can read all tenants - temporary for now as 
an LDAP user as no tenant and is part of the TC operator.
                        # should be removed when LDAP is gone
@@ -188,14 +200,13 @@ sub _is_resource_accessable {
                return 0;
        }
        
-       my $user_tenant = current_user_tenant($self);
+       my $user_tenant = $self->current_user_tenant();
        if (!defined($user_tenant)) {
                #the user has no tenancy, - cannot approach items with tenancy
                return 0;
        }
 
-       $self->_init_tenants_if_needed(undef);
-       my $tenant_record = $self->{tenants_dict}->{$user_tenant};
+       my $tenant_record = $tenants_data->{tenants_dict}->{$user_tenant};
        my $is_active_tenant = $tenant_record->{row}->active;
        if (! $is_active_tenant) {
                #user tenant is in-active - cannot do any operation
@@ -208,7 +219,7 @@ sub _is_resource_accessable {
        }
 
        #checking if the user tenant is an ancestor of the resource tenant
-       for (my $depth = 0; $depth < $self->_max_tenancy_heirarchy(); $depth++) 
{
+       for (my $depth = 0; $depth < $self->_tenancy_heirarchy_limit(); 
$depth++) {
        
                if (!defined($resource_tenant)){
                        #reached top tenant, resource is not under the user 
tenancy
@@ -220,11 +231,11 @@ sub _is_resource_accessable {
                    return 1;
                }
                
-               $resource_tenant =  
$self->{tenants_dict}->{$resource_tenant}->{parent};
+               $resource_tenant =  
$tenants_data->{tenants_dict}->{$resource_tenant}->{parent};
        };
        
        #not found - recursion limit, give only access to root tenant
-       return $self->is_root_tenant(current_user_tenant($self));
+       return $self->is_root_tenant($tenants_data, $user_tenant);
 }
 
 1;

Reply via email to