Skip to content
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

Feat upload json users and groups #2099

Merged
merged 11 commits into from
Oct 4, 2024
9 changes: 9 additions & 0 deletions lib/Ravada/Auth/Group.pm
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ sub remove_member($self, $name) {
$sth->execute($id_user);
}

sub remove_other_members($self, $members) {
my %members = map { $_ => 1 } @$members;

for my $name ($self->members ) {
$self->remove_member($name) if !$members{$name};
}

}

sub _remove_all_members($self) {
my $sth = $$CON->dbh->prepare("DELETE FROM users_group "
." WHERE id_group=?"
Expand Down
102 changes: 102 additions & 0 deletions lib/Ravada/Front.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1912,6 +1912,108 @@ sub upload_users($self, $users, $type, $create=0) {
return ($found, $count, \@error);
}

=head2 upload_users_json

Upload a list of users to the database

=head3 Arguments

=over

=item * string with users and passwords in each line

=item * type: it can be SQL, LDAP or SSO

=back

=cut


sub upload_users_json($self, $data_json, $type='openid') {

my ($found, $count, @error);
my $data;
eval {
$data= decode_json($data_json);
};
if ( $@ ) {
push @error,($@);
$data={}
}

my $result = {
users_found => 0
,users_added => 0
,groups_found => 0
,groups_added => 0
};
if (exists $data->{groups} &&
(!ref($data->{groups}) || ref($data->{groups}) ne 'ARRAY')) {
die "Expecting groups as an array , got ".ref($data->{groups});
}
$data->{groups} = [] if !exists $data->{groups};
for my $g0 (@{$data->{groups}}) {
$result->{groups_found}++;
my $g = $g0;
if (!ref($g)) {
$g = { name => $g0 };
}
$found++;
my $group = Ravada::Auth::Group->new(name => $g->{name});
my $members = delete $g->{members};
if (!$group || !$group->id) {
unless (defined $members && !scalar(@$members) && $data->{options}->{flush} && $data->{options}->{remove_empty}) {
$result->{groups_added}++;
Ravada::Auth::Group::add_group(%$g);
}
} else {
push @error,("Group $g->{name} already added");
}
$self->_add_users($members, $type, $result, \@error, 1);
$group->remove_other_members($members) if $data->{options}->{flush};

for my $m (@$members) {
my $user = Ravada::Auth::SQL->new(name => $m);
$user->add_to_group($g->{name}) unless $user->is_member($g->{name});
}
if ( $data->{options}->{remove_empty} && $group->id && !$group->members ) {
$group->remove();
$result->{groups_removed}++;
push @error,("Group ".$group->name." empty removed");
}
}

$self->_add_users($data->{users}, $type, $result, \@error)
if $data->{users};

return ($result, \@error);
}

sub _add_users($self,$users, $type, $result, $error, $ignore_already=0) {
for my $u0 (@$users) {
$result->{users_found}++;
my $u = $u0;
$u = dclone($u0) if ref($u0);
if (!ref($u)) {
$u = { name => $u0 };
}
if (!exists $u->{is_external}) {
if ($type ne 'sql') {
$u->{is_external} = 1;
$u->{external_auth} = $type ;
}
}
my $user = Ravada::Auth::SQL->new(name => $u->{name});
if ($user && $user->id) {
push @$error,("User $u->{name} already added")
unless $ignore_already;
next;
}
Ravada::Auth::SQL::add_user(%$u);
$result->{users_added}++;
}
}

=head2 create_bundle

Creates a new bundle
Expand Down
52 changes: 43 additions & 9 deletions script/rvd_front
Original file line number Diff line number Diff line change
Expand Up @@ -1845,37 +1845,71 @@ any '/admin/users/upload.#req' => sub($c) {

my $type = $c->req->param('type');

return $c->render(template => "/main/upload_users", done => 0, count => 0, found => 0, type => 'sql') if !$type;
return $c->render(template => "/main/upload_users", done => 0, output => {}
,error => []
,type => 'sql') if !$type;

my $create = ( $c->req->param('create') or 0);

return $c->render(json => { error => "Unknown type $type" })
if $type !~ /^(sql|ldap|sso|openid)/;

my $csv = $c->req->upload('users');
if($csv->headers->content_type !~ m{text/(csv|plain)}) {
my $file = $c->req->upload('users');

if($file->headers->content_type =~ m{text/(csv|plain)}) {
_upload_users_csv($c, $file, $type, $create);
} elsif ( $file->headers->content_type =~ m{application/json}) {
_upload_users_json($c, $file, $type, $create);
} else {
return $c->render(status => 400
,text => "Wrong content type ".$csv->headers->content_type
." , it should be text/csv or plain"
,text => "Wrong content type ".$file->headers->content_type
." , it should be text/csv , application/json or plain"
);

}
};

sub _upload_users_json($c, $file, $type, $create) {

my ($result, $error)=$RAVADA->upload_users_json($file->slurp, $type);

if ($create) {
push @$error,("Warning: create not implemented with json upload");
}
return $c->render(json =>
{
output => $result
,error => $error
}
) if $c->stash('req') eq 'json';

return $c->render(template => "/main/upload_users"
,output => $result
,error => $error
,done => 1
);
}

sub _upload_users_csv($c, $csv, $type, $create) {
my ($found, $count, $error) = $RAVADA->upload_users(
$csv->slurp, $type, $create
);
my $output = {
users_found => $found
,users_added => $count
};

return $c->render(json =>
{ output => "$count users added"
{ output => $output
,error => $error
,done => 1
}) if $c->stash('req') eq 'json';

return $c->render(template => "/main/upload_users"
,count => $count
,found => $found
,error => $error
,done => 1
);
};
}

get '/admin/user/remove/#id' => sub($c) {
return access_denied($c) unless $USER->is_admin;
Expand Down
1 change: 1 addition & 0 deletions t/40_auth_sql.t
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use Test::Ravada;
use_ok('Ravada');
use_ok('Ravada::Auth::SQL');

init();
my $RAVADA = rvd_back();

Ravada::Auth::SQL::add_user(name => 'test',password => $$);
Expand Down
25 changes: 25 additions & 0 deletions t/lib/Test/Ravada.pm
Original file line number Diff line number Diff line change
Expand Up @@ -599,8 +599,32 @@ sub init($config=undef, $sqlite = 1 , $flush=0) {
$Ravada::VM::KVM::VERIFY_ISO = 0;
$Ravada::VM::MIN_DISK_MB = 1;

_clean_old_users();
_clean_old_groups();
}

sub _clean_old_users() {
my $sth = $CONNECTOR->dbh->prepare("SELECT id,name FROM users WHERE name like ? ");
$sth->execute(base_domain_name().'%');
while ( my ($id,$name) = $sth->fetchrow ) {
next if $USER_ADMIN && $name eq $USER_ADMIN->name;
my $user = Ravada::Auth::SQL->search_by_id($id);
next if !$user;
$user->remove();
}
}

sub _clean_old_groups() {
my $sth = $CONNECTOR->dbh->prepare("SELECT id,name FROM groups_local WHERE name like ? ");
$sth->execute(base_domain_name().'%');
while ( my ($id,$name) = $sth->fetchrow ) {
my $g = Ravada::Auth::Group->open($id);
next if !$g;
$g->remove();
}
}


sub _load_remote_config() {
return {} if ! -e $FILE_CONFIG_REMOTE;
my $conf;
Expand Down Expand Up @@ -1573,6 +1597,7 @@ sub _qemu_storage_pool {
sub remove_void_networks($vm=undef) {
if (!defined $vm) {
eval { $vm = rvd_back->search_vm('Void') };
die $@ if $@;
}
my $dir_net = $vm->dir_img()."/networks";
return if ! -e $dir_net;
Expand Down
Loading
Loading