diff options
author | Matthew Somerville <matthew@mysociety.org> | 2020-02-27 07:39:46 +0000 |
---|---|---|
committer | Matthew Somerville <matthew@mysociety.org> | 2020-02-27 07:39:46 +0000 |
commit | b0b6810e372a154b1af7da72c1bd2143e5e251e9 (patch) | |
tree | 1ebbc91b59f8822e483e51f1f486c347718b0e65 | |
parent | 152f8f4e608abc5029104e652f4ef37d4cfe02cb (diff) | |
parent | 18adbe946c1104338e6abff159b4f9877154969c (diff) |
Merge branch 'admin-only-categories'
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rwxr-xr-x | bin/createsuperuser | 2 | ||||
-rwxr-xr-x | bin/update-schema | 1 | ||||
-rw-r--r-- | db/downgrade_0072---0071.sql | 21 | ||||
-rw-r--r-- | db/schema.sql | 2 | ||||
-rw-r--r-- | db/schema_0072-add-staff-contact-state.sql | 23 | ||||
-rw-r--r-- | perllib/DBIx/Class/FixMyStreet/EncodedColumn.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report/New.pm | 6 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Bexley.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/FixMyStreet.pm | 47 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/IsleOfWight.pm | 16 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/TfL.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/ResultSet/Contact.pm | 27 | ||||
-rw-r--r-- | perllib/FixMyStreet/Script/CreateSuperuser.pm | 20 | ||||
-rw-r--r-- | t/app/controller/report_new.t | 203 | ||||
-rw-r--r-- | t/app/controller/report_new_staff.t | 257 | ||||
-rw-r--r-- | t/script/createsuperuser.t | 23 | ||||
-rw-r--r-- | templates/web/base/admin/bodies/contact-form.html | 5 |
18 files changed, 390 insertions, 270 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 809a24675..64b178919 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ - Allow staff users to sign other people up for alerts. - Group categories on body page. #2850 - Add admin UI for managing web manifest themes. #2792 + - 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/createsuperuser b/bin/createsuperuser index 98b36aa36..7a4946228 100755 --- a/bin/createsuperuser +++ b/bin/createsuperuser @@ -30,4 +30,4 @@ BEGIN { use FixMyStreet; use FixMyStreet::Script::CreateSuperuser; -FixMyStreet::Script::CreateSuperuser::createsuperuser(); +exit FixMyStreet::Script::CreateSuperuser::createsuperuser(@ARGV); 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/DBIx/Class/FixMyStreet/EncodedColumn.pm b/perllib/DBIx/Class/FixMyStreet/EncodedColumn.pm index 3be6e4594..82e6e591e 100644 --- a/perllib/DBIx/Class/FixMyStreet/EncodedColumn.pm +++ b/perllib/DBIx/Class/FixMyStreet/EncodedColumn.pm @@ -10,7 +10,7 @@ sub set_column { my $self = shift; if ($_[0] eq 'password') { my $cobrand = $self->result_source->schema->cobrand; - if ($cobrand->moniker eq 'tfl') { + if ($cobrand && $cobrand->moniker eq 'tfl') { if (defined $_[1]) { if (defined $_[2]) { $self->set_extra_metadata(tfl_password => $_[1]); 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/Cobrand/Bexley.pm b/perllib/FixMyStreet/Cobrand/Bexley.pm index 275d7dfaf..0586c18c4 100644 --- a/perllib/FixMyStreet/Cobrand/Bexley.pm +++ b/perllib/FixMyStreet/Cobrand/Bexley.pm @@ -212,7 +212,7 @@ sub dashboard_export_problems_add_columns { my %groups; if ($c->stash->{body}) { - %groups = FixMyStreet::DB->resultset('Contact')->active->search({ + %groups = FixMyStreet::DB->resultset('Contact')->search({ body_id => $c->stash->{body}->id, })->group_lookup; } diff --git a/perllib/FixMyStreet/Cobrand/FixMyStreet.pm b/perllib/FixMyStreet/Cobrand/FixMyStreet.pm index 97a0ab53a..a2dea1df4 100644 --- a/perllib/FixMyStreet/Cobrand/FixMyStreet.pm +++ b/perllib/FixMyStreet/Cobrand/FixMyStreet.pm @@ -131,51 +131,8 @@ sub munge_load_and_group_problems { return unless $where->{category} && $self->{c}->stash->{body}->name eq 'Isle of Wight Council'; - $where->{category} = $self->expand_triage_cat_list($where->{category}); -} - -sub expand_triage_cat_list { - my ($self, $categories) = @_; - - my $b = $self->{c}->stash->{body}; - - my $all_cats = $self->{c}->model('DB::Contact')->not_deleted->search( - { - body_id => $b->id, - send_method => [{ '!=', 'Triage'}, undef] - } - ); - - my %group_to_category; - while ( my $cat = $all_cats->next ) { - next unless $cat->get_extra_metadata('group'); - my $groups = $cat->get_extra_metadata('group'); - $groups = ref $groups eq 'ARRAY' ? $groups : [ $groups ]; - for my $group ( @$groups ) { - $group_to_category{$group} //= []; - push @{ $group_to_category{$group} }, $cat->category; - } - } - - my $cats = $self->{c}->model('DB::Contact')->not_deleted->search( - { - body_id => $b->id, - category => $categories - } - ); - - my @cat_names; - while ( my $cat = $cats->next ) { - if ( $cat->send_method && $cat->send_method eq 'Triage' ) { - # include the category itself - push @cat_names, $cat->category; - push @cat_names, @{ $group_to_category{$cat->category} } if $group_to_category{$cat->category}; - } else { - push @cat_names, $cat->category; - } - } - - return \@cat_names; + my $iow = FixMyStreet::Cobrand->get_class_for_moniker( 'isleofwight' )->new({ c => $self->{c} }); + $where->{category} = $iow->expand_triage_cat_list($where->{category}, $self->{c}->stash->{body}); } sub title_list { diff --git a/perllib/FixMyStreet/Cobrand/IsleOfWight.pm b/perllib/FixMyStreet/Cobrand/IsleOfWight.pm index a46b540ad..db0a20b9c 100644 --- a/perllib/FixMyStreet/Cobrand/IsleOfWight.pm +++ b/perllib/FixMyStreet/Cobrand/IsleOfWight.pm @@ -142,7 +142,7 @@ sub munge_load_and_group_problems { return unless $where->{category}; - $where->{category} = $self->expand_triage_cat_list($where->{category}); + $where->{category} = $self->_expand_triage_cat_list($where->{category}); } sub munge_around_filter_category_list { @@ -151,17 +151,21 @@ sub munge_around_filter_category_list { my $c = $self->{c}; return unless $c->stash->{filter_category}; - my $cat_names = $self->expand_triage_cat_list([ keys %{$c->stash->{filter_category}} ]); + my $cat_names = $self->_expand_triage_cat_list([ keys %{$c->stash->{filter_category}} ]); $c->stash->{filter_category} = { map { $_ => 1 } @$cat_names }; } +sub _expand_triage_cat_list { + my ($self, $categories) = @_; + my $b = $self->{c}->model('DB::Body')->for_areas( $self->council_area_id )->first; + return $self->expand_triage_cat_list($categories, $b); +} + # this assumes that each Triage category has the same name as a group # and uses this to generate a list of categories that a triage category # could be triaged to sub expand_triage_cat_list { - my ($self, $categories) = @_; - - my $b = $self->{c}->model('DB::Body')->for_areas( $self->council_area_id )->first; + my ($self, $categories, $b) = @_; my $all_cats = $self->{c}->model('DB::Contact')->not_deleted->search( { @@ -190,7 +194,7 @@ sub expand_triage_cat_list { my @cat_names; while ( my $cat = $cats->next ) { - if ( $cat->send_method eq 'Triage' ) { + if ( $cat->send_method && $cat->send_method eq 'Triage' ) { # include the category itself push @cat_names, $cat->category; push @cat_names, @{ $group_to_category{$cat->category} } if $group_to_category{$cat->category}; diff --git a/perllib/FixMyStreet/Cobrand/TfL.pm b/perllib/FixMyStreet/Cobrand/TfL.pm index d1cfb8d42..40c2a5257 100644 --- a/perllib/FixMyStreet/Cobrand/TfL.pm +++ b/perllib/FixMyStreet/Cobrand/TfL.pm @@ -244,7 +244,7 @@ sub dashboard_export_problems_add_columns { my %groups; if ($c->stash->{body}) { - %groups = FixMyStreet::DB->resultset('Contact')->active->search({ + %groups = FixMyStreet::DB->resultset('Contact')->search({ body_id => $c->stash->{body}->id, })->group_lookup; } 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/perllib/FixMyStreet/Script/CreateSuperuser.pm b/perllib/FixMyStreet/Script/CreateSuperuser.pm index 69d165abb..cbbea577a 100644 --- a/perllib/FixMyStreet/Script/CreateSuperuser.pm +++ b/perllib/FixMyStreet/Script/CreateSuperuser.pm @@ -7,19 +7,27 @@ use FixMyStreet; use FixMyStreet::DB; sub createsuperuser { - die "Specify a single email address and optionally password to create a superuser or grant superuser status to." if (@ARGV < 1 || @ARGV > 2); + my ($email, $password) = @_; - my $user = FixMyStreet::DB->resultset('User')->find_or_new({ email => $ARGV[0] }); + unless ($email) { + warn "Specify a single email address and optionally password to create a superuser or grant superuser status to.\n"; + return 1; + } + + my $user = FixMyStreet::DB->resultset('User')->find_or_new({ email => $email }); if ( !$user->in_storage ) { - die "Specify a password for this new user." if (@ARGV < 2); - $user->password($ARGV[1]); + unless ($password) { + warn "Specify a password for this new user.\n"; + return 1; + } + $user->password($password); $user->is_superuser(1); $user->insert; } else { $user->update({ is_superuser => 1 }); } print $user->email . " is now a superuser.\n"; + return 0; } - -1;
\ No newline at end of file +1; diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t index 1f5ad2b52..b85bae43a 100644 --- a/t/app/controller/report_new.t +++ b/t/app/controller/report_new.t @@ -2185,207 +2185,4 @@ subtest "extra google analytics code displayed on email confirmation problem cre }; }; - -my $private_perms = $mech->create_user_ok('private_perms@example.org', name => 'private', from_body => $bodies[0]); -subtest "report_mark_private allows users to mark reports as private" => sub { - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], - BASE_URL => 'https://www.fixmystreet.com', - MAPIT_URL => 'http://mapit.uk/', - }, sub { - $mech->log_out_ok; - - $private_perms->user_body_permissions->find_or_create({ - body => $bodies[0], - permission_type => 'report_mark_private', - }); - - $mech->log_in_ok('private_perms@example.org'); - $mech->get_ok('/'); - $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } }, - "submit location" ); - $mech->follow_link_ok( - { text_regex => qr/skip this step/i, }, - "follow 'skip this step' link" - ); - - $mech->submit_form_ok( - { - with_fields => { - title => "Private report", - detail => 'Private report details.', - photo1 => '', - name => 'Joe Bloggs', - may_show_name => '1', - phone => '07903 123 456', - category => 'Trees', - non_public => 1, - } - }, - "submit good details" - ); - - $mech->content_contains('Great work. Now spread the word', 'shown confirmation page'); - } -}; - -my $inspector = $mech->create_user_ok('inspector@example.org', name => 'inspector', from_body => $bodies[0]); -foreach my $test ( - { non_public => 0 }, - { non_public => 1 }, -) { - subtest "inspectors get redirected directly to the report page, non_public=$test->{non_public}" => sub { - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], - BASE_URL => 'https://www.fixmystreet.com', - MAPIT_URL => 'http://mapit.uk/', - }, sub { - $mech->log_out_ok; - - $inspector->user_body_permissions->find_or_create({ - body => $bodies[0], - permission_type => 'planned_reports', - }); - $inspector->user_body_permissions->find_or_create({ - body => $bodies[0], - permission_type => 'report_inspect', - }); - - $mech->log_in_ok('inspector@example.org'); - $mech->get_ok('/'); - $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } }, - "submit location" ); - $mech->follow_link_ok( - { text_regex => qr/skip this step/i, }, - "follow 'skip this step' link" - ); - - $mech->submit_form_ok( - { - with_fields => { - title => "Inspector report", - detail => 'Inspector report details.', - photo1 => '', - name => 'Joe Bloggs', - may_show_name => '1', - phone => '07903 123 456', - category => 'Trees', - non_public => $test->{non_public}, - } - }, - "submit good details" - ); - - like $mech->uri->path, qr/\/report\/[0-9]+/, 'Redirects directly to report'; - } - }; -} - -subtest "check map click ajax response for inspector" => sub { - $mech->log_out_ok; - - my $extra_details; - $inspector->user_body_permissions->find_or_create({ - body => $bodies[0], - permission_type => 'planned_reports', - }); - $inspector->user_body_permissions->find_or_create({ - body => $bodies[0], - permission_type => 'report_inspect', - }); - - $mech->log_in_ok('inspector@example.org'); - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], - MAPIT_URL => 'http://mapit.uk/', - }, sub { - $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' ); - }; - like $extra_details->{category}, qr/data-prefill="0/, 'inspector prefill not set'; - ok !$extra_details->{contribute_as}, 'no contribute as section'; -}; - -subtest "check map click ajax response for inspector and uk cobrand" => sub { - $mech->log_out_ok; - - my $extra_details; - $inspector->user_body_permissions->find_or_create({ - body => $bodies[4], - permission_type => 'planned_reports', - }); - $inspector->user_body_permissions->find_or_create({ - body => $bodies[4], - permission_type => 'report_inspect', - }); - - $mech->log_in_ok('inspector@example.org'); - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ { bromley => '.' } ], - MAPIT_URL => 'http://mapit.uk/', - }, sub { - $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.402096&longitude=0.015784' ); - }; - like $extra_details->{category}, qr/data-prefill="0/, 'inspector prefill not set'; -}; - -for my $test ( - { - desc => 'map click ajax for contribute_as_another_user', - permissions => { - contribute_as_another_user => 1, - contribute_as_anonymous_user => undef, - contribute_as_body => undef, - } - }, - { - desc => 'map click ajax for contribute_as_anonymous_user', - permissions => { - contribute_as_another_user => undef, - contribute_as_anonymous_user => 1, - contribute_as_body => undef, - } - }, - { - desc => 'map click ajax for contribute_as_body', - permissions => { - contribute_as_another_user => undef, - contribute_as_anonymous_user => undef, - contribute_as_body => 1, - } - }, -) { - subtest $test->{desc} => sub { - $mech->log_out_ok; - my $extra_details; - (my $name = $test->{desc}) =~ s/.*(contri.*)/$1/; - my $user = $mech->create_user_ok("$name\@example.org", name => 'test user', from_body => $bodies[0]); - for my $p ( keys %{$test->{permissions}} ) { - next unless $test->{permissions}->{$p}; - $user->user_body_permissions->find_or_create({ - body => $bodies[0], - permission_type => $p, - }); - } - $mech->log_in_ok("$name\@example.org"); - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], - MAPIT_URL => 'http://mapit.uk/', - }, sub { - $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' ); - }; - for my $p ( keys %{$test->{permissions}} ) { - (my $key = $p) =~ s/contribute_as_//; - is $extra_details->{contribute_as}->{$key}, $test->{permissions}->{$p}, "$key correctly set"; - } - - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ { fixmystreet => '.' } ], - MAPIT_URL => 'http://mapit.uk/', - }, sub { - $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.754926&longitude=-1.256179' ); - }; - ok !$extra_details->{contribute_as}, 'no contribute as section for other council'; - }; -} - done_testing(); diff --git a/t/app/controller/report_new_staff.t b/t/app/controller/report_new_staff.t new file mode 100644 index 000000000..ee9dff9e4 --- /dev/null +++ b/t/app/controller/report_new_staff.t @@ -0,0 +1,257 @@ +use FixMyStreet::TestMech; + +# disable info logs for this test run +FixMyStreet::App->log->disable('info'); +END { FixMyStreet::App->log->enable('info'); } + +my $mech = FixMyStreet::TestMech->new; + +my %body_ids; +for my $body ( + { area_id => 2651, name => 'City of Edinburgh Council' }, + { area_id => 2482, name => 'Bromley Council' }, + { area_id => 2237, name => 'Oxfordshire County Council' }, +) { + my $body_obj = $mech->create_body_ok($body->{area_id}, $body->{name}); + $body_ids{$body->{area_id}} = $body_obj->id; +} + +# 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' ); +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' ); + +my $private_perms = $mech->create_user_ok('private_perms@example.org', name => 'private', from_body => $body_ids{2651}); +subtest "report_mark_private allows users to mark reports as private" => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', + BASE_URL => 'https://www.fixmystreet.com', + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->log_out_ok; + + $private_perms->user_body_permissions->find_or_create({ + body_id => $body_ids{2651}, + permission_type => 'report_mark_private', + }); + + $mech->log_in_ok('private_perms@example.org'); + $mech->get_ok('/'); + $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } }, + "submit location" ); + $mech->follow_link_ok( + { text_regex => qr/skip this step/i, }, + "follow 'skip this step' link" + ); + + $mech->submit_form_ok( + { + with_fields => { + title => "Private report", + detail => 'Private report details.', + photo1 => '', + name => 'Joe Bloggs', + may_show_name => '1', + phone => '07903 123 456', + category => 'Trees', + non_public => 1, + } + }, + "submit good details" + ); + + $mech->content_contains('Great work. Now spread the word', 'shown confirmation page'); + } +}; + +my $inspector = $mech->create_user_ok('inspector@example.org', name => 'inspector', from_body => $body_ids{2651}); +foreach my $test ( + { non_public => 0 }, + { non_public => 1 }, +) { + subtest "inspectors get redirected directly to the report page, non_public=$test->{non_public}" => sub { + FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', + BASE_URL => 'https://www.fixmystreet.com', + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $mech->log_out_ok; + + $inspector->user_body_permissions->find_or_create({ + body_id => $body_ids{2651}, + permission_type => 'planned_reports', + }); + $inspector->user_body_permissions->find_or_create({ + body_id => $body_ids{2651}, + permission_type => 'report_inspect', + }); + + $mech->log_in_ok('inspector@example.org'); + $mech->get_ok('/'); + $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } }, + "submit location" ); + $mech->follow_link_ok( + { text_regex => qr/skip this step/i, }, + "follow 'skip this step' link" + ); + + $mech->submit_form_ok( + { + with_fields => { + title => "Inspector report", + detail => 'Inspector report details.', + photo1 => '', + name => 'Joe Bloggs', + may_show_name => '1', + phone => '07903 123 456', + category => 'Trees', + non_public => $test->{non_public}, + } + }, + "submit good details" + ); + + like $mech->uri->path, qr/\/report\/[0-9]+/, 'Redirects directly to report'; + } + }; +} + +subtest "check map click ajax response for inspector" => sub { + $mech->log_out_ok; + + my $extra_details; + $inspector->user_body_permissions->find_or_create({ + body_id => $body_ids{2651}, + permission_type => 'planned_reports', + }); + $inspector->user_body_permissions->find_or_create({ + body_id => $body_ids{2651}, + permission_type => 'report_inspect', + }); + + $mech->log_in_ok('inspector@example.org'); + FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' ); + }; + like $extra_details->{category}, qr/data-prefill="0/, 'inspector prefill not set'; + ok !$extra_details->{contribute_as}, 'no contribute as section'; +}; + +subtest "check map click ajax response for inspector and uk cobrand" => sub { + $mech->log_out_ok; + + my $extra_details; + $inspector->user_body_permissions->find_or_create({ + body_id => $body_ids{2482}, + permission_type => 'planned_reports', + }); + $inspector->user_body_permissions->find_or_create({ + body_id => $body_ids{2482}, + permission_type => 'report_inspect', + }); + + $mech->log_in_ok('inspector@example.org'); + FixMyStreet::override_config { + ALLOWED_COBRANDS => 'bromley', + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.402096&longitude=0.015784' ); + }; + like $extra_details->{category}, qr/data-prefill="0/, 'inspector prefill not set'; +}; + +for my $test ( + { + desc => 'map click ajax for contribute_as_another_user', + permissions => { + contribute_as_another_user => 1, + contribute_as_anonymous_user => undef, + contribute_as_body => undef, + } + }, + { + desc => 'map click ajax for contribute_as_anonymous_user', + permissions => { + contribute_as_another_user => undef, + contribute_as_anonymous_user => 1, + contribute_as_body => undef, + } + }, + { + desc => 'map click ajax for contribute_as_body', + permissions => { + contribute_as_another_user => undef, + contribute_as_anonymous_user => undef, + contribute_as_body => 1, + } + }, +) { + subtest $test->{desc} => sub { + $mech->log_out_ok; + my $extra_details; + (my $name = $test->{desc}) =~ s/.*(contri.*)/$1/; + my $user = $mech->create_user_ok("$name\@example.org", name => 'test user', from_body => $body_ids{2651}); + for my $p ( keys %{$test->{permissions}} ) { + next unless $test->{permissions}->{$p}; + $user->user_body_permissions->find_or_create({ + body_id => $body_ids{2651}, + permission_type => $p, + }); + } + $mech->log_in_ok("$name\@example.org"); + FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=55.952055&longitude=-3.189579' ); + }; + for my $p ( keys %{$test->{permissions}} ) { + (my $key = $p) =~ s/contribute_as_//; + is $extra_details->{contribute_as}->{$key}, $test->{permissions}->{$p}, "$key correctly set"; + } + + FixMyStreet::override_config { + ALLOWED_COBRANDS => 'fixmystreet', + MAPIT_URL => 'http://mapit.uk/', + }, sub { + $extra_details = $mech->get_ok_json( '/report/new/ajax?latitude=51.754926&longitude=-1.256179' ); + }; + ok !$extra_details->{contribute_as}, 'no contribute as section for other council'; + }; +} + +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/t/script/createsuperuser.t b/t/script/createsuperuser.t new file mode 100644 index 000000000..1d4826111 --- /dev/null +++ b/t/script/createsuperuser.t @@ -0,0 +1,23 @@ +use Test::More; +use Test::Output; + +use_ok 'FixMyStreet::Script::CreateSuperuser'; + +stderr_like { FixMyStreet::Script::CreateSuperuser::createsuperuser(); } + qr/Specify a single email address/, 'Email error shown'; +stderr_is { FixMyStreet::Script::CreateSuperuser::createsuperuser('test@example.org'); } + "Specify a password for this new user.\n", 'Password error shown'; +stdout_is { FixMyStreet::Script::CreateSuperuser::createsuperuser('test@example.org', 'password'); } + "test\@example.org is now a superuser.\n", 'Correct message shown'; + +my $user = FixMyStreet::DB->resultset("User")->find({ email => 'test@example.org' }); +ok $user, 'user created'; +is $user->is_superuser, 1, 'is a superuser'; + +$user->update({ is_superuser => 0 }); +stdout_is { FixMyStreet::Script::CreateSuperuser::createsuperuser('test@example.org'); } + "test\@example.org is now a superuser.\n", 'Correct message shown'; +$user->discard_changes; +is $user->is_superuser, 1, 'is a superuser again'; + +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"> |