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-09-18 06:20 am

[dw-free] allow crossposting from clients

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

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

Enable crossposting by default for third party clients.

Patch by [personal profile] superluminal.

Files modified:
  • cgi-bin/ljprotocol.pl
  • htdocs/editjournal.bml
  • htdocs/update.bml
--------------------------------------------------------------------------------
diff -r c7898ce3a58f -r aae36b18c269 cgi-bin/ljprotocol.pl
--- a/cgi-bin/ljprotocol.pl	Fri Sep 18 02:59:12 2009 +0000
+++ b/cgi-bin/ljprotocol.pl	Fri Sep 18 06:20:05 2009 +0000
@@ -982,6 +982,38 @@ sub common_event_validation
            ! LJ::Tags::is_valid_tagstring($req->{props}->{taglist});
 
     return 1;
+}
+
+sub schedule_xposts {
+    my ( $u, $ditemid, $deletep, $fn ) = @_;
+    return unless LJ::isu( $u ) && $ditemid > 0;
+    return unless $fn && ref $fn eq 'CODE';
+
+    my ( @successes, @failures );
+    my $sclient = LJ::theschwartz() or return;
+    my @accounts = DW::External::Account->get_external_accounts( $u );
+
+    foreach my $acct ( @accounts ) {
+        my ( $xpostp, $info ) = $fn->( $acct );
+        next unless $xpostp;
+
+        my $jobargs = {
+            uid       => $u->userid,
+            accountid => $acct->acctid,
+            ditemid   => $ditemid + 0,
+            delete    => $deletep ? 1 : 0,
+            %{$info}
+        };
+
+        my $job = TheSchwartz::Job->new_from_array( 'DW::Worker::XPostWorker', $jobargs );
+        if ( $job && $sclient->insert($job) ) {
+            push @successes, $acct;
+        } else {
+            push @failures, $acct;
+        }
+    }
+
+    return ( \@successes, \@failures );
 }
 
 sub postevent
@@ -1514,6 +1546,10 @@ sub postevent
 
     my $entry = LJ::Entry->new($uowner, jitemid => $jitemid, anum => $anum);
 
