-
Notifications
You must be signed in to change notification settings - Fork 339
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tenant utils #644
Tenant utils #644
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some comments for you. seems to work as i'd expect.
traffic_ops/app/lib/API/Tenant.pm
Outdated
while ( my $row = $rs_data->next ) { | ||
$idnames{ $row->id } = $row->name; | ||
} | ||
my $tenant_utils = UI::TenantUtils->new($self); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesn't seem like it's in the right place. how about putting TenantUtils in the Utils directory?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and then you can just call it Utils::Tenant
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool:) Will do.
I was not aware of this dir, just put it next to the "Util.pm"....
traffic_ops/app/lib/API/Tenant.pm
Outdated
if ( !defined( $params->{parentId}) && !$self->isRootTenant($id) ) { | ||
my $tenant_utils = UI::TenantUtils->new($self); | ||
my $tenants_data = $tenant_utils->create_tenants_data_from_db(undef); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about right here adding something like:
if ( is_root_tenant($tenants_data, $id) ) {
return $self->alert("Root tenant cannot be updated.");
}
I think we agreed that the root tenant can't be updated but I could be wrong. Anyhow, if you put this code right about here, then you won't have to check is_root_tenant() anymore in this function which I think will make your code easier to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed we agreed that a "root" tenant cannot become not root, and a non-root cannot become root. It also cannot be disabled.
Does it mean that a root tenant cannot be changed? I;m not sure but it indeed simolify things.
Will do
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, i would say the root tenant can't be changed in any way. you can't change it's name, or it's active flag or it's parent (which has to be null). that is a record in the database that can't be changed at all thru the api.
traffic_ops/app/lib/API/Tenant.pm
Outdated
#this is a write operation, allowed only by parents of the tenant (which are the owners of the resource of type tenant) | ||
my $current_resource_tenancy = $self->db->resultset('Tenant')->search( { id => $id } )->get_column('parent_id')->single(); | ||
if (!defined($current_resource_tenancy)) { | ||
#no parent - the tenant is its-own owner |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
every tenant must have a parent, right? except for the root tenant. therefore, I don't think this is necessary if you follow my advice above and exit the function if the tenant is the root tenant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed
traffic_ops/app/lib/API/Tenant.pm
Outdated
return $self->alert("Failed to retrieve tenant height."); | ||
} | ||
|
||
if ($parent_depth+$tenant_height+1 > $tenant_utils->max_heirarchy_limit()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we just get rid of the max_heirarchy_limit? that would get rid of your need to figure out depth and height and simplify this code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The limit is there to avoid infinite loops in tenant-utils in case of cyclic parent pointing. There is no way I;m aware of to create such loops but bugs may prove me wrong:)
As I set a limit in the loops themselves, I wanted to keep the code coherent and block the option to create deeper hierarchy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, i see
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so i've been thinking about this a little more. by putting in a max hierarchy depth, you are putting in a safety net in case somehow cyclical parents are created. for example.
root has no parent
foo has baz parent <-- cyclical
bar has foo parent
baz has bar parent
however, this feels pretty hacky putting in this safety net and it could cover up valid problems. i think it's more important to just ensure that the parent for a tenant can never be assigned as itself or as a child tenant and then make sure you have a robust set of tests to validate this. for example:
- root
-- foo
--- bar
---- baz
when updating the bar tenant, bar and baz are invalid parents.
IF a bug slips thru and an infinite loop is created, then we fix it and write a test case to represent the scenario that created an infinite loop to ensure it is fixed and doesn't happen again. safety nets worry me because they may cover up bugs that need to be fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inside your is_ancestor function, you probably need a recursive function to walk down the tree starting with the tenant to be updated to ensure that the new parent is != self or child.
so your function call would look like this
if (!is_ancestor($tenant, $parent)) return $self->alert("Invalid parent")
here's an article regarding recursion in perl: https://perlmaven.com/recursive-subroutines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, safety nets may cover up bugs, but not in this case - the operation will fail instead of crashing or getting stuck. Then we can debug it.
Furthermore, we will have an error in the log pointing out the reason of the failure - what we will not have if we get into an infinite loop/recursion.
traffic_ops/app/lib/API/Tenant.pm
Outdated
my $is_tenant_achestor_of_parent = $tenant_utils->is_anchestor_of($tenants_data, $id, $params->{parentId}); | ||
if (!defined($is_tenant_achestor_of_parent)) | ||
{ | ||
return $self->alert("Failed to check tenant and parent current relations."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this error message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The above test comes to verify we do not create cyclic graph by parent pointing. We check if the designated child is already an ancestor of his parent.
return $self->alert("Failed to retrieve parent tenant depth."); | ||
} | ||
|
||
if ($parent_depth+1 > $tenant_utils->max_heirarchy_limit()-1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
again, if we get rid of the max_heirarchy_limit, then you can simplify this code.
traffic_ops/app/lib/API/Tenant.pm
Outdated
my $tenant_utils = UI::TenantUtils->new($self); | ||
my $tenants_data = $tenant_utils->create_tenants_data_from_db(undef); | ||
|
||
if (!$tenant_utils->is_tenant_resource_accessible($tenants_data, $parent_tenant)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't think that deleting a tenant should matter what the parent tenant is. for example, if this is the tenant hierarcy:
- root
-- tenant 1
--- tenant 1a
--- tenant 1b
and i have a user with tenant = tenant 1a, then i should be able to delete tenant 1a even though i don't have tenant 1 assigned to me. what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the parent as an owner of the child, and as such he is the one to be able to delete it.
It is a matter of taste, but note: anyhow a user must not delete his own tenant...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, that's a good point. if i try to delete my own tenant, i will get back "sorry, this tenant is assigned to a user", right?
traffic_ops/app/lib/API/User.pm
Outdated
@@ -404,7 +406,7 @@ sub current { | |||
my $self = shift; | |||
my @data; | |||
my $current_username = $self->current_user()->{username}; | |||
|
|||
my $tenantUtils = UI::TenantUtils->new($self); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can go away. you are not using this variable.
True.
Note that there is also a matter of consistency: Tenant update can also be
done only by the parent. Would you like to change that as well?
…On Jun 29, 2017 12:23 AM, "Jeremy Mitchell" ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In traffic_ops/app/lib/API/Tenant.pm
<#644 (comment)>
:
> @@ -248,7 +326,17 @@ sub delete {
if ( !defined($tenant) ) {
return $self->not_found();
}
- my $name = $self->db->resultset('Tenant')->search( { id => $id } )->get_column('name')->single();
+
+ my $parent_tenant = $tenant->parent_id;
+
+ my $tenant_utils = UI::TenantUtils->new($self);
+ my $tenants_data = $tenant_utils->create_tenants_data_from_db(undef);
+
+ if (!$tenant_utils->is_tenant_resource_accessible($tenants_data, $parent_tenant)) {
oh, that's a good point. if i try to delete my own tenant, i will get back
"sorry, this tenant is assigned to a user", right?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#644 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AXGkYJ98rZeJkzjhKMlVyTgHkyJFR3Prks5sIsRjgaJpZM4NwdcT>
.
|
file move moved as required |
…o the API for simple testing
Adding the "TenantUtils" class allowing to check if resource is accessible (tenancy wise).
The class provides further tenants related functionality like get the tenants in hierarchic order, check if a tenant is a root tenant, etc.
The tenants API was adjusted to use this class as well as permit "tenant resource" operations based on the current user tenancy