aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Somerville <matthew-github@dracos.co.uk>2019-04-24 19:01:22 +0100
committerMatthew Somerville <matthew-github@dracos.co.uk>2019-05-07 15:30:12 +0100
commit649204bef4fc7326e409640d403fb26d35e36d62 (patch)
tree0360e9853f9d597efbbc2b6bf06786b4a26ee60c
parent30fda70c8a54b912b9bf859b1401e3e3284f558c (diff)
Prevent previous commit issue ever happening again.
-rw-r--r--perllib/Catalyst/Authentication/Store/FixMyStreetUser.pm54
-rw-r--r--perllib/FixMyStreet/App.pm21
-rw-r--r--t/app/controller/token.t4
-rw-r--r--t/app/model/user.t16
4 files changed, 77 insertions, 18 deletions
diff --git a/perllib/Catalyst/Authentication/Store/FixMyStreetUser.pm b/perllib/Catalyst/Authentication/Store/FixMyStreetUser.pm
new file mode 100644
index 000000000..240f4b1de
--- /dev/null
+++ b/perllib/Catalyst/Authentication/Store/FixMyStreetUser.pm
@@ -0,0 +1,54 @@
+package Catalyst::Authentication::Store::FixMyStreetUser;
+
+use Moose;
+use namespace::autoclean;
+extends 'Catalyst::Authentication::Store::DBIx::Class::User';
+
+use Carp;
+use Try::Tiny;
+
+sub AUTOLOAD {
+ my $self = shift;
+ (my $method) = (our $AUTOLOAD =~ /([^:]+)$/);
+ return if $method eq "DESTROY";
+
+ if (my $code = $self->_user->can($method)) {
+ return $self->_user->$code(@_);
+ }
+ elsif (my $accessor =
+ try { $self->_user->result_source->column_info($method)->{accessor} }) {
+ return $self->_user->$accessor(@_);
+ } else {
+ croak sprintf("Can't locate object method '%s'", $method);
+ }
+}
+
+__PACKAGE__->meta->make_immutable(inline_constructor => 0);
+
+1;
+__END__
+
+=head1 NAME
+
+Catalyst::Authentication::Store::FixMyStreetUser - The backing user
+class for the Catalyst::Authentication::Store::DBIx::Class storage
+module, adjusted to die on unknown lookups.
+
+=head1 DESCRIPTION
+
+The Catalyst::Authentication::Store::FixMyStreetUser class implements user
+storage connected to an underlying DBIx::Class schema object.
+
+=head1 SUBROUTINES / METHODS
+
+=head2 AUTOLOAD
+
+Delegates method calls to the underlying user row.
+Unlike the default, dies if an unknown method is called.
+
+=head1 LICENSE
+
+Copyright (c) 2007-2019. All rights reserved. This program is free software;
+you can redistribute it and/or modify it under the same terms as Perl itself.
+
+=cut
diff --git a/perllib/FixMyStreet/App.pm b/perllib/FixMyStreet/App.pm
index 36f736cd2..e9c3fac8d 100644
--- a/perllib/FixMyStreet/App.pm
+++ b/perllib/FixMyStreet/App.pm
@@ -34,6 +34,12 @@ extends 'Catalyst';
our $VERSION = '0.01';
+my $store = { # Catalyst::Authentication::Store::DBIx::Class
+ class => 'DBIx::Class',
+ user_model => 'DB::User',
+ store_user_class => 'Catalyst::Authentication::Store::FixMyStreetUser',
+};
+
__PACKAGE__->config(
# Use REQUEST_URI, not PATH_INFO, to infer path. This fixes an issue
@@ -83,20 +89,14 @@ __PACKAGE__->config(
},
],
},
- store => { # Catalyst::Authentication::Store::DBIx::Class
- class => 'DBIx::Class',
- user_model => 'DB::User',
- },
+ store => $store,
},
no_password => { # use post confirm etc
credential => { # Catalyst::Authentication::Credential::Password
class => 'Password',
password_type => 'none',
},
- store => { # Catalyst::Authentication::Store::DBIx::Class
- class => 'DBIx::Class',
- user_model => 'DB::User',
- },
+ store => $store,
},
access_token => {
use_session => 0,
@@ -106,10 +106,7 @@ __PACKAGE__->config(
# This means the token has to be 18 characters long (as generated by AuthToken)
token_lookup => { like => "%access_token,T18:TOKEN,%" },
},
- store => {
- class => 'DBIx::Class',
- user_model => 'DB::User',
- },
+ store => $store,
},
},
);
diff --git a/t/app/controller/token.t b/t/app/controller/token.t
index 858838865..f7dec1a31 100644
--- a/t/app/controller/token.t
+++ b/t/app/controller/token.t
@@ -1,5 +1,4 @@
use FixMyStreet::TestMech;
-use FixMyStreet::App;
my $mech = FixMyStreet::TestMech->new;
my $user = $mech->create_user_ok('bob@example.com', name => 'Bob');
@@ -8,7 +7,6 @@ subtest 'Zurich special case for C::Tokens->problem_confirm' => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => ['zurich'],
}, sub {
- my $c = FixMyStreet::App->new;
my $zurich = $mech->create_body_ok( 1, 'Zurich' );
my ($report) = $mech->create_problems_for_body(
1, $zurich->id,
@@ -19,7 +17,7 @@ subtest 'Zurich special case for C::Tokens->problem_confirm' => sub {
});
is $report->get_extra_metadata('email_confirmed'), undef, 'email_confirmed not yet set (sanity)';
- my $token = $c->model('DB::Token')->create({ scope => 'problem', data => $report->id });
+ my $token = FixMyStreet::DB->resultset('Token')->create({ scope => 'problem', data => $report->id });
$mech->get_ok('/P/' . $token->token);
$report->discard_changes;
diff --git a/t/app/model/user.t b/t/app/model/user.t
index 5a9c898a2..cbc0fe6cf 100644
--- a/t/app/model/user.t
+++ b/t/app/model/user.t
@@ -1,5 +1,8 @@
use FixMyStreet::TestMech;
use FixMyStreet::DB;
+use Catalyst::Test 'FixMyStreet::App';
+use HTTP::Request::Common;
+use Test::Exception;
my $mech = FixMyStreet::TestMech->new();
$mech->log_in_ok('test@example.com');
@@ -63,9 +66,16 @@ FixMyStreet::override_config {
$mech->content_like(qr/may_show_name[^>c]*>/);
};
-END {
- done_testing();
-}
+subtest 'Check non-existent methods on user object die' => sub {
+ my $c = ctx_request(POST '/auth', { username => 'test@example.com', password_sign_in => 'secret' });
+ throws_ok(
+ sub { $c->user->is_super_user },
+ qr/Can't locate object method 'is_super_user'/,
+ 'attempt to call non-existent method'
+ );
+};
+
+done_testing();
sub create_update {
my ($problem, %params) = @_;