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

feat(grants): grants aliases (#783)

* test(grants): check old and new grants

issue #773

* feature(grants): grants aliases

issue #773
parent 5a0bd1e2
......@@ -652,7 +652,9 @@ sub _update_data {
$self->_remove_old_isos();
$self->_update_isos();
$self->_update_grants();
$self->_rename_grants();
$self->_alias_grants();
$self->_add_grants();
$self->_enable_grants();
$self->_update_user_grants();
......@@ -662,22 +664,50 @@ sub _update_data {
}
sub _update_grants($self) {
sub _rename_grants($self) {
my %rename = (
create_domain => 'create_machine'
,remove_clone => 'remove_clones'
,shutdown_clone => 'shutdown_clones'
);
my $sth_old = $CONNECTOR->dbh->prepare("SELECT id FROM grant_types"
." WHERE name=?"
);
for my $old ( keys %rename ) {
$sth_old->execute($rename{$old});
next if $sth_old->fetchrow;
my $sth = $CONNECTOR->dbh->prepare(
"UPDATE grant_types"
." SET name=? "
." WHERE name = ?"
);
$sth->execute($rename{$old}, $old);
warn "INFO: renaming grant $old to $rename{$old}\n";
}
}
sub _alias_grants($self) {
my %alias= (
remove_clone => 'remove_clones'
,shutdown_clone => 'shutdown_clones'
);
my $sth_old = $CONNECTOR->dbh->prepare("SELECT id FROM grant_types_alias"
." WHERE name=? AND alias=?"
);
while (my ($old, $new) = each(%alias)) {
$sth_old->execute($old, $new);
return if $sth_old->fetch;
my $sth = $CONNECTOR->dbh->prepare(
"INSERT INTO grant_types_alias (name,alias)"
." VALUES(?,?) "
);
$sth->execute($old, $new);
}
}
sub _add_grants($self) {
$self->_add_grant('shutdown', 1);
}
......@@ -740,8 +770,8 @@ sub _enable_grants($self) {
,'clone', 'clone_all', 'create_base', 'create_machine'
,'grant'
,'manage_users'
,'remove', 'remove_all', 'remove_clones', 'remove_clone_all'
,'shutdown', 'shutdown_all', 'shutdown_clones'
,'remove', 'remove_all', 'remove_clone', 'remove_clone_all'
,'shutdown', 'shutdown_all', 'shutdown_clone'
);
$sth = $CONNECTOR->dbh->prepare("SELECT id,name FROM grant_types");
......
......@@ -12,6 +12,7 @@ Ravada::Auth::SQL - SQL authentication library for Ravada
use Carp qw(carp);
use Ravada;
use Ravada::Utils;
use Ravada::Front;
use Digest::SHA qw(sha1_hex);
use Hash::Util qw(lock_hash);
......@@ -152,35 +153,34 @@ sub add_user {
my $user = Ravada::Auth::SQL->search_by_id($id_user);
# temporary allow grant permissions
my $id_grant = _search_id_grant('grant');
$sth = $$CON->dbh->prepare(
"INSERT INTO grants_user "
." (id_grant, id_user, allowed)"
." VALUES(?,?,1) "
);
$sth->execute($id_grant, $id_user);
$sth->finish;
$user->grant_user_permissions($user);
Ravada::Utils::user_daemon->grant_user_permissions($user);
if (!$is_admin) {
$user->grant_user_permissions($user);
$user->revoke($user,'grant');
Ravada::Utils::user_daemon->grant_user_permissions($user);
return $user;
}
$user->grant_admin_permissions($user);
Ravada::Utils::user_daemon->grant_admin_permissions($user);
return $user;
}
sub _search_id_grant {
my $type = shift;
my $sth = $$CON->dbh->prepare("SELECT id FROM grant_types WHERE name = ?");
$sth->execute($type);
sub _search_id_grant($self, $type) {
return $self->{_grant_id}->{$type}
if exists $self->{_grant_id}->{$type};
$self->_load_grants();
my @names = $self->_grant_alternate_name($type);
my $sth = $$CON->dbh->prepare("SELECT id FROM grant_types WHERE "
.join( " OR ", map { "name=?"}@names));
$sth->execute(@names);
my ($id) = $sth->fetchrow;
$sth->finish;
confess "Unknown grant $type" if !$id;
confess "Unknown grant $type\n".Dumper($self->{_grant_alias}, $self->{_grant}) if !$id;
$self->{_grant_id}->{$type} = $id;
return $id;
}
......@@ -558,11 +558,23 @@ Returns if the user is allowed to perform a privileged action
=cut
sub can_do($self, $grant) {
return $self->{_grant}->{$grant} if defined $self->{_grant}->{$grant};
$self->_load_grants();
confess "Unknown permission '$grant'\n" if !exists $self->{_grant}->{$grant};
confess "Wrong grant '$grant'\n".Dumper($self->{_grant_alias})
if $grant !~ /^[a-z_]+$/;
$grant = $self->_grant_alias($grant);
confess "Wrong grant '$grant'\n".Dumper($self->{_grant_alias})
if $grant !~ /^[a-z_]+$/;
return $self->{_grant}->{$grant} if defined $self->{_grant}->{$grant};
confess "Unknown permission '$grant'. Maybe you are using an old release.\n"
."Try removing the table grant_types and start rvd_back again:\n"
."mysql> drop table grant_types;\n"
.Dumper($self->{_grant}, $self->{_grant_alias})
if !exists $self->{_grant}->{$grant};
return $self->{_grant}->{$grant};
}
......@@ -583,6 +595,9 @@ sub can_do_domain($self, $grant, $domain) {
}
sub _load_grants($self) {
$self->_load_aliases();
return if exists $self->{_grant};
my $sth;
eval { $sth= $$CON->dbh->prepare(
"SELECT gt.name, gu.allowed, gt.enabled"
......@@ -597,10 +612,39 @@ sub _load_grants($self) {
$sth->bind_columns(\($name, $allowed, $enabled));
while ($sth->fetch) {
$self->{_grant}->{$name} = $allowed if $enabled;
$self->{_grant_disabled}->{$name} = !$enabled;
my $grant_alias = $self->_grant_alias($name);
$self->{_grant}->{$grant_alias} = $allowed if $enabled;
$self->{_grant_disabled}->{$grant_alias} = !$enabled;
}
$sth->finish;
}
sub _grant_alias($self, $name) {
my $alias = $name;
return $self->{_grant_alias}->{$name} if exists $self->{_grant_alias}->{$name};
return $name;# if exists $self->{_grant}->{$name};
}
sub _grant_alternate_name($self,$name_req) {
my %name = ( $name_req => 1);
while (my($name, $alias) = each %{$self->{_grant_alias}}) {
$name{$name} = 1 if $name_req eq $alias;
$name{$alias} = 1 if $name_req eq $name;
}
return keys %name;
}
sub _load_aliases($self) {
return if exists $self->{_grant_alias};
my $sth = $$CON->dbh->prepare("SELECT name,alias FROM grant_types_alias");
$sth->execute;
while (my $row = $sth->fetchrow_hashref) {
$self->{_grant_alias}->{$row->{name}} = $row->{alias};
}
}
=head2 grant_user_permissions
......@@ -693,7 +737,7 @@ sub grant($self,$user,$permission,$value=1) {
confess "ERROR: permission '$permission' disabled "
if $self->{_grant_disabled}->{$permission};
if ( !$self->can_grant() && $self->name ne $Ravada::USER_DAEMON_NAME ) {
if ( !$self->can_grant() && $self->name ne Ravada::Utils::user_daemon->name ) {
my @perms = $self->list_permissions();
confess "ERROR: ".$self->name." can't grant permissions for ".$user->name."\n"
.Dumper(\@perms);
......@@ -704,7 +748,8 @@ sub grant($self,$user,$permission,$value=1) {
my $value_sql = $user->can_do($permission);
return $value if defined $value_sql && $value_sql eq $value;
my $id_grant = _search_id_grant($permission);
$permission = $self->_grant_alias($permission);
my $id_grant = $self->_search_id_grant($permission);
if (! defined $user->can_do($permission)) {
my $sth = $$CON->dbh->prepare(
"INSERT INTO grants_user "
......@@ -750,6 +795,7 @@ Returns a list of all the available permissions
sub list_all_permissions($self) {
return if !$self->is_admin;
$self->_load_grants();
my $sth = $$CON->dbh->prepare(
"SELECT * FROM grant_types"
......@@ -759,6 +805,7 @@ sub list_all_permissions($self) {
$sth->execute;
my @list;
while (my $row = $sth->fetchrow_hashref ) {
$row->{name} = $self->_grant_alias($row->{name});
lock_hash(%$row);
push @list,($row);
}
......@@ -772,6 +819,7 @@ Returns a list of all the permissions granted to the user
=cut
sub list_permissions($self) {
$self->_load_grants();
my @list;
for my $grant (sort keys %{$self->{_grant}}) {
push @list , ( [$grant => $self->{_grant}->{$grant} ] )
......@@ -862,7 +910,7 @@ sub can_shutdown_machine($self, $domain) {
}
sub grants($self) {
$self->_load_grants() if !$self->{_grant};
$self->_load_grants();
return () if !$self->{_grant};
return %{$self->{_grant}};
}
......
CREATE TABLE `grant_types_alias` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(32) NOT NULL,
`alias` char(32) NOT NULL,
`enabled` int default NULL,
UNIQUE(`name`,`alias`),
PRIMARY KEY (`id`)
);
CREATE TABLE `grant_types_alias` (
`id` integer NOT NULL PRIMARY KEY AUTOINCREMENT
, `name` char(32) NOT NULL
, `alias` char(32) NOT NULL
, `enabled` integer default NULL
, UNIQUE(`name`,`alias`)
);
......@@ -57,7 +57,8 @@ sub test_defaults {
ok(!$user->can_manage_users);
for my $perm (user_admin->list_permissions) {
if ( $perm =~ m{^(clone|change_settings|screenshot|remove)$}) {
$perm = $perm->[0];
if ( $perm =~ m{^(clone|change_settings|screenshot|remove|shutdown)$}) {
is($user->can_do($perm),1,$perm);
} else {
is($user->can_do($perm),undef,$perm);
......@@ -96,6 +97,25 @@ sub test_grant {
}
sub test_alias {
my @list_permissions = user_admin->list_permissions;
my @list_all_permissions = user_admin->list_all_permissions;
my $sth = $test->connector->dbh->prepare("SELECT name, alias FROM grant_types_alias");
$sth->execute;
while ( my ($name, $alias) = $sth->fetchrow) {
eval { is(user_admin->can_do($name),1, $name) };
is($@,'',$name);
eval { is(user_admin->can_do($alias),1, $alias) };
is($@,'',$alias);
ok(grep({ $_->[0] eq $alias } @list_permissions), $alias);
ok(grep({ $_->{name} eq $alias } @list_all_permissions), $alias);
}
}
sub test_operator {
my $usero = create_user("oper$$","bar");
ok(!$usero->is_operator);
......@@ -655,6 +675,8 @@ test_defaults();
test_admin();
test_grant();
test_alias();
test_operator();
my $vm_name = 'Void';
......
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