aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Arter <davea@mysociety.org>2016-09-13 17:17:23 +0100
committerDave Arter <davea@mysociety.org>2016-09-20 16:07:32 +0100
commit9bc2476861811163663b45cac41a2e91273576ed (patch)
tree26ada3a90213334dfbc1f5e6ef6e6d1e9a800878
parentb01df0c7609a1d6c008b943a9936d471cf0e0ce3 (diff)
Add ‘trusted’ flag allowing users to make reports directly
When a trusted user makes a report in a category that requires inspection, it'll be sent immediately (i.e. without being inspected first).
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm33
-rw-r--r--perllib/FixMyStreet/Cobrand/Default.pm6
-rw-r--r--perllib/FixMyStreet/DB/Result/User.pm16
-rw-r--r--perllib/FixMyStreet/Script/Reports.pm11
-rw-r--r--t/app/controller/admin.t1
-rw-r--r--t/app/sendreport/inspection_required.t20
-rw-r--r--templates/web/base/admin/user-form.html25
7 files changed, 106 insertions, 6 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm
index 63ed9f3c6..46ac10d36 100644
--- a/perllib/FixMyStreet/App/Controller/Admin.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin.pm
@@ -1276,14 +1276,14 @@ sub user_edit : Path('user_edit') : Args(1) {
if (!$user->from_body) {
# Non-staff users aren't allowed any permissions or to be in an area
- $user->user_body_permissions->delete_all;
+ $user->admin_user_body_permissions->delete;
$user->area_id(undef);
delete $c->stash->{areas};
delete $c->stash->{fetched_areas_body_id};
} elsif ($c->stash->{available_permissions}) {
my @all_permissions = map { keys %$_ } values %{ $c->stash->{available_permissions} };
my @user_permissions = grep { $c->get_param("permissions[$_]") ? 1 : undef } @all_permissions;
- $user->user_body_permissions->search({
+ $user->admin_user_body_permissions->search({
body_id => $user->from_body->id,
permission_type => { '!=' => \@user_permissions },
})->delete;
@@ -1301,6 +1301,35 @@ sub user_edit : Path('user_edit') : Args(1) {
$user->area_id( $valid_areas{$new_area} ? $new_area : undef );
}
+ # Handle 'trusted' flag(s)
+ my @trusted_bodies = $c->get_param_list('trusted_bodies');
+ if ( $c->user->is_superuser ) {
+ $user->user_body_permissions->search({
+ body_id => { '!=' => \@trusted_bodies },
+ permission_type => 'trusted',
+ })->delete;
+ foreach my $body_id (@trusted_bodies) {
+ $user->user_body_permissions->find_or_create({
+ body_id => $body_id,
+ permission_type => 'trusted',
+ });
+ }
+ } elsif ( $c->user->from_body ) {
+ my %trusted = map { $_ => 1 } @trusted_bodies;
+ my $body_id = $c->user->from_body->id;
+ if ( $trusted{$body_id} ) {
+ $user->user_body_permissions->find_or_create({
+ body_id => $body_id,
+ permission_type => 'trusted',
+ });
+ } else {
+ $user->user_body_permissions->search({
+ body_id => $body_id,
+ permission_type => 'trusted',
+ })->delete;
+ }
+ }
+
unless ($user->email) {
$c->stash->{field_errors}->{email} = _('Please enter a valid email');
return;
diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm
index 47e577372..2b27a8891 100644
--- a/perllib/FixMyStreet/Cobrand/Default.pm
+++ b/perllib/FixMyStreet/Cobrand/Default.pm
@@ -720,6 +720,12 @@ sub available_permissions {
planned_reports => _("Manage planned reports list"),
contribute_as_another_user => _("Create reports/updates on a user's behalf"),
contribute_as_body => _("Create reports/updates as the council"),
+
+ # NB this permission is special in that it can be assigned to users
+ # without their from_body being set. It's included here for
+ # reference, but left commented out because it's not assigned in the
+ # same way as other permissions.
+ # trusted => _("Trusted to make reports that don't need to be inspected"),
},
_("Users") => {
user_edit => _("Edit other users' details"),
diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm
index 56196c7c0..48b688000 100644
--- a/perllib/FixMyStreet/DB/Result/User.pm
+++ b/perllib/FixMyStreet/DB/Result/User.pm
@@ -292,6 +292,22 @@ sub has_body_permission_to {
return $self->has_permission_to($permission_type, $self->from_body->id);
}
+=head2 admin_user_body_permissions
+
+Some permissions aren't managed in the normal way via the admin, e.g. the
+'trusted' permission. This method returns a query that excludes such exceptional
+permissions.
+
+=cut
+
+sub admin_user_body_permissions {
+ my $self = shift;
+
+ return $self->user_body_permissions->search({
+ permission_type => { '!=' => 'trusted' },
+ });
+}
+
sub contributing_as {
my ($self, $other, $c, $bodies) = @_;
$bodies = [ keys %$bodies ] if ref $bodies eq 'HASH';
diff --git a/perllib/FixMyStreet/Script/Reports.pm b/perllib/FixMyStreet/Script/Reports.pm
index ab0d90ba8..8816d0e3a 100644
--- a/perllib/FixMyStreet/Script/Reports.pm
+++ b/perllib/FixMyStreet/Script/Reports.pm
@@ -144,9 +144,14 @@ sub send(;$) {
$reporters{ $sender } ||= $sender->new();
my $inspection_required = $sender_info->{contact}->get_extra_metadata('inspection_required') if $sender_info->{contact};
- if ( $inspection_required && !$row->get_extra_metadata('inspected') ) {
- $skip = 1;
- debug_print("skipped because not yet inspected", $row->id) if $debug_mode;
+ if ( $inspection_required ) {
+ unless (
+ $row->get_extra_metadata('inspected') ||
+ $row->user->has_permission_to( trusted => $row->bodies_str )
+ ) {
+ $skip = 1;
+ debug_print("skipped because not yet inspected", $row->id) if $debug_mode;
+ }
}
if ( $reporters{ $sender }->should_skip( $row ) ) {
diff --git a/t/app/controller/admin.t b/t/app/controller/admin.t
index 8c3cde4b7..7ba84b652 100644
--- a/t/app/controller/admin.t
+++ b/t/app/controller/admin.t
@@ -1165,6 +1165,7 @@ my %default_perms = (
"permissions[template_edit]" => undef,
"permissions[responsepriority_edit]" => undef,
"permissions[category_edit]" => undef,
+ trusted_bodies => undef,
);
FixMyStreet::override_config {
diff --git a/t/app/sendreport/inspection_required.t b/t/app/sendreport/inspection_required.t
index 178fa2a1f..88a48e991 100644
--- a/t/app/sendreport/inspection_required.t
+++ b/t/app/sendreport/inspection_required.t
@@ -52,8 +52,28 @@ subtest 'Report is sent when inspected' => sub {
ok $report->whensent, 'Report marked as sent';
};
+subtest 'Uninspected report is sent when made by trusted user' => sub {
+ $mech->clear_emails_ok;
+ $report->unset_extra_metadata('inspected');
+ $report->whensent( undef );
+ $report->update;
+
+ $user->user_body_permissions->find_or_create({
+ body => $body,
+ permission_type => 'trusted',
+ });
+ ok $user->has_permission_to('trusted', $report->bodies_str_ids), 'User can make trusted reports';
+
+ FixMyStreet::DB->resultset('Problem')->send_reports();
+
+ $report->discard_changes;
+ $mech->email_count_is( 1 );
+ ok $report->whensent, 'Report marked as sent';
+};
+
done_testing();
END {
+ $mech->delete_user($user);
$mech->delete_body($body);
}
diff --git a/templates/web/base/admin/user-form.html b/templates/web/base/admin/user-form.html
index 38191e095..40e0b510a 100644
--- a/templates/web/base/admin/user-form.html
+++ b/templates/web/base/admin/user-form.html
@@ -85,10 +85,33 @@
[% loc("You can add an abusive user's email to the abuse list, which automatically hides (and never sends) reports they create.") %]
</p>
</div>
-
+
[% loc('Flagged:') %] <input type="checkbox" id="flagged" name="flagged"[% user.flagged ? ' checked' : '' %]>
</li>
+ [% UNLESS user.is_superuser %]
+ <li>
+ <div class="admin-hint">
+ <p>
+ [% loc("Reports made by trusted users will be sent to the responsible body without being inspected first.") %]
+ </p>
+ </div>
+ [% IF c.user.is_superuser %]
+ [% loc('Trusted by bodies:') %]<br />
+ <select id='body' name='trusted_bodies' multiple>
+ [% FOR body IN bodies %]
+ <option value="[% body.id %]"[% ' selected' IF user.has_permission_to('trusted', body.id) %]>[% body.name %]</option>
+ [% END %]
+ </select>
+ [% ELSE %]
+ <label>
+ [% loc('Trusted:') %]
+ <input type="checkbox" id="trusted_bodies" name="trusted_bodies" value="[% c.user.from_body.id %]" [% 'checked' IF user.has_permission_to('trusted', c.user.from_body.id) %]>
+ </label>
+ [% END %]
+ </li>
+ [% END %]
+
[% IF c.user.is_superuser %]
<li>
<div class="admin-hint">