mark: A photo of Mark kneeling on top of the Taal Volcano in the Philippines. It was a long hike. (Default)
Mark Smith ([staff profile] mark) wrote in [site community profile] changelog2009-04-15 02:02 am

[dw-free] Allow importing of your journal from another LiveJournal-based site.

[commit: http://hg.dwscoalition.org/dw-free/rev/0fd5c96b9882]

http://bugs.dwscoalition.org/show_bug.cgi?id=114

Add verification step to the importer so we can move password checks off to
a separate IP address. Also fixes the issue of someone importing some other
random user's bio and userpics.

Patch by [staff profile] mark.

Files modified:
  • bin/worker/content-importer-verify
  • bin/worker/import-scheduler
  • cgi-bin/DW/Worker/ContentImporter.pm
  • cgi-bin/DW/Worker/ContentImporter/LiveJournal/Verify.pm
  • cgi-bin/LJ/Event/ImportStatus.pm
  • htdocs/misc/import.bml
--------------------------------------------------------------------------------
diff -r c56a6080fdcd -r 0fd5c96b9882 bin/worker/content-importer-verify
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/worker/content-importer-verify	Wed Apr 15 02:02:34 2009 +0000
@@ -0,0 +1,32 @@
+#!/usr/bin/perl
+#
+# content-importer-verify
+#
+# This importer job only does verification steps, which is responsible for
+# doing checks on the username and password given by the user.  This should
+# be run on a server on an IP other than your main import workers.
+#
+# Authors:
+#      Andrea Nall <anall@andreanall.com>
+#      Mark Smith <mark@dreamwidth.org>
+#
+# Copyright (c) 2009 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself.  For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+
+use strict;
+use lib "$ENV{LJHOME}/cgi-bin";
+
+require 'ljlib.pl';
+
+use LJ::Worker::TheSchwartz;
+use DW::Worker::ContentImporter::LiveJournal::Verify;
+
+schwartz_decl( "DW::Worker::ContentImporter::LiveJournal::Verify" );
+
+$0 = 'content-importer [bored]';
+
+schwartz_work();
diff -r c56a6080fdcd -r 0fd5c96b9882 bin/worker/import-scheduler
--- a/bin/worker/import-scheduler	Tue Apr 14 17:34:07 2009 +0000
+++ b/bin/worker/import-scheduler	Wed Apr 15 02:02:34 2009 +0000
@@ -109,6 +109,7 @@ sub worker {
             lj_userpics => 'DW::Worker::ContentImporter::LiveJournal::Userpics',
             lj_friends => 'DW::Worker::ContentImporter::LiveJournal::Friends',
             lj_friendgroups => 'DW::Worker::ContentImporter::LiveJournal::FriendGroups',
+            lj_verify => 'DW::Worker::ContentImporter::LiveJournal::Verify',
         }->{ $item->{item} } || die 'unknown item ';
 
         my $sh = LJ::theschwartz()
diff -r c56a6080fdcd -r 0fd5c96b9882 cgi-bin/DW/Worker/ContentImporter.pm
--- a/cgi-bin/DW/Worker/ContentImporter.pm	Tue Apr 14 17:34:07 2009 +0000
+++ b/cgi-bin/DW/Worker/ContentImporter.pm	Wed Apr 15 02:02:34 2009 +0000
@@ -164,14 +164,14 @@ sub temp_fail {
     return;
 }
 
-=head2 C<< $class->ok( $import_data, $item, $job )>>
+=head2 C<< $class->ok( $import_data, $item, $job, $show )>>
 
 Successfully end this import job.
 
 =cut
 
 sub ok {
-    my ( $class, $imp, $item, $job ) = @_;
+    my ( $class, $imp, $item, $job, $show ) = @_;
     $0 = 'content-importer [bored]';
 
     if ( my $dbh = LJ::get_db_writer() ) {
@@ -182,7 +182,8 @@ sub ok {
     }
 
     # advise the user this finished
-    LJ::Event::ImportStatus->new( $imp->{userid}, $item, { type => 'ok' } )->fire;
+    LJ::Event::ImportStatus->new( $imp->{userid}, $item, { type => 'ok' } )->fire
+        unless defined $show && $show == 0;
 
     $job->completed;
     return;
diff -r c56a6080fdcd -r 0fd5c96b9882 cgi-bin/DW/Worker/ContentImporter/LiveJournal/Verify.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Worker/ContentImporter/LiveJournal/Verify.pm	Wed Apr 15 02:02:34 2009 +0000
@@ -0,0 +1,89 @@
+#!/usr/bin/perl
+#
+# DW::Worker::ContentImporter::LiveJournal::Verify
+#
+# Importer worker for LiveJournal-based site verification of logins and
+# passwords.
+#
+# Authors:
+#      Andrea Nall <anall@andreanall.com>
+#      Mark Smith <mark@dreamwidth.org>
+#
+# Copyright (c) 2009 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself.  For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+#
+
+package DW::Worker::ContentImporter::LiveJournal::Verify;
+use strict;
+use base 'DW::Worker::ContentImporter::LiveJournal';
+
+use Carp qw/ croak confess /;
+
+sub work {
+    my ( $class, $job ) = @_;
+
+    eval { try_work( $class, $job ); };
+    if ( $@ ) {
+        warn "Failure running job: $@\n";
+        return $class->temp_fail( $job, 'Failure running job: %s', $@ );
+    }
+}
+
+sub try_work {
+    my ( $class, $job ) = @_;
+    my $opts = $job->arg;
+    my $data = $class->import_data( $opts->{userid}, $opts->{import_data_id} );
+
+    # failure wrappers for convenience
+    my $fail      = sub { return $class->fail( $data, 'lj_verify', $job, @_ ); };
+    my $ok        = sub { return $class->ok( $data, 'lj_verify', $job, @_ ); };
+    my $temp_fail = sub { return $class->temp_fail( $data, 'lj_verify', $job, @_ ); };
+
+    # setup
+    my $u = LJ::load_userid( $data->{userid} )
+        or return $fail->( 'Unable to load target with id %d.', $data->{userid} );
+    $0 = sprintf( 'content-importer [verify: %s(%d)]', $u->user, $u->id );
+
+    # we verify by doing a simple tags call.  yes, this means that we end up
+    # getting a user's tags twice... but I'm okay with that, we'll live
+    my $r = $class->call_xmlrpc( $data, 'getusertags' );
+
+    # now, we have to see if the error contains 'Invalid password' or something else
+    if ( $r && $r->{fault} && $r->{faultString} =~ /Invalid password/ ) {
+        # mark the rest of the import as aborted, since something went wrong
+        my $dbh = LJ::get_db_writer();
+        $dbh->do(
+            q{UPDATE import_items SET status = 'aborted'
+              WHERE userid = ? AND item <> 'lj_verify'
+              AND import_data_id = ? AND status = 'init'},
+            undef, $u->id, $opts->{import_data_id}        
+        );
+
+        # this is a permanent failure.  if the password is bad, we're not going to ever
+        # bother retrying.  that's life.
+        return $fail->( 'Username or password rejected by ' . $data->{hostname} . '.' );
+    }
+
+    # if we got any other type of failure, call it temporary...
+    return $temp_fail->( 'XMLRPC failure: ' . $r->{faultString} )
+        if ! $r || $r->{fault};
+
+    # mark the next group as ready to schedule
+    my $dbh = LJ::get_db_writer();
+    $dbh->do(
+        q{UPDATE import_items SET status = 'ready'
+          WHERE userid = ? AND item IN ('lj_bio', 'lj_userpics', 'lj_friendgroups', 'lj_tags')
+          AND import_data_id = ? AND status = 'init'},
+        undef, $u->id, $opts->{import_data_id}        
+    );
+
+    # okay, but don't fire off a message to say it's done, this job doesn't matter to
+    # the user unless it fails
+    return $ok->( 0 );
+}
+
+
+1;
diff -r c56a6080fdcd -r 0fd5c96b9882 cgi-bin/LJ/Event/ImportStatus.pm
--- a/cgi-bin/LJ/Event/ImportStatus.pm	Tue Apr 14 17:34:07 2009 +0000
+++ b/cgi-bin/LJ/Event/ImportStatus.pm	Wed Apr 15 02:02:34 2009 +0000
@@ -41,6 +41,7 @@ sub new {
         lj_friends      => 4,
         lj_friendgroups => 5,
         lj_userpics     => 6,
+        lj_verify       => 7,
 
         # other import types ...
     }->{$type};
@@ -87,6 +88,7 @@ sub as_html {
         4 => 'friends have',
         5 => 'friend groups have',
         6 => 'usericons have',
+        7 => 'import has',
     }->{$self->arg1} || 'ERROR, INVALID TYPE';
 
     # now success message
diff -r c56a6080fdcd -r 0fd5c96b9882 htdocs/misc/import.bml
--- a/htdocs/misc/import.bml	Tue Apr 14 17:34:07 2009 +0000
+++ b/htdocs/misc/import.bml	Wed Apr 15 02:02:34 2009 +0000
@@ -79,12 +79,16 @@ body<=
             $POST{lj_friendgroups} = 1;
         }
 
+        # everybody needs a verifier
+        $POST{lj_verify} = 1;
+
         # default job status
         my @jobs = (
-            ['lj_userpics',     'ready'],
-            ['lj_bio',          'ready'],
-            ['lj_tags',         'ready'],
-            ['lj_friendgroups', 'ready'],
+            ['lj_verify',       'ready'],
+            ['lj_userpics',     'init'],
+            ['lj_bio',          'init'],
+            ['lj_tags',         'init'],
+            ['lj_friendgroups', 'init'],
 #            ['lj_friends',      'init' ],
             ['lj_entries',      'init' ],
             ['lj_comments',     'init' ],
--------------------------------------------------------------------------------

Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org