diff options
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Admin.pm | 79 | ||||
-rw-r--r-- | t/app/controller/admin.t | 92 | ||||
-rw-r--r-- | templates/web/default/admin/search_users.html | 29 | ||||
-rw-r--r-- | templates/web/default/admin/user_edit.html | 21 |
4 files changed, 221 insertions, 0 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm index ae4154e98..f0790cbff 100644 --- a/perllib/FixMyStreet/App/Controller/Admin.pm +++ b/perllib/FixMyStreet/App/Controller/Admin.pm @@ -586,6 +586,83 @@ sub report_edit : Path('report_edit') : Args(1) { return 1; } + +sub search_users: Path('search_users') : Args(0) { + my ( $self, $c ) = @_; + + $c->forward('check_page_allowed'); + + if (my $search = $c->req->param('search')) { + $c->stash->{searched} = 1; + + my $search = $c->req->param('search'); + my $isearch = '%' . $search . '%'; + + my $search_n = 0; + $search_n = int($search) if $search =~ /^\d+$/; + + my $users = $c->model('DB::User')->search( + { + -or => [ + email => { ilike => $isearch }, + name => { ilike => $isearch }, + from_council => $search_n, + ] + } + ); + + $c->stash->{users} = [ $users->all ]; + } + + return 1; +} + +sub user_edit : Path('user_edit') : Args(1) { + my ( $self, $c, $id ) = @_; + + $c->forward('check_page_allowed'); + $c->forward('get_token'); + + my $user = $c->model('DB::User')->find( { id => $id } ); + $c->stash->{user} = $user; + + my @area_types = $c->cobrand->area_types; + my $areas = mySociety::MaPit::call('areas', \@area_types); + + my @councils_ids = sort { strcoll($areas->{$a}->{name}, $areas->{$b}->{name}) } keys %$areas; + @councils_ids = $c->cobrand->filter_all_council_ids_list( @councils_ids ); + + $c->stash->{council_ids} = \@councils_ids; + $c->stash->{council_details} = $areas; + + if ( $c->req->param('submit') ) { + $c->forward('check_token'); + + my $edited = 0; + + if ( $user->email ne $c->req->param('email') || + $user->name ne $c->req->param('name' ) || + $user->from_council != $c->req->param('council') ) { + $edited = 1; + } + + $user->name( $c->req->param('name') ); + $user->email( $c->req->param('email') ); + $user->from_council( $c->req->param('council') || undef ); + $user->update; + + if ($edited) { + $c->forward( 'log_edit', [ $id, 'user', 'edit' ] ); + } + + $c->stash->{status_message} = + '<p><em>' . _('Updated!') . '</em></p>'; + } + + return 1; +} + + =head2 set_allowed_pages Sets up the allowed_pages stash entry for checking if the current page is @@ -605,10 +682,12 @@ sub set_allowed_pages : Private { 'search_reports' => [_('Search Reports'), 2], 'timeline' => [_('Timeline'), 3], 'questionnaire' => [_('Survey Results'), 4], + 'search_users' => [_('Search Users'), 5], 'council_contacts' => [undef, undef], 'council_edit' => [undef, undef], 'report_edit' => [undef, undef], 'update_edit' => [undef, undef], + 'user_edit' => [undef, undef], } } diff --git a/t/app/controller/admin.t b/t/app/controller/admin.t index 51c55c323..2ada0d2ea 100644 --- a/t/app/controller/admin.t +++ b/t/app/controller/admin.t @@ -721,6 +721,98 @@ subtest 'report search' => sub { $mech->content_like( qr{<tr [^>]*hidden[^>]*> \s* <td> \s* $r_id \s* </td>}xs ); }; +subtest 'user search' => sub { + $mech->get_ok('/admin/search_users'); + $mech->get_ok('/admin/search_users?search=' . $user->name); + + $mech->content_contains( $user->name); + my $u_id = $user->id; + $mech->content_like( qr{user_edit/$u_id">Edit</a>} ); + + $mech->get_ok('/admin/search_users?search=' . $user->email); + + $mech->content_like( qr{user_edit/$u_id">Edit</a>} ); + + $user->from_council(2509); + $user->update; + $mech->get_ok('/admin/search_users?search=2509' ); + $mech->content_contains(2509); +}; + +$log_entries = FixMyStreet::App->model('DB::AdminLog')->search( + { + object_type => 'user', + object_id => $user->id + }, + { + order_by => { -desc => 'id' }, + } +); + +is $log_entries->count, 0, 'no admin log entries'; + +for my $test ( + { + desc => 'edit user name', + fields => { + name => 'Test User', + email => 'test@example.com', + council => 2509, + }, + changes => { + name => 'Changed User', + }, + log_count => 1, + log_entries => [qw/edit/], + }, + { + desc => 'edit user email', + fields => { + name => 'Changed User', + email => 'test@example.com', + council => 2509, + }, + changes => { + email => 'changed@example.com', + }, + log_count => 2, + log_entries => [qw/edit edit/], + }, + { + desc => 'edit user council', + fields => { + name => 'Changed User', + email => 'changed@example.com', + council => 2509, + }, + changes => { + council => 2607, + }, + log_count => 3, + log_entries => [qw/edit edit edit/], + }, +) { + subtest $test->{desc} => sub { + $mech->get_ok( '/admin/user_edit/' . $user->id ); + + my $visible = $mech->visible_form_values; + is_deeply $visible, $test->{fields}, 'expected user'; + + my $expected = { + %{ $test->{fields} }, + %{ $test->{changes} } + }; + + $mech->submit_form_ok( { with_fields => $expected } ); + + $visible = $mech->visible_form_values; + is_deeply $visible, $expected, 'user updated'; + + $mech->content_contains( 'Updated!' ); + }; +} + + $mech->delete_user( $user ); $mech->delete_user( $user2 ); $mech->delete_user( $user3 ); diff --git a/templates/web/default/admin/search_users.html b/templates/web/default/admin/search_users.html new file mode 100644 index 000000000..43fdebf2b --- /dev/null +++ b/templates/web/default/admin/search_users.html @@ -0,0 +1,29 @@ +[% INCLUDE 'admin/header.html' title=loc('Search Users') %] +[% PROCESS 'admin/report_blocks.html' %] + +<form method="get" action="[% c.uri_for('search_users') %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> + <label for="search">[% loc('Search:') %]</label> <input type="text" name="search" size="30" id="search"> +</form> + + +[% IF searched %] +<table cellspacing="0" cellpadding="2" border="1"> + <tr> + <th>[% loc('Name') %]</th> + <th>[% loc('Email') %]</th> + <th>[% loc('Council') %]</th> + <th>*</th> + </tr> +[%- FOREACH user IN users %] + <tr> + <td>[% PROCESS value_or_nbsp value=user.name %]</td> + <td>[% PROCESS value_or_nbsp value=user.email %]</td> + <td>[% PROCESS value_or_nbsp value=user.from_council %]</td> + <td><a href="[% c.uri_for( 'user_edit', user.id ) %]">[% loc('Edit') %]</a></td> + </tr> +[%- END -%] +</table> + +[% END %] + +[% INCLUDE 'admin/footer.html' %] diff --git a/templates/web/default/admin/user_edit.html b/templates/web/default/admin/user_edit.html new file mode 100644 index 000000000..7db8f5c63 --- /dev/null +++ b/templates/web/default/admin/user_edit.html @@ -0,0 +1,21 @@ +[% INCLUDE 'admin/header.html' title=tprintf(loc('Editing user %d'), user.id ) -%] +[% PROCESS 'admin/report_blocks.html' %] + +[% status_message %] + +<form method="post" action="[% c.uri_for( 'user_edit', user.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> + <input type="hidden" name="token" value="[% token %]" > + <input type="hidden" name="submit" value="1" > +<ul> +<li>[% loc('Name:') %] <input type='text' name='name' id='name' value='[% user.name | html %]'></li> +<li>[% loc('Email:') %] <input type='text' id='email' name='email' value='[% user.email | html %]'></li> +<li>[% loc('Council:') %] <select id='council' name='council'> + <option value=''>[% loc('No council') %]</option> +[% FOR council IN council_ids %] + <option value="[% council %]"[% ' selected' IF council == user.from_council %]>[% council_details.$council.name %]</option> +[% END %] +</select> +</ul> +<input type="submit" name="Submit changes" value="[% loc('Submit changes') %]" ></form> + +[% INCLUDE 'admin/footer.html' %] |