aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xperllib/FixMyStreet/App/Controller/About.pm1
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports.pm34
-rw-r--r--perllib/FixMyStreet/Cobrand/FixMyStreet.pm98
-rw-r--r--t/cobrand/fixmystreet.t47
-rw-r--r--templates/web/fixmystreet.com/about/council-dashboard.html60
-rw-r--r--web/cobrands/fixmystreet.com/fmsforcouncils.scss2
6 files changed, 231 insertions, 11 deletions
diff --git a/perllib/FixMyStreet/App/Controller/About.pm b/perllib/FixMyStreet/App/Controller/About.pm
index 233da25d3..48a5dfffd 100755
--- a/perllib/FixMyStreet/App/Controller/About.pm
+++ b/perllib/FixMyStreet/App/Controller/About.pm
@@ -23,6 +23,7 @@ sub page : Path("/about") : Args(1) {
my $template = $c->forward('find_template');
$c->detach('/page_error_404_not_found', []) unless $template;
$c->stash->{template} = $template;
+ $c->cobrand->call_hook('about_hook');
}
sub index : Path("/about") : Args(0) {
diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm
index e19c7628f..b0015acc5 100644
--- a/perllib/FixMyStreet/App/Controller/Reports.pm
+++ b/perllib/FixMyStreet/App/Controller/Reports.pm
@@ -71,6 +71,7 @@ sub index : Path : Args(0) {
my $dashboard = eval {
my $data = FixMyStreet->config('TEST_DASHBOARD_DATA');
+ # uncoverable branch true
unless ($data) {
my $fn = '../data/all-reports-dashboard';
if ($c->stash->{body}) {
@@ -155,6 +156,7 @@ sub ward : Path : Args(2) {
$c->res->redirect($ward);
$c->detach;
}
+ $c->cobrand->call_hook('council_dashboard_hook');
$c->go('index');
}
@@ -330,17 +332,35 @@ sub body_check : Private {
# Oslo/ kommunes sharing a name in Norway
return if $c->cobrand->reports_body_check( $c, $q_body );
+ my $body = $c->forward('body_find', [ $q_body ]);
+ if ($body) {
+ $c->stash->{body} = $body;
+ return;
+ }
+
+ # No result, bad body name.
+ $c->detach( 'redirect_index' );
+}
+
+=head2
+
+Given a string, try and find a body starting with/matching that string.
+Returns the matching body object if found.
+
+=cut
+
+sub body_find : Private {
+ my ($self, $c, $q_body) = @_;
+
# We must now have a string to check
my @bodies = $c->model('DB::Body')->search( { name => { -like => "$q_body%" } } )->all;
if (@bodies == 1) {
- $c->stash->{body} = $bodies[0];
- return;
+ return $bodies[0];
} else {
foreach (@bodies) {
if (lc($_->name) eq lc($q_body) || $_->name =~ /^\Q$q_body\E (Borough|City|District|County) Council$/i) {
- $c->stash->{body} = $_;
- return;
+ return $_;
}
}
}
@@ -353,13 +373,9 @@ sub body_check : Private {
if (@translations == 1) {
if ( my $body = $c->model('DB::Body')->find( { id => $translations[0]->object_id } ) ) {
- $c->stash->{body} = $body;
- return;
+ return $body;
}
}
-
- # No result, bad body name.
- $c->detach( 'redirect_index' );
}
=head2 ward_check
diff --git a/perllib/FixMyStreet/Cobrand/FixMyStreet.pm b/perllib/FixMyStreet/Cobrand/FixMyStreet.pm
index c50721334..a50a22ff9 100644
--- a/perllib/FixMyStreet/Cobrand/FixMyStreet.pm
+++ b/perllib/FixMyStreet/Cobrand/FixMyStreet.pm
@@ -1,6 +1,9 @@
package FixMyStreet::Cobrand::FixMyStreet;
use base 'FixMyStreet::Cobrand::UK';
+use strict;
+use warnings;
+
use mySociety::Random;
use constant COUNCIL_ID_BROMLEY => 2482;
@@ -62,5 +65,98 @@ sub extra_contact_validation {
return %errors;
}
-1;
+=head2 council_dashboard_hook
+
+This is for council-specific dashboard pages, which can only be seen by
+superusers and logged-in users with an email domain matching a body name.
+
+=cut
+
+sub council_dashboard_hook {
+ my $self = shift;
+ my $c = $self->{c};
+
+ unless ( $c->user_exists ) {
+ $c->res->redirect('/about/council-dashboard');
+ $c->detach;
+ }
+
+ return if $c->user->is_superuser;
+
+ my $body = $c->user->from_body || _user_to_body($c);
+ if ($body) {
+ # Matching URL and user's email body
+ return if $body->id eq $c->stash->{body}->id;
+
+ # Matched /a/ body, redirect to its summary page
+ $c->stash->{body} = $body;
+ $c->stash->{wards} = [ { name => 'summary' } ];
+ $c->detach('/reports/redirect_body');
+ }
+
+ $c->res->redirect('/about/council-dashboard');
+}
+sub _user_to_body {
+ my $c = shift;
+ my $email = lc $c->user->email;
+ return _email_to_body($c, $email);
+}
+
+sub _email_to_body {
+ my ($c, $email) = @_;
+ my ($domain) = $email =~ m{ @ (.*) \z }x;
+
+ my @data = eval { FixMyStreet->path_to('../data/fixmystreet-councils.csv')->slurp };
+ my $body;
+ foreach (@data) {
+ chomp;
+ my ($d, $b) = split /\|/;
+ if ($d eq $domain) {
+ $body = $b;
+ last;
+ }
+ }
+ # If we didn't find a lookup entry, default to the first part of the domain
+ unless ($body) {
+ $domain =~ s/\.gov\.uk$//;
+ $body = ucfirst $domain;
+ }
+
+ $body = $c->forward('/reports/body_find', [ $body ]);
+ return $body;
+}
+
+sub about_hook {
+ my $self = shift;
+ my $c = $self->{c};
+
+ if ($c->stash->{template} eq 'about/council-dashboard.html') {
+ $c->stash->{form_name} = $c->get_param('name') || '';
+ $c->stash->{email} = $c->get_param('username') || '';
+ if ($c->user_exists) {
+ my $body = _user_to_body($c);
+ if ($body) {
+ $c->stash->{body} = $body;
+ $c->stash->{wards} = [ { name => 'summary' } ];
+ $c->detach('/reports/redirect_body');
+ }
+ }
+ if (my $email = $c->get_param('username')) {
+ $email = lc $email;
+ $email =~ s/\s+//g;
+ my $body = _email_to_body($c, $email);
+ if ($body) {
+ # Send confirmation email (hopefully)
+ $c->stash->{template} = 'auth/general.html';
+ $c->detach('/auth/general');
+ } else {
+ $c->stash->{no_body_found} = 1;
+ $c->set_param('em', $email); # What the contact form wants
+ $c->detach('/contact/submit');
+ }
+ }
+ }
+}
+
+1;
diff --git a/t/cobrand/fixmystreet.t b/t/cobrand/fixmystreet.t
new file mode 100644
index 000000000..eda93e187
--- /dev/null
+++ b/t/cobrand/fixmystreet.t
@@ -0,0 +1,47 @@
+use FixMyStreet::Script::UpdateAllReports;
+
+use FixMyStreet::TestMech;
+my $mech = FixMyStreet::TestMech->new;
+
+my $body = $mech->create_body_ok( 2514, 'Birmingham' );
+
+my $data;
+FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+ $data = FixMyStreet::Script::UpdateAllReports::generate_dashboard($body);
+};
+
+FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ TEST_DASHBOARD_DATA => $data,
+ ALLOWED_COBRANDS => 'fixmystreet',
+}, sub {
+ # Not logged in, redirected
+ $mech->get_ok('/reports/Birmingham/summary');
+ is $mech->uri->path, '/about/council-dashboard';
+
+ $mech->submit_form_ok({ with_fields => { username => 'someone@somewhere.example.org' }});
+ $mech->content_contains('We will be in touch');
+ # XXX Check email arrives
+
+ $mech->log_in_ok('someone@somewhere.example.org');
+ $mech->get_ok('/reports/Birmingham/summary');
+ is $mech->uri->path, '/about/council-dashboard';
+ $mech->content_contains('Ending in .gov.uk');
+
+ $mech->submit_form_ok({ with_fields => { name => 'Someone', username => 'someone@birmingham.gov.uk' }});
+ $mech->content_contains('Now check your email');
+ # XXX Check email arrives, click link
+
+ $mech->log_in_ok('someone@birmingham.gov.uk');
+ # Logged in, redirects
+ $mech->get_ok('/about/council-dashboard');
+ is $mech->uri->path, '/reports/Birmingham/summary';
+ $mech->content_contains('Top 5 wards');
+
+};
+
+END {
+ done_testing();
+}
diff --git a/templates/web/fixmystreet.com/about/council-dashboard.html b/templates/web/fixmystreet.com/about/council-dashboard.html
new file mode 100644
index 000000000..7acaee207
--- /dev/null
+++ b/templates/web/fixmystreet.com/about/council-dashboard.html
@@ -0,0 +1,60 @@
+[% extra_css = BLOCK %]
+ <link rel="stylesheet" href="[% version('/cobrands/fixmystreet.com/fmsforcouncils.css') %]">
+ <link href="https://fonts.googleapis.com/css?family=Rubik:400,500" rel="stylesheet">
+[% END %]
+
+[% IF no_body_found %]
+
+[% INCLUDE header.html
+ title = 'FixMyStreet Professional', bodyclass = 'fullwidthpage'
+%]
+
+<div class="confirmation-header confirmation-header--inbox">
+ <h1>Thanks!</h1>
+ <p>We will be in touch with a confirmation link soon.</p>
+</div>
+
+[% ELSE %]
+
+[% INCLUDE header.html
+ title = 'FixMyStreet Professional', bodyclass = 'fms-for-councils fullwidthpage'
+%]
+
+<div class="fixed-container">
+ <div class="council-header">
+ <h1 class="councils-logo">FixMyStreet Professional</h1>
+ </div>
+ <div class="councils-hero">
+ <div class="councils-hero__demo-access">
+ <p>To access a council-specific version of our main dashboard page,
+ please provide your name and email below and we'll send you a link.</p>
+ <form method="post" class="councils-hero__demo-access__form">
+ <div class="form-group">
+ <label for="demo-name">Name</label>
+ <span class="required">required</span>
+ <input type="text" name="name" id="demo-name" required value="[% form_name | html %]">
+ </div>
+ <div class="form-group">
+ <label for="demo-email">Contact email</label>
+ <span class="required">required</span>
+ <input type="email" name="username" id="demo-email" required value="[% email | html %]">
+ <p class="form-note">Ending in .gov.uk, or other official council domain</p>
+ </div>
+ <div class="form-group submit-group">
+ <input type="hidden" name="r" value="about/council-dashboard">
+ <input type="hidden" name="extra.referer" value="[% c.req.headers.referer | html %]">
+ <input type="hidden" name="subject" value="Council dashboard request">
+ <input type="hidden" name="message" value="Filled in the council dashboard form">
+ <input type="hidden" name="recipient" value="bettercities">
+ <input type="hidden" name="dest" value="from_council">
+ <input type="submit" value="Let me in" class="btn">
+ </div>
+ </form>
+ </div>
+ </div>
+
+</div>
+
+[% END %]
+
+[% INCLUDE footer.html %]
diff --git a/web/cobrands/fixmystreet.com/fmsforcouncils.scss b/web/cobrands/fixmystreet.com/fmsforcouncils.scss
index ee166b8fd..0e7c6a281 100644
--- a/web/cobrands/fixmystreet.com/fmsforcouncils.scss
+++ b/web/cobrands/fixmystreet.com/fmsforcouncils.scss
@@ -147,7 +147,7 @@ $fms-pink: #E65376;
border-radius: 3px;
color: #fff;
padding: 2em;
- margin: 4em auto -4em auto;
+ margin: 4em auto 4em auto;
max-width: 26em;
position: relative;
z-index: 1;