incorporate user auth functionality
Tara L Andrews [Wed, 11 Jul 2012 19:33:51 +0000 (21:33 +0200)]
12 files changed:
Makefile.PL
lib/stemmaweb.pm
lib/stemmaweb/Controller/Root.pm
lib/stemmaweb/Controller/Users.pm [new file with mode: 0644]
lib/stemmaweb/View/Email/Template.pm [new file with mode: 0644]
root/src/auth/login.tt [new file with mode: 0644]
root/src/auth/register.tt [new file with mode: 0644]
root/src/index.tt
root/src/register-plain.tt [new file with mode: 0644]
stemmaweb.conf
t/controller_Users.t [new file with mode: 0644]
t/view_Email-Template.t [new file with mode: 0644]

index a31e6ed..7c833af 100644 (file)
@@ -18,6 +18,16 @@ requires 'Catalyst::Model::KiokuDB';
 requires 'Catalyst::View::Download::Plain';
 requires 'Catalyst::View::JSON';
 requires 'Catalyst::View::TT';
+requires 'Catalyst::View::Email::Template';
+## Auth:
+requires 'Catalyst::Plugin::Authentication';
+requires 'Catalyst::Plugin::Session';
+requires 'Catalyst::Plugin::Session::Store::File';
+requires 'Catalyst::Plugin::Session::State::Cookie';
+requires 'CatalystX::Controller::Auth';
+requires 'Catalyst::TraitFor::Controller::reCAPTCHA';
+requires 'LWP::Protocol::https';
+##
 requires 'Moose';
 requires 'TryCatch';
 requires 'namespace::autoclean';
index 94121c1..4563222 100644 (file)
@@ -4,6 +4,10 @@ use namespace::autoclean;
 
 use Catalyst::Runtime 5.80;
 
+use Search::GIN::Extract::Class;
+use Search::GIN::Extract::Attributes;
+use Search::GIN::Extract::Multiplex;
+
 # Set flags and add plugins for the application.
 #
 # Note that ORDERING IS IMPORTANT here as plugins are initialized in order,
@@ -20,6 +24,12 @@ use Catalyst qw/
     ConfigLoader
     Static::Simple
     Unicode::Encoding
+    Authentication
+    Session
+    Session::Store::File
+    Session::State::Cookie
+    StatusMessage
+    StackTrace
 /;
 
 extends 'Catalyst';
@@ -48,6 +58,65 @@ __PACKAGE__->config(
                        stemmaweb->path_to( 'root', 'src' ),
                ],
        },
+    ## kiokudb auth store testing
+    'Plugin::Authentication' => {
+        default => {
+            credential => {
+                class => 'Password',
+                password_field => 'password',
+                password_type => 'self_check',
+            },
+            store => {
+                class => 'Model::KiokuDB',
+                model_name => 'Directory',
+            },
+        },
+        openid => {
+            credential => {
+                class => 'OpenID',
+                extensions => ['http://openid.net/srv/ax/1.0' => 
+                    {
+                        ns          => 'ax',
+                        uri         => 'http://openid.net/srv/ax/1.0',
+                        mode        => 'fetch_request',
+                        required    => 'email',
+                        'type.email' => 'http://axschema.org/contact/email',
+                        # type        => {
+                        #     email => 'http://axschema.org/contact/email'
+                        # }
+                    }
+                    ],
+            },
+            store => {
+                class => 'Model::KiokuDB',
+                model_name => 'Directory',
+            },
+            auto_create_user => 1,
+        },
+    },
+    ## Auth with CatalystX::Controller::Auth
+    'Controller::Users' => {
+        model => 'User',
+        login_id_field => 'username',
+        login_db_field => 'username',
+        action_after_login => '/index',
+        action_after_register => '/index', 
+        register_email_from  => '"MyApp" <somebody@example.com>',
+        register_email_subject => 'Registration to stemmaweb',
+        register_email_template_plain => 'register-plain.tt',
+        realm => 'default',
+        login_fields => { openid => [qw/openid_identifier/],
+                          default => [qw/username password remember/],
+        },
+    },
+    'View::Email::Template' => {
+        stash_key => 'email_template',
+    },
+
+    recaptcha => {
+        pub_key => '',
+        priv_key => '',
+    },
 );
 
 # Start the application