+    if ( $u->equals( $uowner ) && $req->{xpost} ne '0' ) {
+        schedule_xposts( $u, $ditemid, 0, sub { ((shift)->xpostbydefault, {}) } );
+    }
+
     # run local site-specific actions
     LJ::run_hooks("postpost", {
         'itemid'    => $jitemid,
@@ -1567,6 +1603,8 @@ sub editevent
 sub editevent
 {
     my ($req, $err, $flags) = @_;
+    my $res;
+    my $deleted = 0;
     un_utf8_request($req);
 
     return undef unless authenticate($req, $err, $flags);
@@ -1623,6 +1661,8 @@ sub editevent
          "compressed, security, allowmask, year, month, day, ".
          "rlogtime, anum FROM log2 WHERE journalid=$ownerid AND jitemid=$itemid");
 
+    my $ditemid = $itemid * 256 + $oldevent->{anum};
+
     ($oldevent->{subject}, $oldevent->{event}) = $dbcm->selectrow_array
         ("SELECT subject, event FROM logtext2 ".
          "WHERE journalid=$ownerid AND jitemid=$itemid");
@@ -1641,6 +1681,20 @@ sub editevent
     ### make sure this user is allowed to edit this entry
     return fail($err,302)
         unless ($ownerid == $oldevent->{'ownerid'});
+
+    ### load existing meta-data
+    my %curprops;
+    LJ::load_log_props2($dbcm, $ownerid, [ $itemid ], \%curprops);
+
+    # xpost helper for later
+    my $schedule_xposts = sub {
+        my $xpost_string = $curprops{$itemid}->{xpost};
+        if ( $xpost_string && $u->equals( $uowner ) && $req->{xpost} ne '0' ) {
+            my $xpost_info = DW::External::Account->xpost_string_to_hash( $xpost_string );
+            schedule_xposts( $u, $ditemid, $deleted,
+                             sub { ($xpost_info->{(shift)->acctid}, {}) } );
+        }
+    };
 
     ### what can they do to somebody elses entry?  (in shared journal)
     ### can edit it if they own or maintain the journal, but not if the journal is read-only
@@ -1668,6 +1722,8 @@ sub editevent
     # simple logic for deleting an entry
     if (!$flags->{'use_old_content'} && $req->{'event'} !~ /\S/)
     {
+        $deleted = 1;
+
         # if their newesteventtime prop equals the time of the one they're deleting
         # then delete their newesteventtime.
         if ($u->{'userid'} == $uowner->{'userid'}) {
@@ -1683,7 +1739,7 @@ sub editevent
         # delete is initiated.
         $uowner->log_event('delete_entry', {
                 remote => $u,
-                actiontarget => ($req->{itemid} * 256 + $oldevent->{anum}),
+                actiontarget => $ditemid,
                 method => 'protocol',
             })
             unless $flags->{noauth};
@@ -1694,8 +1750,10 @@ sub editevent
         # what they just deleted.  (or something... probably rare.)
         LJ::set_userprop($u, "dupsig_post", undef);
 
-        my $res = { 'itemid' => $itemid,
-                    'anum' => $oldevent->{'anum'} };
+        # pass the delete
+        $schedule_xposts->();
+
+        $res = { itemid => $itemid, anum => $oldevent->{anum} };
         return $res;
     }
 
@@ -1722,10 +1780,6 @@ sub editevent
     # updating an entry:
     return undef
         unless common_event_validation($req, $err, $flags);
-
-    ### load existing meta-data
-    my %curprops;
-    LJ::load_log_props2($dbcm, $ownerid, [ $itemid ], \%curprops);
 
     ## handle meta-data (properties)
     my %props_byname = ();
@@ -1813,7 +1867,7 @@ sub editevent
                        LJ::mysqldate_to_time($eventtime, 1),
                        LJ::mysqldate_to_time($oldevent->{'logtime'}, 1),
                        $sec,
-                       $itemid*256 + $oldevent->{'anum'});
+                       $ditemid);
 
         LJ::MemCache::set([$ownerid, "log2:$ownerid:$itemid"], $row);
 
@@ -1894,7 +1948,7 @@ sub editevent
 
     LJ::memcache_kill($ownerid, "dayct2");
 
-    my $res = { 'itemid' => $itemid };
+    $res = { itemid => $itemid };
     if (defined $oldevent->{'anum'}) {
         $res->{'anum'} = $oldevent->{'anum'};
         $res->{'url'} = LJ::item_link($uowner, $itemid, $oldevent->{'anum'});
@@ -1919,6 +1973,9 @@ sub editevent
         my @handles = $sclient->insert_jobs(@jobs);
         # TODO: error on failure?  depends on the job I suppose?  property of the job?
     }
+
+    # ensure our xposted edit fires
+    $schedule_xposts->();
 
     return $res;
 }
diff -r c7898ce3a58f -r aae36b18c269 htdocs/editjournal.bml
--- a/htdocs/editjournal.bml	Fri Sep 18 02:59:12 2009 +0000
+++ b/htdocs/editjournal.bml	Fri Sep 18 06:20:05 2009 +0000
@@ -205,6 +205,7 @@ body<=
                             'user' => $u->{'user'},
                             'usejournal' => $usejournal,
                             'itemid' => $itemid,
+                            'xpost' => '0'
                             );
                 LJ::entry_form_decode(\%req, \%POST);
 
