Add the ability to apply a minsecurity for each remote account you can
crosspost to. Behaves the same way as local minsecurity, and retains the
minsecurity on edit (if you set a minsecurity of access-only, if you edit an
entry to public here the security will remain friends-only on the other site.
If you edit an entry to private here, the security will be changed to private
on the other site.).
Patch by allen.
diffs (413 lines):
diff -r 65a29c20761c -r df531c62cb65 bin/upgrading/update-db-general.pl
--- a/bin/upgrading/update-db-general.pl Mon Sep 20 22:09:58 2010 +0800
+++ b/bin/upgrading/update-db-general.pl Tue Sep 21 17:03:48 2010 +0800
@@ -2821,6 +2821,7 @@ CREATE table externalaccount (
serviceurl varchar(128),
xpostbydefault enum('1','0') NOT NULL default '0',
recordlink enum('1','0') NOT NULL default '0',
+ options blob,
primary key (userid, acctid),
index (userid)
)
@@ -3925,6 +3926,11 @@ EOF
}
set_dbnote( "unsplit_stats_timestamps", 1 )
}
+
+ unless ( column_type( 'externalaccount', 'options' ) ) {
+ do_alter( 'externalaccount',
+ "ALTER TABLE externalaccount ADD COLUMN options blob");
+ }
});
diff -r 65a29c20761c -r df531c62cb65 cgi-bin/DW/External/Account.pm
--- a/cgi-bin/DW/External/Account.pm Mon Sep 20 22:09:58 2010 +0800
+++ b/cgi-bin/DW/External/Account.pm Tue Sep 21 17:03:48 2010 +0800
@@ -30,9 +30,9 @@ sub _memcache_stored_props {
sub _memcache_stored_props {
# first element of props is a VERSION
# next - allowed object properties
- return qw/ 2
+ return qw/ 3
userid acctid
- siteid username password servicename servicetype serviceurl
xpostbydefault recordlink
+ siteid username password servicename servicetype serviceurl
xpostbydefault recordlink options
/;
}
sub _memcache_hashref_to_object {
@@ -81,7 +81,7 @@ sub get_external_accounts {
return @accounts;
}
- my $sth = $u->prepare("SELECT userid, acctid, siteid, username, password,
servicename, servicetype, serviceurl, xpostbydefault, recordlink FROM
externalaccount WHERE userid=?");
+ my $sth = $u->prepare( "SELECT userid, acctid, siteid, username, password,
servicename, servicetype, serviceurl, xpostbydefault, recordlink, options FROM
externalaccount WHERE userid=?" );
$sth->execute($u->userid);
LJ::throw($u->errstr) if $u->err;
@@ -107,7 +107,7 @@ sub get_external_account {
return $cached_value;
}
- my $sth = $u->prepare("SELECT userid, siteid, acctid, username, password,
servicename, servicetype, serviceurl, xpostbydefault, recordlink FROM
externalaccount WHERE userid=? and acctid=?");
+ my $sth = $u->prepare( "SELECT userid, siteid, acctid, username, password,
servicename, servicetype, serviceurl, xpostbydefault, recordlink, options FROM
externalaccount WHERE userid=? and acctid=?" );
$sth->execute($u->userid, $acctid);
LJ::throw($u->err) if ($u->err);
@@ -164,7 +164,7 @@ sub xpost_string_to_hash {
# instance methods
sub absorb_row {
my ($self, $row) = @_;
- for my $f (qw(username siteid password servicename servicetype serviceurl
xpostbydefault recordlink)) {
+ for my $f ( qw( username siteid password servicename servicetype
serviceurl xpostbydefault recordlink options ) ) {
$self->{$f} = $row->{$f};
}
return $self;
@@ -184,7 +184,10 @@ sub create {
my $protocol = DW::External::XPostProtocol->get_protocol($protocol_id);
my $encryptedpassword = $protocol->encrypt_password($opts->{password});
- $u->do("INSERT INTO externalaccount (userid, acctid, siteid, username,
password, servicename, servicetype, serviceurl, xpostbydefault, recordlink)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", undef, $u->{userid}, $acctid,
$opts->{siteid}, $opts->{username}, $encryptedpassword, $opts->{servicename},
$opts->{servicetype}, $opts->{serviceurl}, $opts->{xpostbydefault} ? '1' : '0',
$opts->{recordlink} ? '1' : '0' );
+ # convert the options hashref to a single field
+ my $options_blob = $class->xpost_hash_to_string( $opts->{options} );
+
+ $u->do( "INSERT INTO externalaccount ( userid, acctid, siteid, username,
password, servicename, servicetype, serviceurl, xpostbydefault, recordlink,
options ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )", undef, $u->{userid},
$acctid, $opts->{siteid}, $opts->{username}, $encryptedpassword,
$opts->{servicename}, $opts->{servicetype}, $opts->{serviceurl},
$opts->{xpostbydefault} ? '1' : '0', $opts->{recordlink} ? '1' : '0',
$options_blob );
LJ::throw($u->errstr) if $u->err;
@@ -396,6 +399,17 @@ sub recordlink {
return $_[0]->{recordlink};
}
+# returns the (protocol-specific) options as a hash ref
+sub options {
+ my $self = $_[0];
+ unless ( $self->{options_map} ) {
+ my $options_map = DW::External::Account->xpost_string_to_hash(
$self->{options} );
+ $self->{options_map} = $options_map;
+ }
+
+ return $self->{options_map};
+}
+
# if there is an external site configured, returns it; otherwise returns undef
sub externalsite {
return undef unless $_[0]->{siteid};
@@ -496,4 +510,26 @@ sub set_password {
return 1;
}
+# sets the (protocol-specific) options. takes a hashref as the options
+# argument.
+sub set_options {
+ my ( $self, $options ) = @_;
+
+ my $u = $self->owner;
+
+ # convert the hash to a string.
+ my $newvalue = DW::External::Account->xpost_hash_to_string( $options );
+
+ $u->do( "UPDATE externalaccount SET options=? WHERE userid=? AND
acctid=?", undef, $newvalue, $u->{userid}, $self->acctid );
+ LJ::throw($u->errstr) if $u->err;
+
+ # set options to the new value and clear options_map
+ $self->{options} = $newvalue;
+ $self->{options_map} = undef;
+
+ $self->_remove_from_memcache($self->_memcache_id);
+
+ return 1;
+}
+
1;
diff -r 65a29c20761c -r df531c62cb65 cgi-bin/DW/External/Site.pm
--- a/cgi-bin/DW/External/Site.pm Mon Sep 20 22:09:58 2010 +0800
+++ b/cgi-bin/DW/External/Site.pm Tue Sep 21 17:03:48 2010 +0800
@@ -144,4 +144,10 @@ sub pre_crosspost_hook {
return $_[1];
}
+# returns the servicetype
+sub servicetype {
+ return $_[0]->{servicetype};
+}
+
+
1;
diff -r 65a29c20761c -r df531c62cb65 cgi-bin/DW/External/XPostProtocol.pm
--- a/cgi-bin/DW/External/XPostProtocol.pm Mon Sep 20 22:09:58 2010 +0800
+++ b/cgi-bin/DW/External/XPostProtocol.pm Tue Sep 21 17:03:48 2010 +0800
@@ -164,4 +164,9 @@ sub supports_challenge {
return 0;
}
+# returns the options for this protocol
+sub protocol_options {
+ return ();
+}
+
1;
diff -r 65a29c20761c -r df531c62cb65
cgi-bin/DW/External/XPostProtocol/LJXMLRPC.pm
--- a/cgi-bin/DW/External/XPostProtocol/LJXMLRPC.pm Mon Sep 20 22:09:58
2010 +0800
+++ b/cgi-bin/DW/External/XPostProtocol/LJXMLRPC.pm Tue Sep 21 17:03:48
2010 +0800
@@ -292,6 +292,16 @@ sub entry_to_req {
}
}
+ # check minsecurity if set
+ if ( my $minsecurity = $extacct->options->{minsecurity} ) {
+ if ( $minsecurity eq "private" ) {
+ $req->{security} = "private";
+ } elsif ( ( $minsecurity eq "friends" ) && ( $req->{security} eq
"public" ) ) {
+ $req->{security} = 'usemask';
+ $req->{allowmask} = 1;
+ }
+ }
+
# set the date.
my $eventtime = $entry->eventtime_mysql;
$eventtime =~ /^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d)/;
@@ -572,4 +582,25 @@ sub supports_challenge {
return 1;
}
+# returns the options for this protocol
+sub protocol_options {
+ my ( $self, $extacct, $POST ) = @_;
+ my $option = {
+ type => 'select',
+ description => BML::ml( '.protocol.ljxmlrpc.minsecurity.desc' ),
+ opts => {
+ id => 'minsecurity',
+ name => 'minsecurity',
+ selected => $POST ? $POST->{minsecurity} : ( $extacct &&
$extacct->options && $extacct->options->{minsecurity} ) ?
$extacct->options->{minsecurity} : 'public',
+ },
+ options => [
+ 'public', BML::ml( '.protocol.ljxmlrpc.minsecurity.public' ),
+ 'friends', BML::ml( '.protocol.ljxmlrpc.minsecurity.friends' ),
+ 'private', BML::ml( '.protocol.ljxmlrpc.minsecurity.private' ),
+ ],
+ };
+ my @return_value = ( $option );
+ return @return_value;
+}
+
1;
diff -r 65a29c20761c -r df531c62cb65 htdocs/js/externalaccount.js
--- a/htdocs/js/externalaccount.js Mon Sep 20 22:09:58 2010 +0800
+++ b/htdocs/js/externalaccount.js Tue Sep 21 17:03:48 2010 +0800
@@ -1,4 +1,9 @@
+// the siteProtocol (if edit), or the map of sites to protocols (if new)
+var siteProtocol = null;
+var siteProtocolMap = {};
+// callback for updating the site selection. if selecting 'custom site',
+// shows the customsitetable. also calls to updateProtocolSelection().
function updateSiteSelection() {
var siteSelect = document.getElementById("createacct");
if (siteSelect != null && siteSelect.site != null) {
@@ -9,5 +14,42 @@ function updateSiteSelection() {
customsitetable.style.display='none';
}
}
+ updateProtocolSelection();
}
+// returns the currently selected protocol. if we're editing an account,
+// uses the preset siteProtocol. otherwise checks the siteProtocolMap (if a
+// configured site is selected) or the selected servicetype (if a custom site
+// is selected)
+function getProtocol() {
+ if (siteProtocol != null)
+ return siteProtocool;
+
+ var siteSelect = document.getElementById("createacct");
+ if (siteSelect != null && siteSelect.site != null) {
+ var customsitetable = document.getElementById('customsite');
+ if (siteSelect.site.value == -1) {
+ return $('servicetype').value;
+ } else {
+ return siteProtocolMap[siteSelect.site.value];
+ }
+ }
+}
+
+// updates the protocol selection. shows/hides the appropriate options rows.
+function updateProtocolSelection() {
+ var protocol = getProtocol();
+ var optionBodies = DOM.getElementsByTagAndClassName(document, "tbody",
"protocol_options") || [];
+ for (var i = 0; i < optionBodies.length; i++) {
+ var optionBody = optionBodies[i];
+ if ( optionBody.id != protocol + '_options' ) {
+ optionBody.style.display='none';
+ } else {
+ optionBody.style.display='';
+ }
+ }
+
+}
+
+LiveJournal.register_hook("page_load", updateProtocolSelection);
+
diff -r 65a29c20761c -r df531c62cb65 htdocs/manage/externalaccount.bml
--- a/htdocs/manage/externalaccount.bml Mon Sep 20 22:09:58 2010 +0800
+++ b/htdocs/manage/externalaccount.bml Tue Sep 21 17:03:48 2010 +0800
@@ -77,28 +77,37 @@ use strict;
$body .= LJ::html_hidden('acctid', $editacct->acctid);
}
- my @sitevalues;
- my @sites = DW::External::Site->get_xpost_sites;
-
- foreach my $site (sort { $a->{sitename} cmp $b->{sitename} } @sites) {
- push @sitevalues, $site->{siteid}, $site->{sitename};
- }
- # add custom
- push @sitevalues, '-1';
- push @sitevalues, $ML{'.setting.xpost.option.site.custom'};
+ $body .= "<br />";
my %protocols = DW::External::XPostProtocol->get_all_protocols;
- my %protocolselectmap;
- foreach my $protocol (keys %protocols) {
- $protocolselectmap{$protocol} = $protocol;
- }
-
- $body .= "<br />";
$body .= "<tr><td class='setting_label'><label for='site'>" .
$ML{'.setting.xpost.option.site'} . "</label></td>";
if ($editpage) {
$body .= "<td>" . $editacct->servername . "</td>\n";
+ $body .= "<script type='text/javascript'>\n siteProtocol = '" .
$editacct->protocol->protocolid . "';\n</script>\n";
} else {
+ my @sitevalues;
+ my @sites = DW::External::Site->get_xpost_sites;
+
+ # sort the sites for the site dropdown, but also add in the protocol
+ # map for the options hide/show
+ $body .= "<script type='text/javascript'>\n";
+ foreach my $site (sort { $a->{sitename} cmp $b->{sitename} } @sites) {
+ push @sitevalues, $site->{siteid}, $site->{sitename};
+ $body .= "siteProtocolMap[" . $site->{siteid} . "] = '" .
$site->servicetype . "';\n";
+ }
+ $body .= "</script>\n";
+
+ # add the custom site option
+ push @sitevalues, '-1';
+ push @sitevalues, $ML{'.setting.xpost.option.site.custom'};
+
+ # the values for the protocol selection dropdown for custom sites
+ my %protocolselectmap;
+ foreach my $protocol (keys %protocols) {
+ $protocolselectmap{$protocol} = $protocol;
+ }
+
$body .= "<td>" . LJ::html_select({
name => "site",
onchange => "updateSiteSelection()",
@@ -110,7 +119,7 @@ use strict;
$body .= "<td>" . LJ::html_select({
name => "servicetype",
id => "servicetype",
- onchange => "updateProtocolSelection" }, %protocolselectmap);
+ onchange => "updateProtocolSelection()" }, %protocolselectmap);
my $servicetype_errdiv = errdiv(\%errs, "servicetype");
$body .= "<br />$servicetype_errdiv" if $servicetype_errdiv;
@@ -233,6 +242,22 @@ use strict;
$body .= "<br />$savepassword_errdiv" if $savepassword_errdiv;
$body .= "</td></tr>\n";
+ # put in the protocol option section for each protocol
+ foreach my $protocol_id ( keys %protocols ) {
+ my $protocol = $protocols{$protocol_id};
+ my @protocol_options = $protocol->protocol_options( $editacct,
LJ::did_post() ? \%POST : undef );
+ if ( @protocol_options ) {
+ $body .= "<tbody class='protocol_options' id='" . $protocol_id .
"_options'><tr><td>" . BML::ml( '.protocol.options', { protocol =>
$protocol->protocolid } ) . "</td>\n";
+ $body .="<td>";
+ foreach my $option ( @protocol_options ) {
+ if ( $option->{type} eq 'select' ) {
+ $body .= "<label for=" . $option->{opts}->{propid} . ">" .
LJ::ehtml( $option->{description} ) . "</label>" . LJ::html_select(
$option->{opts}, @{$option->{options}} ) . "</td>\n";
+ }
+ }
+ }
+ $body .= "</td></tr></tbody>\n";
+ }
+
$body .= "<tr><td>";
$body .= "<br />";
$body .= LJ::html_submit(undef, $editpage ? $ML{'.btn.update'} :
$ML{'.btn.create'});
@@ -338,7 +363,19 @@ sub create_external_account {
}
}
- if ($ok) {
+ if ( $ok ) {
+ # check the options, if any.
+ my $protocol;
+ if ( $opts{siteid} ) {
+ my $site = DW::External::Site->get_site_by_id( $opts{siteid} );
+ $protocol = DW::External::XPostProtocol->get_protocol(
$site->servicetype );
+ } else {
+ $protocol = DW::External::XPostProtocol->get_protocol(
$opts{servicetype} );
+ }
+ my $options = parse_options( $protocol, $POST );
+
+ $opts{options} = $options;
+
# if the user requested that we don't save their password, then
# don't save their password.
$opts{password} = "" unless $opts{savepassword};
@@ -367,7 +404,7 @@ sub account_isvalid {
my $siteid = $extacct->{site};
my $externalsite = DW::External::Site->get_site_by_id( $siteid );
$proxyurl = "http://" . $externalsite->{domain} . "/interface/xmlrpc";
- $protocol_id = $externalsite->{servicetype};
+ $protocol_id = $externalsite->servicetype;
} else {
$proxyurl = $extacct->{serviceurl};
$protocol_id = $extacct->{servicetype};
@@ -408,7 +445,23 @@ sub edit_external_account {
$acct->set_xpostbydefault($POST{xpostbydefault});
$acct->set_recordlink($POST{recordlink});
+ $acct->set_options( parse_options( $acct->protocol, $POST ) );
+
return "&update=" . $acct->acctid;
+}
+
+# returns the appropriate options from the post.
+sub parse_options {
+ my ( $protocol, $POST ) = @_;
+ my $options = {};
+ foreach my $option ( $protocol->protocol_options ) {
+ my $option_name = $option->{opts}->{name};
+ my $value = $POST{$option_name};
+ if ( $value ) {
+ $options->{$option_name} = $value;
+ }
+ }
+ return $options;
}
_code?>
diff -r 65a29c20761c -r df531c62cb65 htdocs/manage/externalaccount.bml.text
--- a/htdocs/manage/externalaccount.bml.text Mon Sep 20 22:09:58 2010 +0800
+++ b/htdocs/manage/externalaccount.bml.text Tue Sep 21 17:03:48 2010 +0800
@@ -7,6 +7,16 @@
.error.maxacct.plural=You are already at your limit of [[max_accts]] accounts.
.error.maxacct.singular=You are already at your limit of [[max_accts]] account.
+
+.protocol.ljxmlrpc.minsecurity.desc=Minimum Security
+
+.protocol.ljxmlrpc.minsecurity.friends=Friends
+
+.protocol.ljxmlrpc.minsecurity.private=Private
+
+.protocol.ljxmlrpc.minsecurity.public=Public
+
+.protocol.options=[[protocol]] options
.settings.xpost.error.ipban=Too many log-in attempts. Please try creating the
account again later.
_______________________________________________
dw-changelog mailing list
[email protected]
http://lists.dwscoalition.org/mailman/listinfo/dw-changelog