Support email-attribute fetching from OpenID
Jess Robinson [Mon, 28 May 2012 14:58:23 +0000 (14:58 +0000)]
- store display value as email attribute
- default to id if no display value
- show display value on index page
- add tests for openid type users

lib/Text/Tradition/Directory.pm
lib/Text/Tradition/User.pm
stemmaweb/lib/stemmaweb/Controller/Users.pm
stemmaweb/root/src/index.tt
t/text_tradition_user.t

index 341da5c..ed5f9b2 100644 (file)
@@ -367,7 +367,8 @@ Create a new user object, store in the KiokuDB backend, and return it.
 
 sub add_user {
     my ($self, $userinfo) = @_;
-    my $username = $userinfo->{url} || $userinfo->{username};
+
+    my $username = $userinfo->{username};
     my $password = $userinfo->{password};
     my $role = $userinfo->{role} || 'user';
 
@@ -377,6 +378,7 @@ sub add_user {
     my $user = Text::Tradition::User->new(
         id => $username,
         password => ($password ? crypt_password($password) : ''),
+        display => ($userinfo->{display} ? $userinfo->{display} : $username),
         role => $role,
     );
 
@@ -386,13 +388,41 @@ sub add_user {
 }
 
 sub create_user {
-    my $self = shift;
-    return $self->add_user(@_);
+    my ($self, $userinfo) = @_;
+
+    ## No username means probably an OpenID based user
+    if(!exists $userinfo->{username}) {
+        extract_openid_data($userinfo);
+    }
+
+    return $self->add_user($userinfo);
+}
+
+## Not quite sure where this method should be.. Auth /
+## Credential::OpenID just pass us back the chunk of extension data
+sub extract_openid_data {
+    my ($userinfo) = @_;
+
+    ## Spec says SHOULD use url as identifier
+    $userinfo->{username} = $userinfo->{url};
+
+    ## Use email addy as display if available
+    if(exists $userinfo->{extensions} &&
+         exists $userinfo->{extensions}{'http://openid.net/srv/ax/1.0'} &&
+         defined $userinfo->{extensions}{'http://openid.net/srv/ax/1.0'}{'value.email'}) {
+        ## Somewhat ugly attribute extension reponse, contains
+        ## google-email string which we can use as the id
+
+        $userinfo->{display} = $userinfo->{extensions}{'http://openid.net/srv/ax/1.0'}{'value.email'};
+    }
+
+    return;
 }
 
 =head2 find_user
 
-Takes a hashref of C<username>, optionally C<openid_identifier>.
+Takes a hashref of C<username>, and possibly openIDish results from
+L<Net::OpenID::Consumer>.
 
 Fetches the user object for the given username and returns it.
 
@@ -400,17 +430,21 @@ Fetches the user object for the given username and returns it.
 
 sub find_user {
     my ($self, $userinfo) = @_;
-    ## url or display?
-    # 'display' => 'castaway.myopenid.com',
-    # 'url' => 'http://castaway.myopenid.com/',
-    my $username = $userinfo->{url} || $userinfo->{username};
+
+    ## No username means probably an OpenID based user
+    if(!exists $userinfo->{username}) {
+        extract_openid_data($userinfo);
+    }
+
+    my $username = $userinfo->{username};
 
     ## No logins if user is deactivated (use lookup to fetch to re-activate)
     my $user = $self->lookup(Text::Tradition::User->id_for_user($username));
-    return if($user && !$user->active);
+    return if(!$user || !$user->active);
+
+    print STDERR "Found user, $username, display is :", $user->display, ":\n";
 
     return $user;
-    
 }
 
 =head2 modify_user
index 7e53bb4..18a91df 100644 (file)
@@ -8,6 +8,7 @@ with qw(KiokuX::User);
 
 ## 'id' provided by KiokuX::User stores our username
 has 'password'   => (is => 'rw', required => 1);
+has 'display' => (is => 'rw', lazy => 1, builder => '_build_display');
 ## Change this default active value if you want/need to have an admin confirm a user after they self-create.
 has 'active'     => (is => 'rw', default => sub { 1; });
 has 'role'       => (is => 'rw', default => sub { 'user' });
@@ -28,6 +29,13 @@ after add_tradition => sub {
         unless $tradition->has_user && $tradition->user->id eq $self->id;
 };
 
+sub _build_display {
+    my ($self) = @_;
+
+    ## no display set, so use username/id
+    return $self->id;
+}
+
 sub remove_tradition {
     my ($self, $tradition) = @_;
 
@@ -42,7 +50,7 @@ sub remove_tradition {
 sub is_admin {
     my ($self) = @_;
 
-    return $self->role eq 'admin';
+    return $self->role && $self->role eq 'admin';
 }
 
 1;
index accc85b..19a72b5 100644 (file)
@@ -19,7 +19,7 @@ Catalyst Controller.
 sub base :Chained('/') :PathPart('') :CaptureArgs(0)
 {
         my ( $self, $c ) = @_;
+
         $self->next::method( $c );
 }
 
index f2325b4..945f1e8 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">[% IF c.user_exists %]Hello! [% c.user.id %] [% 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>
+      <span class="mainnav">[% IF c.user_exists %]Hello! [% c.user.get_object.display %] [% 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>
index 5297df4..bf36587 100644 (file)
@@ -27,6 +27,7 @@ my $new_user = $user_store->add_user({ username => 'fred',
                                        password => 'bloggspass'});
 isa_ok($new_user, 'Text::Tradition::User');
 is($new_user->active, 1, 'New user created and active');
+is($new_user->display, 'fred', 'Display value set to username');
 ok(!$new_user->is_admin, 'New user is not an admin');
 
 ## find user
@@ -207,3 +208,54 @@ TODO: {
     is(scalar @admin_tlist, scalar @tlist, 'Got all traditions for admin user');
 
 }
+
+{
+    ## Add/find simple openid user with OpenIDish parameters:
+
+    my $openid_user = $user_store->create_user({ 
+        url => 'http://username.myopenid.com',
+        display => 'username.myopenid.com',
+    });
+    ok($openid_user, 'Created user from OpenID params');
+
+    my $get_openid_user = $user_store->find_user({
+        url => 'http://username.myopenid.com',
+        display => 'username.myopenid.com',
+    });
+
+    ok($openid_user == $get_openid_user, 'Found OpenID user again');
+    is($get_openid_user->id, 'http://username.myopenid.com', 'Set id to unique url from openid');
+    is($get_openid_user->display, 'username.myopenid.com', 'Kept original display value');
+}
+
+{
+    ## Add/find openid user with email attribute:
+    my $openid_user = $user_store->create_user({ 
+        url => 'http://blahblah.com/foo/bar/baz/lotsofjunk',
+        display => 'http://blahblah.com/foo/bar/baz/lotsofjunk',
+        extensions => {
+            'http://openid.net/srv/ax/1.0' => { 
+                'value.email' => 'fredbloggs@blahblah.com',
+                'type.email' => 'http://axschema.org/contact/email',
+                'mode' => 'fetch_response',
+            },
+        },
+    });
+    ok($openid_user, 'Created user from OpenID params');
+
+    my $get_openid_user = $user_store->find_user({
+        url => 'http://blahblah.com/foo/bar/baz/lotsofjunk',
+        display => 'http://blahblah.com/foo/bar/baz/lotsofjunk',
+        extensions => {
+            'http://openid.net/srv/ax/1.0' => { 
+                'value.email' => 'fredbloggs@blahblah.com',
+                'type.email' => 'http://axschema.org/contact/email',
+                'mode' => 'fetch_response',
+            },
+        },
+    });
+
+    ok($openid_user == $get_openid_user, 'Found OpenID user again');
+    is($get_openid_user->id, 'http://blahblah.com/foo/bar/baz/lotsofjunk', 'Set id to unique url from openid');
+    is($get_openid_user->display, 'fredbloggs@blahblah.com', 'Set display value to email from extension');
+}