Commit 0a533f48 authored by IKEDA Soji's avatar IKEDA Soji
Browse files

WWSympa: new request handler move_list (formerly copy_list and rename_list) to...

WWSympa: new request handler move_list (formerly copy_list and rename_list) to be integrated to Sympa::Request framework.
parent 8e7a2c78
......@@ -122,6 +122,21 @@
<p><strong>
[%|loc(shared_doc.name)%]Do you really want to delete %1?[%END%]
</strong></p>
[%~ ELSIF confirm_action == 'move_list' ~%]
<h2><i class="fa fa-check-circle"></i>
[% IF mode == 'copy' ~%]
[%|loc%]Copy List[%END%]
[%~ ELSE ~%]
[%|loc%]Rename List[%END%]
[%~ END %]
</h2>
<p><strong>
[% IF mode == 'copy' ~%]
[%|loc%]Do you really want to copy this list?[%END%]
[%~ ELSE ~%]
[%|loc%]Do you really want to rename this list?[%END%]
[%~ END %]
</strong></p>
[%~ ELSIF confirm_action == 'move_user' ~%]
<h2><i class="fa fa-check-circle"></i>
[%|loc%]Changing user's email[%END%]
......@@ -162,13 +177,6 @@
<p><strong>
[%|loc(template_name)%]Do you really want to remove %1?[%END%]
</strong></p>
[%~ ELSIF confirm_action == 'rename_list' ~%]
<h2><i class="fa fa-check-circle"></i>
[%|loc%]Rename List[%END%]
</h2>
<p><strong>
[%|loc%]Do you really want to rename this list?[%END%]
</strong></p>
[%~ ELSIF confirm_action == 'restore_list' ~%]
<h2><i class="fa fa-check-circle"></i>
[%|loc%]Restore List[%END%]
......@@ -287,6 +295,10 @@
[%|loc(email)%]To this end we will send you an email to this address: %1 with a validation link.[%END%]
[%|loc%]Please check your mailbox now.[%END%]
</div>
[%~ ELSIF confirm_action == 'move_list' ~%]
<input type="hidden" name="new_listname" value="[% new_listname %]" />
<input type="hidden" name="new_robot" value="[% new_robot %]" />
<input type="hidden" name="mode" value="[% mode %]" />
[%~ ELSIF confirm_action == 'remove_arc' ~%]
<input type="hidden" name="yyyy" value="[% yyyy %]" />
<input type="hidden" name="month" value="[% month %]" />
......@@ -298,9 +310,6 @@
<input type="hidden" name="scope" value="[% scope %]" />
<input type="hidden" name="template_name" value="[% template_name %]" />
<input type="hidden" name="tpl_lang" value="[% tpl_lang %]" />
[%~ ELSIF confirm_action == 'rename_list' ~%]
<input type="hidden" name="new_listname" value="[% new_listname %]" />
<input type="hidden" name="new_robot" value="[% new_robot %]" />
[%~ ELSIF confirm_action == 'rt_delete' ~%]
<input type="hidden" name="message_template"
value="[% message_template %]" />
......
......@@ -261,7 +261,7 @@ our %comm = (
'viewbounce' => 'do_viewbounce',
'redirect' => 'do_redirect',
'rename_list_request' => 'do_rename_list_request',
'rename_list' => 'do_rename_list',
'move_list' => 'do_move_list',
'copy_list' => 'do_copy_list',
'reviewbouncing' => 'do_reviewbouncing',
'resetbounce' => 'do_resetbounce',
......@@ -349,6 +349,7 @@ my %comm_aliases = (
'ignoresig' => 'decl_del',
'ignoresub' => 'decl_add',
'del_fromsig' => 'auth_del',
'rename_list' => 'move_list',
'sigrequest' => 'signoff',
'subrequest' => 'subscribe',
);
......@@ -467,7 +468,7 @@ our %action_args = (
'attach' => ['list', 'dir', 'file'],
'stats' => ['list'],
'edit_list_request' => ['list', 'group'],
'rename_list' => ['list', 'new_listname', 'new_robot'],
'move_list' => ['list', 'new_listname', 'new_robot'],
'copy_list' => ['list', 'new_listname', 'new_robot'],
'redirect' => [],
'viewlogs' => ['list', 'page', 'size', 'sortby'],
......@@ -603,7 +604,7 @@ our %required_args = (
'remind' => ['param.list', 'param.user.email'],
'remove_arc' => ['param.list'],
'remove_template' => ['webormail'],
'rename_list' =>
'move_list' =>
['param.user.email', 'param.list', 'new_listname', 'new_robot'],
'copy_list' =>
['param.user.email', 'param.list', 'new_listname', 'new_robot'],
......@@ -701,7 +702,7 @@ our %required_privileges = (
'rebuildarc' => ['listmaster'],
'reject' => ['editor', 'owner', 'listmaster'],
'remove_template' => ['listmaster'],
'rename_list' => ['privileged_owner'],
'move_list' => ['privileged_owner'],
'copy_list' => ['owner', 'listmaster'],
'rename_list_request' => ['privileged_owner'],
'resetbounce' => ['owner', 'editor'],
......@@ -767,7 +768,7 @@ my %action_type = (
'stats' => 'admin',
'decl_del' => 'admin',
'decl_add' => 'admin',
'rename_list' => 'admin',
'move_list' => 'admin',
'copy_list' => 'admin',
'rename_list_request' => 'admin',
'arc_manage' => 'admin',
......@@ -11189,174 +11190,85 @@ sub do_rename_list_request {
return '1';
}
 
# Compat. <= 6.2.20
sub do_copy_list {
wwslog('info', '(%s, %s)', $in{'new_listname'}, $in{'new_robot'});
my $success = do_rename_list('copy');
if ($success == 1) {
web_db_stat_log(
list => $in{'new_listname'},
operation => 'copy_list',
);
return $success;
}
return undef;
$in{'mode'} = 'copy';
goto &do_move_list; # "&" is required.
}
 
# in order to rename a list you must be list owner and you must be allowed to
# create new list
sub do_rename_list {
# In order to rename a list you must be list owner and you must be allowed to
# create new list.
sub do_move_list {
wwslog('info', '(%s, %s, mode=%s)',
$in{'new_listname'}, $in{'new_robot'}, @_);
my $mode = shift;
$in{'new_listname'}, $in{'new_robot'}, $in{'mode'});
 
if ($in{'new_listname'} =~ /[A-Z]/) {
$in{'new_listname'} = lc($in{'new_listname'});
Sympa::Report::notice_report_web('listname_lowercased', {},
$param->{'action'});
unless ($in{'new_robot'} and Conf::valid_robot($in{'new_robot'})) {
wwslog('err', 'Unknown robot %s', $robot);
Sympa::Report::reject_report_web('user', 'unknown_robot',
{new_robot => $in{'new_robot'}}, $param->{action});
return undef;
}
$param->{'new_listname'} = $in{'new_listname'};
$param->{'new_robot'} = $in{'new_robot'};
$param->{'mode'} = $in{'mode'};
 
unless ($mode and $mode eq 'copy') {
# Don't rename the list included in other list.
if ($list->is_included) {
Sympa::Report::reject_report_web('user', 'cannot_rename_list',
{reason => 'included'},
$param->{'action'}, $list);
wwslog('Cannot rename list %s: Included by other list', $list);
web_db_log(
{ 'status' => 'error',
'error_type' => 'cannot_rename_list',
}
);
return undef;
}
# Action confirmed?
my $next_action = $session->confirm_action(
$in{'action'}, $in{'response_action'},
arg => $in{'new_listname'} . '@' . $in{'new_robot'},
previous_action => ($in{'previous_action'} || 'admin')
);
return $next_action unless $next_action eq '1';
 
# Action confirmed?
my $next_action = $session->confirm_action(
$in{'action'}, $in{'response_action'},
arg => $in{'new_listname'} . '@' . $in{'new_robot'},
previous_action => ($in{'previous_action'} || 'admin')
);
return $next_action unless $next_action eq '1';
}
my $spindle = Sympa::Spindle::ProcessRequest(
context => $in{'new_robot'},
action => 'move_list',
listname => $in{'new_listname'},
current_list => $list,
mode => $in{'mode'},
sender => $param->{'user'}{'email'},
( $param->{'user'}{'email'}
? (md5_check => 1)
: ()
),
 
my $result = Sympa::Admin::rename_list(
list => $list,
new_listname => $in{'new_listname'},
new_robot => $in{'new_robot'},
mode => $mode,
auth_method => $param->{'auth_method'},
user_email => $param->{'user'}{'email'},
remote_host => $param->{'remote_host'},
remote_addr => $param->{'remote_addr'},
aliases => $param->{'aliases'},
status => $param->{'status'},
scenario_context => {
sender => $param->{'user'}{'email'},
remote_host => $param->{'remote_host'},
remote_addr => $param->{'remote_addr'},
},
);
 
if ($result eq 'incorrect_listname') {
Sympa::Report::reject_report_web('user', 'incorrect_listname',
{'bad_listname' => $in{'new_listname'}},
$param->{'action'}, $list);
wwslog('info', 'Incorrect listname %s', $in{'new_listname'});
web_db_log(
{ 'parameters' => "$in{'new_listname'},$in{'new_robot'}",
'status' => 'error',
'error_type' => 'incorrect_listname'
}
);
unless ($spindle and $spindle->spin) {
return 'rename_list_request';
}
 
} elsif ($result eq 'authorization') {
Sympa::Report::reject_report_web('auth', 'authorization', {},
$param->{'action'}, $list);
wwslog('info', 'Not owner');
web_db_log(
{ 'parameters' => "$in{'new_listname'},$in{'new_robot'}",
'status' => 'error',
'error_type' => 'authorization'
}
);
return undef;
} elsif ($result eq 'internal') {
Sympa::Report::reject_report_web(
'intern',
'unable_to_rename_list',
{'new_listname' => $in{'new_listname'}},
$param->{'action'},
$list,
$param->{'user'}{'email'},
$robot
);
wwslog('err', 'Can\'t rename list %s to %s@%s',
$list, $in{'new_listname'}, $in{'new_robot'});
web_db_log(
{ 'parameters' => "$in{'new_listname'},$in{'new_robot'}",
'status' => 'error',
'error_type' => 'internal'
}
);
return undef;
} elsif ($result eq 'list_already_exists') {
Sympa::Report::reject_report_web('user', 'list_already_exists',
{'new_listname' => $in{'new_listname'}},
$param->{'action'}, $list);
wwslog(
'info',
'Could not rename list %s for %s: new list %s already existing list',
$in{'listname'},
$param->{'user'}{'email'},
$in{'new_listname'}
);
web_db_log(
{ 'parameters' => "$in{'new_listname'},$in{'new_robot'}",
'status' => 'error',
'error_type' => 'list_already_exists'
}
);
return undef;
foreach my $report (@{$spindle->{stash} || []}) {
if ($report->[1] eq 'notice') {
Sympa::Report::notice_report_web(@{$report}[2, 3],
$param->{'action'});
} else {
Sympa::Report::reject_report_web(@{$report}[1 .. 3],
$param->{action});
}
}
unless (@{$spindle->{stash} || []}) {
Sympa::Report::notice_report_web('performed', {}, $param->{'action'});
}
 
} elsif ($result eq 'incorrect_listname') {
Sympa::Report::reject_report_web('user', 'listname_matches_aliases',
{'new_listname' => $in{'new_listname'}},
$param->{'action'}, $list);
wwslog('info', 'Incorrect listname %s', $in{'new_listname'});
web_db_log(
{ 'parameters' => "$in{'new_listname'},$in{'new_robot'}",
'status' => 'error',
'error_type' => 'incorrect_listname'
}
);
if (grep { $_->[1] ne 'notice' } @{$spindle->{stash} || []}) {
return 'rename_list_request';
} elsif ($result eq 'unknown_robot') {
wwslog('info', 'Unknown robot %s', $in{'new_robot'});
Sympa::Report::reject_report_web('user', 'unknown_robot',
{'new_robot' => $in{'new_robot'}},
$param->{'action'}, $list);
web_db_log(
{ 'parameters' => "$in{'new_listname'},$in{'new_robot'}",
'status' => 'error',
'error_type' => 'unknown_robot'
}
);
return undef;
}
 
## Were aliases installed?
if ($param->{'aliases'} == 1) {
# Were aliases installed?
if (grep { $_->[1] eq 'notice' and $_->[2] eq 'auto_aliases' }
@{$spindle->{stash} || []}) {
$param->{'auto_aliases'} = 1;
} else {
$param->{'auto_aliases'} = 0;
}
 
# set list status to pending if creation list is moderated
if ($param->{'status'} eq 'pending') {
Sympa::Report::notice_report_web('pending_list', {},
$param->{'action'}, $list);
}
my $new_list = Sympa::List->new($in{'new_listname'}, $in{'new_robot'});
if ($in{'new_robot'} eq $robot) {
$param->{'redirect_to'} = Sympa::get_url(
......@@ -11370,12 +11282,7 @@ sub do_rename_list {
}
 
$param->{'list'} = $in{'new_listname'};
web_db_log(
{ 'parameters' => "$in{'new_listname'},$in{'new_robot'}",
'status' => 'success'
}
);
$list->save_config($param->{'user'}{'email'});
return 1;
}
 
......
......@@ -99,6 +99,7 @@ nobase_modules_DATA = \
Sympa/Request/Handler/last.pm \
Sympa/Request/Handler/lists.pm \
Sympa/Request/Handler/modindex.pm \
Sympa/Request/Handler/move_list.pm \
Sympa/Request/Handler/move_user.pm \
Sympa/Request/Handler/reject.pm \
Sympa/Request/Handler/remind.pm \
......
......@@ -43,21 +43,17 @@ use strict;
use warnings;
use Encode qw();
use English qw(-no_match_vars);
use File::Copy qw();
use Sympa;
use Conf;
use Sympa::Constants;
use Sympa::DatabaseManager;
use Sympa::Language;
use Sympa::List;
use Sympa::LockedFile;
use Sympa::Log;
use Sympa::Regexps;
use Sympa::Robot;
use Sympa::Scenario;
use Sympa::Template;
use Sympa::Tools::File;
my $language = Sympa::Language->instance;
my $log = Sympa::Log->instance;
......@@ -728,517 +724,11 @@ sub update_list {
return $list;
}
########################################################
# rename_list
########################################################
# Rename a list or move a list to another virtual host
#
# IN : - list
# - new_listname
# - new_robot
# - mode : 'copy'
# - auth_method
# - user_email
# - remote_host
# - remote_addr
# - options : 'skip_authz' to skip authorization scenarios eval
#
# OUT via reference :
# - aliases
# - status : 'pending'
#
# OUT : - scalar
# undef : error
# 1 : success
# string : error code
#######################################################
sub rename_list {
my (%param) = @_;
$log->syslog('info', '',);
my $list = $param{'list'};
my $robot = $list->{'domain'};
my $old_listname = $list->{'name'};
# check new listname syntax
my $new_listname = lc($param{'new_listname'});
my $listname_regexp = Sympa::Regexps::listname();
unless ($new_listname =~ /^$listname_regexp$/i
and length $new_listname <= Sympa::Constants::LIST_LEN()) {
$log->syslog('err', 'Incorrect listname %s', $new_listname);
return 'incorrect_listname';
}
# If list is included by another list, then it cannot be renamed.
unless ($param{'mode'} and $param{'mode'} eq 'copy') {
if ($list->is_included) {
$log->syslog('err',
'List %s is included by other list: cannot rename it', $list);
return 'intern';
}
}
## Evaluate authorization scenario unless run as listmaster (sympa.pl)
my ($result, $r_action, $reason);
unless ($param{'options'}{'skip_authz'}) {
$result = Sympa::Scenario::request_action(
$param{'new_robot'},
'create_list',
$param{'auth_method'},
{ 'sender' => $param{'user_email'},
'remote_host' => $param{'remote_host'},
'remote_addr' => $param{'remote_addr'}
}
);
if (ref($result) eq 'HASH') {
$r_action = $result->{'action'};
$reason = $result->{'reason'};
}
unless ($r_action =~ /do_it|listmaster/) {
$log->syslog('err', 'Authorization error');
return 'authorization';
}
}
## Check listname on SMTP server
my $res = list_check_smtp($param{'new_listname'}, $param{'new_robot'});
unless (defined($res)) {
$log->syslog('err', 'Can\'t check list %.128s on %.128s',
$param{'new_listname'}, $param{'new_robot'});
return 'internal';
}
if ($res
|| ($list->{'name'} ne $param{'new_listname'})
&& ## Do not test if listname did not change
( Sympa::List->new(
$param{'new_listname'}, $param{'new_robot'},
{'just_try' => 1}
)
)
) {
$log->syslog(
'err',
'Could not rename list %s on %s: new list %s on %s already existing list',
$list->{'name'},
$robot,
$param{'new_listname'},
$param{'new_robot'}
);
return 'list_already_exists';
}
my $regx = Conf::get_robot_conf($param{'new_robot'}, 'list_check_regexp');
if ($regx) {
if ($param{'new_listname'} =~ /^(\S+)-($regx)$/) {
$log->syslog('err',
'Incorrect listname %s matches one of service aliases',
$param{'new_listname'});
return 'incorrect_listname';
}
}
unless ($param{'mode'} eq 'copy') {
$list->savestats();
## Dump subscribers
$list->_save_list_members_file(
"$list->{'dir'}/subscribers.closed.dump");
$param{'aliases'} = remove_aliases($list, $list->{'domain'});
}
## Rename or create this list directory itself
my $new_dir;
## Default robot
if (-d "$Conf::Conf{'home'}/$param{'new_robot'}") {
$new_dir =
$Conf::Conf{'home'} . '/'
. $param{'new_robot'} . '/'
. $param{'new_listname'};
} elsif ($param{'new_robot'} eq $Conf::Conf{'domain'}) {
$new_dir = $Conf::Conf{'home'} . '/' . $param{'new_listname'};
} else {
$log->syslog('err', 'Unknown robot %s', $param{'new_robot'});
return 'unknown_robot';
}
## If we are in 'copy' mode, create en new list
if ($param{'mode'} eq 'copy') {
unless (
$list = clone_list_as_empty(
$list->{'name'}, $list->{'domain'},
$param{'new_listname'}, $param{'new_robot'},
$param{'user_email'}
)
) {
$log->syslog('err', 'Unable to load %s while renaming',
$param{'new_listname'});
return 'internal';
}
}
# set list status to pending if creation list is moderated
if ($r_action =~ /listmaster/) {
$list->{'admin'}{'status'} = 'pending';
Sympa::send_notify_to_listmaster(
$list,
'request_list_renaming',
{ 'new_listname' => $param{'new_listname'},
'old_listname' => $old_listname,
'email' => $param{'user_email'},
'mode' => $param{'mode'}
}
);
$param{'status'} = 'pending';
}
## Save config file for the new() later to reload it
$list->save_config($param{'user_email'});
## This code should be in Sympa::List::rename()
unless ($param{'mode'} eq 'copy') {
unless (File::Copy::move($list->{'dir'}, $new_dir)) {
$log->syslog('err', 'Unable to rename %s to %s: %m',
$list->{'dir'}, $new_dir);
return 'internal';
}
## Rename archive
my $arc_dir =
Conf::get_robot_conf($robot, 'arc_path') . '/' . $list->get_id;
my $new_arc_dir =
Conf::get_robot_conf($param{'new_robot'}, 'arc_path') . '/'
. $param{'new_listname'} . '@'
. $param{'new_robot'};
if (-d $arc_dir && $arc_dir ne $new_arc_dir) {
unless (File::Copy::move($arc_dir, $new_arc_dir)) {
$log->syslog('err', 'Unable to rename archive %s', $arc_dir);
# continue even if there is some troubles with archives
# return undef;
}
}
## Rename bounces
my $bounce_dir = $list->get_bounce_dir();
my $new_bounce_dir =
Conf::get_robot_conf($param{'new_robot'}, 'bounce_path') . '/'
. $param{'new_listname'} . '@'
. $param{'new_robot'};
if (-d $bounce_dir && $bounce_dir ne $new_bounce_dir) {
unless (File::Copy::move($bounce_dir, $new_bounce_dir)) {
$log->syslog('err',
"Unable to rename bounces from $bounce_dir to $new_bounce_dir"
);
}
}
# if subscribtion are stored in database rewrite the database
Sympa::List::rename_list_db($list, $param{'new_listname'},
$param{'new_robot'});
}
my $sdm = Sympa::DatabaseManager->instance;
# Move stats
unless (
$sdm
and $sdm->do_prepared_query(
q{UPDATE stat_table
SET list_stat = ?, robot_stat = ?
WHERE list_stat = ? AND robot_stat = ?},
$param{'new_listname'}, $param{'new_robot'},
$list->{'name'}, $robot
)
) {
$log->syslog(
'err',
'Unable to transfer stats from list %s@%s to list %s@%s',
$param{'new_listname'},
$param{'new_robot'},
$list->{'name'},
$robot
);
}
# Move stat counters
unless (
$sdm->do_prepared_query(
q{UPDATE stat_counter_table
SET list_counter = ?, robot_counter = ?
WHERE list_counter = ? AND robot_counter = ?},
$param{'new_listname'}, $param{'new_robot'},
$list->{'name'}, $robot
)
) {
$log->syslog(
'err',
'Unable to transfer stat counter from list %s@%s to list %s@%s',