Lookup openid users to convert via Email if OpenID lookup fails
Jess Robinson [Thu, 5 Feb 2015 18:24:52 +0000 (18:24 +0000)]
Ensure we actually transfer traditions to the new user
More Tests for the above

lib/Text/Tradition/Directory.pm
lib/stemmaweb/Authentication/Credential/Google.pm
script/maketestdb.pl
t/07google.t
t/lib/stemmaweb/Test/DB.pm

index c669bd8..451fbf4 100644 (file)
@@ -550,8 +550,9 @@ sub _find_gplus {
     # Do we have a user with the google id already?
 
     my $user = $self->find_user({
-            username => $sub
-        });
+        username => $sub
+    });
+    warn "Found by google+id" if $user;
 
     if ($user) {
         return $user;
@@ -560,8 +561,11 @@ sub _find_gplus {
     # Do we have a user with the openid?
 
     $user = $self->find_user({
-            url => $openid
-        });
+        url => $openid
+    });
+    warn "Found by openid" if $user;
+    $user ||= $self->find_user({ email => $userinfo->{email} });
+    warn "Found by email" if $user;
 
     if (!$user) {
         return undef;
@@ -580,6 +584,8 @@ sub _find_gplus {
     foreach my $t (@{ $user->traditions }) {
         $new_user->add_tradition($t);
     }
+    $self->update(@{ $user->traditions });
+    $self->update($new_user);
 
     # $self->delete_user({ username => $user->id });
     return $new_user;
index 32f22c9..267127f 100644 (file)
@@ -53,6 +53,7 @@ sub authenticate {
     $c->req->body_params->{email};
 
     my $userinfo = $self->decode($id_token);
+    $userinfo->{email} = $authinfo->{email};
 
     my $sub = $userinfo->{sub};
     my $openid = $userinfo->{openid_id};
index f26659d..3a24907 100755 (executable)
@@ -40,9 +40,9 @@ say "Created test database";
 my $user = $dir->add_user({ username => 'user@example.org', password => 'UserPass' });
 my $admin = $dir->add_user({ username => 'admin@example.org', 
        password => 'AdminPass', role => 'admin' });
-my $openid_user = $dir->add_user({
-        username => 'https://www.google.com/accounts/o8/id?id=AItOawlFTlpuHGcI67tqahtw7xOod9VNWffB-Qg',
-        password => 'pass'
+my $openid_user = $dir->create_user({
+        url      => 'https://www.google.com/accounts/o8/id?id=AItOawlFTlpuHGcI67tqahtw7xOod9VNWffB-Qg',
+        extensions => {'http://openid.net/srv/ax/1.0' => { 'value.email' =>'openid@example.org' } },
     });
 die "Failed to create test users" unless $user && $admin && $openid_user;
 say "Created users";
@@ -51,8 +51,11 @@ my $t1 = Text::Tradition->new( input => 'Self', file => 't/data/besoin.xml' );
 die "Failed to create test tradition #1" unless $t1;
 $t1->add_stemma( dotfile => 't/data/besoin_stemweb.dot' );
 $user->add_tradition( $t1 );
-$openid_user->add_tradition($t1);
+my $t2 = Text::Tradition->new( input => 'Self', file => 't/data/besoin.xml' );
+$t2->add_stemma( dotfile => 't/data/besoin_stemweb.dot' );
+$openid_user->add_tradition($t2);
 $dir->store( $user );
+$dir->store( $openid_user );
 say "Created test user tradition";
 
 my $t2 = Text::Tradition->new( input => 'Tabular', sep_char => ',', 
index 37f0a66..c02faba 100644 (file)
@@ -30,6 +30,7 @@ my $ua = Test::WWW::Mechanize->new;
 io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
 
 {
+    diag("Create OpenID based Google account");
     my $scope = $dir->new_scope;
 
     $ua->get_ok('http://localhost/login');
@@ -37,15 +38,18 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
     local *Catalyst::Authentication::Credential::OpenID::authenticate = sub {
         my ( $self, $c, $realm, $authinfo ) = @_;
 
-        return $realm->find_user({ url => 'https://www.google.com/accounts/o8/id' }, $c);
+        return $realm->find_user({
+            url => 'https://www.google.com/accounts/o8/id?id=XYZ',
+            email => 'test@example.com',
+                                 }, $c);
     };
 
-    ok !$dir->find_user({ url => 'https://www.google.com/accounts/o8/id' }), 'No such user, yet.';
+    ok !$dir->find_user({ url => 'https://www.google.com/accounts/o8/id?id=XYZ' }), 'No such user, yet.';
 
     $ua->submit_form(
         form_number => 2,
         fields => {
-            openid_identifier => 'https://www.google.com/accounts/o8/id',
+            openid_identifier => 'https://www.google.com/accounts/o8/id?id=XYZ',
         },
     );
 
@@ -53,19 +57,24 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
 
     $ua->get('/');
 
-    $ua->content_contains('Hello! https://www.google.com/accounts/o8/id!', 'We are logged in.');
+    $ua->content_contains('Hello! test@example.com!', 'We are logged in.');
 
-    ok $dir->find_user({ url => 'https://www.google.com/accounts/o8/id' }), 'The user is now there.';
+    diag("Verify new OpenID Google account exists");
+    ok $dir->find_user({ url => 'https://www.google.com/accounts/o8/id?id=XYZ',
+                         email => 'test@example.com',
+                       }), 'The user is now there.';
     $ua->get('/logout');
 
     # Converting to Google ID.
 
+    diag("Login/Convert to new Google+ account");
     local *stemmaweb::Authentication::Credential::Google::authenticate = sub {
         my ( $self, $c, $realm, $authinfo ) = @_;
 
         return $realm->find_user({
-                openid_id => 'https://www.google.com/accounts/o8/id',
+                openid_id => 'https://www.google.com/accounts/o8/id?id=XYZ',
                 sub        => 42,
+                email => $authinfo->{email},
             }, $c);
     };
     $ua->get_ok('http://localhost/login');
@@ -74,7 +83,74 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
         form_number => 1,
         fields => {
             id_token => 'something',
-            email    => 'email@example.org',
+            email    => 'test@example.com',
+        },
+    );
+
+    $ua->content_contains('You have logged in.', 'G+ login works');
+
+    $ua->get('/');
+
+    $ua->content_contains('Hello! test@example.com!', 'We are logged in.');
+
+    $ua->get_ok('/logout', 'Logged out');
+}
+
+{
+    diag("Create OpenID based Google account for email match");
+    my $scope = $dir->new_scope;
+
+    $ua->get_ok('http://localhost/login');
+
+    local *Catalyst::Authentication::Credential::OpenID::authenticate = sub {
+        my ( $self, $c, $realm, $authinfo ) = @_;
+
+        return $realm->find_user({
+            url => 'https://www.google.com/accounts/o8/id?id=42XYZ',
+            email => 'test42@example.com',
+                                 }, $c);
+    };
+
+    ok !$dir->find_user({ url => 'https://www.google.com/accounts/o8/id?id=42XYZ' }), 'No such user, yet.';
+
+    $ua->submit_form(
+        form_number => 2,
+        fields => {
+            openid_identifier => 'https://www.google.com/accounts/o8/id?id=42XYZ',
+        },
+    );
+
+    $ua->content_contains('You have logged in.', 'Openid login works');
+
+    $ua->get('/');
+
+    $ua->content_contains('Hello! test42@example.com!', 'We are logged in.');
+
+    diag("Verify new OpenID Google account for email match exists");
+    ok $dir->find_user({ url => 'https://www.google.com/accounts/o8/id?id=42XYZ',
+                         email => 'test42@example.com',
+                       }), 'The user is now there.';
+    $ua->get('/logout');
+
+    # Converting to Google ID.
+
+    diag("Login/Convert to new Google+ account matching only on email");
+    local *stemmaweb::Authentication::Credential::Google::authenticate = sub {
+        my ( $self, $c, $realm, $authinfo ) = @_;
+
+        return $realm->find_user({
+                openid_id => 'https://www.google.com/accounts/o8/id?id=45XYZ',
+                sub        => 45,
+                email => $authinfo->{email},
+            }, $c);
+    };
+    $ua->get_ok('http://localhost/login');
+
+    $ua->submit_form(
+        form_number => 1,
+        fields => {
+            id_token => 'something',
+            email    => 'test42@example.com',
         },
     );
 
@@ -82,15 +158,67 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
 
     $ua->get('/');
 
-    $ua->content_contains('Hello! 42!', 'We are logged in.');
+    $ua->content_contains('Hello! test42@example.com!', 'We are logged in.');
+
+    $ua->get('/logout');
 }
 
 {
+    diag("Test converting OpenID based Google account with traditions");
     my $scope = $dir->new_scope;
 
-    # ok !$dir->find_user({ url => 'https://www.google.com/accounts/o8/id' }), 'Old google-openid is gone.';
+    my $openid_u = $dir->find_user({ url => 'https://www.google.com/accounts/o8/id?id=AItOawlFTlpuHGcI67tqahtw7xOod9VNWffB-Qg',
+                         email => 'openid@example.org',
+                       });
+    ok($openid_u, 'The user is there.');
+
+    diag("Login/Convert to new Google+ account");
+    local *stemmaweb::Authentication::Credential::Google::authenticate = sub {
+        my ( $self, $c, $realm, $authinfo ) = @_;
+
+        return $realm->find_user({
+                openid_id => 'https://www.google.com/accounts/o8/id?id=AItOawlFTlpuHGcI67tqahtw7xOod9VNWffB-Qg',
+                sub        => 450,
+                email => $authinfo->{email},
+            }, $c);
+    };
+    $ua->get_ok('http://localhost/login');
+
+    $ua->submit_form(
+        form_number => 1,
+        fields => {
+            id_token => 'something',
+            email    => 'openid@example.org',
+        },
+    );
+
+    $ua->content_contains('You have logged in.', 'G+ login works');
+    $ua->get('/');
+    $ua->content_contains('Hello! openid@example.org!', 'We are logged in.');
+
+    my $gplus_u = $dir->find_user({
+        openid_id => 'https://www.google.com/accounts/o8/id?id=AItOawlFTlpuHGcI67tqahtw7xOod9VNWffB-Qg',
+        sub        => 450,
+        email => 'openid@example.org'
+    });
 
-    ok $dir->find_user({ sub => 42, openid_id => 'https://www.google.com/accounts/o8/id' }), 'The G+ user is there.';
+    foreach my $trad_id (0..$#{ $openid_u->traditions }) {
+        is($gplus_u->traditions->[$trad_id]->name, $openid_u->traditions->[$trad_id]->name, 'Traditions were copied over to G+ user');
+    }
+
+    $ua->get('/logout');
+}
+
+{
+    diag("Verify we can login the new Google+ account again");
+    my $scope = $dir->new_scope;
+#    ok !$dir->find_user({ url => 'https://www.google.com/accounts/o8/id?id=XYZ' }), 'Old google-openid is gone.';
+
+    ok $dir->find_user({
+        sub => 42,
+        openid_id => 'https://www.google.com/accounts/o8/id?id=XYZ',
+        email    => 'test@example.com',
+    }), 'The G+ user is there.';
 
     $ua->get('/logout');
 
@@ -100,8 +228,9 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
         my ( $self, $c, $realm, $authinfo ) = @_;
 
         return $realm->find_user({
-                openid_id => 'https://www.google.com/accounts/o8/id',
+                openid_id => 'https://www.google.com/accounts/o8/id?id=XYZ',
                 sub        => 42,
+                email      => $authinfo->{email},
             }, $c);
     };
 
@@ -109,7 +238,7 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
         form_number => 1,
         fields => {
             id_token => 'something',
-            email   => 'email@example.org',
+            email   => 'test@example.com',
         },
     );
 
@@ -117,16 +246,16 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
 
     $ua->get('/');
 
-    $ua->content_contains('Hello! 42!', 'We are logged in.');
+    $ua->content_contains('Hello! test@example.com!', 'We are logged in.');
 }
 
 # Brand new user just from open id.
 
 {
+    diag("Create a fresh Google+ user");
     my $scope = $dir->new_scope;
 
-
-    ok !$dir->find_user({ sub => 2, openid_id => 'https://www.google.com/accounts/o8/id2' }), 'The G+ user is not yet there.';
+    ok !$dir->find_user({ sub => 2, openid_id => 'https://www.google.com/accounts/o8/id2?id=XYZ', email => 'test2@exmple.com' }), 'The G+ user is not yet there.';
 
     $ua->get('/logout');
 
@@ -136,8 +265,9 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
         my ( $self, $c, $realm, $authinfo ) = @_;
 
         return $realm->find_user({
-                openid_id => 'https://www.google.com/accounts/o8/id2',
+                openid_id => 'https://www.google.com/accounts/o8/id2?id=XYZ',
                 sub        => 2,
+                email      => $authinfo->{email},
             }, $c);
     };
 
@@ -145,7 +275,7 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
         form_number => 1,
         fields => {
             id_token => 'something',
-            email   => 'email@example.org',
+            email    => 'test2@example.com',
         },
     );
 
@@ -153,9 +283,9 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
 
     $ua->get('/');
 
-    $ua->content_contains('Hello! 2!', 'We are logged in.');
+    $ua->content_contains('Hello! test2@example.com!', 'We are logged in.');
 
-    ok $dir->find_user({ sub => 2, openid_id => 'https://www.google.com/accounts/o8/id2' }), 'The G+ user is there.';
+    ok $dir->find_user({ sub => 2, openid_id => 'https://www.google.com/accounts/o8/id2?id=XYZ', email => 'test2@example.com' }), 'The G+ user is there.';
 
     $ua->get('/logout');
 
@@ -165,7 +295,7 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
         form_number => 1,
         fields => {
             id_token => 'something',
-            email   => 'email@example.org',
+            email    => 'test2@example.com',
         },
     );
 
@@ -173,7 +303,7 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
 
     $ua->get('/');
 
-    $ua->content_contains('Hello! 2!', 'We are logged in.');
+    $ua->content_contains('Hello! test2@example.com!', 'We are logged in.');
 }
 
 # Decoding token