@@ -242,46 +243,31 @@ body<=
                 # selected crosspost.
                 my $xpost_result = '';
                 if ($journalu == $remote && ($POST{prop_xpost_check} || $GET{prop_xpost_check})) {
-                    my @xpost_success;
-                    my @xpost_errors;
-
-                    # get the accounts for the user
-                    my @accounts = DW::External::Account->get_external_accounts($remote);
-                    foreach my $acct(@accounts) {
-                        my $acctid = $acct->acctid;
-                        # see if we said to xpost to this account
-                        if ($POST{"prop_xpost_$acctid"} || $GET{"prop_xpost_$acctid"}) {
-                            # get the auth information
-                            my %auth;
-                            if ($POST{"prop_xpost_resp_$acctid"} || $GET{"prop_xpost_resp_$acctid"}) {
-                                $auth{auth_response} = $POST{"prop_xpost_resp_$acctid"} || $GET{"prop_xpost_resp_$acctid"};
-                                $auth{auth_challenge} = $POST{"prop_xpost_chal_$acctid"} || $GET{"prop_xpost_chal_$acctid"};
-                            } else {
-                                $auth{password} = $POST{"prop_xpost_password_$acctid"} || $GET{"prop_xpost_password_$acctid"};
-                            }
-                            # send this to theschwartz to crosspost
-                            my $sclient = LJ::theschwartz();
-                            my $job = TheSchwartz::Job->new_from_array(
-                                'DW::Worker::XPostWorker', { 
-                                    'uid' => $remote->userid, 
-                                    'ditemid' => $ditemid, 
-                                    'accountid' => $acctid, 
-                                    'password' => $auth{password}, 
-                                    'auth_challenge' => $auth{auth_challenge}, 
-                                    'auth_response' => $auth{auth_response},
-                                    'delete' => $deleted } );
-                            # if we have a client and job, then request 
-                            # the crosspost
-                            if ($sclient && $job && $sclient->insert($job)) {
-                                push @xpost_success, "<li>" . BML::ml('xpost.request.success', {'account' => $acct->displayname}) . "</li>";
-                            } else {
-                                # one of them didn't work.
-                                push @xpost_errors, "<li><div style='color: red;'><strong>" . BML::ml('xpost.request.failed', { 'account' => $acct->displayname, 'editurl' => $edititemlink })  . " </strong></div></li>";
-                            }
-                        }
-                    }
-                    $xpost_result .= join ("\n", @xpost_success);
-                    $xpost_result .= join ("\n", @xpost_errors);
+                    my ($xpost_successes, $xpost_failures) =
+                        LJ::Protocol::schedule_xposts($remote, $ditemid, $deleted,
+                                                      sub {
+                                                          my $acctid = (shift)->acctid;
+                                                          ($POST{"prop_xpost_$acctid"} || $GET{"prop_xpost_$acctid"},
+                                                           {password => $POST{"prop_xpost_password_$acctid"}
+                                                                        || $GET{"prop_xpost_password_$acctid"},
+                                                            auth_challenge => $POST{"prop_xpost_chal_$acctid"}
+                                                                              || $GET{"prop_xpost_chal_$acctid"},
+                                                            auth_response => $POST{"prop_xpost_resp_$acctid"}
+                                                                             || $GET{"prop_xpost_resp_$acctid"}})
+                                                      });
+                    $xpost_result .= join("\n",
+                                          map {"<li>"
+                                               . BML::ml('xpost.request.success',
+                                                         {account => $_->displayname})
+                                               . "</li>"}
+                                              @{$xpost_successes});
+                    $xpost_result .= join("\n",
+                                          map {"<li><div style='color: red;'><strong>"
+                                               . BML::ml('xpost.request.failed',
+                                                         {account => $_->displayname,
+                                                          'editurl' => $edititemlink})
+                                               . " </strong></div></li>"}
+                                              @{$xpost_failures});
                 }
 
                 my $result = "<?h1 $ML{'.success.head'} h1?>";
diff -r c7898ce3a58f -r aae36b18c269 htdocs/update.bml
--- a/htdocs/update.bml	Fri Sep 18 02:59:12 2009 +0000
+++ b/htdocs/update.bml	Fri Sep 18 06:20:05 2009 +0000
@@ -375,6 +375,7 @@
                     'password'    => $POST{'password'},
                     'usejournal'  => $POST{'usejournal'},
                     'tz'          => 'guess',
+                    'xpost'       => '0'
                     );
 
         LJ::entry_form_decode(\%req, \%POST);
