aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rwxr-xr-xbin/update-schema1
-rw-r--r--db/downgrade_0072---0071.sql21
-rw-r--r--db/schema.sql2
-rw-r--r--db/schema_0072-add-staff-contact-state.sql23
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/New.pm6
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Contact.pm27
-rw-r--r--t/app/controller/report_new_staff.t32
-rw-r--r--templates/web/base/admin/bodies/contact-form.html5
9 files changed, 111 insertions, 7 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 38cafc2ad..fd60691d6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -43,6 +43,7 @@
- Allow report as another user with only name.
- Allow staff users to sign other people up for alerts.
- Group categories on body page. #2850
+ - Add a new "staff" contact state.
- New features:
- Categories can be listed under more than one group #2475
- OpenID Connect login support. #2523
diff --git a/bin/update-schema b/bin/update-schema
index 7941bc542..8f31085c9 100755
--- a/bin/update-schema
+++ b/bin/update-schema
@@ -212,6 +212,7 @@ else {
# (assuming schema change files are never half-applied, which should be the case)
sub get_db_version {
return 'EMPTY' if ! table_exists('problem');
+ return '0072' if constraint_contains('contacts_state_check', 'staff');
return '0071' if table_exists('manifest_theme');
return '0070' if column_like('alert_type', "ref='new_problems'", 'head_title', '{{SITE_NAME}}');
return '0069' if constraint_contains('admin_log_object_type_check', 'template');
diff --git a/db/downgrade_0072---0071.sql b/db/downgrade_0072---0071.sql
new file mode 100644
index 000000000..aa649f63d
--- /dev/null
+++ b/db/downgrade_0072---0071.sql
@@ -0,0 +1,21 @@
+BEGIN;
+
+ALTER TABLE contacts DROP CONSTRAINT contacts_state_check;
+
+ALTER TABLE contacts ADD CONSTRAINT contacts_state_check CHECK (
+ state = 'unconfirmed'
+ or state = 'confirmed'
+ or state = 'inactive'
+ or state = 'deleted'
+);
+
+ALTER TABLE contacts_history DROP CONSTRAINT contacts_history_state_check;
+
+ALTER TABLE contacts_history ADD CONSTRAINT contacts_history_state_check CHECK (
+ state = 'unconfirmed'
+ or state = 'confirmed'
+ or state = 'inactive'
+ or state = 'deleted'
+);
+
+COMMIT;
diff --git a/db/schema.sql b/db/schema.sql
index 0e38ad862..ed21aded6 100644
--- a/db/schema.sql
+++ b/db/schema.sql
@@ -100,6 +100,7 @@ create table contacts (
state = 'unconfirmed'
or state = 'confirmed'
or state = 'inactive'
+ or state = 'staff'
or state = 'deleted'
),
@@ -137,6 +138,7 @@ create table contacts_history (
state = 'unconfirmed'
or state = 'confirmed'
or state = 'inactive'
+ or state = 'staff'
or state = 'deleted'
),
diff --git a/db/schema_0072-add-staff-contact-state.sql b/db/schema_0072-add-staff-contact-state.sql
new file mode 100644
index 000000000..efaac2d20
--- /dev/null
+++ b/db/schema_0072-add-staff-contact-state.sql
@@ -0,0 +1,23 @@
+BEGIN;
+
+ALTER TABLE contacts DROP CONSTRAINT contacts_state_check;
+
+ALTER TABLE contacts ADD CONSTRAINT contacts_state_check CHECK (
+ state = 'unconfirmed'
+ or state = 'confirmed'
+ or state = 'inactive'
+ or state = 'staff'
+ or state = 'deleted'
+);
+
+ALTER TABLE contacts_history DROP CONSTRAINT contacts_history_state_check;
+
+ALTER TABLE contacts_history ADD CONSTRAINT contacts_history_state_check CHECK (
+ state = 'unconfirmed'
+ or state = 'confirmed'
+ or state = 'inactive'
+ or state = 'staff'
+ or state = 'deleted'
+);
+
+COMMIT;
diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm
index 14aa7b83e..ef1905c98 100644
--- a/perllib/FixMyStreet/App/Controller/Report/New.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/New.pm
@@ -690,11 +690,7 @@ sub setup_categories_and_bodies : Private {
$c->cobrand->call_hook(munge_report_new_bodies => \%bodies);
- my $contacts #
- = $c #
- ->model('DB::Contact') #
- ->active
- ->search( { 'me.body_id' => [ keys %bodies ] }, { prefetch => 'body' } );
+ my $contacts = $c->model('DB::Contact')->for_new_reports($c, \%bodies);
my @contacts = $c->cobrand->categories_restriction($contacts)->all_sorted;
$c->cobrand->call_hook(munge_report_new_contacts => \@contacts);
diff --git a/perllib/FixMyStreet/DB/ResultSet/Contact.pm b/perllib/FixMyStreet/DB/ResultSet/Contact.pm
index 1643f9931..eb502c190 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Contact.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Contact.pm
@@ -17,7 +17,7 @@ Filter down to not deleted contacts (so active or inactive).
sub not_deleted {
my $rs = shift;
- return $rs->search( { $rs->me('state') => { '!=' => 'deleted' } } );
+ return $rs->search( { $rs->me('state') => { -not_in => [ 'deleted', 'staff' ] } } );
}
sub active {
@@ -25,6 +25,31 @@ sub active {
$rs->search( { $rs->me('state') => [ 'unconfirmed', 'confirmed' ] } );
}
+sub for_new_reports {
+ my ($rs, $c, $bodies) = @_;
+ my $params = {
+ $rs->me('body_id') => [ keys %$bodies ],
+ };
+
+ if ($c->user_exists && $c->user->from_body) {
+ # Everything normal OR staff state in the user body
+ $params->{'-or'} = [
+ $rs->me('state') => [ 'unconfirmed', 'confirmed' ],
+ {
+ $rs->me('body_id') => $c->user->from_body->id,
+ $rs->me('state') => 'staff',
+ },
+ ];
+ } elsif ($c->user_exists && $c->user->is_superuser) {
+ # Everything normal OR any staff states
+ $params->{$rs->me('state')} = [ 'unconfirmed', 'confirmed', 'staff' ];
+ } else {
+ $params->{$rs->me('state')} = [ 'unconfirmed', 'confirmed' ];
+ }
+
+ $rs->search($params, { prefetch => 'body' });
+}
+
sub translated {
my $rs = shift;
my $schema = $rs->result_source->schema;
diff --git a/t/app/controller/report_new_staff.t b/t/app/controller/report_new_staff.t
index 5d4d05e52..ee9dff9e4 100644
--- a/t/app/controller/report_new_staff.t
+++ b/t/app/controller/report_new_staff.t
@@ -18,7 +18,7 @@ for my $body (
# Let's make some contacts to send things to!
$mech->create_contact_ok( body_id => $body_ids{2651}, category => 'Street lighting', email => 'highways@example.com' );
-$mech->create_contact_ok( body_id => $body_ids{2651}, category => 'Trees', email => 'trees@example.com' );
+my $edin_trees = $mech->create_contact_ok( body_id => $body_ids{2651}, category => 'Trees', email => 'trees@example.com' );
$mech->create_contact_ok( body_id => $body_ids{2482}, category => 'Trees', email => 'trees@example.com' );
$mech->create_contact_ok( body_id => $body_ids{2237}, category => 'Trees', email => 'trees-2247@example.com' );
@@ -224,4 +224,34 @@ for my $test (
};
}
+subtest 'staff-only categories when reporting' => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ MAPIT_TYPES => ['UTA'],
+ }, sub {
+ $inspector->update({ is_superuser => 1 });
+ $mech->log_in_ok('inspector@example.org');
+
+ $mech->get_ok('/admin/body/' . $body_ids{2651} . '/Trees');
+ $mech->submit_form_ok({ with_fields => { state => 'staff' } }, 'mark Trees as staff-only');
+ $edin_trees->discard_changes;
+ is $edin_trees->state, 'staff', 'category is staff only';
+
+ my $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' );
+ is_deeply [ sort keys %{$extra_details->{by_category}} ], [ 'Street lighting', 'Trees' ], 'Superuser can see staff-only category';
+
+ $inspector->update({ is_superuser => 0 });
+ $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' );
+ is_deeply [ sort keys %{$extra_details->{by_category}} ], [ 'Street lighting', 'Trees' ], 'Body staff user can see staff-only category';
+
+ $inspector->update({ from_body => $body_ids{2482} });
+ $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' );
+ is_deeply [ sort keys %{$extra_details->{by_category}} ], [ 'Street lighting' ], 'Different body staff user cannot see staff-only category';
+
+ $mech->log_out_ok;
+ $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' );
+ is_deeply [ sort keys %{$extra_details->{by_category}} ], [ 'Street lighting' ], 'Normal user cannot see staff-only category';
+ };
+};
+
done_testing;
diff --git a/templates/web/base/admin/bodies/contact-form.html b/templates/web/base/admin/bodies/contact-form.html
index 921cb1380..b698fcea2 100644
--- a/templates/web/base/admin/bodies/contact-form.html
+++ b/templates/web/base/admin/bodies/contact-form.html
@@ -40,6 +40,11 @@
<label for="state-deleted">[% loc('Deleted') %]</label>
<p class="form-hint" id="state-deleted-hint">[% loc('Prevent new reports from using this category, <em>and</em> also remove it from map filters.') %]</p>
</div>
+ <div class="form-check form-check--inline">
+ <input type="radio" name="state" id="state-staff" aria-describedby="state-staff-hint" value="staff"[% ' checked' IF contact.state == 'staff' %]>
+ <label for="state-staff">[% loc('Staff only') %]</label>
+ <p class="form-hint" id="state-staff-hint">[% loc('Only staff users will be able to add reports in this category.') %]</p>
+ </div>
</fieldset>
<p class="form-check">