diff options
author | Dave Arter <davea@mysociety.org> | 2018-03-29 10:14:50 +0100 |
---|---|---|
committer | Dave Arter <davea@mysociety.org> | 2018-04-03 16:31:12 +0100 |
commit | 8e8e3e1370b8b7744f9491ff78563f40c475e872 (patch) | |
tree | 5cf9c7ff5bbb79eacb2d57933187359baf6f886d | |
parent | 246a419d5026f9ff067b2a34c375d34044225042 (diff) |
User import admin page
This is intended to be an internal tool for quickly creating staff
users in bulk. As such, it's hidden at /admin/user_import and is only
available to superusers.
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Admin.pm | 46 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Default.pm | 1 | ||||
-rw-r--r-- | templates/web/base/admin/user_import.html | 76 |
4 files changed, 124 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 16c91b885..e1ccaf4ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ - Users with 'user_edit' permission can search for users/reports. #2027 - Don't send sent-report emails to as-body/as-anonymous reports. - Show Open311 service code as tooltip on admin category checkboxes. #2049 + - Bulk user import admin page. #2057 - Development improvements: - Add HTML email previewer. - Add CORS header to Open311 output. #2022 diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm index 96fe086c3..1256ae3b7 100644 --- a/perllib/FixMyStreet/App/Controller/Admin.pm +++ b/perllib/FixMyStreet/App/Controller/Admin.pm @@ -12,6 +12,7 @@ use DateTime::Format::Strptime; use List::Util 'first'; use List::MoreUtils 'uniq'; use mySociety::ArrayUtils; +use Text::CSV; use FixMyStreet::SendReport; use FixMyStreet::SMS; @@ -1636,6 +1637,51 @@ sub user_edit : Path('user_edit') : Args(1) { return 1; } +sub user_import : Path('user_import') { + my ( $self, $c, $id ) = @_; + + $c->forward('/auth/get_csrf_token'); + return unless $c->user_exists && $c->user->is_superuser; + + if ($c->req->method eq 'POST') { + $c->forward('/auth/check_csrf_token'); + $c->stash->{new_users} = []; + $c->stash->{existing_users} = []; + + my @all_permissions = map { keys %$_ } values %{ $c->cobrand->available_permissions }; + my %available_permissions = map { $_ => 1 } @all_permissions; + + my $csv = Text::CSV->new({ binary => 1}); + my $fh = $c->req->upload('csvfile')->fh; + $csv->getline($fh); # discard the header + while (my $row = $csv->getline($fh)) { + my ($name, $email, $from_body, $permissions) = @$row; + my @permissions = split(/:/, $permissions); + + my $user = FixMyStreet::DB->resultset("User")->find_or_new({ email => $email, email_verified => 1 }); + if ($user->in_storage) { + push @{$c->stash->{existing_users}}, $user; + next; + } + + $user->name($name); + $user->from_body($from_body || undef); + $user->update_or_insert; + + my @user_permissions = grep { $available_permissions{$_} } @permissions; + foreach my $permission_type (@user_permissions) { + $user->user_body_permissions->find_or_create({ + body_id => $user->from_body->id, + permission_type => $permission_type, + }); + } + + push @{$c->stash->{new_users}}, $user; + } + + } +} + sub contact_cobrand_extra_fields : Private { my ( $self, $c, $contact ) = @_; diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm index 8c4d8be53..99b247412 100644 --- a/perllib/FixMyStreet/Cobrand/Default.pm +++ b/perllib/FixMyStreet/Cobrand/Default.pm @@ -645,6 +645,7 @@ sub admin_pages { $pages->{flagged} = [ _('Flagged'), 7 ]; $pages->{states} = [ _('States'), 8 ]; $pages->{config} = [ _('Configuration'), 9]; + $pages->{user_import} = [ undef, undef ]; }; # And some that need special permissions if ( $user->has_body_permission_to('category_edit') ) { diff --git a/templates/web/base/admin/user_import.html b/templates/web/base/admin/user_import.html new file mode 100644 index 000000000..f866ed955 --- /dev/null +++ b/templates/web/base/admin/user_import.html @@ -0,0 +1,76 @@ +[% INCLUDE 'admin/header.html' title=loc("User Import") -%] +[% PROCESS 'admin/report_blocks.html' %] + +[% status_message %] + +<form method="post" id="user_edit" action="[% c.uri_for( 'user_import' ) %]" enctype="multipart/form-data" accept-charset="utf-8"> + <input type="hidden" name="token" value="[% csrf_token %]" > + <input type="hidden" name="submit" value="1" > + + <p> + <label> + [% loc('CSV File') %] + <input type="file" name="csvfile" id="form_csvfile" /> + </label> + <input type="submit" class="btn" name="Import users" value="[% loc('Import users') %]" /> + </p> +</form> + +[% IF new_users %] + <h2>[% tprintf(loc('Created %d new users'), new_users.size ) %]</h2> + <table> + <tr> + <th>[% loc('Name') %]</th> + <th>[% loc('Email') %]</th> + <th>[% loc('Body') %]</th> + </tr> + [% FOREACH user IN new_users %] + <tr> + <td> + <a href="[% c.uri_for_action( 'admin/user_edit', user.id ) %]"> + [% user.name %] + </a> + </td> + <td>[% user.email %]</td> + <td>[% user.from_body.name %]</td> + </tr> + [% END %] + </table> +[% END %] + +[% IF existing_users %] + <h2>[% tprintf(loc("%d users already existed"), existing_users.size) %]</h2> + <p>[% loc("These users weren't updated.") %]</p> + <table> + <tr> + <th>[% loc('Name') %]</th> + <th>[% loc('Email') %]</th> + <th>[% loc('Body') %]</th> + </tr> + [% FOREACH user IN existing_users %] + <tr> + <td> + <a href="[% c.uri_for_action( 'admin/user_edit', user.id ) %]"> + [% user.name %] + </a> + </td> + <td>[% user.email %]</td> + <td>[% user.from_body.name %]</td> + </tr> + [% END %] + </table> +[% END %] + +<h2>[% loc('Usage notes') %]</h2> +<p>[% loc('This page is a quick way to create many new staff users in one go.') %]</p> +<p>[% loc("Existing users won't be modified.") %]</p> +<p> + [% loc("The uploaded CSV file must contain a header row, and records must have the following fields (in this order):") %] + <pre>name,email,from_body,permissions</pre> + <ul> + <li><code>from_body</code>: [% loc("the database id of the body to associate that user with, e.g. <code>2217</code> for Buckinghamshire.") %]</li> + <li><code>permissions</code>: [% loc("a colon-separated list of permissions to grant that user, e.g. <code>contribute_as_body:moderate:user_edit</code>.") %]</li> + </ul> +</p> + +[% INCLUDE 'admin/footer.html' %] |