@@ -445,48 +446,32 @@
                     # crosspost if we're posting to our own journal and have
                     # selected crosspost.
                     if ($ju == $remote && ($POST{prop_xpost_check} || $GET{prop_xpost_check})) {
-                        my @xpost_success;
-                        my @xpost_errors;
-
-                        # get the accounts for the user
-                        my @accounts = DW::External::Account->get_external_accounts($remote);
-                        foreach my $acct(@accounts) {
-                            my $acctid = $acct->acctid;
-                            # see if we said to xpost to this account
-                            if ($POST{"prop_xpost_$acctid"} || $GET{"prop_xpost_$acctid"}) {
-                                # xpost to this account.
-                                my $result = {};
-                                my %auth;
-                                if ($POST{"prop_xpost_resp_$acctid"} || $GET{"prop_xpost_resp_$acctid"}) {
-                                    $auth{auth_response} = $POST{"prop_xpost_resp_$acctid"} || $GET{"prop_xpost_resp_$acctid"};
-                                    $auth{auth_challenge} = $POST{"prop_xpost_chal_$acctid"} || $GET{"prop_xpost_chal_$acctid"};
-                                } else {
-                                    $auth{password} = $POST{"prop_xpost_password_$acctid"} || $GET{"prop_xpost_password_$acctid"};
-                                }
-                                # send this to theschwartz to crosspost
-                                my $sclient = LJ::theschwartz();
-                                my $job = TheSchwartz::Job->new_from_array(
-                                    'DW::Worker::XPostWorker', { 
-                                        'uid' => $remote->userid, 
-                                        'ditemid' => $itemid, 
-                                        'accountid' => $acctid, 
-                                        'password' => $auth{password}, 
-                                        'auth_challenge' => $auth{auth_challenge}, 
-                                        'auth_response' => $auth{auth_response} });
-                                # if we have a client and job, then request 
-                                # the crosspost
-                                if ($sclient && $job && $sclient->insert($job)) {
-                                    push @xpost_success, "<li>" . BML::ml('xpost.request.success', {'account' => $acct->displayname}) . "</li>";
-                                } else {
-                                    # one of them didn't work.
-                                    push @xpost_errors, "<li><div style='color: red;'><strong>" . BML::ml('xpost.request.failed', { 'account' => $acct->displayname, 'editurl' => $edititemlink })  . " </strong></div></li>";
-                                }
-                            }
-                        }
-
+                        my ($xpost_successes, $xpost_errors) =
+                            LJ::Protocol::schedule_xposts($remote, $itemid, 0,
+                                                          sub {
+                                                              my $acctid = (shift)->acctid;
+                                                              ($POST{"prop_xpost_$acctid"} || $GET{"prop_xpost_$acctid"},
+                                                               {password => $POST{"prop_xpost_password_$acctid"}
+                                                                            || $GET{"prop_xpost_password_$acctid"},
+                                                                auth_challenge => $POST{"prop_xpost_chal_$acctid"}
+                                                                                  || $GET{"prop_xpost_chal_$acctid"},
+                                                                auth_response => $POST{"prop_xpost_resp_$acctid"}
+                                                                                 || $GET{"prop_xpost_resp_$acctid"}})
+                                                          });
                         $$body .= "<ul>\n";
-                        $$body .= join ("\n", @xpost_success);
-                        $$body .= join ("\n", @xpost_errors);
+                        $$body .= join("\n",
+                                       map { "<li>"
+                                             . BML::ml('xpost.request.success',
+                                                       {account => $_->displayname})
+                                             . "</li>" }
+                                           @{$xpost_successes});
+                        $$body .= join("\n",
+                                       map { "<li><div style='color: red;'><strong>"
+                                             . BML::ml('xpost.request.failed',
+                                                       {account => $_->displayname,
+                                                        editurl => $edititemlink })
+                                             . " </strong></div></li>" }
+                                           @{$xpost_errors});
                         $$body .= "</ul>\n";
                         $$body .= "<br/>";
                     }
--------------------------------------------------------------------------------