aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--conf/httpd.conf2
-rw-r--r--db/schema_0004-create_users_from_comments_and_link.sql4
-rw-r--r--perl-external/files.txt9
-rw-r--r--perl-external/minicpan/modules/02packages.details.txt.gzbin13545 -> 19147 bytes
-rw-r--r--perl-external/modules.txt1
-rw-r--r--perllib/FixMyStreet/App/Controller/JSON.pm114
-rw-r--r--perllib/FixMyStreet/TestMech.pm62
-rw-r--r--t/app/controller/json.t109
-rwxr-xr-xweb/json.cgi50
9 files changed, 311 insertions, 40 deletions
diff --git a/conf/httpd.conf b/conf/httpd.conf
index 1a090226b..8d70c475d 100644
--- a/conf/httpd.conf
+++ b/conf/httpd.conf
@@ -109,7 +109,7 @@ RewriteRule /(.+) /$1 [L]
# RewriteRule ^/contact(.*) /contact.cgi$1 [L]
RewriteRule ^/flickr(.*) /flickr.cgi$1 [L]
RewriteRule ^/fun(.*) /fun.cgi$1 [L]
-RewriteRule ^/json(.*) /json.cgi$1 [L]
+# RewriteRule ^/json(.*) /json.cgi$1 [L]
# RewriteRule ^/photo(.*) /photo.cgi$1 [L]
RewriteRule ^/questionnaire(.*) /questionnaire.cgi$1 [L]
# RewriteRule ^/reports(.*) /reports.cgi$1 [L]
diff --git a/db/schema_0004-create_users_from_comments_and_link.sql b/db/schema_0004-create_users_from_comments_and_link.sql
index 6dc50f531..0e4e2b5f2 100644
--- a/db/schema_0004-create_users_from_comments_and_link.sql
+++ b/db/schema_0004-create_users_from_comments_and_link.sql
@@ -32,10 +32,10 @@ WHERE users.name = '';
ALTER table comment
ADD COLUMN anonymous BOOL;
-UPDATE comment SET anonymous = true WHERE name = '';
-
UPDATE comment SET anonymous = false WHERE name <> '';
+UPDATE comment SET anonymous = true WHERE anonymous is NULL;
+
-- tidy up now everythings in place
ALTER table comment
ALTER COLUMN user_id SET NOT NULL;
diff --git a/perl-external/files.txt b/perl-external/files.txt
index 5df413ba8..82d7fe669 100644
--- a/perl-external/files.txt
+++ b/perl-external/files.txt
@@ -61,6 +61,7 @@
/authors/id/C/CI/CINE/Lingua-Stem-Snowball-Da-1.01.tar.gz
/authors/id/C/CK/CKRAS/DateTime-Format-HTTP-0.40.tar.gz
/authors/id/C/CO/COGENT/Tree-DAG_Node-1.06.tar.gz
+/authors/id/C/CO/CORION/parent-0.225.tar.gz
/authors/id/C/CR/CRENZ/Module-Find-0.10.tar.gz
/authors/id/D/DA/DAGOLDEN/CPAN-Meta-2.110580.tar.gz
/authors/id/D/DA/DAGOLDEN/CPAN-Meta-YAML-0.003.tar.gz
@@ -80,6 +81,12 @@
/authors/id/D/DO/DOY/Package-Stash-0.26.tar.gz
/authors/id/D/DO/DOY/Package-Stash-XS-0.22.tar.gz
/authors/id/D/DO/DOY/Try-Tiny-0.09.tar.gz
+/authors/id/D/DR/DROLSKY/Class-Factory-Util-1.7.tar.gz
+/authors/id/D/DR/DROLSKY/DateTime-0.70.tar.gz
+/authors/id/D/DR/DROLSKY/DateTime-Format-Builder-0.80.tar.gz
+/authors/id/D/DR/DROLSKY/DateTime-Format-Strptime-1.5000.tar.gz
+/authors/id/D/DR/DROLSKY/DateTime-Locale-0.45.tar.gz
+/authors/id/D/DR/DROLSKY/DateTime-TimeZone-1.34.tar.gz
/authors/id/D/DR/DROLSKY/File-ChangeNotify-0.19.tar.gz
/authors/id/D/DR/DROLSKY/File-Slurp-9999.13.tar.gz
/authors/id/D/DR/DROLSKY/Moose-1.24.tar.gz
@@ -128,10 +135,12 @@
/authors/id/G/GB/GBARR/Scalar-List-Utils-1.23.tar.gz
/authors/id/G/GE/GETTY/HTTP-Body-1.11.tar.gz
/authors/id/G/GR/GRODITI/MooseX-Types-Common-0.001002.tar.gz
+/authors/id/G/GR/GROMMEL/Math-Round-0.06.tar.gz
/authors/id/I/IL/ILMARI/Class-Unload-0.07.tar.gz
/authors/id/I/IN/INGY/Spiffy-0.30.tar.gz
/authors/id/I/IN/INGY/Test-Base-0.59.tar.gz
/authors/id/J/JE/JESSE/HTTP-Server-Simple-0.44.tar.gz
+/authors/id/J/JH/JHOBLITT/DateTime-Format-ISO8601-0.07.tar.gz
/authors/id/J/JP/JPEACOCK/version-0.88.tar.gz
/authors/id/J/JR/JROCKWAY/Context-Preserve-0.01.tar.gz
/authors/id/K/KA/KASEI/Class-Accessor-0.34.tar.gz
diff --git a/perl-external/minicpan/modules/02packages.details.txt.gz b/perl-external/minicpan/modules/02packages.details.txt.gz
index 3beda027e..c4bc9e1e8 100644
--- a/perl-external/minicpan/modules/02packages.details.txt.gz
+++ b/perl-external/minicpan/modules/02packages.details.txt.gz
Binary files differ
diff --git a/perl-external/modules.txt b/perl-external/modules.txt
index 1d027ca1a..63a40b770 100644
--- a/perl-external/modules.txt
+++ b/perl-external/modules.txt
@@ -21,6 +21,7 @@ DBIx::Class::FilterColumn
DBIx::Class::Schema::Loader
DBIx::Class::Storage::DBI
DateTime::Format::HTTP
+DateTime::Format::ISO8601
Email::Address
Email::Send
Email::Simple
diff --git a/perllib/FixMyStreet/App/Controller/JSON.pm b/perllib/FixMyStreet/App/Controller/JSON.pm
new file mode 100644
index 000000000..c437aafc0
--- /dev/null
+++ b/perllib/FixMyStreet/App/Controller/JSON.pm
@@ -0,0 +1,114 @@
+package FixMyStreet::App::Controller::JSON;
+use Moose;
+use namespace::autoclean;
+
+BEGIN { extends 'Catalyst::Controller'; }
+
+use JSON;
+use DateTime;
+use DateTime::Format::ISO8601;
+
+=head1 NAME
+
+FixMyStreet::App::Controller::JSON - Catalyst Controller
+
+=head1 DESCRIPTION
+
+Provide information as JSON
+
+=head1 METHODS
+
+=head2 json
+
+=cut
+
+sub json : Path : Args(0) {
+ my ( $self, $c ) = @_;
+
+ # gather the parameters
+ my $type = $c->req->param('type') || '';
+ my $start_date = $c->req->param('start_date') || '';
+ my $end_date = $c->req->param('end_date') || '';
+
+ my $yyyy_mm_dd = qr{^\d{4}-\d\d-\d\d$};
+ if ( $start_date !~ $yyyy_mm_dd
+ || $end_date !~ $yyyy_mm_dd )
+ {
+ $c->stash->{error} = 'Invalid dates supplied';
+ return;
+ }
+
+ # convert the dates to datetimes and trap errors
+ my $iso8601 = DateTime::Format::ISO8601->new;
+ my $start_dt = eval { $iso8601->parse_datetime($start_date); };
+ my $end_dt = eval { $iso8601->parse_datetime($end_date); };
+ unless ( $start_dt && $end_dt ) {
+ $c->stash->{error} = 'Invalid dates supplied';
+ return;
+ }
+
+ # check that the dates are sane
+ if ( $start_dt > $end_dt ) {
+ $c->stash->{error} = 'Start date after end date';
+ return;
+ }
+
+ # check that the type is supported
+ unless ( $type eq 'new_problems' || $type eq 'fixed_problems' ) {
+ $c->stash->{error} = 'Invalid type supplied';
+ return;
+ }
+
+ # query the database
+ $c->stash->{response} =
+ $type eq 'new_problems'
+ ? Problems::created_in_interval( $start_date, $end_date )
+ : Problems::fixed_in_interval( $start_date, $end_date );
+}
+
+# If we convert this code to be fully DBIC based then the following snippet is a
+# good start. The roadblock to doing it fully is the 'site_restriction' in the
+# SQL which is currently provided as SQL, rather than something that could be
+# easily added to the DBIC query. The hardest cobrand to change would be the
+# cities - so perhaps do it after we know wether that needs to be kept or not.
+#
+# my $state =
+# $type eq 'new_problems' ? 'confirmed'
+# : $type eq 'fixed_problems' ? 'fixed_problems'
+# : die;
+#
+# my $one_day = DateTime::Duration->new( days => 1 );
+#
+# my $problems = $c->model('DB::Problem')->search(
+# {
+# created => {
+# '>=' => $start_dt,
+# '<=' => $end_dt + $one_day,
+# },
+# state => $state,
+# # ------ add is site_restriction here -------
+# },
+# {
+# columns => [
+# 'id', 'title', 'council', 'category',
+# 'detail', 'name', 'anonymous', 'confirmed',
+# 'whensent', 'service',
+# ]
+# }
+# );
+
+sub end : Private {
+ my ( $self, $c ) = @_;
+
+ my $response =
+ $c->stash->{error}
+ ? { error => $c->stash->{error} }
+ : $c->stash->{response};
+
+ $c->res->content_type('application/json; charset=utf-8');
+ $c->res->body( encode_json( $response || {} ) );
+}
+
+__PACKAGE__->meta->make_immutable;
+
+1;
diff --git a/perllib/FixMyStreet/TestMech.pm b/perllib/FixMyStreet/TestMech.pm
index 35f934299..4c4a3b3eb 100644
--- a/perllib/FixMyStreet/TestMech.pm
+++ b/perllib/FixMyStreet/TestMech.pm
@@ -15,6 +15,7 @@ use Web::Scraper;
use Carp;
use Email::Send::Test;
use Digest::SHA1 'sha1_hex';
+use JSON;
=head1 NAME
@@ -53,6 +54,26 @@ sub logged_in_ok {
"logged in" );
}
+=head2 create_user_ok
+
+ $user = $mech->create_user_ok( $email );
+
+Create a test user (or find it and return if it already exists).
+
+=cut
+
+sub create_user_ok {
+ my $self = shift;
+ my ($email) = @_;
+
+ my $user =
+ FixMyStreet::App->model('DB::User')
+ ->find_or_create( { email => $email } );
+ ok $user, "found/created user for $email";
+
+ return $user;
+}
+
=head2 log_in_ok
$user = $mech->log_in_ok( $email_address );
@@ -65,10 +86,7 @@ sub log_in_ok {
my $mech = shift;
my $email = shift;
- my $user =
- FixMyStreet::App->model('DB::User')
- ->find_or_create( { email => $email } );
- ok $user, "found/created user for $email";
+ my $user = $mech->create_user_ok($email);
# store the old password and then change it
my $old_password_sha1 = $user->password;
@@ -129,14 +147,11 @@ sub delete_user {
$mech->log_out_ok;
for my $p ( $user->problems ) {
- ok( $_->delete, "delete comment " . $_->text )
- for $p->comments;
+ ok( $_->delete, "delete comment " . $_->text ) for $p->comments;
ok( $p->delete, "delete problem " . $p->title );
}
- ok( $_->delete, "delete comment " . $_->text )
- for $user->comments;
- ok( $_->delete, "delete alert " . $_->alert_type )
- for $user->alerts;
+ ok( $_->delete, "delete comment " . $_->text ) for $user->comments;
+ ok( $_->delete, "delete alert " . $_->alert_type ) for $user->alerts;
ok $user->delete, "delete test user " . $user->email;
return 1;
@@ -223,7 +238,7 @@ arrayref of TEXTs. If none found return empty arrayref.
sub page_errors {
my $mech = shift;
my $result = scraper {
- process 'p.error', 'errors[]', 'TEXT';
+ process 'p.error', 'errors[]', 'TEXT';
process 'ul.error', 'errors[]', 'TEXT';
}
->scrape( $mech->response );
@@ -332,7 +347,6 @@ sub extract_problem_title {
return $result->{title};
}
-
=head2 extract_problem_banner
$banner = $mech->extract_problem_banner;
@@ -434,4 +448,28 @@ sub session_cookie_expiry {
return $expires || 0;
}
+=head2 get_ok_json
+
+ $decoded = $mech->get_ok_json( $url );
+
+Get the url, check that it was JSON and then decode and return the body.
+
+=cut
+
+sub get_ok_json {
+ my $mech = shift;
+ my $url = shift;
+
+ # try to get the response
+ $mech->get_ok($url)
+ || return undef;
+ my $res = $mech->response;
+
+ # check that the content-type of response is correct
+ croak "Response was not JSON"
+ unless $res->header('Content-Type') =~ m{^application/json\b};
+
+ return decode_json( $res->content );
+}
+
1;
diff --git a/t/app/controller/json.t b/t/app/controller/json.t
new file mode 100644
index 000000000..2c9ff4a61
--- /dev/null
+++ b/t/app/controller/json.t
@@ -0,0 +1,109 @@
+use strict;
+use warnings;
+
+use Test::More;
+
+use FixMyStreet::TestMech;
+my $mech = FixMyStreet::TestMech->new;
+
+subtest "check that a bad request produces the appropriate response" => sub {
+
+ my $bad_date = "Invalid dates supplied";
+ my $mad_date = "Start date after end date";
+ my $bad_type = "Invalid type supplied";
+
+ my %tests = (
+ '' => $bad_date,
+ 'foo=bar' => $bad_date,
+ 'type=&start_date=&end_date=' => $bad_date,
+ 'type=&start_date=bad&end_date=2000-02-01' => $bad_date,
+ 'type=&start_date=2000-01-01&end_date=bad' => $bad_date,
+ 'type=&start_date=2000-02-31&end_date=2000-02-01' => $bad_date,
+ 'type=&start_date=2000-01-01&end_date=2000-02-31' => $bad_date,
+
+ 'type=&start_date=2000-02-01&end_date=2000-01-01' => $mad_date,
+
+ 'type=&start_date=2000-01-01&end_date=2000-02-01' => $bad_type,
+ 'type=foo&start_date=2000-01-01&end_date=2000-02-01' => $bad_type,
+ );
+
+ foreach my $q ( sort keys %tests ) {
+ is_deeply #
+ $mech->get_ok_json("/json?$q"), #
+ { error => $tests{$q} }, #
+ "correct error for query '$q'";
+ }
+
+};
+
+is_deeply #
+ $mech->get_ok_json(
+ "/json?type=new_problems&start_date=2000-01-01&end_date=2000-02-01"), #
+ [], #
+ "correct response";
+
+# put an entry in the database for this test
+my $user = $mech->create_user_ok('test@example.com');
+
+my $problem_args = {
+ postcode => 'sw1a 1aa',
+ council => '2501',
+ areas => ',105164,11806,11827,2247,2501,34817,42011,66045,70786,8519,',
+ category => 'test category',
+ title => 'Test title',
+ detail => 'Test detail',
+ used_map => 't',
+ name => 'Test Name',
+ created => '2000-01-01 12:00:00',
+ confirmed => '2000-01-01 12:01:00',
+ state => 'confirmed',
+ lang => 'en-gb',
+ service => '',
+ cobrand => '',
+ cobrand_data => '',
+ lastupdate => '2000-01-01 12:00:00',
+ whensent => undef,
+ send_questionnaire => 't',
+ latitude => '51.4531988729771',
+ longitude => '-0.23021896608596',
+};
+my $problem = $user->add_to_problems( { %$problem_args, anonymous => 0 } );
+my $anon_problem = $user->add_to_problems( { %$problem_args, anonymous => 1 } );
+
+ok $problem, "created normal test problem";
+ok $anon_problem, "created anon test problem";
+
+is_deeply #
+ $mech->get_ok_json(
+ "/json?type=new_problems&start_date=2000-01-01&end_date=2000-02-01"), #
+ [
+ {
+ 'anonymous' => 0,
+ 'category' => 'test category',
+ 'confirmed' => '2000-01-01 12:01:00',
+ 'council' => 'Wandsworth Borough Council',
+ 'detail' => 'Test detail',
+ 'id' => $problem->id,
+ 'name' => 'Test Name',
+ 'service' => 'Web interface',
+ 'title' => 'Test title',
+ 'whensent' => undef
+ },
+ {
+ 'anonymous' => 1,
+ 'category' => 'test category',
+ 'confirmed' => '2000-01-01 12:01:00',
+ 'council' => 'Wandsworth Borough Council',
+ 'detail' => 'Test detail',
+ 'id' => $anon_problem->id,
+ 'name' => '',
+ 'service' => 'Web interface',
+ 'title' => 'Test title',
+ 'whensent' => undef
+ }
+ ],
+ "correct response";
+
+$mech->delete_user($user);
+
+done_testing();
diff --git a/web/json.cgi b/web/json.cgi
index 512750988..70ae2a76f 100755
--- a/web/json.cgi
+++ b/web/json.cgi
@@ -8,28 +8,28 @@
#
# $Id: json.cgi,v 1.4 2010-01-20 11:31:26 matthew Exp $
-use strict;
-use Error qw(:try);
-use JSON;
-use Standard;
-
-sub main {
- my $q = shift;
- my $problems;
- my $type = $q->param('type') || '';
- my $start_date = $q->param('start_date') || '';
- my $end_date = $q->param('end_date') || '';
- if ($start_date !~ /^\d{4}-\d\d-\d\d$/ || $end_date !~ /^\d{4}-\d\d-\d\d$/) {
- $problems = { error => 'Invalid dates supplied' };
- } elsif ($type eq 'new_problems') {
- $problems = Problems::created_in_interval($start_date, $end_date);
- } elsif ($type eq 'fixed_problems') {
- $problems = Problems::fixed_in_interval($start_date, $end_date);
- }
- print $q->header( -type => 'application/json; charset=utf-8' );
- print JSON::to_json($problems);
-}
-
-
-Page::do_fastcgi(\&main);
-
+# use strict;
+# use Error qw(:try);
+# use JSON;
+# use Standard;
+#
+# sub main {
+# my $q = shift;
+# my $problems;
+# my $type = $q->param('type') || '';
+# my $start_date = $q->param('start_date') || '';
+# my $end_date = $q->param('end_date') || '';
+# if ($start_date !~ /^\d{4}-\d\d-\d\d$/ || $end_date !~ /^\d{4}-\d\d-\d\d$/) {
+# $problems = { error => 'Invalid dates supplied' };
+# } elsif ($type eq 'new_problems') {
+# $problems = Problems::created_in_interval($start_date, $end_date);
+# } elsif ($type eq 'fixed_problems') {
+# $problems = Problems::fixed_in_interval($start_date, $end_date);
+# }
+# print $q->header( -type => 'application/json; charset=utf-8' );
+# print JSON::to_json($problems);
+# }
+#
+#
+# Page::do_fastcgi(\&main);
+#