@@ -181,7 +311,7 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
 {
     my $scope = $dir->new_scope;
 
-    ok !$dir->find_user({ sub => 4242, openid_id => 'https://www.google.com/accounts/o8/id3' }), 'The G+ user is not yet there.';
+    ok !$dir->find_user({ sub => 4242, openid_id => 'https://www.google.com/accounts/o8/id3', email => 'email@example.org' }), 'The G+ user is not yet there.';
 
     $ua->get('/logout');
 
@@ -201,7 +331,7 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
 
     $ua->content_contains('Hello! email@example.org!', 'We are logged in.');
 
-    ok $dir->find_user({ sub => 4242, openid_id => 'https://www.google.com/accounts/o8/id3' }), 'The G+ user is there.';
+    ok $dir->find_user({ sub => 4242, openid_id => 'https://www.google.com/accounts/o8/id3', email => 'email@example.org' }), 'The G+ user is there.';
 
     $ua->get('/logout');
 
@@ -219,7 +349,7 @@ io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
 
     $ua->get('/');
 
-    $ua->content_contains('Hello! email@example.org!', 'We ar logged in.');
+    $ua->content_contains('Hello! email@example.org!', 'We are logged in.');
 }
 
 io("$FindBin::Bin/var")->rmtree if io("$FindBin::Bin/var")->exists;
index 1104d84..ebc9d07 100644 (file)
@@ -38,14 +38,21 @@ sub new_db {
 
     # Create users
     my $user = $dir->add_user({ username => 'user@example.org', password => 'UserPass' });
-    my $openid_user = $dir->add_user({ username => 'http://localhost/' });
+    my $openid_user = $dir->create_user({
+        url      => 'https://www.google.com/accounts/o8/id?id=AItOawlFTlpuHGcI67tqahtw7xOod9VNWffB-Qg',
+        extensions => {'http://openid.net/srv/ax/1.0' => { 'value.email' =>'openid@example.org' } },
+    });
 
+    my $t1 = Text::Tradition->new( input => 'Self', file => 't/data/besoin.xml' );
+    $t1->add_stemma( dotfile => 't/data/besoin_stemweb.dot' );
+    $openid_user->add_tradition($t1);
+    $dir->store( $openid_user );
 
     my $t2 = Text::Tradition->new( input => 'Tabular', sep_char => ',', 
     file => 't/data/florilegium.csv' );
     $t2->add_stemma( dotfile => 't/data/florilegium.dot' );
-
     $user->add_tradition($t2);
+    $dir->store( $user );
 
     return $dir;
 }