Commit 8f62bf6d authored by serk's avatar serk Committed by Francesc Guasch
Browse files

Feature/996 new permission to rename (#997)

feat(grants): rename permission & _add_grant update description

* Added rename/rename_all/rename_clone grants.
* Added new feature when _add_grant(x, x, x, $description) is different from the BD updates it.
* added function to the conditions "can_manage_machine", "is_operator", "can_list_clones" and "can_list_machines".
* simple test checking the listing with rename_all and rename_clone
* simple test for rename
* major fix on SQL error _add_grant

issue #996
parent f4cc0072
......@@ -916,19 +916,29 @@ sub _alias_grants($self) {
}
sub _add_grants($self) {
$self->_add_grant('shutdown', 1,"Can shutdown own virtual machines");
$self->_add_grant('screenshot', 1,"Can get a screenshot of own virtual machines");
$self->_add_grant('start_many',0,"Can have more than one machine started")
$self->_add_grant('rename', 0,"Can rename any virtual machine owned by the user.");
$self->_add_grant('rename_all', 0,"Can rename any virtual machine.");
$self->_add_grant('rename_clones', 0,"Can rename clones from virtual machines owned by the user.");
$self->_add_grant('shutdown', 1,"Can shutdown own virtual machines.");
$self->_add_grant('screenshot', 1,"Can get a screenshot of own virtual machines.");
$self->_add_grant('start_many',0,"Can have more than one machine started.")
}
sub _add_grant($self, $grant, $allowed, $description) {
my $sth = $CONNECTOR->dbh->prepare(
"SELECT id FROM grant_types WHERE name=?"
"SELECT id, description FROM grant_types WHERE name=?"
);
$sth->execute($grant);
my ($id) = $sth->fetchrow();
my ($id, $current_description) = $sth->fetchrow();
$sth->finish;
if ($id && $current_description ne $description) {
my $sth = $CONNECTOR->dbh->prepare(
"UPDATE grant_types SET description = ? WHERE id = ?;"
);
$sth->execute($description, $id);
$sth->finish;
}
return if $id;
$sth = $CONNECTOR->dbh->prepare("INSERT INTO grant_types (name, description)"
......@@ -979,6 +989,7 @@ sub _enable_grants($self) {
,'clone', 'clone_all', 'create_base', 'create_machine'
,'grant'
,'manage_users'
,'rename', 'rename_all', 'rename_clones'
,'remove', 'remove_all', 'remove_clone', 'remove_clone_all'
,'screenshot'
,'shutdown', 'shutdown_all', 'shutdown_clone'
......
......@@ -365,7 +365,9 @@ sub is_operator {
return $self->is_admin()
|| $self->can_shutdown_clones()
# || $self->can_hibernate_clone()
|| $self->can_change_settings_clones()
|| $self->can_change_settings_clones()
|| $self->can_rename_all()
|| $self->can_rename_clones()
|| $self->can_remove_clones()
|| $self->can_remove_clone_all()
|| $self->can_create_base()
......@@ -402,7 +404,8 @@ Returns true if the user can list all machines that are clones and its bases
sub can_list_clones {
my $self = shift;
return 1 if $self->is_admin()
|| $self->can_remove_clone_all();
|| $self->can_rename_clones
|| $self->can_remove_clone_all;
return 0;
}
......@@ -414,7 +417,7 @@ Returns true if the user can list all machines that are clones from his bases
=cut
sub can_list_clones_from_own_base($self) {
return 1 if $self->can_remove_clones || $self->can_remove_clone_all
return 1 if $self->can_remove_clones || $self->can_remove_clone_all
|| $self->can_shutdown_clones
|| $self->can_change_settings_clones;
return 0;
......@@ -430,6 +433,7 @@ Returns true if the user can list all the virtual machines at the web frontend
sub can_list_machines {
my $self = shift;
return 1 if $self->is_admin()
|| $self->can_rename_all()
|| $self->can_remove_all || $self->can_remove_clone_all
|| $self->can_shutdown_all
|| $self->can_change_settings_all()
......@@ -617,7 +621,7 @@ Returns if the user is allowed to perform a privileged action in a virtual machi
=cut
sub can_do_domain($self, $grant, $domain) {
my %valid_grant = map { $_ => 1 } qw(change_settings shutdown);
my %valid_grant = map { $_ => 1 } qw(change_settings shutdown rename);
confess "Invalid grant here '$grant'" if !$valid_grant{$grant};
return 0 if !$self->can_do($grant) && !$domain->id_base;
......@@ -898,18 +902,15 @@ sub can_manage_machine($self, $domain) {
$domain = Ravada::Front::Domain->open($domain) if !ref $domain;
return 1 if $self->can_change_settings($domain);
return 1 if $self->can_clone_all
|| $self->can_change_settings($domain)
|| $self->can_rename_all
|| $self->can_remove_all
|| ($self->can_remove_clone_all && $domain->id_base)
|| ($self->can_remove && $domain->id_owner == $self->id);
return 1 if $self->can_remove_all;
return 1 if $self->can_remove_clone_all
&& $domain->id_base;
return 1 if $self->can_clone_all;
return 1 if $self->can_remove && $domain->id_owner == $self->id;
if ( ($self->can_remove_clones || $self->can_change_settings_clones) && $domain->id_base ) {
if ( ($self->can_remove_clones || $self->can_change_settings_clones || $self->can_rename_clones)
&& $domain->id_base ) {
my $base = Ravada::Front::Domain->open($domain->id_base);
return 1 if $base->id_owner == $self->id;
}
......
......@@ -449,11 +449,7 @@ get '/machine/info/(:id).(:type)' => sub {
my ($domain) = _search_requested_machine($c);
return access_denied($c) if !$domain;
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;
return access_denied($c,"Access denied to user ".$USER->name) unless $USER->can_manage_machine($domain->id);
my $info = $domain->info($USER);
if ($domain->is_active && !$info->{ip}) {
......@@ -465,7 +461,7 @@ get '/machine/info/(:id).(:type)' => sub {
get '/machine/requests/(:id).json' => sub {
my $c = shift;
my $id_domain = $c->stash('id');
return access_denied($c) if !$USER->can_manage_machine($id_domain);
return access_denied($c) unless $USER->can_manage_machine($id_domain);
$c->render(json => $RAVADA->list_requests($id_domain,10));
};
......
#!perl
use strict;
use warnings;
use Test::More;
use Test::SQL::Data;
use lib 't/lib';
use Test::Ravada;
use Ravada;
use Ravada::Domain;
use Data::Dumper;
# create the mock database
my $test = Test::SQL::Data->new(config => 't/etc/sql.conf');
# init ravada for testing
init();
##############################################################################
# full test
##############################################################################
sub test_rename {
my ($vm_name, $vm_hash, $domain_name, $domain_hash, $user) = @_;
my $new_domain_name = new_domain_name();
{
my $rvd_back = rvd_back();
ok($domain_hash,"[$vm_name] Expecting found $domain_name")
or return;
eval { $domain_hash->rename(name => $new_domain_name, user => $user) };
ok(!$@,"Expecting error='' , got ='".($@ or '')."'") or return;
}
my $domain_hash_0 = $vm_hash->search_domain($domain_name);
ok(!$domain_hash_0,"[$vm_name] Expecting not found $domain_name");
my $domain_hash_1 = $vm_hash->search_domain($new_domain_name);
ok($domain_hash_1,"[$vm_name] Expecting renamed domain $new_domain_name")
or return;
return $new_domain_name;
}
sub test_can_list_all {
my ($vm_hash, $vm_name, $user) = @_;
my ($domain_hash_0, $domain_name_0) = create_simple_domain($vm_hash, $vm_name, user_admin);
my ($domain_hash_1, $domain_name_1) = create_simple_domain($vm_hash, $vm_name, $user);
my $list = rvd_front->list_machines($user);
ok(grep { $_->{'name'} eq $domain_name_0 } @$list );
ok(grep { $_->{'name'} eq $domain_name_1 } @$list );
$domain_hash_1->remove(user_admin);
$domain_hash_0->remove(user_admin);
}
sub test_list_clones_from_own_base {
my ($vm_hash, $vm_name, $user) = @_;
my ($domain_hash_0, $domain_name_0) = create_simple_domain($vm_hash, $vm_name, user_admin);
my ($domain_hash_1, $domain_name_1) = create_simple_domain($vm_hash, $vm_name, $user);
my ($domain_hash_2, $domain_name_2) = create_simple_clone($domain_hash_1, user_admin);
my $list = rvd_front->list_machines($user);
ok(grep { $_->{'name'} eq $domain_name_1} @$list );
ok(grep { $_->{'name'} eq $domain_name_2 } @$list );
is(scalar @$list, 2);
$domain_hash_2->remove(user_admin);
$domain_hash_1->remove(user_admin);
$domain_hash_0->remove(user_admin);
}
sub create_simple_domain {
my ($vm_hash, $vm_name, $user) = @_;
my $domain_name = new_domain_name();
my $domain_hash = $vm_hash->create_domain(name => $domain_name
, id_owner => $user->id
, arg_create_dom($vm_name));
$domain_hash->stop() if $domain_hash->is_active();
return ($domain_hash, $domain_name);
}
sub create_simple_clone {
my ($domain_hash, $user) = @_;
$domain_hash->prepare_base( $user );
$domain_hash->is_public(1);
my $clone_name = new_domain_name;
my $clone_hash = $domain_hash->clone(
name => $clone_name
, user => $user
);
$clone_hash->stop() if $clone_hash->is_active();
return ($clone_hash, $clone_name);
}
##############################################################################
# environment
##############################################################################
sub test_admin_grant {
my ($vm_hash, $vm_name) = @_;
my ($domain_hash, $domain_name) = create_simple_domain($vm_hash, $vm_name, user_admin);
test_rename($vm_name, $vm_hash, $domain_name, $domain_hash, user_admin);
$domain_hash->remove(user_admin);
}
sub test_own_grant {
my ($vm_hash, $vm_name) = @_;
my $user_own = create_user("kevin.garvey","sleepwalk");
user_admin->grant($user_own,'create_machine');
user_admin->grant($user_own,'rename');
my ($domain_hash, $domain_name) = create_simple_domain($vm_hash, $vm_name, $user_own);
test_rename($vm_name, $vm_hash, $domain_name, $domain_hash, $user_own);
$domain_hash->remove(user_admin);
$user_own->remove();
}
sub test_all_grant {
my ($vm_hash, $vm_name) = @_;
my $user_all = create_user("kevin.garvey2","sleepwalk");
user_admin->grant($user_all,'create_machine');
user_admin->grant($user_all,'rename_all');
test_can_list_all($vm_hash, $vm_name, $user_all);
my ($domain_hash, $domain_name) = create_simple_domain($vm_hash, $vm_name, user_admin);
test_rename($vm_name, $vm_hash, $domain_name, $domain_hash, $user_all);
$domain_hash->remove(user_admin);
$user_all->remove();
}
sub test_clones_grant {
my ($vm_hash, $vm_name) = @_;
my $user_clones = create_user("kevin.garvey3","sleepwalk");
user_admin->grant($user_clones,'create_machine');
user_admin->grant($user_clones,'rename_clones');
test_list_clones_from_own_base($vm_hash, $vm_name, $user_clones);
my ($domain_hash, $domain_name) = create_simple_domain($vm_hash, $vm_name, $user_clones);
my ($clone_hash, $clone_name) = create_simple_clone($domain_hash, user_admin);
test_rename($vm_name, $vm_hash, $clone_name, $clone_hash, $user_clones);
$clone_hash->remove(user_admin);
$domain_hash->remove(user_admin);
$user_clones->remove();
}
##############################################################################
# main
##############################################################################
clean();
use_ok('Ravada');
for my $vm_name ( vm_names() ) {
my $vm_hash;
eval { $vm_hash = rvd_back->search_vm($vm_name) };
SKIP: {
my $msg = "SKIPPED test: No $vm_name VM found ";
if ($vm_hash && $vm_name =~ /kvm/i && $>) {
$msg = "SKIPPED: Test must run as root";
$vm_hash = undef;
}
diag($msg) if !$vm_hash;
skip $msg,10 if !$vm_hash;
diag("Testing rename on $vm_name");
test_admin_grant($vm_hash, $vm_name);
test_own_grant($vm_hash, $vm_name);
test_all_grant($vm_hash, $vm_name);
test_clones_grant($vm_hash, $vm_name);
}
}
clean();
done_testing();
......@@ -10,19 +10,23 @@
</div>
% }
% if ($USER->can_change_settings($domain->id)) {
% if ($USER->can_change_settings($domain->id) || $USER->can_rename($domain->id)) {
<div class="tab-content" id="nav-tabContent">
% if ($USER->can_change_settings($domain->id)) {
<div class="tab-pane fade show active" id="nav-description" role="tabpanel" aria-labelledby="nav-description-tab">
%= include 'main/vm_description'
</div>
%}
% if ($USER->can_rename($domain->id)) {
<div class="tab-pane fade" id="nav-rename" role="tabpanel" aria-labelledby="nav-rename-tab">
% if ($domain->is_base) {
%= include 'main/vm_locked_is_base'
% } else {
%= include 'main/vm_rename'
% }
% if ($domain->is_base) {
%= include 'main/vm_locked_is_base'
% } else {
%= include 'main/vm_rename'
% }
</div>
% }
<div class="tab-pane fade" id="nav-options" role="tabpanel" aria-labelledby="nav-options-tab">
%= include 'main/vm_options'
......
......@@ -3,7 +3,7 @@
% if ($USER->can_change_settings($domain->id)) {
<a class="nav-item nav-link active" id="nav-description-tab" ng-click="refresh_machine()" href="#nav-description" data-toggle="tab" role="tab" aria-controls="nav-description" aria-selected="true"><%=l 'Description' %></a>
% }
% if ($USER->can_change_settings($domain->id) && $USER->is_admin ) {
% if ($USER->can_rename($domain->id) ) {
<a class="nav-item nav-link" id="nav-rename-tab" ng-click="refresh_machine()" href="#nav-rename" data-toggle="tab" role="tab" aria-controls="nav-rename" aria-selected="false"><%=l 'Rename' %></a>
% }
% if ($USER->can_change_settings($domain->id) ) {
......
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