index 3b6ba88..90f9e8a 100644 (file)
@@ -41,15 +41,15 @@ sub index :Path :Args(0) {
 
  GET /directory
 
-Serves a snippet of HTML that lists the available texts.  Eventually this will be available texts by user.
+Serves a snippet of HTML that lists the available texts.  This returns texts belonging to the logged-in user if any, otherwise it returns all public texts.
 
 =cut
+
 sub directory :Local :Args(0) {
        my( $self, $c ) = @_;
     my $m = $c->model('Directory');
-    # TODO not used yet, will load user texts later
-    my $user = $c->request->param( 'user' ) || 'ALL';
-    my @textlist = $m->traditionlist();
+    my $user = $c->user_exists ? $c->user->get_object : 'public';
+    my @textlist = $m->traditionlist($user);
     $c->stash->{texts} = \@textlist;
        $c->stash->{template} = 'directory.tt';
 }
diff --git a/lib/stemmaweb/Controller/Users.pm b/lib/stemmaweb/Controller/Users.pm
new file mode 100644 (file)
index 0000000..8a5c6ac
--- /dev/null
@@ -0,0 +1,102 @@
+package stemmaweb::Controller::Users;
+use Moose;
+use namespace::autoclean;
+
+BEGIN {extends 'CatalystX::Controller::Auth'; }
+with 'Catalyst::TraitFor::Controller::reCAPTCHA';
+
+=head1 NAME
+
+stemmaweb::Controller::Users - Catalyst Controller
+
+=head1 DESCRIPTION
+
+The Users controller is based on L<CatalystX::Controller::Auth>, see
+there for most of the functionality. Any localised parts are described
+below.
+
+This controller uses L<Catalyst::TraitFor::Controller::reCAPTCHA> to
+create and check a reCaptcha form shown on the C<register> form to
+help prevent spam signups.
+
+=head1 METHODS
+
+=cut
+
+sub base :Chained('/') :PathPart('') :CaptureArgs(0)
+{
+        my ( $self, $c ) = @_;
+
+        $self->next::method( $c );
+}
+
+=head2 index
+
+The index action is not currently used.
+
+=cut
+
+sub index :Path :Args(0) {
+    my ( $self, $c ) = @_;
+
+    $c->response->body('Matched stemmaweb::Controller::Users in Users.');
+}
+
+=head2 login with openid
+
+Logging in with openid/google requires two passes through the login
+action, on the 2nd pass the C<openid-check> value is passed in when
+the openid providing webserver links the user back to the stemmaweb
+site. This adaption to the C<login> action sets the realm we are
+authenticating against to be C<openid> in this case.
+
+=cut
+
+before login => sub {
+  my($self, $c) = @_;
+  $c->req->param( realm => 'openid')
+    if $c->req->param('openid-check');
+};
+
+=head2 register with recaptcha
+
+This adapts the C<register> action to add the recaptcha HTML to the
+page, and verify the recaptcha info entered is correct when the form
+is submitted. If the recaptcha is not correct, we just redisplay the
+form with an error message.
+
+=cut
+
+before register => sub {
+    my ($self, $c) = @_;
+
+    ## Puts HTML into stash in "recaptcha" key.
+    $c->forward('captcha_get');
+
+    ## When submitting, check recaptcha passes, else re-draw form
+    if($c->req->method eq 'POST') {
+        if(!$c->forward('captcha_check')) {
+            
+            ## Need these two lines to detach, so end can draw the correct template again:
+            my $form = $self->form_handler->new( active => [ $self->login_id_field, 'password', 'confirm_password' ] );
+            $c->stash( template => $self->register_template, form => $form );
+
+            $c->detach();
+        }
+    }
+};
+
+=head1 AUTHOR
+
+A clever guy
+
+=head1 LICENSE
+
+This library is free software. You can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+__PACKAGE__->meta->make_immutable;
+
+1;
diff --git a/lib/stemmaweb/View/Email/Template.pm b/lib/stemmaweb/View/Email/Template.pm
new file mode 100644 (file)
index 0000000..91f3784
--- /dev/null
@@ -0,0 +1,34 @@
+package stemmaweb::View::Email::Template;
+
+use strict;
+use base 'Catalyst::View::Email::Template';
+
+__PACKAGE__->config(
+    stash_key       => 'email',
+    template_prefix => ''
+);
+
+=head1 NAME
+
+stemmaweb::View::Email::Template - Templated Email View for stemmaweb
+
+=head1 DESCRIPTION
+
+View for sending template-generated email from stemmaweb. 
+
+=head1 AUTHOR
+
+A clever guy
+
+=head1 SEE ALSO
+
+L<stemmaweb>
+
+=head1 LICENSE
+
+This library is free software, you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+1;
diff --git a/root/src/auth/login.tt b/root/src/auth/login.tt
new file mode 100644 (file)
index 0000000..7779789
--- /dev/null
@@ -0,0 +1,38 @@
+[% IF status_msg %]
+                       <p>[% status_msg | html %]</p>
+[% END %]
+[% IF error_msg %]
+                       <p class="error">[% error_msg | html %]</p>
+[% END %]
+
+[% IF form.has_errors %]
+                       <p class="error">Some fields had errors:</p>
+                                       
+                       <ul class="errors">
+       [% FOREACH msg IN form.errors %]
+                               <li>[% msg | html %]</li>
+       [% END %]
+                       </ul>
+[% END %]
+
+       <form method="post" action="[% c.uri_for_action('/users/login').hostless | html %]" autocomplete="off">
+
+    <input type="hidden" name="realm" value="openid"/>
+    <input type="hidden" name="openid_identifier" value="https://www.google.com/accounts/o8/id"/>
+    <input type="submit" value="Sign in with Google"/>
+
+       </form>
+
+[% UNLESS c.req.param('realm') == 'openid' %]
+       <form method="post" action="[% c.uri_for_action('/users/login').hostless | html %]" autocomplete="off">
+
+    <input type="hidden" name="realm" value="default"/>
+
+       [% form.field('username').render %]
+       [% form.field('password').render %]
+       [% form.field('remember').render %]
+
+       [% form.field('submit').render %]
+
+       </form>
+[% END %]
\ No newline at end of file
diff --git a/root/src/auth/register.tt b/root/src/auth/register.tt
new file mode 100644 (file)
index 0000000..2f91791
--- /dev/null
@@ -0,0 +1,31 @@
+[% IF status_msg %]
+                       <p>[% status_msg | html %]</p>
+[% END %]
+[% IF error_msg %]
+                       <p class="error">[% error_msg | html %]</p>
+[% END %]
+
+[% IF form.has_errors %]
+                       <p class="error">Some fields had errors:</p>
+                                       
+                       <ul class="errors">
+       [% FOREACH msg IN form.errors %]
+                               <li>[% msg | html %]</li>
+       [% END %]
+                       </ul>
+[% END %]
+
+       <form method="post" action="[% c.uri_for_action('/users/register').hostless | html %]" autocomplete="off">
+
+       [% form.field('username').render %] (email)
+       [% form.field('password').render %]
+       [% form.field('confirm_password').render %]
+
+    [% IF recaptcha_error %]
+          <p class="error">[% recaptcha_error | html %]</p>
+    [% END %]
+    [% recaptcha %]
+
+       [% form.field('submit').render %]
+
+       </form>
\ No newline at end of file
index 61fe470..68cebc7 100644 (file)
@@ -14,7 +14,7 @@ $(document).ready(function() {
 
     <div id="topbanner">
       <h1>Stemmaweb - a collection of tools for analysis of collated texts</h1>
-      <span class="mainnav"><a href="[% c.uri_for( 'about.html' ) %]">About<a> | <a href="[% c.uri_for( 'doc.html' ) %]">Help</a></span>
+      <span class="mainnav">[% IF c.user_exists %]Hello! [% c.user.get_object.email %] [% ELSE %]<a href="[% c.uri_for('/login') %]">Login</a> | <a href="[% c.uri_for('/register') %]">Register</a> | [% END %]<a href="[% c.uri_for( 'about.html' ) %]">About<a> | <a href="[% c.uri_for( 'doc.html' ) %]">Help</a></span>
     </div>
     <div id="directory_container">
       <h2>Text directory</h2>
diff --git a/root/src/register-plain.tt b/root/src/register-plain.tt
new file mode 100644 (file)
index 0000000..517cc8c
--- /dev/null
@@ -0,0 +1,2 @@
+Thank you for registering with Stemmaweb!
+
index a64ce1e..a0169dc 100644 (file)
@@ -3,4 +3,7 @@
 name = stemmaweb
 <Model Directory>
     dsn dbi:SQLite:dbname=db/traditions.db
-</Model>
\ No newline at end of file
+</Model>
+<Model User>
+    dsn dbi:SQLite:dbname=db/traditions.db
+</Model>
diff --git a/t/controller_Users.t b/t/controller_Users.t
new file mode 100644 (file)
index 0000000..7fe5bfd
--- /dev/null
@@ -0,0 +1,10 @@
+use strict;
+use warnings;
+use Test::More;
+
+
+use Catalyst::Test 'stemmaweb';
+use stemmaweb::Controller::Users;
+
+ok( request('/users')->is_success, 'Request should succeed' );
+done_testing();
diff --git a/t/view_Email-Template.t b/t/view_Email-Template.t
new file mode 100644 (file)
index 0000000..acaf00a
--- /dev/null
@@ -0,0 +1,8 @@
+use strict;
+use warnings;
+use Test::More;
+
+
+BEGIN { use_ok 'stemmaweb::View::Email::Template' }
+
+done_testing();