diff --git a/lib/Ravada/Auth/Group.pm b/lib/Ravada/Auth/Group.pm index 469c934d0..1b3c76467 100644 --- a/lib/Ravada/Auth/Group.pm +++ b/lib/Ravada/Auth/Group.pm @@ -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=?" diff --git a/lib/Ravada/Front.pm b/lib/Ravada/Front.pm index 81388f440..8f04c903b 100644 --- a/lib/Ravada/Front.pm +++ b/lib/Ravada/Front.pm @@ -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 diff --git a/script/rvd_front b/script/rvd_front index c2b19b0e4..134e91b92 100644 --- a/script/rvd_front +++ b/script/rvd_front @@ -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; diff --git a/t/40_auth_sql.t b/t/40_auth_sql.t index a058340d8..24d2b7ae2 100644 --- a/t/40_auth_sql.t +++ b/t/40_auth_sql.t @@ -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 => $$); diff --git a/t/lib/Test/Ravada.pm b/t/lib/Test/Ravada.pm index 1ab20576a..a1776d586 100644 --- a/t/lib/Test/Ravada.pm +++ b/t/lib/Test/Ravada.pm @@ -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; @@ -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; diff --git a/t/mojo/60_upload.t b/t/mojo/60_upload.t index 1877a7bdd..ffb5f4f6b 100644 --- a/t/mojo/60_upload.t +++ b/t/mojo/60_upload.t @@ -6,7 +6,7 @@ use Data::Dumper; use Test::More; use Test::Mojo; use Mojo::File 'path'; -use Mojo::JSON qw(decode_json); +use Mojo::JSON qw(encode_json decode_json); use lib 't/lib'; use Test::Ravada; @@ -68,7 +68,7 @@ sub test_upload_users_nopassword( $type, $mojo=0 ) { die $t->tx->res->body if $t->tx->res->code != 200; my $response = $t->tx->res->json(); - like($response->{output}, qr/2 users added/); + is($response->{output}->{users_added} ,2); is_deeply($response->{error},[]); } else { rvd_front->upload_users($users, $type); @@ -99,7 +99,7 @@ sub test_upload_users( $type, $create=0, $mojo=0 ) { die $t->tx->res->body if $t->tx->res->code != 200; my $response = $t->tx->res->json(); - like($response->{output}, qr/2 users added/); + is($response->{output}->{users_added} ,2); is_deeply($response->{error},[]); } else { rvd_front->upload_users($users, $type, $create); @@ -123,7 +123,7 @@ sub test_upload_users( $type, $create=0, $mojo=0 ) { die $t->tx->res->body if $t->tx->res->code != 200; my $response = $t->tx->res->json(); - like($response->{output}, qr/0 users added/); + is($response->{output}->{users_added},0); is(scalar(@{$response->{error}}),2); test_users_added($type, $user1, $user2); @@ -262,6 +262,466 @@ sub test_upload_group($mojo=0) { } +sub test_upload_json_fail() { + + _do_upload_users_fail(0); + _do_upload_users_fail(1); +} + +sub _do_upload_users_fail($mojo, $type='openid') { + my ($result, $error); + if (!$mojo) { + ($result, $error)=rvd_front->upload_users_json("wrong", $type); + } else { + $t->post_ok('/admin/users/upload.json' => form => { + type => $type + ,create => 0 + ,users => { content => "wrong", filename => 'data.json' + , 'Content-Type' => 'application/json' }, + })->status_is(200); + die $t->tx->res->body if $t->tx->res->code != 200; + + my $response = $t->tx->res->json(); + $result = $response->{output}; + $error = $response->{error}; + } + like($error->[0],qr/malformed JSON/); + is_deeply($result, { groups_found => 0 , groups_added => 0, users_found => 0, users_added => 0}); +} + +sub test_upload_json() { + + test_upload_json_members(); + + test_upload_json_members_flush(); + test_upload_json_members_remove_empty(); + + test_upload_json_users_groups(); + test_upload_json_users_groups2(); + test_upload_json_users_admin(); + test_upload_json_users_pass(); + test_upload_json_users(); +} + +sub _do_upload_users_json($data, $mojo, $exp_result=undef, $type='openid') { + + confess if ref($mojo); + confess if defined $exp_result && !ref($exp_result); + + my $data_h = $data; + if (ref($data)) { + $data = encode_json($data); + } else { + $data_h = decode_json($data); + } + if (!defined $exp_result) { + $exp_result= { groups_found => 0, groups_added => 0, users_found=>0, users_added => 0}; + if ($data_h->{groups}) { + $exp_result->{groups_found} = scalar(@{$data_h->{groups}}); + $exp_result->{groups_added} = scalar(@{$data_h->{groups}}); + confess"not array groups\n".Dumper($data_h) if ref($data_h->{groups}) ne 'ARRAY'; + for my $g ($data_h->{groups}) { + next if !ref($g) || ref($g) ne 'HASH' || !exists $g->{members}; + $exp_result->{users_found} += scalar(@{$g->{members}}); + $exp_result->{users_added} += scalar(@{$g->{members}}); + } + } + if ($data_h->{users}) { + $exp_result->{users_found} += scalar(@{$data_h->{users}}); + $exp_result->{users_added} += scalar(@{$data_h->{users}}); + }; + } + my $users = $data_h->{users}; + if ($users) { + for my $user (@$users) { + my $name = $user; + $name = $user->{name} if ref($user); + next if !$name; + remove_old_user($name); + } + } + my ($result, $error); + if (!$mojo) { + ($result, $error)=rvd_front->upload_users_json($data, $type); + } else { + my $url='/admin/users/upload.json'; + $t->post_ok( $url => form => { + type => $type + ,create => 0 + ,users => { content => $data, filename => 'data.json' + , 'Content-Type' => 'application/json' }, + })->status_is(200); + die $t->tx->res->body if $t->tx->res->code != 200; + + my $response = $t->tx->res->json(); + $result = $response->{output}; + $error = $response->{error}; + } + + for my $err (@$error) { + ok(0,$err) unless $err =~ /already added|empty removed/; + } + is_deeply($result, $exp_result) or die Dumper(["mojo=$mojo",$data,$error,$result, $exp_result]); + +} + +sub test_upload_json_users() { + _do_test_upload_json_users(0); + _do_test_upload_json_users(1); +} + +sub _do_test_upload_json_users($mojo) { + my @users = ( new_domain_name(), new_domain_name() ); + my $data = { + users => \@users + }; + + _do_upload_users_json( { users => \@users },$mojo ); + + for my $name ( @users ) { + my $user = Ravada::Auth::SQL->new(name => $name); + ok($user->id, "Expecting user $name created"); + is($user->external_auth, 'openid'); + + $user = undef; + eval { + $user = Ravada::Auth->login( $name , ''); + }; + like($@,qr/login failed/i); + ok(!$user) or warn $user->name; + } +} + +sub test_upload_json_users_groups() { + + _do_test_upload_json_users_groups(0); + _do_test_upload_json_users_groups(1); +} + +sub _do_test_upload_json_users_groups($mojo) { + my @users = ( + {name => new_domain_name() } + , {name => new_domain_name(), is_admin => 1 } + ); + my @groups = ( + new_domain_name() + ,new_domain_name() + ); + my $data = { + users => \@users + ,groups => \@groups + }; + + _do_upload_users_json( encode_json( $data ), $mojo, { groups_found => 2, groups_added => 2, users_found => 2, users_added => 2} ); + for my $u ( @users ) { + my $user = Ravada::Auth::SQL->new(name => $u->{name}); + ok($user->id, "Expecting user $u->{name} created"); + } + for my $g ( @groups) { + my $group = Ravada::Auth::Group->new(name => $g); + ok($group->id, "Expecting group $g created"); + } + +} + +sub test_upload_json_users_groups2() { + _do_test_upload_json_users_groups2(0); + _do_test_upload_json_users_groups2(1); +} + +sub _do_test_upload_json_users_groups2($mojo) { + my @users = ( + {name => new_domain_name() } + , {name => new_domain_name(), is_admin => 1 } + ); + my @groups = ( + {name => new_domain_name() } + ,{name => new_domain_name() } + ); + my $data = { + users => \@users + ,groups => \@groups + }; + + _do_upload_users_json( $data, $mojo ); + for my $u ( @users ) { + my $user = Ravada::Auth::SQL->new(name => $u->{name}); + ok($user->id, "Expecting user $u->{name} created"); + } + for my $g ( @groups) { + my $group = Ravada::Auth::Group->new(name => $g->{name}); + ok($group->id, "Expecting group $g->{name} created"); + } + +} + +sub test_upload_json_members() { + _do_test_upload_json_members(0); + _do_test_upload_json_members(1); +} + +sub _do_test_upload_json_members($mojo=0) { + my @users_g0 = ( + new_domain_name() + ,new_domain_name() + ); + + my @groups = ( + {name => new_domain_name() + ,members => \@users_g0 } + ,{name => new_domain_name() } + ); + my $data = { + groups => \@groups + }; + + _do_upload_users_json( encode_json( $data ),$mojo,{ groups_found => 2,groups_added => 2, users_found => 2, users_added => 2} ); + for my $u ( @users_g0 ) { + my $user = Ravada::Auth::SQL->new(name => $u ); + ok($user->id, "Expecting user $u created"); + } + for my $g ( @groups) { + my $group = Ravada::Auth::Group->new(name => $g->{name}); + ok($group->id, "Expecting group $g->{name} created"); + } + + my $g0 = Ravada::Auth::Group->new(name => $groups[0]->{name}); + ok($g0->members,"Expecting members in ".$g0->name); + + for my $m (@{$groups[0]->{members}}) { + my ($found) = grep (/^$m$/ , $g0->members); + ok($found,"Expecting $m member"); + } + + my $g1 = Ravada::Auth::Group->new(name => $groups[1]->{name}); + ok(!$g1->members,"Expecting no members in ".$g1->name); + + # add more users + my @users_g0b = ( + new_domain_name() + ,new_domain_name() + ,$users_g0[0] + ); + + $groups[0]->{members} = \@users_g0b; + + _do_upload_users_json( encode_json( {groups => \@groups}),$mojo, { groups_found => 2,groups_added => 0, users_found => 3, users_added => 2} ); + + for my $name ( @users_g0 , @users_g0b ) { + + my $user = Ravada::Auth::SQL->new(name => $name ); + ok($user->id, "Expecting user $name created mojo=$mojo") or exit; + + my $g0 = Ravada::Auth::Group->new(name => $groups[0]->{name}); + my ($found) = grep (/^$name$/ , $g0->members); + ok($found,"Expecting $name member"); + } +} + +sub test_upload_json_members_flush() { + _do_test_upload_json_members_flush(0); + _do_test_upload_json_members_flush(1); +} + +sub _do_test_upload_json_members_flush($mojo) { + my @users_g0 = ( + new_domain_name() + ,new_domain_name() + ); + + my @groups = ( + {name => new_domain_name() + ,members => \@users_g0 } + ,{name => new_domain_name() } + ); + my $data = { + groups => \@groups + }; + + _do_upload_users_json( encode_json( $data ),$mojo,{ groups_found => 2,groups_added => 2, users_found => 2, users_added => 2} ); + for my $u ( @users_g0 ) { + my $user = Ravada::Auth::SQL->new(name => $u ); + ok($user->id, "Expecting user $u created"); + } + for my $g ( @groups) { + my $group = Ravada::Auth::Group->new(name => $g->{name}); + ok($group->id, "Expecting group $g->{name} created"); + } + + my $g0 = Ravada::Auth::Group->new(name => $groups[0]->{name}); + ok($g0->members,"Expecting members in ".$g0->name); + + for my $m (@{$groups[0]->{members}}) { + my ($found) = grep (/^$m$/ , $g0->members); + ok($found,"Expecting $m member"); + } + + my $g1 = Ravada::Auth::Group->new(name => $groups[1]->{name}); + ok(!$g1->members,"Expecting no members in ".$g1->name); + + # add more users + my @users_g0b = ( + new_domain_name() + ,new_domain_name() + ,$users_g0[0] + ); + + $groups[0]->{members} = \@users_g0b; + + _do_upload_users_json( encode_json( {groups => \@groups, options => {'flush' => 1}}),$mojo, { groups_found => 2,groups_added => 0, users_found => 3, users_added => 2} ); + + for my $name ( $users_g0[1] ) { + + my $user = Ravada::Auth::SQL->new(name => $name ); + ok($user->id, "Expecting user $name created"); + + my $g0 = Ravada::Auth::Group->new(name => $groups[0]->{name}); + my ($found) = grep (/^$name$/ , $g0->members); + ok(!$found,"Expecting no $name member") or exit; + } + + for my $name ( @users_g0b ) { + + my $user = Ravada::Auth::SQL->new(name => $name ); + ok($user->id, "Expecting user $name created"); + + my $g0 = Ravada::Auth::Group->new(name => $groups[0]->{name}); + my ($found) = grep (/^$name$/ , $g0->members); + ok($found,"Expecting $name member"); + } + +} + +sub test_upload_json_members_remove_empty() { + _do_test_upload_json_members_remove_empty(0); + _do_test_upload_json_members_remove_empty(1); +} + +sub _do_test_upload_json_members_remove_empty($mojo) { + my @users_g0 = ( + new_domain_name() + ,new_domain_name() + ); + + my @groups = ( + {name => new_domain_name() + ,members => \@users_g0 } + ,{name => new_domain_name() } + ); + my $data = { + groups => \@groups + }; + + _do_upload_users_json( encode_json( $data ), $mojo, { groups_found => 2,groups_added => 2, users_found => 2, users_added => 2} ); + for my $u ( @users_g0 ) { + my $user = Ravada::Auth::SQL->new(name => $u ); + ok($user->id, "Expecting user $u created"); + } + for my $g ( @groups) { + my $group = Ravada::Auth::Group->new(name => $g->{name}); + ok($group->id, "Expecting group $g->{name} created"); + } + + my $g0 = Ravada::Auth::Group->new(name => $groups[0]->{name}); + ok($g0->members,"Expecting members in ".$g0->name); + + for my $m (@{$groups[0]->{members}}) { + my ($found) = grep (/^$m$/ , $g0->members); + ok($found,"Expecting $m member"); + } + + my $g1 = Ravada::Auth::Group->new(name => $groups[1]->{name}); + ok(!$g1->members,"Expecting no members in ".$g1->name); + + # add more users + my @users_g0b = ( + new_domain_name() + ,new_domain_name() + ,$users_g0[0] + ); + + $groups[1]->{members} = \@users_g0b; + $groups[0]->{members} = []; + + _do_upload_users_json( encode_json( {groups => \@groups, options => {'flush'=>1,'remove_empty'=>1}}), $mojo, { groups_found => 2,groups_added => 0, users_found => 3, users_added => 2, groups_removed => 1} ); + + for my $name ( @users_g0b ) { + + my $user = Ravada::Auth::SQL->new(name => $name ); + ok($user->id, "Expecting user $name created"); + + my $g1 = Ravada::Auth::Group->new(name => $groups[1]->{name}); + ok($g1 && $g1->id) or exit; + my ($found) = grep (/^$name$/ , $g0->members); + ok(!$found,"Expecting $name member") or exit; + } + + $g0 = Ravada::Auth::Group->new(name => $groups[0]->{name}); + ok(!$g0->id,"Expecting $groups[0]->{name} removed"); + +} + + + + +sub test_upload_json_users_admin() { + _do_test_upload_json_users_admin(0); + _do_test_upload_json_users_admin(1); +} + +sub _do_test_upload_json_users_admin($mojo) { + my @users = ( + {name => new_domain_name() } + , {name => new_domain_name(), is_admin => 0 } + , {name => new_domain_name(), is_admin => 1 } + ); + my $data = { + users => \@users + }; + + _do_upload_users_json( $data, $mojo ); + + for my $u ( @users ) { + my ($name, $password) = ($u->{name} , $u->{password}); + my $user = Ravada::Auth::SQL->new(name => $name); + ok($user->id, "Expecting user $name created"); + is($user->external_auth, 'openid') or exit; + $u->{is_admin}=0 if !exists $u->{is_admin}; + is($user->is_admin, $u->{is_admin}); + } + + +} + +sub test_upload_json_users_pass() { + _do_test_upload_json_users_pass(0); + _do_test_upload_json_users_pass(1); +} + +sub _do_test_upload_json_users_pass($mojo) { + my $p1='a'; + my $p2 = 'b'; + my @users = ( + {name => new_domain_name(), password => $p1 } + , {name => new_domain_name(), password => $p2 } + ); + + _do_upload_users_json( encode_json( { users => \@users }), $mojo, undef, 'sql' ); + + for my $u ( @users ) { + my ($name, $password) = ($u->{name} , $u->{password}); + my $user = Ravada::Auth::SQL->new(name => $name); + ok($user->id, "Expecting user $name created"); + is($user->external_auth, '') or exit; + + $user = undef; + eval { + $user = Ravada::Auth::login( $name , $password); + }; + is($@,''); + ok($user,"Expecting $name/$password") or exit; + } +} ################################################################################ @@ -278,6 +738,10 @@ test_upload_no_admin($t); _login($t); +test_upload_json_fail(); + +test_upload_json(); + test_upload_group(); test_upload_group(1); # mojo test_upload_group(2); # mojo post diff --git a/t/user/10_domains.t b/t/user/10_domains.t index 2d16597e4..0490c76f7 100644 --- a/t/user/10_domains.t +++ b/t/user/10_domains.t @@ -11,6 +11,7 @@ use_ok('Ravada'); use_ok('Ravada::VM::Void'); use_ok('Ravada::Auth::SQL'); +init(); my $ravada = rvd_back(); # diff --git a/t/user/35_share.t b/t/user/35_share.t index f0948ade7..40d8a13ef 100644 --- a/t/user/35_share.t +++ b/t/user/35_share.t @@ -134,6 +134,7 @@ sub test_machine_info_shared($user, $clone) { ############################################################## +init(); clean(); for my $vm_name ( vm_names() ) { diff --git a/templates/main/upload_users.html.ep b/templates/main/upload_users.html.ep index 564159b53..fbb81a09f 100644 --- a/templates/main/upload_users.html.ep +++ b/templates/main/upload_users.html.ep @@ -39,7 +39,7 @@
- @@ -60,8 +60,15 @@
% } else { - <%= $found %> <%=l 'users found in uploaded file' %>, - <%= $count %> <%=l 'created' %>. + <%= $output->{users_found} %> <%=l 'users found in uploaded file' %>, + <%= $output->{users_added} %> <%=l 'created' %>. +% if (exists $output->{groups_found}) { + <%= $output->{groups_found} %> <%=l 'groups found in uploaded file' %>, + <%= $output->{groups_added} %> <%=l 'created' %>. +% } +% if (exists $output->{groups_removed}) { + <%= $output->{groups_removed} %> <%= l 'groups removed'%>. +% }
<%=l 'Errors found' %>: <%= scalar(@$error) %>