aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--db/alert_types.sql18
-rw-r--r--db/schema.sql10
-rw-r--r--db/schema_0024-add_non_public_categories_and_problems.sql37
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm7
-rw-r--r--perllib/FixMyStreet/App/Controller/Report.pm7
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/New.pm9
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports.pm4
-rw-r--r--perllib/FixMyStreet/App/Controller/Root.pm7
-rw-r--r--perllib/FixMyStreet/DB/Result/Contact.pm6
-rw-r--r--perllib/FixMyStreet/DB/Result/Problem.pm8
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/AlertType.pm4
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Nearby.pm1
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Problem.pm4
-rw-r--r--perllib/FixMyStreet/TestMech.pm107
-rw-r--r--t/app/controller/admin.t347
-rw-r--r--t/app/controller/alert_new.t190
-rw-r--r--t/app/controller/around.t26
-rw-r--r--t/app/controller/index.t16
-rw-r--r--t/app/controller/report_display.t31
-rw-r--r--t/app/controller/report_new.t68
-rw-r--r--t/app/controller/reports.t42
-rw-r--r--templates/web/default/admin/council_contacts.html9
-rw-r--r--templates/web/default/admin/council_edit.html3
-rw-r--r--templates/web/default/admin/report_edit.html1
24 files changed, 790 insertions, 172 deletions
diff --git a/db/alert_types.sql b/db/alert_types.sql
index 4ebd33cf9..4116d29dc 100644
--- a/db/alert_types.sql
+++ b/db/alert_types.sql
@@ -17,7 +17,7 @@ insert into alert_type
item_title, item_link, item_description, template)
values ('new_problems', '', '',
'New problems on FixMyStreet', '/', 'The latest problems reported by users',
- 'problem', 'problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc',
+ 'problem', 'problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc',
'{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem');
-- New fixed problems anywhere on the site
@@ -28,7 +28,7 @@ insert into alert_type
item_title, item_link, item_description, template)
values ('new_fixed_problems', '', '',
'Problems recently reported fixed on FixMyStreet', '/', 'The latest problems reported fixed by users',
- 'problem', 'problem.state in (''fixed'', ''fixed - user'', ''fixed - council'')', 'lastupdate desc',
+ 'problem', 'problem.non_public = ''f'' and problem.state in (''fixed'', ''fixed - user'', ''fixed - council'')', 'lastupdate desc',
'{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem');
-- New problems around a location
@@ -39,7 +39,7 @@ insert into alert_type
item_title, item_link, item_description, template)
values ('local_problems', '', '',
'New local problems on FixMyStreet', '/', 'The latest local problems reported by users',
- 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc',
+ 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc',
'{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-nearby');
-- New problems around a location
@@ -50,7 +50,7 @@ insert into alert_type
item_title, item_link, item_description, template)
values ('local_problems_state', '', '',
'New local problems on FixMyStreet', '/', 'The latest local problems reported by users',
- 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.state in (?)', 'created desc',
+ 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in (?)', 'created desc',
'{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-nearby');
-- New problems around a postcode
@@ -61,7 +61,7 @@ insert into alert_type
item_title, item_link, item_description, template)
values ('postcode_local_problems', '', '',
'New problems near {{POSTCODE}} on FixMyStreet', '/', 'The latest local problems reported by users',
- 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc',
+ 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')', 'created desc',
'{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-nearby');
-- New problems around a postcode with a particular state
@@ -72,7 +72,7 @@ insert into alert_type
item_title, item_link, item_description, template)
values ('postcode_local_problems_state', '', '',
'New problems near {{POSTCODE}} on FixMyStreet', '/', 'The latest local problems reported by users',
- 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.state in (?)', 'created desc',
+ 'problem_find_nearby(?, ?, ?) as nearby,problem', 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in (?)', 'created desc',
'{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-nearby');
-- New problems sent to a particular council
@@ -83,7 +83,7 @@ insert into alert_type
item_title, item_link, item_description, template)
values ('council_problems', '', '',
'New problems to {{COUNCIL}} on FixMyStreet', '/reports', 'The latest problems for {{COUNCIL}} reported by users',
- 'problem', 'problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and (council like ''%''||?||''%''
+ 'problem', 'problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and (council like ''%''||?||''%''
or council is null) and areas like ''%,''||?||'',%''', 'created desc',
'{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-council'
);
@@ -97,7 +97,7 @@ insert into alert_type
values ('ward_problems', '', '',
'New problems for {{COUNCIL}} within {{WARD}} ward on FixMyStreet', '/reports',
'The latest problems for {{COUNCIL}} within {{WARD}} ward reported by users',
- 'problem', 'problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and (council like ''%''||?||''%''
+ 'problem', 'problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and (council like ''%''||?||''%''
or council is null) and areas like ''%,''||?||'',%''', 'created desc',
'{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-ward'
);
@@ -111,7 +111,7 @@ insert into alert_type
values ('area_problems', '', '',
'New problems within {{NAME}}''s boundary on FixMyStreet', '/reports',
'The latest problems within {{NAME}}''s boundary reported by users', 'problem',
- 'problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and areas like ''%,''||?||'',%''', 'created desc',
+ 'problem.non_public = ''f'' and problem.state in (''confirmed'', ''investigating'', ''planned'', ''in progress'', ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and areas like ''%,''||?||'',%''', 'created desc',
'{{title}}, {{confirmed}}', '/report/{{id}}', '{{detail}}', 'alert-problem-area'
);
diff --git a/db/schema.sql b/db/schema.sql
index 832104991..6e9396f45 100644
--- a/db/schema.sql
+++ b/db/schema.sql
@@ -81,7 +81,10 @@ create table contacts (
note text not null,
-- extra fields required for open311
- extra text
+ extra text,
+
+ -- for things like missed bin collections
+ non_public boolean default 'f'
);
create unique index contacts_area_id_category_idx on contacts(area_id, category);
@@ -198,7 +201,10 @@ create table problem (
send_fail_timestamp timestamp,
-- record send_method used, which can be used to infer usefulness of external_id
- send_method_used text
+ send_method_used text,
+
+ -- for things like missed bin collections
+ non_public BOOLEAN default 'f'
);
create index problem_state_latitude_longitude_idx on problem(state, latitude, longitude);
create index problem_user_id_idx on problem ( user_id );
diff --git a/db/schema_0024-add_non_public_categories_and_problems.sql b/db/schema_0024-add_non_public_categories_and_problems.sql
new file mode 100644
index 000000000..c133b3ef2
--- /dev/null
+++ b/db/schema_0024-add_non_public_categories_and_problems.sql
@@ -0,0 +1,37 @@
+BEGIN;
+
+ ALTER TABLE contacts
+ ADD COLUMN non_public BOOLEAN DEFAULT 'f';
+
+ ALTER TABLE problem
+ ADD COLUMN non_public BOOLEAN DEFAULT 'f';
+
+
+ UPDATE alert_type set item_where = 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in
+ (''confirmed'', ''investigating'', ''planned'', ''in progress'',
+ ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')' WHERE ref = 'postcode_local_problems';
+ UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in
+ (''confirmed'', ''investigating'', ''planned'', ''in progress'',
+ ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'' )' WHERE ref = 'new_problems';
+ UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in (''fixed'', ''fixed - user'', ''fixed - council'')' WHERE ref = 'new_fixed_problems';
+ UPDATE alert_type set item_where = 'nearby.problem_id = problem.id and problem.non_public = ''f'' and problem.state in
+ (''confirmed'', ''investigating'', ''planned'', ''in progress'',
+ ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'')' WHERE ref = 'local_problems';
+ UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in
+ (''confirmed'', ''investigating'', ''planned'', ''in progress'',
+ ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and
+ (council like ''%''||?||''%'' or council is null) and
+ areas like ''%,''||?||'',%''' WHERE ref = 'council_problems';
+ UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in
+ (''confirmed'', ''investigating'', ''planned'', ''in progress'',
+ ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and
+ (council like ''%''||?||''%'' or council is null) and
+ areas like ''%,''||?||'',%''' WHERE ref = 'ward_problems';
+ UPDATE alert_type set item_where = 'problem.non_public = ''f'' and problem.state in
+ (''confirmed'', ''investigating'', ''planned'', ''in progress'',
+ ''fixed'', ''fixed - council'', ''fixed - user'', ''closed'') and
+ areas like ''%,''||?||'',%''' WHERE ref = 'area_problems';
+
+commit;
+
+COMMIT;
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm
index 298c75352..ef299d224 100644
--- a/perllib/FixMyStreet/App/Controller/Admin.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin.pm
@@ -301,6 +301,7 @@ sub update_contacts : Private {
$contact->email( $email );
$contact->confirmed( $c->req->param('confirmed') ? 1 : 0 );
$contact->deleted( $c->req->param('deleted') ? 1 : 0 );
+ $contact->non_public( $c->req->param('non_public') ? 1 : 0 );
$contact->note( $c->req->param('note') );
$contact->whenedited( \'ms_current_timestamp()' );
$contact->editor( $editor );
@@ -640,6 +641,7 @@ sub report_edit : Path('report_edit') : Args(1) {
}
my $flagged = $c->req->param('flagged') ? 1 : 0;
+ my $non_public = $c->req->param('non_public') ? 1 : 0;
# do this here so before we update the values in problem
if ( $c->req->param('anonymous') ne $problem->anonymous
@@ -647,8 +649,10 @@ sub report_edit : Path('report_edit') : Args(1) {
|| $c->req->param('email') ne $problem->user->email
|| $c->req->param('title') ne $problem->title
|| $c->req->param('detail') ne $problem->detail
- || $flagged != $problem->flagged )
+ || $flagged != $problem->flagged
+ || $non_public != $problem->non_public )
{
+ warn "edited";
$edited = 1;
}
@@ -658,6 +662,7 @@ sub report_edit : Path('report_edit') : Args(1) {
$problem->state( $c->req->param('state') );
$problem->name( $c->req->param('name') );
$problem->flagged( $flagged );
+ $problem->non_public( $non_public );
if ( $c->req->param('email') ne $problem->user->email ) {
my $user = $c->model('DB::User')->find_or_create(
diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm
index d36ba32fe..cda569860 100644
--- a/perllib/FixMyStreet/App/Controller/Report.pm
+++ b/perllib/FixMyStreet/App/Controller/Report.pm
@@ -74,6 +74,13 @@ sub load_problem_or_display_error : Private {
'/page_error_410_gone',
[ _('That report has been removed from FixMyStreet.') ] #
);
+ } elsif ( $problem->non_public ) {
+ if ( !$c->user || $c->user->id != $problem->user->id ) {
+ $c->detach(
+ '/page_error_403_access_denied',
+ [ _('That report cannot be viewed on FixMyStreet.') ] #
+ );
+ }
}
$c->stash->{problem} = $problem;
diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm
index ede0cd219..a2c5e6a0c 100644
--- a/perllib/FixMyStreet/App/Controller/Report/New.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/New.pm
@@ -595,6 +595,8 @@ sub setup_categories_and_councils : Private {
my @category_options = (); # categories to show
my $category_label = undef; # what to call them
my %category_extras = (); # extra fields to fill in for open311
+ my %non_public_categories =
+ (); # categories for which the reports are not public
# FIXME - implement in cobrand
if ( $c->cobrand->moniker eq 'emptyhomes' ) {
@@ -646,6 +648,8 @@ sub setup_categories_and_councils : Private {
$category_extras{ $contact->category } = $contact->extra
if $contact->extra;
+
+ $non_public_categories{ $contact->category } = 1 if $contact->non_public;
}
$seen{$contact->category} = 1;
}
@@ -663,6 +667,7 @@ sub setup_categories_and_councils : Private {
$c->stash->{category_label} = $category_label;
$c->stash->{category_options} = \@category_options;
$c->stash->{category_extras} = \%category_extras;
+ $c->stash->{non_public_categories} = \%non_public_categories;
$c->stash->{category_extras_json} = encode_json \%category_extras;
$c->stash->{extra_name_info} = $first_council->{id} == COUNCIL_ID_BROMLEY ? 1 : 0;
@@ -872,6 +877,10 @@ sub process_report : Private {
};
}
+ if ( $c->stash->{non_public_categories}->{ $report->category } ) {
+ $report->non_public( 1 );
+ }
+
$c->cobrand->process_extras( $c, $contacts[0]->area_id, \@extra );
if ( @extra ) {
diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm
index 37766db44..dd725be19 100644
--- a/perllib/FixMyStreet/App/Controller/Reports.pm
+++ b/perllib/FixMyStreet/App/Controller/Reports.pm
@@ -236,6 +236,7 @@ sub council_check : Private {
type => $area_types,
min_generation => $c->cobrand->area_min_generation
);
+
if (keys %$areas == 1) {
($c->stash->{council}) = values %$areas;
return;
@@ -318,7 +319,8 @@ sub load_and_group_problems : Private {
my $page = $c->req->params->{p} || 1;
my $where = {
- state => [ FixMyStreet::DB::Result::Problem->visible_states() ]
+ non_public => 0,
+ state => [ FixMyStreet::DB::Result::Problem->visible_states() ]
};
if ($c->stash->{ward}) {
$where->{areas} = { 'like', '%,' . $c->stash->{ward}->{id} . ',%' };
diff --git a/perllib/FixMyStreet/App/Controller/Root.pm b/perllib/FixMyStreet/App/Controller/Root.pm
index 7f7d7f5fd..769a147bf 100644
--- a/perllib/FixMyStreet/App/Controller/Root.pm
+++ b/perllib/FixMyStreet/App/Controller/Root.pm
@@ -94,6 +94,13 @@ sub page_error_410_gone : Private {
$c->response->status(410);
}
+sub page_error_403_access_denied : Private {
+ my ( $self, $c, $error_msg ) = @_;
+ $c->stash->{template} = 'index.html';
+ $c->stash->{error} = $error_msg;
+ $c->response->status(403);
+}
+
=head2 end
Attempt to render a view, if needed.
diff --git a/perllib/FixMyStreet/DB/Result/Contact.pm b/perllib/FixMyStreet/DB/Result/Contact.pm
index c32b75d0c..cad12f1fc 100644
--- a/perllib/FixMyStreet/DB/Result/Contact.pm
+++ b/perllib/FixMyStreet/DB/Result/Contact.pm
@@ -36,13 +36,15 @@ __PACKAGE__->add_columns(
{ data_type => "text", is_nullable => 0 },
"extra",
{ data_type => "text", is_nullable => 1 },
+ "non_public",
+ { data_type => "boolean", default_value => \"false", is_nullable => 1 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->add_unique_constraint("contacts_area_id_category_idx", ["area_id", "category"]);
-# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-03-08 17:19:55
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hyvU0bMWSFxEPAJT7wqM/Q
+# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-08-31 10:29:17
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:t6yOPhZmedV/eH6AUvHI6w
__PACKAGE__->filter_column(
extra => {
diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm
index 9ae040acc..a1cf107a9 100644
--- a/perllib/FixMyStreet/DB/Result/Problem.pm
+++ b/perllib/FixMyStreet/DB/Result/Problem.pm
@@ -85,13 +85,15 @@ __PACKAGE__->add_columns(
"geocode",
{ data_type => "bytea", is_nullable => 1 },
"send_fail_count",
- { data_type => "integer", is_nullable => 1 },
+ { data_type => "integer", default_value => 0, is_nullable => 0 },
"send_fail_reason",
{ data_type => "text", is_nullable => 1 },
"send_fail_timestamp",
{ data_type => "timestamp", is_nullable => 1 },
"send_method_used",
{ data_type => "text", is_nullable => 1 },
+ "non_public",
+ { data_type => "boolean", default_value => \"false", is_nullable => 1 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->has_many(
@@ -114,8 +116,8 @@ __PACKAGE__->belongs_to(
);
-# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-05-03 16:05:20
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:EvwI91Ot7SioQWqwnXRTBQ
+# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-08-31 10:25:34
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:mudIAiLAUdmK8gGWIPiq6g
# Add fake relationship to stored procedure table
__PACKAGE__->has_one(
diff --git a/perllib/FixMyStreet/DB/ResultSet/AlertType.pm b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm
index a0320ccc3..2d206d84e 100644
--- a/perllib/FixMyStreet/DB/ResultSet/AlertType.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm
@@ -65,6 +65,9 @@ sub email_alerts ($) {
# call checks if this is the host that sends mail for this cobrand.
next unless $cobrand->email_host;
+ # this is for the new_updates alerts
+ next if $row->{non_public} and $row->{user_id} != $row->{alert_user_id};
+
my $hashref_restriction = $cobrand->site_restriction( $row->{cobrand_data} );
FixMyStreet::App->model('DB::AlertSent')->create( {
@@ -151,6 +154,7 @@ sub email_alerts ($) {
where nearby.problem_id = problem.id
and problem.user_id = users.id
and problem.state in ($states)
+ and problem.non_public = 'f'
and problem.confirmed >= ? and problem.confirmed >= ms_current_timestamp() - '7 days'::interval
and (select whenqueued from alert_sent where alert_sent.alert_id = ? and alert_sent.parameter::integer = problem.id) is null
and users.email <> ?
diff --git a/perllib/FixMyStreet/DB/ResultSet/Nearby.pm b/perllib/FixMyStreet/DB/ResultSet/Nearby.pm
index 83fc85a88..191223572 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Nearby.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Nearby.pm
@@ -8,6 +8,7 @@ sub nearby {
my ( $rs, $c, $dist, $ids, $limit, $mid_lat, $mid_lon, $interval ) = @_;
my $params = {
+ non_public => 0,
state => [ FixMyStreet::DB::Result::Problem::visible_states() ],
};
$params->{'current_timestamp-lastupdate'} = { '<', \"'$interval'::interval" }
diff --git a/perllib/FixMyStreet/DB/ResultSet/Problem.pm b/perllib/FixMyStreet/DB/ResultSet/Problem.pm
index bac367b87..2f426e8ca 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Problem.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Problem.pm
@@ -85,7 +85,8 @@ sub _recent {
$key .= ":$site_key:$num";
my $query = {
- state => [ FixMyStreet::DB::Result::Problem->visible_states() ],
+ non_public => 0,
+ state => [ FixMyStreet::DB::Result::Problem->visible_states() ],
};
$query->{photo} = { '!=', undef } if $photos;
@@ -141,6 +142,7 @@ sub around_map {
$attr->{rows} = $limit if $limit;
my $q = {
+ non_public => 0,
state => [ FixMyStreet::DB::Result::Problem->visible_states() ],
latitude => { '>=', $min_lat, '<', $max_lat },
longitude => { '>=', $min_lon, '<', $max_lon },
diff --git a/perllib/FixMyStreet/TestMech.pm b/perllib/FixMyStreet/TestMech.pm
index 2a49cc2f8..2a9c3ba7b 100644
--- a/perllib/FixMyStreet/TestMech.pm
+++ b/perllib/FixMyStreet/TestMech.pm
@@ -378,6 +378,49 @@ sub extract_update_metas {
return \@metas;
}
+=head2 extract_problem_list
+
+ $problems = $mech->extract_problem_list
+
+Returns an array ref of all problem titles on a page featuring standard issue lists
+
+=cut
+
+sub extract_problem_list {
+ my $mech = shift;
+
+ my $result = scraper {
+ process 'ul.issue-list-a li a h4', 'problems[]', 'TEXT';
+ }->scrape( $mech->response );
+
+ return $result->{ problems } || [];
+}
+
+=head2 extract_report_stats
+
+ $stats = $mech->extract_report_stats
+
+Returns a hash ref keyed by council name of all the council stats from the all reports
+page. Each value is an array ref with the first element being the council name and the
+rest being the stats in the order the appear in each row.
+
+=cut
+
+sub extract_report_stats {
+ my $mech = shift;
+
+ my $result = scraper {
+ process 'tr[align=center]', 'councils[]' => scraper {
+ process 'td.title a', 'council', 'TEXT',
+ process 'td', 'stats[]', 'TEXT'
+ }
+ }->scrape( $mech->response );
+
+ my %councils = map { $_->{council} => $_->{stats} } @{ $result->{councils} };
+
+ return \%councils;
+}
+
=head2 visible_form_values
$hashref = $mech->visible_form_values( );
@@ -475,4 +518,68 @@ sub get_ok_json {
return decode_json( $res->content );
}
+sub delete_problems_for_council {
+ my $mech = shift;
+ my $council = shift;
+
+ my $reports = FixMyStreet::App->model('DB::Problem')->search( { council => $council } );
+ if ( $reports ) {
+ for my $r ( $reports->all ) {
+ $r->comments->delete;
+ }
+ $reports->delete;
+ }
+}
+
+sub create_problems_for_council {
+ my ( $mech, $count, $council, $title, $params ) = @_;
+
+ my $dt = DateTime->now() || $params->{dt};
+
+ my $user =
+ FixMyStreet::App->model('DB::User')
+ ->find_or_create( { email => 'test@example.com', name => 'Test User' } )
+ or $params->{user};
+
+ delete $params->{user};
+ delete $params->{dt};
+
+ my @problems;
+
+ while ($count) {
+ my $default_params = {
+ postcode => 'SW1A 1AA',
+ council => $council,
+ areas => ',105255,11806,11828,2247,2504,',
+ category => 'Other',
+ title => "$title Test $count for $council",
+ detail => "$title Test $count for $council Detail",
+ used_map => 't',
+ name => 'Test User',
+ anonymous => 'f',
+ state => 'confirmed',
+ confirmed => $dt->ymd . ' ' . $dt->hms,
+ lang => 'en-gb',
+ service => '',
+ cobrand => 'default',
+ cobrand_data => '',
+ send_questionnaire => 't',
+ latitude => '51.5016605453401',
+ longitude => '-0.142497580865087',
+ user_id => $user->id,
+ photo => 1,
+ };
+
+ my %report_params = ( %$default_params, %$params );
+
+ my $problem =
+ FixMyStreet::App->model('DB::Problem')->create( \%report_params );
+
+ push @problems, $problem;
+ $count--;
+ }
+
+ return @problems;
+}
+
1;
diff --git a/t/app/controller/admin.t b/t/app/controller/admin.t
index 09d99cfdf..839bfd6b9 100644
--- a/t/app/controller/admin.t
+++ b/t/app/controller/admin.t
@@ -163,19 +163,32 @@ subtest 'check contact creation' => sub {
$mech->get_ok('/admin/council_contacts/2650');
$mech->submit_form_ok( { with_fields => {
- category => 'test category',
- email => 'test@example.com',
- note => 'test note',
+ category => 'test category',
+ email => 'test@example.com',
+ note => 'test note',
+ non_public => undef,
} } );
$mech->content_contains( 'test category' );
$mech->content_contains( '<td>test@example.com' );
$mech->content_contains( '<td>test note' );
+ $mech->content_contains( '<td>Public' );
+
+ $mech->submit_form_ok( { with_fields => {
+ category => 'private category',
+ email => 'test@example.com',
+ note => 'test note',
+ non_public => 'on',
+ } } );
+
+ $mech->content_contains( 'private category' );
+ $mech->content_contains( '<td>Non Public' );
$mech->submit_form_ok( { with_fields => {
category => 'test/category',
email => 'test@example.com',
note => 'test/note',
+ non_public => 'on',
} } );
$mech->get_ok('/admin/council_edit/2650/test/category');
@@ -187,11 +200,21 @@ subtest 'check contact editing' => sub {
$mech->submit_form_ok( { with_fields => {
email => 'test2@example.com',
note => 'test2 note',
+ non_public => undef,
} } );
$mech->content_contains( 'test category' );
$mech->content_contains( '<td>test2@example.com' );
$mech->content_contains( '<td>test2 note' );
+ $mech->content_contains( '<td>Public' );
+
+ $mech->submit_form_ok( { with_fields => {
+ email => 'test2@example.com',
+ note => 'test2 note',
+ non_public => 'on',
+ } } );
+
+ $mech->content_contains( '<td>Non Public' );
$mech->get_ok('/admin/council_edit/2650/test%20category');
$mech->content_contains( '<td><strong>test2@example.com' );
@@ -293,206 +316,229 @@ ok $report, "created test report - $report_id";
foreach my $test (
{
description => 'edit report title',
- fields => {
- title => 'Report to Edit',
- detail => 'Detail for Report to Edit',
- state => 'confirmed',
- name => 'Test User',
- email => $user->email,
- anonymous => 0,
- flagged => undef,
- },
- changes => {
- title => 'Edited Report',
+ fields => {
+ title => 'Report to Edit',
+ detail => 'Detail for Report to Edit',
+ state => 'confirmed',
+ name => 'Test User',
+ email => $user->email,
+ anonymous => 0,
+ flagged => undef,
+ non_public => undef,
},
- log_count => 1,
- log_entries => [ qw/edit/ ],
- resend => 0,
+ changes => { title => 'Edited Report', },
+ log_count => 1,
+ log_entries => [qw/edit/],
+ resend => 0,
},
{
description => 'edit report description',
- fields => {
- title => 'Edited Report',
- detail => 'Detail for Report to Edit',
- state => 'confirmed',
- name => 'Test User',
- email => $user->email,
- anonymous => 0,
- flagged => undef,
+ fields => {
+ title => 'Edited Report',
+ detail => 'Detail for Report to Edit',
+ state => 'confirmed',
+ name => 'Test User',
+ email => $user->email,
+ anonymous => 0,
+ flagged => undef,
+ non_public => undef,
},
- changes => {
- detail => 'Edited Detail',
- },
- log_count => 2,
- log_entries => [ qw/edit edit/ ],
- resend => 0,
+ changes => { detail => 'Edited Detail', },
+ log_count => 2,
+ log_entries => [qw/edit edit/],
+ resend => 0,
},
{
description => 'edit report user name',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'confirmed',
- name => 'Test User',
- email => $user->email,
- anonymous => 0,
- flagged => undef,
- },
- changes => {
- name => 'Edited User',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Test User',
+ email => $user->email,
+ anonymous => 0,
+ flagged => undef,
+ non_public => undef,
},
- log_count => 3,
- log_entries => [ qw/edit edit edit/ ],
- resend => 0,
- user => $user,
+ changes => { name => 'Edited User', },
+ log_count => 3,
+ log_entries => [qw/edit edit edit/],
+ resend => 0,
+ user => $user,
},
{
description => 'edit report set flagged true',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'confirmed',
- name => 'Edited User',
- email => $user->email,
- anonymous => 0,
- flagged => undef,
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Edited User',
+ email => $user->email,
+ anonymous => 0,
+ flagged => undef,
+ non_public => undef,
},
changes => {
- flagged => 'on',
+ flagged => 'on',
},
- log_count => 4,
- log_entries => [ qw/edit edit edit edit/ ],
- resend => 0,
- user => $user,
+ log_count => 4,
+ log_entries => [qw/edit edit edit edit/],
+ resend => 0,
+ user => $user,
},
{
description => 'edit report user email',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'confirmed',
- name => 'Edited User',
- email => $user->email,
- anonymous => 0,
- flagged => 'on',
- },
- changes => {
- email => $user2->email,
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Edited User',
+ email => $user->email,
+ anonymous => 0,
+ flagged => 'on',
+ non_public => undef,
},
- log_count => 5,
- log_entries => [ qw/edit edit edit edit edit/ ],
- resend => 0,
- user => $user2,
+ changes => { email => $user2->email, },
+ log_count => 5,
+ log_entries => [qw/edit edit edit edit edit/],
+ resend => 0,
+ user => $user2,
},
{
description => 'change state to unconfirmed',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'confirmed',
- name => 'Edited User',
- email => $user2->email,
- anonymous => 0,
- flagged => 'on',
- },
- changes => {
- state => 'unconfirmed'
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Edited User',
+ email => $user2->email,
+ anonymous => 0,
+ flagged => 'on',
+ non_public => undef,
},
+ changes => { state => 'unconfirmed' },
log_count => 6,
- log_entries => [ qw/state_change edit edit edit edit edit/ ],
- resend => 0,
+ log_entries => [qw/state_change edit edit edit edit edit/],
+ resend => 0,
},
{
description => 'change state to confirmed',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'unconfirmed',
- name => 'Edited User',
- email => $user2->email,
- anonymous => 0,
- flagged => 'on',
- },
- changes => {
- state => 'confirmed'
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'unconfirmed',
+ name => 'Edited User',
+ email => $user2->email,
+ anonymous => 0,
+ flagged => 'on',
+ non_public => undef,
},
+ changes => { state => 'confirmed' },
log_count => 7,
- log_entries => [ qw/state_change state_change edit edit edit edit edit/ ],
- resend => 0,
+ log_entries => [qw/state_change state_change edit edit edit edit edit/],
+ resend => 0,
},
{
description => 'change state to fixed',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'confirmed',
- name => 'Edited User',
- email => $user2->email,
- anonymous => 0,
- flagged => 'on',
- },
- changes => {
- state => 'fixed'
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Edited User',
+ email => $user2->email,
+ anonymous => 0,
+ flagged => 'on',
+ non_public => undef,
},
+ changes => { state => 'fixed' },
log_count => 8,
- log_entries => [ qw/state_change state_change state_change edit edit edit edit edit/ ],
+ log_entries =>
+ [qw/state_change state_change state_change edit edit edit edit edit/],
resend => 0,
},
{
description => 'change state to hidden',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'fixed',
- name => 'Edited User',
- email => $user2->email,
- anonymous => 0,
- flagged => 'on',
- },
- changes => {
- state => 'hidden'
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'fixed',
+ name => 'Edited User',
+ email => $user2->email,
+ anonymous => 0,
+ flagged => 'on',
+ non_public => undef,
},
- log_count => 9,
- log_entries => [ qw/state_change state_change state_change state_change edit edit edit edit edit/ ],
+ changes => { state => 'hidden' },
+ log_count => 9,
+ log_entries => [
+ qw/state_change state_change state_change state_change edit edit edit edit edit/
+ ],
resend => 0,
},
{
description => 'edit and change state',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'hidden',
- name => 'Edited User',
- email => $user2->email,
- anonymous => 0,
- flagged => 'on',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'hidden',
+ name => 'Edited User',
+ email => $user2->email,
+ anonymous => 0,
+ flagged => 'on',
+ non_public => undef,
},
changes => {
- state => 'confirmed',
+ state => 'confirmed',
anonymous => 1,
},
- log_count => 11,
- log_entries => [ qw/edit state_change state_change state_change state_change state_change edit edit edit edit edit/ ],
+ log_count => 11,
+ log_entries => [
+ qw/edit state_change state_change state_change state_change state_change edit edit edit edit edit/
+ ],
resend => 0,
},
{
description => 'resend',
- fields => {
- title => 'Edited Report',
- detail => 'Edited Detail',
- state => 'confirmed',
- name => 'Edited User',
- email => $user2->email,
- anonymous => 1,
- flagged => 'on',
- },
- changes => {
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Edited User',
+ email => $user2->email,
+ anonymous => 1,
+ flagged => 'on',
+ non_public => undef,
},
- log_count => 12,
- log_entries => [ qw/resend edit state_change state_change state_change state_change state_change edit edit edit edit edit/ ],
+ changes => {},
+ log_count => 12,
+ log_entries => [
+ qw/resend edit state_change state_change state_change state_change state_change edit edit edit edit edit/
+ ],
resend => 1,
},
-) {
+ {
+ description => 'non public',
+ fields => {
+ title => 'Edited Report',
+ detail => 'Edited Detail',
+ state => 'confirmed',
+ name => 'Edited User',
+ email => $user2->email,
+ anonymous => 1,
+ flagged => 'on',
+ non_public => undef,
+ },
+ changes => {
+ non_public => 'on',
+ },
+ log_count => 13,
+ log_entries => [
+ qw/edit resend edit state_change state_change state_change state_change state_change edit edit edit edit edit/
+ ],
+ resend => 0,
+ },
+ )
+{
subtest $test->{description} => sub {
$log_entries->reset;
$mech->get_ok("/admin/report_edit/$report_id");
@@ -523,6 +569,8 @@ foreach my $test (
}
$test->{changes}->{flagged} = 1 if $test->{changes}->{flagged};
+ $test->{changes}->{non_public} = 1 if $test->{changes}->{non_public};
+
is $report->$_, $test->{changes}->{$_}, "$_ updated" for grep { $_ ne 'email' } keys %{ $test->{changes} };
if ( $test->{user} ) {
@@ -547,6 +595,7 @@ subtest 'change email to new user' => sub {
email => $report->user->email,
anonymous => 1,
flagged => 'on',
+ non_public => 'on',
};
is_deeply( $mech->visible_form_values(), $fields, 'initial form values' );
diff --git a/t/app/controller/alert_new.t b/t/app/controller/alert_new.t
index d66590c57..84634273a 100644
--- a/t/app/controller/alert_new.t
+++ b/t/app/controller/alert_new.t
@@ -464,4 +464,194 @@ subtest "Test normal alert signups and that alerts are sent" => sub {
$mech->delete_user($user2);
};
+for my $test (
+ {
+ desc => 'check non public reports are not included in council problems alerts',
+ alert_params => {
+ alert_type => 'council_problems',
+ parameter => '2651',
+ parameter2 => '2651',
+ }
+ },
+ {
+ desc => 'check non public reports are not included in ward problems alerts',
+ alert_params => {
+ alert_type => 'ward_problems',
+ parameter => '2651',
+ parameter2 => '20728',
+ }
+ },
+ {
+ desc => 'check non public reports are not included in local problems alerts',
+ alert_params => {
+ alert_type => 'local_problems',
+ parameter => '-3.189944',
+ parameter2 => '55.951963',
+ }
+ },
+ {
+ desc => 'check non public reports are not included in area problems alerts',
+ alert_params => {
+ alert_type => 'area_problems',
+ parameter => '20728',
+ parameter2 => '20728',
+ }
+ },
+) {
+ subtest $test->{desc} => sub {
+ my $user1 = FixMyStreet::App->model('DB::User')
+ ->find_or_create( { email => 'reporter@example.com', name => 'Reporter User' } );
+ ok $user1, "created test user";
+ $user1->alerts->delete;
+
+ my $user2 = FixMyStreet::App->model('DB::User')
+ ->find_or_create( { email => 'alerts@example.com', name => 'Alert User' } );
+ ok $user2, "created test user";
+ $user2->alerts->delete;
+
+ my $dt = DateTime->now->add( minutes => -30 );
+ my $r_dt = $dt->clone->add( minutes => 20 );
+
+ my $alert_params = $test->{alert_params};
+ $alert_params->{user} = $user1;
+ $alert_params->{whensubscribed} = $dt;
+ $alert_params->{confirmed} = 1;
+
+ my $alert_user1 = FixMyStreet::App->model('DB::Alert')->create( $alert_params );
+ ok $alert_user1, "alert created";
+
+ my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( {
+ postcode => 'EH1 1BB',
+ council => '2651',
+ areas => ',11808,135007,14419,134935,2651,20728,',
+ category => 'Street lighting',
+ title => 'Alert test for non public reports',
+ detail => 'Testing Detail',
+ used_map => 1,
+ name => $user2->name,
+ anonymous => 0,
+ state => 'confirmed',
+ confirmed => $r_dt,
+ lastupdate => $r_dt,
+ whensent => $r_dt->clone->add( minutes => 5 ),
+ lang => 'en-gb',
+ service => '',
+ cobrand => 'default',
+ cobrand_data => '',
+ send_questionnaire => 1,
+ latitude => '55.951963',
+ longitude => '-3.189944',
+ user_id => $user2->id,
+ non_public => 1,
+ } );
+
+ $mech->clear_emails_ok;
+ FixMyStreet::App->model('DB::AlertType')->email_alerts();
+ $mech->email_count_is(0);
+
+ $report->update( { non_public => 0 } );
+ FixMyStreet::App->model('DB::AlertType')->email_alerts();
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ like $email->body, qr/Alert test for non public reports/, 'alert contains public report';
+
+ $mech->delete_user( $user1 );
+ $mech->delete_user( $user2 );
+ };
+}
+
+subtest 'check new updates alerts for non public reports only go to report owner' => sub {
+ my $user1 = FixMyStreet::App->model('DB::User')
+ ->find_or_create( { email => 'reporter@example.com', name => 'Reporter User' } );
+ ok $user1, "created test user";
+ $user1->alerts->delete;
+
+ my $user2 = FixMyStreet::App->model('DB::User')
+ ->find_or_create( { email => 'alerts@example.com', name => 'Alert User' } );
+ ok $user2, "created test user";
+ $user2->alerts->delete;
+
+ my $user3 = FixMyStreet::App->model('DB::User')
+ ->find_or_create( { email => 'updates@example.com', name => 'Update User' } );
+ ok $user3, "created test user";
+
+ my $dt = DateTime->now->add( minutes => -30 );
+ my $r_dt = $dt->clone->add( minutes => 20 );
+
+ my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( {
+ postcode => 'EH1 1BB',
+ council => '2651',
+ areas => ',11808,135007,14419,134935,2651,20728,',
+ category => 'Street lighting',
+ title => 'Alert test for non public reports',
+ detail => 'Testing Detail',
+ used_map => 1,
+ name => $user2->name,
+ anonymous => 0,
+ state => 'confirmed',
+ confirmed => $r_dt,
+ lastupdate => $r_dt,
+ whensent => $r_dt->clone->add( minutes => 5 ),
+ lang => 'en-gb',
+ service => '',
+ cobrand => 'default',
+ cobrand_data => '',
+ send_questionnaire => 1,
+ latitude => '55.951963',
+ longitude => '-3.189944',
+ user_id => $user2->id,
+ non_public => 1,
+ } );
+
+ my $update = FixMyStreet::App->model('DB::Comment')->create( {
+ problem_id => $report->id,
+ user_id => $user3->id,
+ name => 'Anonymous User',
+ mark_fixed => 'false',
+ text => 'This is some more update text',
+ state => 'confirmed',
+ confirmed => $r_dt->clone->add( minutes => 8 ),
+ anonymous => 't',
+ } );
+
+ my $alert_user1 = FixMyStreet::App->model('DB::Alert')->create( {
+ user => $user1,
+ alert_type => 'new_updates',
+ parameter => $report->id,
+ confirmed => 1,
+ whensubscribed => $dt,
+ } );
+ ok $alert_user1, "alert created";
+
+
+ $mech->clear_emails_ok;
+ FixMyStreet::App->model('DB::AlertType')->email_alerts();
+ $mech->email_count_is(0);
+
+ my $alert_user2 = FixMyStreet::App->model('DB::Alert')->create( {
+ user => $user2,
+ alert_type => 'new_updates',
+ parameter => $report->id,
+ confirmed => 1,
+ whensubscribed => $dt,
+ } );
+ ok $alert_user2, "alert created";
+
+ FixMyStreet::App->model('DB::AlertType')->email_alerts();
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ like $email->body, qr/This is some more update text/, 'alert contains update text';
+
+ $mech->clear_emails_ok;
+ $report->update( { non_public => 0 } );
+ FixMyStreet::App->model('DB::AlertType')->email_alerts();
+ $mech->email_count_is(1);
+ $email = $mech->get_email;
+ like $email->body, qr/This is some more update text/, 'alert contains update text';
+
+ $mech->delete_user( $user1 );
+ $mech->delete_user( $user2 );
+ $mech->delete_user( $user3 );
+};
+
done_testing();
diff --git a/t/app/controller/around.t b/t/app/controller/around.t
index db03e00f4..e1c76ff9f 100644
--- a/t/app/controller/around.t
+++ b/t/app/controller/around.t
@@ -78,4 +78,30 @@ foreach my $test (
};
}
+subtest 'check non public reports are not displayed on around page' => sub {
+ my $params = {
+ postcode => 'EH99 1SP',
+ latitude => 55.9519637512,
+ longitude => -3.17492254484,
+ };
+ my @edinburgh_problems =
+ $mech->create_problems_for_council( 5, 2651, 'Around page', $params );
+
+ $mech->get_ok('/');
+ $mech->submit_form_ok( { with_fields => { pc => 'EH99 1SP' } },
+ "good location" );
+ $mech->content_contains( 'Around page Test 3 for 2651',
+ 'problem to be marked non public visible' );
+
+ my $private = $edinburgh_problems[2];
+ ok $private->update( { non_public => 1 } ), 'problem marked non public';
+
+ $mech->get_ok('/');
+ $mech->submit_form_ok( { with_fields => { pc => 'EH99 1SP' } },
+ "good location" );
+ $mech->content_lacks( 'Around page Test 3 for 2651',
+ 'problem marked non public is not visible' );
+};
+
+
done_testing();
diff --git a/t/app/controller/index.t b/t/app/controller/index.t
index bf9124ee0..86d5e2d8c 100644
--- a/t/app/controller/index.t
+++ b/t/app/controller/index.t
@@ -55,4 +55,20 @@ subtest "does pc, (x,y), (e,n) or (lat,lon) go to /around" => sub {
}
};
+$mech->delete_problems_for_council( 2651 );
+
+my @edinburgh_problems = $mech->create_problems_for_council(5, 2651, 'Front page');
+is scalar @edinburgh_problems, 5, 'correct number of edinburgh problems created';
+
+$mech->get_ok('/');
+$mech->content_contains('Front page Test 3 for 2651', 'problem to be marked non public visible');
+$mech->content_contains('5</big> reports recently', 'number of recent problems correct');
+
+my $private = $edinburgh_problems[2];
+ok $private->update( { non_public => 1 } ), 'problem marked non public';
+
+$mech->get_ok('/');
+$mech->content_lacks('Front page Test 3 for 2651', 'non public problem is not visible');
+$mech->content_contains('5</big> reports recently', 'non public problems listed in recent problems stats');
+
done_testing();
diff --git a/t/app/controller/report_display.t b/t/app/controller/report_display.t
index 6c2733e36..3bb0913f1 100644
--- a/t/app/controller/report_display.t
+++ b/t/app/controller/report_display.t
@@ -16,6 +16,11 @@ my $user =
->find_or_create( { email => 'test@example.com', name => 'Test User' } );
ok $user, "created test user";
+my $user2 =
+ FixMyStreet::App->model('DB::User')
+ ->find_or_create( { email => 'test2@example.com', name => 'Other User' } );
+ok $user2, "created test user";
+
my $dt = DateTime->new(
year => 2011,
month => 04,
@@ -98,6 +103,32 @@ subtest "change report to hidden and check for 410 status" => sub {
ok $report->update( { state => 'confirmed' } ), 'confirm report again';
};
+subtest "change report to non_public and check for 403 status" => sub {
+ ok $report->update( { non_public => 1 } ), 'make report non public';
+ ok $mech->get("/report/$report_id"), "get '/report/$report_id'";
+ is $mech->res->code, 403, "access denied";
+ is $mech->uri->path, "/report/$report_id", "at /report/$report_id";
+ $mech->content_contains('That report cannot be viewed on FixMyStreet.');
+ ok $report->update( { non_public => 0 } ), 'make report public';
+};
+
+subtest "check owner of report can view non public reports" => sub {
+ ok $report->update( { non_public => 1 } ), 'make report non public';
+ $mech->log_in_ok( $report->user->email );
+ ok $mech->get("/report/$report_id"), "get '/report/$report_id'";
+ is $mech->res->code, 200, "report can be viewed";
+ is $mech->uri->path, "/report/$report_id", "at /report/$report_id";
+ $mech->log_out_ok;
+
+ $mech->log_in_ok( $user2->email );
+ ok $mech->get("/report/$report_id"), "get '/report/$report_id'";
+ is $mech->res->code, 403, "access denied to user who is not report creator";
+ is $mech->uri->path, "/report/$report_id", "at /report/$report_id";
+ $mech->content_contains('That report cannot be viewed on FixMyStreet.');
+ $mech->log_out_ok;
+ ok $report->update( { non_public => 0 } ), 'make report public';
+};
+
subtest "test a good report" => sub {
$mech->get_ok("/report/$report_id");
is $mech->uri->path, "/report/$report_id", "at /report/$report_id";
diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t
index 65bd71af2..2e7e60f75 100644
--- a/t/app/controller/report_new.t
+++ b/t/app/controller/report_new.t
@@ -788,6 +788,74 @@ foreach my $test (
}
+subtest "test report creation for a category that is non public" => sub {
+ $mech->log_out_ok;
+ $mech->clear_emails_ok;
+
+ # check that the user does not exist
+ my $test_email = 'test-2@example.com';
+
+ my $user = FixMyStreet::App->model('DB::User')->find_or_create( { email => $test_email } );
+ ok $user, "test user does exist";
+
+ $contact1->update( { non_public => 1 } );
+
+ # submit initial pc form
+ $mech->get_ok('/around');
+ $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB', } },
+ "submit location" );
+
+ # click through to the report page
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
+ "follow 'skip this step' link" );
+
+ $mech->submit_form_ok(
+ {
+ button => 'submit_register',
+ with_fields => {
+ title => 'Test Report',
+ detail => 'Test report details.',
+ photo => '',
+ email => 'test-2@example.com',
+ name => 'Joe Bloggs',
+ category => 'Street lighting',
+ }
+ },
+ "submit good details"
+ );
+
+ # find the report
+ my $report = $user->problems->first;
+ ok $report, "Found the report";
+
+ # Check the report is not public
+ ok $report->non_public, 'report is not public';
+
+ my $email = $mech->get_email;
+ ok $email, "got an email";
+ like $email->body, qr/confirm the problem/i, "confirm the problem";
+
+ my ($url) = $email->body =~ m{(http://\S+)};
+ ok $url, "extracted confirm url '$url'";
+
+ # confirm token
+ $mech->get_ok($url);
+ $report->discard_changes;
+
+ is $report->state, 'confirmed', "Report is now confirmed";
+
+ $mech->logged_in_ok;
+ $mech->get_ok( '/report/' . $report->id, 'user can see own report' );
+
+ $mech->log_out_ok;
+ ok $mech->get("/report/" . $report->id), "fetched report";
+ is $mech->res->code, 403, "access denied to report";
+
+ # cleanup
+ $mech->delete_user($user);
+ $contact1->update( { non_public => 0 } );
+};
+
$contact2->category( "Pothol\xc3\xa9s" );
$contact2->update;
$mech->get_ok( '/report/new/ajax?latitude=' . $saved_lat . '&longitude=' . $saved_lon );
diff --git a/t/app/controller/reports.t b/t/app/controller/reports.t
index 801dbeddb..a4dab6597 100644
--- a/t/app/controller/reports.t
+++ b/t/app/controller/reports.t
@@ -1,10 +1,21 @@
use strict;
use warnings;
use Test::More;
-use Test::WWW::Mechanize::Catalyst 'FixMyStreet::App';
+use FixMyStreet::TestMech;
use mySociety::MaPit;
+use FixMyStreet::App;
+use DateTime;
-ok( my $mech = Test::WWW::Mechanize::Catalyst->new, 'Created mech object' );
+ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' );
+
+$mech->delete_problems_for_council( 2504 );
+$mech->delete_problems_for_council( 2651 );
+
+my @edinburgh_problems = $mech->create_problems_for_council(3, 2651, 'All reports');
+my @westminster_problems = $mech->create_problems_for_council(5, 2504, 'All reports');
+
+is scalar @westminster_problems, 5, 'correct number of westminster problems created';
+is scalar @edinburgh_problems, 3, 'correct number of edinburgh problems created';
# Run the cron script that makes the data for /reports so we don't get an error.
system( "bin/cron-wrapper update-all-reports" );
@@ -13,8 +24,35 @@ system( "bin/cron-wrapper update-all-reports" );
$mech->get_ok('/reports');
$mech->title_like(qr{Summary reports});
$mech->content_contains('Birmingham');
+
+my $stats = $mech->extract_report_stats;
+
+is $stats->{'City of Edinburgh Council'}->[1], 3, 'correct number of reports for Edinburgh';
+is $stats->{'Westminster City Council'}->[1], 5, 'correct number of reports for Westminster';
+
$mech->follow_link_ok( { text_regex => qr/Birmingham/ } );
+$mech->get_ok('/reports/Westminster');
+$mech->title_like(qr/Westminster City Council/);
+$mech->content_contains('Westminster City Council');
+$mech->content_contains('All reports Test 3 for 2504', 'problem to be marked non public visible');
+
+my $problems = $mech->extract_problem_list;
+is scalar @$problems, 5, 'correct number of problems displayed';
+
+my $private = $westminster_problems[2];
+ok $private->update( { non_public => 1 } ), 'problem marked non public';
+
+$mech->get_ok('/reports/Westminster');
+$problems = $mech->extract_problem_list;
+is scalar @$problems, 4, 'only public problems are displayed';
+
+$mech->content_lacks('All reports Test 3 for 2504', 'non public problem is not visible');
+
+$mech->get_ok('/reports');
+$stats = $mech->extract_report_stats;
+is $stats->{'Westminster City Council'}->[1], 5, 'non public reports included in stats';
+
SKIP: {
skip( "Need 'emptyhomes' in ALLOWED_COBRANDS config", 8 )
unless FixMyStreet::Cobrand->exists('emptyhomes');
diff --git a/templates/web/default/admin/council_contacts.html b/templates/web/default/admin/council_contacts.html
index e35c8cda2..60e270c7c 100644
--- a/templates/web/default/admin/council_contacts.html
+++ b/templates/web/default/admin/council_contacts.html
@@ -38,6 +38,7 @@
<th>[% loc('Deleted') %]</th>
<th>[% loc('Last editor') %]</th>
<th>[% loc('Note') %]</th>
+ <th>[% loc('Public') %]</th>
<th>[% loc('When edited') %]</th>
<th>[% loc('Confirm') %]</th>
</tr>
@@ -49,6 +50,7 @@
<td>[% IF contact.deleted %][% loc('Yes') %][% ELSE %][% loc('No') %][% END %]</td>
<td>[% contact.editor %]</td>
<td>[% contact.note | html %]</td>
+ <td>[% contact.non_public ? loc('Non Public') : loc('Public') %]</td>
<td>[% contact.whenedited.ymd _ ' ' _ contact.whenedited.hms %]</td>
<td><input type="checkbox" name="confirmed" value="[% contact.category %]"></td>
</tr>
@@ -81,7 +83,7 @@
<input type="checkbox" name="confirmed" value="1" id="confirmed">
<label for="confirmed">[% loc('Confirmed') %]</label>
- <input type="checkbox" name="deleted" value="1"id="deleted">
+ <input type="checkbox" name="deleted" value="1" id="deleted">
<label for="deleted">[% loc('Deleted') %]</label>
</p>
@@ -90,6 +92,11 @@
</p>
<p>
+ <input type="checkbox" name="non_public" value="1" id="non_public">
+ <label for="non_public">[% loc('Private') %]</label>
+ </p>
+
+ <p>
<input type="hidden" name="area_id" value="[% area_id %]" >
<input type="hidden" name="posted" value="new" >
<input type="hidden" name="token" value="[% token %]" >
diff --git a/templates/web/default/admin/council_edit.html b/templates/web/default/admin/council_edit.html
index 0968d3570..9ec0578ff 100644
--- a/templates/web/default/admin/council_edit.html
+++ b/templates/web/default/admin/council_edit.html
@@ -26,7 +26,8 @@
<strong>[% loc('Email:') %] </strong>
<input type="text" name="email" value="[% contact.email | html %]" size="30">
<input type="checkbox" name="confirmed" value="1" id="confirmed"[% ' checked' IF contact.confirmed %]> <label for="confirmed">[% loc('Confirmed' ) %]</label>
- <input type="checkbox" name="deleted" value="1" id="deleted"[% ' checked' IF contact.deleted %]> <label for="deleted">[% loc('Deleted') %]</label><br>
+ <input type="checkbox" name="deleted" value="1" id="deleted"[% ' checked' IF contact.deleted %]> <label for="deleted">[% loc('Deleted') %]</label>
+ <input type="checkbox" name="non_public" value="1" id="non_public"[% ' checked' IF contact.non_public %]> <label for="non_public">[% loc('Private') %]</label><br>
<strong>[% loc('Note:') %] </strong><textarea name="note" rows="3" cols="40">[% contact.note | html %]</textarea> <br>
diff --git a/templates/web/default/admin/report_edit.html b/templates/web/default/admin/report_edit.html
index 9ef7e8248..d283037c2 100644
--- a/templates/web/default/admin/report_edit.html
+++ b/templates/web/default/admin/report_edit.html
@@ -40,6 +40,7 @@
<li>[% loc('Extra data:') %] [% problem.extra ? 'Yes' : 'No' %]</li>
<li>[% loc('Going to send questionnaire?') %] [% IF problem.send_questionnaire %][% loc('Yes') %][% ELSE %][% loc('No') %][% END %]</li>
<li><label for="flagged">[% loc('Flagged:') %]</label> <input type="checkbox" name="flagged"[% ' checked' IF problem.flagged %]></li>
+<li><label for="non_public">[% loc('Private:') %]</label> <input type="checkbox" name="non_public"[% ' checked' IF problem.non_public %]></li>
[% IF problem.photo %]
[% photo = problem.get_photo_params %]