[dw-free] Implement renaming for communities
[commit: http://hg.dwscoalition.org/dw-free/rev/3467e0caff10]
http://bugs.dwscoalition.org/show_bug.cgi?id=2281
Community renames: communities may rename to personal journals under the
maintainer's control, or to unregistered usernames.
Patch by
fu.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=2281
Community renames: communities may rename to personal journals under the
maintainer's control, or to unregistered usernames.
Patch by
Files modified:
- bin/upgrading/en.dat
- cgi-bin/DW/Controller/Rename.pm
- cgi-bin/DW/User/Rename.pm
- cgi-bin/weblib.pl
- htdocs/shop/renames.bml.text
- t/rename.t
- views/rename.tt
- views/rename.tt.text
--------------------------------------------------------------------------------
diff -r 4954905b7319 -r 3467e0caff10 bin/upgrading/en.dat
--- a/bin/upgrading/en.dat Fri Aug 20 14:25:23 2010 +0800
+++ b/bin/upgrading/en.dat Fri Aug 20 18:22:13 2010 +0800
@@ -2433,6 +2433,8 @@ protocol.readonly=Your account is tempor
rename.error.invalidaccounttype=Only personal journals can own rename tokens.
+rename.error.invalidjournaltypeto=This username is in use and is not a personal journal; only personal journals may be renamed to.
+
rename.error.invalidfrom=Tried to rename an invalid journal.
rename.error.invalidstatusfrom=Cannot rename [[from]]: must be an active journal, not deleted or suspended.
diff -r 4954905b7319 -r 3467e0caff10 cgi-bin/DW/Controller/Rename.pm
--- a/cgi-bin/DW/Controller/Rename.pm Fri Aug 20 14:25:23 2010 +0800
+++ b/cgi-bin/DW/Controller/Rename.pm Fri Aug 20 18:22:13 2010 +0800
@@ -47,6 +47,9 @@ sub rename_handler {
my $post_args = DW::Request->get->post_args || {};
my $get_args = DW::Request->get->get_args || {};
+ $get_args->{type} ||= "P";
+ $get_args->{type} = "P" unless $get_args->{type} =~ m/^(P|C)$/;
+
if ( $r->method eq "POST" ) {
# this is kind of ugly. Basically, it's a rendered template if it's a success, and a list of errors if it failed
@@ -74,15 +77,31 @@ sub rename_handler {
} else {
$vars->{token} = $token;
+ # not using the regular authas logic because we want to exclude the current username
+ my $authas = LJ::make_authas_select( $remote,
+ { selectonly => 1,
+ type => $get_args->{type},
+ authas => $post_args->{authas} || $get_args->{authas},
+ } );
+
+ $authas .= $remote->user if $get_args->{type} eq "P";
+
+ my @rel_types = $get_args->{type} eq "P"
+ ? qw( trusted_by watched_by trusted watched communities )
+ : ();
+
# initialize the form based on previous posts (in case of error) or with some default values
$vars->{form} = {
- from => $remote->user,
- journalurl => $remote->journal_base,
+ authas => $authas,
+ journaltype => $get_args->{type},
+ journalurl => $get_args->{type} eq "P" ? $remote->journal_base : LJ::journal_base( "communityname", "community" ),
+ pageurl => "/rename/" . $token->token,
token => $token->token,
to => $post_args->{touser} || $get_args->{to} || "",
redirect => $post_args->{redirect} || "disconnect",
+ rel_types => \@rel_types,
rel_options => %$post_args ? { map { $_ => 1 } $post_args->get( "rel_options" ) }
- : { map { $_ => 1 } qw( trusted_by watched_by trusted watched communities ) },
+ : { map { $_ => 1 } @rel_types },
others => %$post_args ? { map { $_ => 1 } $post_args->get( "others" ) }
: { email => 0 },
};
@@ -102,13 +121,12 @@ sub handle_post {
sub handle_post {
my ( $token, $post_args ) = @_;
- # FIXME: replace with official tt-implementation
return ( 0, [ LJ::Lang::ml( '/rename.tt.error.invalidform' ) ] ) unless LJ::check_form_auth( $post_args->{lj_form_auth} );
my $errref = [];
# the journal we are going to rename; yourself or (eventually) a community you maintain
- my $journal = LJ::get_remote();
+ my $journal = LJ::get_authas_user( $post_args->{authas} );
push @$errref, LJ::Lang::ml( '/rename.tt.error.nojournal' ) unless $journal;
my $fromusername = $journal ? $journal->user : "";
@@ -136,7 +154,7 @@ sub handle_post {
}
# try the rename and see if there are any errors
- $journal->rename( $tousername, token => $token, redirect => $redirect_journal, redirect_email => $other_opts{email}, %del_rel, errref => $errref );
+ $journal->rename( $tousername, user => LJ::get_remote(), token => $token, redirect => $redirect_journal, redirect_email => $other_opts{email}, %del_rel, errref => $errref );
return ( 1, success_ml( "/rename.tt.success", { from => $fromusername, to => $journal->user } ) ) unless @$errref;
diff -r 4954905b7319 -r 3467e0caff10 cgi-bin/DW/User/Rename.pm
--- a/cgi-bin/DW/User/Rename.pm Fri Aug 20 14:25:23 2010 +0800
+++ b/cgi-bin/DW/User/Rename.pm Fri Aug 20 18:22:13 2010 +0800
@@ -99,22 +99,37 @@ sub can_rename_to {
return 0;
}
- # only personal accounts can be renamed
+ my $check_basics = sub {
+ my ( $fromu, $tou ) = @_;
+
+ # able to rename to unregistered accounts
+ return { ret => 1 } unless $tou;
+
+ # some journals can not be renamed to
+ if ( $tou->is_suspended || $tou->is_readonly || $tou->is_locked || $tou->is_memorial || $tou->is_renamed ) {
+ push @$errref, LJ::Lang::ml( 'rename.error.invalidstatusto', { to => $tou->ljuser_display } );
+ return { ret => 0 };
+ }
+
+ # expunged users can always be renamed to
+ return { ret => 1 } if $tou->is_expunged;
+
+ # communities cannot be renamed to
+ if ( ! $tou->is_personal ) {
+ push @$errref, LJ::Lang::ml( 'rename.error.invalidjournaltypeto' );
+ return { ret => 0 };
+ }
+ };
+
+ # only personal and community accounts can be renamed
if ( $self->is_personal ) {
# able to rename to unregistered accounts
my $tou = LJ::load_user( $tousername );
- return 1 unless $tou;
- # some journals can not be renamed to
- if ( $tou->is_suspended || $tou->is_readonly || $tou->is_locked || $tou->is_memorial || $tou->is_renamed ) {
- push @$errref, LJ::Lang::ml( 'rename.error.invalidstatusto', { to => $self->ljuser_display } );
- return 0;
- }
-
- # expunged users can always be renamed to
- return 1 if $tou->is_expunged;
-
+ # check basic stuff that is common for all types of renames
+ my $rv = $check_basics->( $self, $tou );
+ return $rv->{ret} if $rv;
# deleted and visible journals have extra safeguards:
# person-to-person
@@ -122,6 +137,21 @@ sub can_rename_to {
push @$errref, LJ::Lang::ml( 'rename.error.unauthorized', { to => $tou->ljuser_display } );
return 0;
+ } elsif ( $self->is_community && LJ::isu( $opts{user} ) ) {
+ my $admin = $opts{user};
+
+ # user must be able to control (be an admin of) community
+ return 0 unless $admin->can_manage_other( $self );
+
+ my $tou = LJ::load_user( $tousername );
+
+ # check basic stuff that is common for all renames
+ my $rv = $check_basics->( $self, $tou );
+ return $rv->{ret} if $rv;
+
+ # community-to-person
+ # able to rename to another personal journal under admin's control
+ return 1 if DW::User::Rename::_are_same_person( $admin, $tou );
}
# be strict in what we accept
@@ -147,8 +177,9 @@ sub rename {
my $errref = $opts{errref} || [];
+ my $remote = LJ::isu( $opts{user} ) ? $opts{user} : $self;
push @$errref, LJ::Lang::ml( 'rename.error.tokeninvalid' ) unless $opts{token} && $opts{token}->isa( "DW::RenameToken" )
- && $opts{token}->ownerid == $self->userid;
+ && $opts{token}->ownerid == $remote->userid;
push @$errref, LJ::Lang::ml( 'rename.error.tokenapplied' ) if $opts{token} && $opts{token}->applied;
my $can_rename_to = $self->can_rename_to( $tousername, %opts );
@@ -254,7 +285,16 @@ sub _rename {
$self->break_redirects;
DW::User::Rename->create_redirect_journal( $fromusername, $tousername ) if $opts{redirect};
- my $del = $self->delete_relationships( del_trusted_by => $opts{del_trusted_by}, del_watched_by => $opts{del_watched_by}, del_trusted => $opts{del_trusted}, del_watched => $opts{del_watched}, del_communities => $opts{del_communities} );
+
+ my $del = "";
+ if ( $self->is_personal ) {
+ $del = $self->delete_relationships(
+ del_trusted_by => $opts{del_trusted_by},
+ del_watched_by => $opts{del_watched_by},
+ del_trusted => $opts{del_trusted},
+ del_watched => $opts{del_watched},
+ del_communities => $opts{del_communities} );
+ }
# this deletes the email under the old username
DW::User::Rename->break_email_redirection( $fromusername, $tousername ) unless $opts{redirect} && $opts{redirect_email};
@@ -350,6 +390,8 @@ sub delete_relationships {
sub delete_relationships {
my ( $self, %opts ) = @_;
+ return unless $self->is_personal;
+
if ( $opts{del_trusted_by} ) {
foreach ( $self->trusted_by_users ) {
$_->remove_edge( $self, trust => {} );
diff -r 4954905b7319 -r 3467e0caff10 cgi-bin/weblib.pl
--- a/cgi-bin/weblib.pl Fri Aug 20 14:25:23 2010 +0800
+++ b/cgi-bin/weblib.pl Fri Aug 20 18:22:13 2010 +0800
@@ -191,15 +191,20 @@ sub make_authas_select {
# only do most of form if there are options to select from
if (@list > 1 || $list[0] ne $u->{'user'}) {
my $ret;
- my $label = $BML::ML{'web.authas.label'};
- $label = $BML::ML{'web.authas.label.comm'} if ($opts->{'type'} eq "C");
- $ret = ($opts->{'label'} || $label) . " ";
+ unless ( $opts->{selectonly} ) {
+ my $label = $BML::ML{'web.authas.label'};
+ $label = $BML::ML{'web.authas.label.comm'} if ($opts->{'type'} eq "C");
+ $ret = ($opts->{'label'} || $label) . " ";
+ }
+
$ret .= LJ::html_select({ 'name' => 'authas',
'selected' => $opts->{'authas'} || $u->{'user'},
'class' => 'hideable',
},
map { $_, $_ } @list) . " ";
- $ret .= LJ::html_submit(undef, $opts->{'button'} || $BML::ML{'web.authas.btn'});
+ $ret .= LJ::html_submit(undef, $opts->{'button'} || $BML::ML{'web.authas.btn'})
+ unless $opts->{selectonly};
+
return $ret;
}
diff -r 4954905b7319 -r 3467e0caff10 htdocs/shop/renames.bml.text
--- a/htdocs/shop/renames.bml.text Fri Aug 20 14:25:23 2010 +0800
+++ b/htdocs/shop/renames.bml.text Fri Aug 20 18:22:13 2010 +0800
@@ -12,9 +12,9 @@
.giftfor.username=Username to receive this rename token:
-.intro.gift=Buy a rename token for someone else to allow them to change their journal's username.
+.intro.gift=Buy a rename token for someone else to allow them to change their journal's username, or the username of a community they manage.
-.intro.self=Buy a rename token for your journal to change your username.
+.intro.self=Buy a rename token for your journal to change your username, or the username of a community you manage.
.action=Once your payment has gone through, the token will be listed on <a [[aopts]]>the rename page</a>.
diff -r 4954905b7319 -r 3467e0caff10 t/rename.t
--- a/t/rename.t Fri Aug 20 14:25:23 2010 +0800
+++ b/t/rename.t Fri Aug 20 18:22:13 2010 +0800
@@ -299,8 +299,7 @@ note( "-- username issues" );
}
note( "-- community-to-unregistered" );
-TODO: {
- local $TODO = "community to unregistered";
+{
my $admin = temp_user();
my $fromu = temp_comm();
my $tousername = $fromu->username . "_renameto";
@@ -315,8 +314,9 @@ TODO: {
ok( ! LJ::load_user( $tousername ), "Username '$tousername' is unregistered" );
ok( $fromu->can_rename_to( $tousername, user => $admin ), "Can rename to $tousername" );
- ok( $fromu->rename( $tousername, token => new_token( $fromu ), user => $admin ), "Renamed community to $tousername" );
+ ok( $fromu->rename( $tousername, token => new_token( $admin ), user => $admin ), "Renamed community to $tousername" );
+ LJ::update_user( $admin, { status => 'A' } );
ok( $admin->is_validated, "Admin was validated so could rename.");
LJ::update_user( $admin, { status => 'N' } );
ok( ! $admin->is_validated && ! $fromu->can_rename_to( $tousername . "_rename", user => $admin ), "Admin no longer validated; can no longer rename" );
@@ -351,13 +351,12 @@ TODO: {
ok( $admin->can_manage( $tou ), "User can manage community tou" );
ok( $fromu->can_rename_to( $tousername, user => $admin ), $admin->user . " can rename community fromu to existing community $tousername (is admin of both)" );
- ok( $fromu->rename( $tousername, token => new_token( $fromu ), user => $admin ), $admin->user . " renamed community fromu to existing community $tousername" );
+ ok( $fromu->rename( $tousername, token => new_token( $admin ), user => $admin ), $admin->user . " renamed community fromu to existing community $tousername" );
}
note( "-- community-to-personal" );
-TODO: {
- local $TODO = "community to personal";
- my ( $admin, $tou ) = $create_users->();
+{
+ my ( $admin, $tou ) = $create_users->( validated => 1 );
my $fromu = temp_comm();
my $tousername = $tou->user;
@@ -367,14 +366,14 @@ TODO: {
ok( ! $fromu->can_rename_to( $tousername, user => $admin ), "Cannot rename fromu to existing user $tousername (tou is a personal journal not under admin's control)" );
- ( $admin, $tou ) = $create_users->( match => 1 );
+ ( $admin, $tou ) = $create_users->( match => 1, validated => 1 );
$tousername = $tou->user;
# make admin of fromu
LJ::set_rel( $fromu, $admin, "A" );
delete $LJ::REQ_CACHE_REL{$fromu->userid."-".$admin->userid."-A"};
ok( $fromu->can_rename_to( $tousername, user => $admin ), $admin->user . " can rename community fromu to existing user $tousername (tou is a personal journal under admin's control)" );
- ok( $fromu->rename( $tousername, token => new_token( $fromu ), user => $admin ), $admin->user . " renamed community fromu to existing community $tousername" );
+ ok( $fromu->rename( $tousername, token => new_token( $admin ), user => $admin ), $admin->user . " renamed community fromu to existing community $tousername" );
}
note( "-- personal-to-community" );
diff -r 4954905b7319 -r 3467e0caff10 views/rename.tt
--- a/views/rename.tt Fri Aug 20 14:25:23 2010 +0800
+++ b/views/rename.tt Fri Aug 20 18:22:13 2010 +0800
@@ -34,31 +34,38 @@ the same terms as Perl itself. For a co
<label for="token">[%- '.form.rename.token.label' | ml -%]</label> [%- form.token | html -%]
</div>
<div class="formfield">
- <label>[%- '.form.rename.fromuser.label' | ml -%]</label> [% form.from | html %]
+ <label>[%- '.form.rename.fromuser.label' | ml -%]</label> [% form.authas %]
+ [% IF form.journaltype == "P" %]
+ <a href="[%- form.pageurl | url -%]?type=C">[%- '.form.switchtype.comm' | ml -%]</a>
+ [% ELSE %]
+ <a href="[%- form.pageurl | url -%]">[%- '.form.switchtype.journal' | ml -%]</a>
+ [% END %]
</div>
<div class="formfield">
<label for="touser">[%- '.form.rename.touser.label' | ml -%]</label><input type="text" id="touser" name="touser" value="[%- form.to | html -%]" />
</div>
<div class="formfield">
<fieldset>
- <legend>What do you want to do with your old username?</legend>
- <input type="radio" name="redirect" value="forward" id="redirect_forward" [% 'checked="checked"' IF form.redirect == "forward" %]/><label for="redirect_forward">[%- '.form.rename.forward.label' | ml %]</label>
- <p class='detail'>[%- '.form.rename.forward.note' | ml( journalurl = form.journalurl ) %]</p>
- <input type="radio" name="redirect" value="disconnect" id="redirect_disconnect" [% 'checked="checked"' IF form.redirect == 'disconnect' %]/><label for="redirect_disconnect">[%- '.form.rename.disconnect.label' | ml %]</label>
- <p class='detail'>[%- '.form.rename.disconnect.note' | ml( journalurl = form.journalurl ) %]</p>
+ <legend>[%- '.form.rename.oldusername.header.' _ form.journaltype | ml -%]</legend>
+ <input type="radio" name="redirect" value="forward" id="redirect_forward" [% 'checked="checked"' IF form.redirect == "forward" %]/><label for="redirect_forward">[%- '.form.rename.forward.label.' _ form.journaltype | ml %]</label>
+ <p class='detail'>[%- '.form.rename.forward.note.' _ form.journaltype | ml( journalurl = form.journalurl ) %]</p>
+ <input type="radio" name="redirect" value="disconnect" id="redirect_disconnect" [% 'checked="checked"' IF form.redirect == 'disconnect' %]/><label for="redirect_disconnect">[%- '.form.rename.disconnect.label.' _ form.journaltype | ml %]</label>
+ <p class='detail'>[%- '.form.rename.disconnect.note.' _ form.journaltype | ml( journalurl = form.journalurl ) %]</p>
</fieldset>
</div>
</fieldset>
+ [% IF form.rel_types.size > 0 %]
<fieldset class="relationships">
<legend>[% '.form.relationships.header' | ml %]</legend>
- [% FOREACH rel IN [ "watched_by", "trusted_by", "watched", "trusted", "communities" ] %]
+ [% FOREACH rel IN form.rel_types %]
<div class="formfield">
<input type="checkbox" name="rel_options" value="[% rel %]" id="rel_[% rel %]" [%- 'checked="checked"' IF form.rel_options.$rel -%] /><label for="rel_[% rel %]">[% ".form.relationships.$rel" | ml %]</label>
</div>
[% END %]
</fieldset>
+ [% END %]
<fieldset class="others">
<legend>[% '.form.others.header' | ml %]</legend>
@@ -105,14 +112,23 @@ the same terms as Perl itself. For a co
<p>[% '.token.list.header' | ml %]</p>
<ul>
[% FOREACH token = unused_tokens %]
- <li>[% token.token | html %] - <a href="/rename/[%- token.token | url %]
- [%- IF checkusername.user AND checkusername.status == 'available' ~%]
- ?to=[% checkusername.user | url ~%]
- ">[% '.token.list.item.withname' | ml( username = checkusername.user ) %]
- [%- ELSE ~%]
- ">[% '.token.list.item' | ml %]
- [% END ~%]
- </a></li>
+ <li>[% token.token | html %] - <a href="[%- dw.site | url %]/rename/[% token.token | url %]
+ [%~ IF checkusername.user AND checkusername.status == 'available' ~%]
+ ?to=[%~ checkusername.user | url ~%]
+ ">[%~ '.token.list.item.withname' | ml( username = checkusername.user ) ~%]
+ [%~ ELSE ~%]
+ ">[%~ '.token.list.item' | ml ~%]
+ [%~ END ~%]
+ </a>
+ <a href="[%- dw.site | url %]/rename/[% token.token | url %]?type=C
+ [%~ IF checkusername.user AND checkusername.status == 'available' ~%]
+ &to=[%~ checkusername.user | url ~%]
+ ">[%~ '.token.list.item.comm.withname' | ml( username = checkusername.user ) ~%]
+ [%~ ELSE ~%]
+ ">[%~ '.token.list.item.comm' | ml ~%]
+ [%~ END ~%]
+ </a>
+ </li>
[% END %]
</ul>
[% ELSE %]
diff -r 4954905b7319 -r 3467e0caff10 views/rename.tt.text
--- a/views/rename.tt.text Fri Aug 20 14:25:23 2010 +0800
+++ b/views/rename.tt.text Fri Aug 20 18:22:13 2010 +0800
@@ -44,19 +44,35 @@
.form.rename.header=Rename
-.form.rename.disconnect.label=Disconnect your old username from your new username, leaving the old username free to use
+.form.rename.disconnect.label.C=Disconnect the old username from the new username, leaving the old username free to use
-.form.rename.disconnect.note=[[journalurl]] will not point to your new username; comments and community entries that you posted will still show your new username.
+.form.rename.disconnect.label.P=Disconnect your old username from your new username, leaving the old username free to use
-.form.rename.forward.label=Forward your old username to your new username
+.form.rename.disconnect.note.C=[[journalurl]] will not point to the new username.
-.form.rename.forward.note=[[journalurl]] will automatically redirect to your new username.
+.form.rename.disconnect.note.P=[[journalurl]] will not point to your new username; comments and community entries that you posted will still show your new username.
+
+.form.rename.forward.label.C=Forward your community's old username to the new username
+
+.form.rename.forward.label.P=Forward your old username to your new username
+
+.form.rename.forward.note.C=[[journalurl]] will automatically redirect to your community's new username.
+
+.form.rename.forward.note.P=[[journalurl]] will automatically redirect to your new username.
.form.rename.fromuser.label=Rename from
+
+.form.rename.oldusername.header.C=What do you want to do with your community's old username?
+
+.form.rename.oldusername.header.P=What do you want to do with your old username?
.form.rename.token.label=Rename token
.form.rename.touser.label=Rename to
+
+.form.switchtype.comm=rename a community you own
+
+.form.switchtype.journal=rename your journal
.success=Successfully renamed journal from [[from]] to [[to]].
@@ -71,6 +87,10 @@
.token.list.item.withname=Use token to rename journal to [[username]]
+.token.list.item.comm= Use token to rename a community
+
+.token.list.item.comm.withname=Use token to rename a community to [[username]]
+
.token.notoken=<a [[aopts]]>Purchase a rename token</a> to perform a rename.
.token.used=Token has been used: [[token]]
--------------------------------------------------------------------------------
