Unverified Commit 7c872709 authored by Francesc Guasch's avatar Francesc Guasch Committed by GitHub
Browse files

698 grants (#824)

* test(frontend): list machines

returns only machines available to the user

issue #698

* wip(grants): fixed list and settings

list own clones and machines
change settings to own clones and machines

issue #698

* fix(frontend): list bases only show public to non-admins

issue #698

* fix(backend): check iso file wasn't picking the right arg

this is because we cherry-picked this code

issue #780

* wip(grants): can list own machines if can create

issue #698

* wip(frontend): properly show and hide action buttons

issue #698

* test(backend): check deep recurson from frontend

issue #698

* wip(backend): fix deep recurson from frontend

issue #698

* Grants revision

* fix(backend): removed domains return inactive

issue #698

* wip(frontend): allow manage machine

issue #698

* wip(fronted): hide clones if listing large for user

issue #698

* wip(grants): fixed list machines when can remove all

issue #698

* fix(frontend): settings is now manage

issue #698

* fix clone permisions

* Fix remove_clones , remove_clones_all & remove

* Fix can_change_settings_clones

* fix show grants when user has grant permissions

* fix show users when user has manage_users permission

* fix jump into /admin/users without permissions

* feat(grants): show restore button only if user allowed

issue #698

* wip(text): title

* wip(text): title

Issue #698

* feat(grants): manage machine

issue #698

* fix(grants): only admin user can rename

as long as we don't have the can_rename grant

issue #698

* feat(frontend): show user permissions

issue #698

* fix(grants): allow remove clones if remove all

grant access to front and show the remove clones info and form

issue #698

* fix(backend): show display URL if allowed

issue #698

* feat(grants): screenshot permission

issue #698

* fix(grants): check change settings allowed for machine

issue #698

* wip(grants): fixed list and settings

list own clones and machines
change settings to own clones and machines

issue #698

* fix(backend): check iso file wasn't picking the right arg

this is because we cherry-picked this code

issue #780

* wip(grants): can list own machines if can create

issue #698

* Grants revision

* wip(frontend): allow manage machine

issue #698

* fix clone permisions

* feat(grants): show restore button only if user allowed

issue #698

* wip(text): title

* feat(grants): manage machine

issue #698

* fix(grants): only admin user can rename

as long as we don't have the can_rename grant

issue #698

* feat(frontend): show user permissions

issue #698

* fix(grants): allow remove clones if remove all

grant access to front and show the remove clones info and form

issue #698

* fix(backend): show display URL if allowed

issue #698

* feat(grants): screenshot permission

issue #698

* fix(grants): check change settings allowed for machine

issue #698

* test(frontend): get domain drivers

issue #809

* wip(frontend): get domain drivers from front

issue #809

* fix(drivers): moved get drivers to front

issue #809

* test(settings): check settings aplied and readable

issue #809

* feat(grants): allow access to machine settings

issue #698

* wip(grants) grant grant permission

issue #698
parent fd0c3de3
......@@ -864,6 +864,7 @@ sub _enable_grants($self) {
,'grant'
,'manage_users'
,'remove', 'remove_all', 'remove_clone', 'remove_clone_all'
,'screenshot'
,'shutdown', 'shutdown_all', 'shutdown_clone'
,'screenshot'
);
......@@ -2372,7 +2373,7 @@ sub _cmd_set_driver {
confess "Unkown domain ".Dumper($request) if !$domain;
die "USER $uid not authorized to set driver for domain ".$domain->name
if $domain->id_owner != $user->id && !$user->is_admin;
unless $user->can_change_settings($domain->id);
$domain->set_driver_id($request->args('id_option'));
$domain->needs_restart(1) if $domain->is_active;
......
......@@ -353,6 +353,7 @@ sub is_operator {
|| $self->can_create_machine
|| $self->can_list_machines
|| $self->can_change_settings_all()
|| $self->can_grant()
|| 0;
}
......@@ -588,7 +589,7 @@ sub can_do_domain($self, $grant, $domain) {
return 0 if !$self->can_do($grant) && !$domain->id_base;
return 1 if $self->can_do("${grant}_all");
return 1 if $domain->id_owner == $self->id;
return 1 if $domain->id_owner == $self->id && $self->can_do($grant);
if ($self->can_do("${grant}_clones") && $domain->id_base) {
my $base = Ravada::Front::Domain->open($domain->id_base);
......@@ -661,7 +662,7 @@ sub grant_user_permissions($self,$user) {
$self->grant($user, 'change_settings');
$self->grant($user, 'remove');
$self->grant($user, 'shutdown');
# $self->grant($user, 'screenshot');
$self->grant($user, 'screenshot');
}
=head2 grant_operator_permissions
......
......@@ -86,7 +86,7 @@ requires 'get_controller_by_name';
requires 'list_controllers';
requires 'set_controller';
requires 'remove_controller';
#
##########################################################
has 'domain' => (
......@@ -505,7 +505,7 @@ sub _allowed {
eval { $id_owner = $self->id_owner };
my $err = $@;
confess "User ".$user->name." [".$user->id."] not allowed to access ".$self->domain
confess "User ".$user->name." [".$user->id."] not allowed to access ".$self->name
." owned by ".($id_owner or '<UNDEF>')
if (defined $id_owner && $id_owner != $user->id );
......@@ -858,12 +858,15 @@ sub info($self, $user) {
,name => $self->name
,is_active => $self->is_active
,spice_password => $self->spice_password
,display_url => $self->display($user)
,description => $self->description
,msg_timeout => ( $self->_msg_timeout or undef)
,has_clones => ( $self->has_clones or undef)
,needs_restart => ( $self->needs_restart or 0)
};
eval {
$info->{display_url} = $self->display($user);
};
die $@ if $@ && $@ !~ /not allowed/i;
if (!$info->{description} && $self->id_base) {
my $base = Ravada::Front::Domain->open($self->id_base);
$info->{description} = $base->description;
......
......@@ -154,7 +154,7 @@ sub list_machines_user {
if ($clone) {
$base{is_locked} = $clone->is_locked;
if ($clone->is_active && !$clone->is_locked) {
if ($clone->is_active && !$clone->is_locked && $user->can_screenshot) {
my $req = Ravada::Request->screenshot_domain(
id_domain => $clone->id
,filename => "$DIR_SCREENSHOTS/".$clone->id.".png"
......@@ -164,7 +164,9 @@ sub list_machines_user {
$base{screenshot} = ( $clone->_data('file_screenshot')
or $base{screenshot});
$base{is_active} = $clone->is_active;
$base{id_clone} = $clone->id
$base{id_clone} = $clone->id;
$base{can_remove} = 0;
$base{can_remove} = 1 if $user->can_remove && $clone->id_owner == $user->id;
}
$base{screenshot} =~ s{^/var/www}{};
lock_hash(%base);
......@@ -187,21 +189,6 @@ sub list_machines($self, $user) {
push @list,(@$machines);
}
=pod
if ($user->can_remove_clone_all()) {
my $machines = $self->list_bases( );
for my $base (@$machines) {
my $clones = $self->list_domains( id_base => $base->{id} );
next if !scalar @$clones;
push @list, ($base);
push @list, @{$clones};
}
}
=cut
push @list,(@{$self->list_clones()}) if $user->can_list_clones;
if ($user->can_create_base || $user->can_create_machine || $user->is_operator) {
my $machines = $self->list_domains(id_owner => $user->id);
......
......@@ -60,14 +60,16 @@ Argument: name
=cut
sub get_driver($self, $name) {
sub get_driver {
my $self = shift;
my $name = shift;
my $sub = $GET_DRIVER_SUB{$name};
confess "I can't get driver $name for domain ".$self->name
die "I can't get driver $name for domain ".$self->name
if !$sub;
$self->xml_description_inactive if ref($self) !~ /Front/;
$self->xml_description if ref($self) !~ /Front/;
return $sub->($self);
}
......
......@@ -75,6 +75,7 @@ our %VALID_ARG = (
our %CMD_SEND_MESSAGE = map { $_ => 1 }
qw( create start shutdown prepare_base remove remove_base rename_domain screenshot download
autostart_domain hibernate hybernate
change_owner
change_max_memory change_curr_memory
add_hardware remove_hardware set_driver
);
......
......@@ -606,7 +606,7 @@ sub _domain_create_from_iso {
my $device_cdrom;
confess "Template ".$iso->{name}." has no URL, iso_file argument required."
if !$iso->{url} && !$iso->{device} && !$iso_file;
if !$iso->{url} && !$iso_file && !$iso->{device};
if ($iso_file) {
if ( $iso_file ne "<NONE>") {
......
......@@ -342,8 +342,11 @@ get '/machine/info/(:id).(:type)' => sub {
my ($domain) = _search_requested_machine($c);
return access_denied($c) if !$domain;
return access_denied($c) unless $USER->is_admin
|| $domain->id_owner == $USER->id;
return access_denied($c,"Access denied to user ".$USER->name) unless $USER->is_admin
|| $domain->id_owner == $USER->id
|| $USER->can_change_settings($domain->id)
|| $USER->can_remove_machine($domain->id)
|| $USER->can_clone_all;
$c->render(json => $domain->info($USER) );
};
......@@ -406,7 +409,8 @@ any '/machine/remove_clones/(:id).(:type)' => sub {
return access_denied($c)
unless
$USER -> can_remove_clone_all()
|| $USER ->can_remove_clone();
|| $USER->can_remove_clone()
|| $USER->can_remove_all();
return remove_clones($c);
};
......@@ -470,14 +474,9 @@ get '/machine/exists/#name' => sub {
};
get '/machine/rename/#id' => sub {
my $c = shift;
return access_denied($c) if !$USER -> can_rename();
return rename_machine($c);
};
get '/machine/rename/#id/#value' => sub {
my $c = shift;
return access_denied($c) if !$USER->can_manage_machine($c->stash('id'));
return rename_machine($c);
};
......@@ -1154,11 +1153,17 @@ sub _search_req_base_error {
sub access_denied {
my $c = shift;
my $msg = 'Access denied to '.$c->req->url->to_abs->path;
my $msg = shift;
$msg .= ' for user '.$USER->name if $USER && !$USER->is_temporary;
if (!$msg) {
$msg = 'Access denied to '.$c->req->url->to_abs->path;
$msg .= ' for user '.$USER->name if $USER && !$USER->is_temporary;
}
return $c->render(text => $msg);
if (defined $c->stash('type') && $c->stash('type') eq 'json') {
return $c->render(json => { error => $msg }, status => 403);
}
return $c->render(text => $msg, status => 403);
}
sub base_id {
......@@ -1641,7 +1646,7 @@ sub copy_machine {
return login($c) if !_logged_in($c);
my $id_base= $c->param('id_base');
my $id_base= $c->param('id_base') or confess "Missing param id_base";
my $ram = $c->param('copy_ram');
$ram = 0 if $ram !~ /^\d+(\.\d+)?$/;
......@@ -1653,7 +1658,7 @@ sub copy_machine {
my ($param_name) = grep /^copy_name_\d+/,(@{$c->req->params->names});
my $base = $RAVADA->search_domain_by_id($id_base);
my $base = $RAVADA->search_domain_by_id($id_base) or confess "I can't find domain $id_base";
my $name = $c->req->param($param_name) if $param_name;
$name = $base->name."-".$USER->name if !$name;
......@@ -1693,7 +1698,6 @@ sub rename_machine {
my $id_domain = $c->stash('id');
my $new_name = $c->stash('value');
return login($c) if !_logged_in($c);
return access_denied($c) if !$USER->is_admin();
#return $c->render(data => "Machine id not found in $uri ")
return $c->render(data => "Machine id not found")
......
......@@ -178,6 +178,9 @@ sub test_remove_clone {
$clone->remove($usera);
$domain->remove($usera);
for $clone ( $domain->clones ) {
$clone->remove($usera);
}
$user->remove();
$usera->remove();
......@@ -209,6 +212,9 @@ sub test_view_clones {
eval{ $clones = rvd_front->list_clones() };
is(scalar @$clones, 0) or return;
$clone->remove(user_admin);
$domain->remove(user_admin);
$usera->remove();
$user->remove();
}
......@@ -342,6 +348,7 @@ sub test_shutdown_all {
$domain->remove($usera);
$user->remove();
$usera->remove();
}
sub test_remove_clone_all {
......@@ -399,6 +406,8 @@ sub test_remove_clone_all {
$clone->remove($usera);
$domain->remove($usera);
$domain2->remove($usera);
$other_domain->remove($usera);
$user->remove();
$usera->remove();
......@@ -494,12 +503,13 @@ sub test_frontend {
$list_machines = rvd_front->list_domains( id_owner => $user->id );
is (scalar @$list_machines, 1 );
create_domain($vm_name, $user);
my $domain_other = create_domain($vm_name, $user);
$list_machines = rvd_front->list_domains( id_owner => $user->id );
is (scalar @$list_machines, 2 );
$clone->remove( $usera );
$domain->remove( $usera );
$domain_other->remove( $usera );
$usera->remove;
$user->remove;
......@@ -575,6 +585,10 @@ sub test_create_domain {
eval { $base->remove($usera) if $domain };
is($@,'');
$base->remove(user_admin) if !$base->is_removed;
$clone->remove(user_admin) if !$clone->is_removed;
$domain->remove(user_admin) if !$domain->is_removed;
$user->remove();
$usera->remove();
diag("done test create");
......@@ -664,7 +678,6 @@ sub test_create_domain2 {
}
sub test_change_settings($vm_name) {
my $vm = rvd_back->search_vm($vm_name);
my $user = create_user("oper_cs$$","bar");
......@@ -740,7 +753,9 @@ test_operator();
clean();
for my $vm_name (vm_names()) {
next if $vm_name eq 'KVM' && $>;
diag("Testing VM $vm_name");
test_change_settings($vm_name);
test_shutdown_clone($vm_name);
......@@ -758,6 +773,11 @@ for my $vm_name (vm_names()) {
test_create_domain2($vm_name);
test_view_clones($vm_name);
test_prepare_base($vm_name);
test_frontend($vm_name);
test_create_domain($vm_name);
test_create_domain2($vm_name);
test_view_clones($vm_name);
test_clone_all($vm_name);
}
......
% for my $grant ($_user->list_permissions) {
<li><b><%= $grant->[0] %> </b>: <%= $grant->[1] %></li>
% }
......@@ -35,7 +35,7 @@
<a type="button" class="btn btn-success" ng-hide="host_action == machine.id"
href="/machine/clone/{{machine.id}}.html"><strong><i class="fa fa-play" aria-hidden="true"></i>&nbsp;<%=l 'Start' %></strong></a>
<a type="button" class="btn btn-danger"
ng-show="machine.id_clone && !machine.is_active"
ng-show="machine.id_clone && !machine.is_active && machine.can_remove"
ng-click="host_restore=machine.id_clone; $parent.refresh=20"
><strong><i class="fas fa-redo" aria-hidden="true"></i>&nbsp;<%=l 'Restore' %></strong></a>
<div ng-show="machine.id_clone && host_restore == machine.id_clone">
......@@ -57,6 +57,7 @@
ng-show="host_action == machine.id && !host_restore"
>
<a type="button" class="btn btn-default btn-sm"
ng-show="machine.can_remove"
ng-click="host_restore=machine.id_clone"
><%=l 'Restore' %></a>
......
......@@ -8,7 +8,7 @@ ment">
<div class="page-header">
<div class="panel panel-default">
<div class="panel-heading">
<h2><%=l 'User' %><%= $user->name %></h2>
<h2><%=l 'User' %>&nbsp;<%= $user->name %></h2>
</div> <!-- del panel heading-->
</div>
<ul class="nav nav-tabs" id="myTab">
......
......@@ -12,16 +12,6 @@
<div class="page-header">
<div class="panel panel-default">
<div class="panel-heading">
%#<<<<<<< HEAD:templates/bootstrap/users.html.ep
%# <h2>Users List
%# <button style="float: right; margin: 0 10px;" class="btn btn-info" onclick="location.reload('forceGet')"><i class="fa fa-refresh" aria-hidden="true"></i></button>
%# <button type="button" style="float: right; margin: 0 10px;" class="btn btn-success" onclick = "location='/users/register'">Add new user</button>
%# </h2>
%# </div>
%#
%# <sol-show-listusers></sol-show-listusers>
%#
%#=======
<h2>Request <%= $request->{command} %> <%= $request->args->{name} %> <%= $request->{status} %></h2>
<p>
<a href="/request/<%= $request->{id} %>.html">Refresh</a>
......
......@@ -29,6 +29,7 @@ h !DOCTYPE html>
%= include 'main/settings_machine_tabs_head'
%= include 'main/settings_machine_tabs_body'
</div>
<div class="alert alert-danger" ng-show="error">{{error}}</div>
</div><!-- del panel default-->
</div><!-- del page-header -->
</div><!-- del ng-controller -->
......
......@@ -2,7 +2,7 @@
% if ($USER->can_change_settings($domain->id)) {
<li class="nav active"><a ng-click="refresh_machine()" href="#description" data-toggle="tab"><%=l 'Description' %></a></li>
% }
% if ($USER->can_change_settings($domain->id) ) {
% if ($USER->can_change_settings($domain->id) && $USER->is_admin ) {
<li class="nav"><a ng-click="refresh_machine()" href="#rename" data-toggle="tab"><%=l 'Rename' %></a></li>
% }
% if ($USER->can_change_settings($domain->id) ) {
......
......@@ -5,7 +5,7 @@
<form class="form-inline" method="post" action="/machine/copy">
<div class="row">
<div class="col-md-2">
<input class="form-control" type="hidden" name="id_base" value="{{showmachine.id}}-copy">
<input class="form-control" type="hidden" name="id_base" value="{{showmachine.id}}">
<label class="control-label"
for="copy_name_{{showmachine.id}}"><%=l 'Name' %></label>
</div>
......
......@@ -17,7 +17,7 @@
</div>
<div ng-show="!domain_remove_done">
% if ($USER->can_remove_clone_all) {
% if ($USER->can_remove_clone_all || $USER->can_remove_all) {
<a ng-show="showmachine.has_clones > 0" type="button" class="btn btn-danger"
ng-click="domain_remove_clones=1"
>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment