# Functions for managing resellers

# list_resellers()
# Returns a list of all reseller users. A reseller is a Webmin user with
# access to this module, and has the 'reseller' ACL option set
sub list_resellers
{
&require_acl();
local ($u, @rv);
foreach $u (&acl::list_users()) {
	if (&indexof($module_name, @{$u->{'modules'}}) >= 0) {
		local %acl = &get_reseller_acl($u->{'name'});
		if ($acl{'reseller'}) {
			local %gacl = &get_module_acl($u->{'name'}, "");
			$u->{'acl'} = \%acl;
			$u->{'acl'}->{'readonly'} = $gacl{'readonly'};
			push(@rv, $u);
			}
		}
	}
return @rv;
}

# get_reseller(name)
# Returns the hash for a reseller with a given name, or undef
sub get_reseller
{
local ($name) = @_;
&require_acl();
local @users = &acl::list_users();
local ($rv) = grep { $_->{'name'} eq $name } @users;
return undef if (!$rv || &indexof($module_name, @{$rv->{'modules'}}) < 0);
local %acl = &get_reseller_acl($name);
return undef if (!$acl{'reseller'});
$rv->{'acl'} = \%acl;
local %gacl = &get_module_acl($name, "");
$rv->{'acl'}->{'readonly'} = $gacl{'readonly'};
return $rv;
}

# create_reseller(&reseller)
# Create a new reseller account, by adding the Webmin user
sub create_reseller
{
local ($resel) = @_;
&require_acl();
if (!$resel->{'modules'}) {
	$resel->{'modules'} = [ $module_name,
			       split(/\s+/, $config{'reseller_modules'}) ];
	# Grant other core modules. This still refers to the old avail_
	# config variabes, but thats OK as they get populated from the
	# default template.
	foreach my $m (@reseller_modules) {
		my $am = $m eq "bind8" ? "dns" : $m;
		push(@{$resel->{'modules'}}, $m) if ($config{'avail_'.$am});
		}

	# Grant modules from plugins
	my @doms = &get_domain_by("reseller", $resel->{'name'});
	if (@doms) {
		foreach my $p (@plugins) {
			my @pmods = &plugin_call($p, "feature_webmin",
						 $doms[0], \@doms);
			foreach my $pm (@pmods) {
				next if (!$config{'avail_'.$pm->[0]});
				push(@{$resel->{'modules'}}, $pm->[0]);
				if ($pm->[1]) {
					&save_module_acl(
					  $pm->[1], $resel->{'name'}, $pm->[0]);
					}
				}
			}
		}
	}
if (!exists($resel->{'theme'})) {
	$resel->{'theme'} = $config{'reseller_theme'} eq "*" ?
				undef : $config{'reseller_theme'};
	}
$resel->{'desc'} = $resel->{'acl'}->{'desc'};
&acl::create_user($resel);
$resel->{'acl'}->{'reseller'} = 1;
$resel->{'acl'}->{'noconfig'} = 1;
$resel->{'acl'}->{'stop'} = 0;
$resel->{'acl'}->{'local'} = 0;
$resel->{'acl'}->{'import'} = 0;
&save_module_acl($resel->{'acl'}, $resel->{'name'}, $module_name);
local %gacl = &get_module_acl($resel->{'name'}, "");
$gacl{'readonly'} = $resel->{'acl'}->{'readonly'};
$gacl{'fileunix'} = 'nobody';
&save_module_acl(\%gacl, $resel->{'name'}, "");
&set_reseller_acl($resel);
&register_post_action(\&restart_webmin);
}

# delete_reseller(&reseller)
# Remove a reseller account, and dis-associate any domains from it
sub delete_reseller
{
&require_acl();
&acl::delete_user($_[0]->{'name'});
&register_post_action(\&restart_webmin);

# Disconnect domains
foreach my $d (&get_domain_by("reseller", $_[0]->{'name'})) {
	delete($d->{'reseller'});
	&save_domain($d);
	}

# Remove scheduled backups by the reseller
foreach my $sched (&list_scheduled_backups()) {
	if ($sched->{'owner'} eq $_[0]->{'name'}) {
		&delete_scheduled_backup($sched);
		}
	}

# Remove plans owned by reseller
foreach my $plan (&list_plans()) {
	if ($plan->{'owner'} eq $_[0]->{'name'}) {
		&delete_plan($plan);
		}
	}
}

# modify_reseller(&reseller, &old)
# Updates a reseller Webmin user, and possibly any associated domains
sub modify_reseller
{
local ($resel, $old) = @_;
&require_acl();

# Grant or take away modules
foreach my $m (@reseller_modules) {
	my $am = $m eq "bind8" ? "dns" : $m;
	if ($config{'avail_'.$am}) {
		@{$resel->{'modules'}} = &unique(@{$resel->{'modules'}}, $m);
		}
	else {
		@{$resel->{'modules'}} = grep { $_ ne $m } @{$resel->{'modules'}};
		}
	}

# Grant modules from plugins
@{$resel->{'modules'}} = grep { &indexof($_, @plugins) < 0 }
			      @{$resel->{'modules'}};
my @doms = &get_domain_by("reseller", $resel->{'name'});
if (@doms) {
	foreach my $p (@plugins) {
		my @pmods = &plugin_call($p, "feature_webmin",
					 $doms[0], \@doms);
		foreach my $pm (@pmods) {
			next if (!$config{'avail_'.$pm->[0]});
			push(@{$resel->{'modules'}}, $pm->[0]);
			if ($pm->[1]) {
				&save_module_acl(
				  $pm->[1], $resel->{'name'}, $pm->[0]);
				}
			}
		}
	}

# Save the reseller's webmin user and ACL
$resel->{'desc'} = $resel->{'acl'}->{'desc'};
&acl::modify_user($old->{'name'}, $resel);
&save_module_acl($resel->{'acl'}, $resel->{'name'}, $module_name);
local %gacl = &get_module_acl($resel->{'name'}, "");
$gacl{'readonly'} = $resel->{'acl'}->{'readonly'};
&save_module_acl(\%gacl, $resel->{'name'}, "");
&register_post_action(\&restart_webmin);

# Update any virtual servers that use the old reseller name
if ($resel->{'name'} ne $old->{'name'}) {
	foreach my $d (&get_domain_by("reseller", $old->{'name'})) {
		$d->{'reseller'} = $resel->{'name'};
		&save_domain($d);
		}
	}

# Update any plans owned by the reseller
if ($resel->{'name'} ne $old->{'name'}) {
	foreach my $plan (&list_plans()) {
		if ($plan->{'owner'} eq $old->{'name'}) {
			$plan->{'owner'} = $resel->{'name'};
			}
		local @prs = split(/\s+/, $plan->{'resellers'});
		local $idx = &indexof($old->{'name'}, @prs);
		if ($idx >= 0) {
			@prs[$idx] = $resel->{'name'};
			$plan->{'resellers'} = join(" ", @prs);
			}
		&save_plan($plan);
		}
	}

# Set Webmin ACL
&set_reseller_acl($resel);
}

# set_reseller_acl(&reseller)
# Sets the reseller's ACL in other Webmin modules
sub set_reseller_acl
{
local ($resel) = @_;
local @doms = &get_domain_by("reseller", $_[0]->{'name'});

# Grant access to logs for domain owners
if (&indexof("webminlog", @{$resel->{'modules'}}) >= 0) {
	local %acl = ( 'rollback' => 0 );
	local @wdoms = grep { $_->{'webmin'} && !$_->{'parent'} } @doms;
	local @users = &unique(map { $_->{'user'} } @wdoms);
	$acl{'users'} = join(" ", $_[0]->{'name'}, @users);
	&save_module_acl(\%acl, $_[0]->{'name'}, "webminlog");
	}

# Grant access to domains' mailboxes
if (&indexof("mailboxes", @{$resel->{'modules'}}) >= 0) {
	local %acl = ( 'noconfig' => 1,
		       'fmode' => 1,
		       'from' => join(" ", map { $_->{'dom'} }
					       grep { $_->{'mail'} } @doms),
		       'canattach' => 0,
		       'candetach' => 0,
		       'dir' => &mail_domain_base($doms[0]),
		       'mmode' => 5,
		       'musers' => join(" ", &unique(map { $_->{'gid'} } @doms))
		     );
	&save_module_acl(\%acl, $_[0]->{'name'}, "mailboxes");
	}

# Grant access to DNS domains
if (&indexof("bind8", @{$resel->{'modules'}}) >= 0) {
        local %acl = ( 'noconfig' => 1,
                       'zones' => join(" ", map { $_->{'dom'} }
                                             grep { $_->{'dns'} } @doms),
                       'dir' => &resolve_links($doms[0]->{'home'}),
                       'master' => 0,
                       'slave' => 0,
                       'forward' => 0,
                       'delegation' => 0,
                       'defaults' => 0,
                       'reverse' => 0,
                       'multiple' => 1,
                       'ro' => 0,
                       'apply' => 2,
                       'file' => 0,
                       'params' => 1,
                       'opts' => 0,
                       'delete' => 0,
                       'gen' => 1,
                       'whois' => 1,
                       'findfree' => 1,
                       'slaves' => 0,
                       'remote' => 0,
                       'views' => 0,
                       'vlist' => '' );
	&save_module_acl(\%acl, $_[0]->{'name'}, "bind8");
	}

# Grant access to syslog logs for owned domains
if (&indexof("syslog", @{$resel->{'modules'}}) >= 0) {
	local @extras;
	local %done;
	foreach my $sd (@doms) {
		# Add Apache logs, for domains with websites and separate logs
		if ($sd->{'web'} && !$sd->{'alias_mode'}) {
			local $alog = &get_website_log($sd, 0);
			local $elog = &get_website_log($sd, 1);
			push(@extras, $alog." ".&text('webmin_alog',
						      $sd->{'dom'}))
				if ($alog && !$done{$alog}++);
			push(@extras, $elog." ".&text('webmin_elog',
						      $sd->{'dom'}))
				if ($elog && !$done{$elog}++);
			}
		# Add FTP logs
		if ($sd->{'ftp'}) {
			local $flog = &get_proftpd_log($sd->{'ip'});
			push(@extras, $flog." ".&text('webmin_flog',
						     $sd->{'dom'}))
				if ($flog && !$done{$flog}++);
			}
		}
	local %acl = ( 'extras' => join("\t", @extras),
		       'any' => 0,
		       'noconfig' => 1,
		       'noedit' => 1,
		       'syslog' => 0,
		       'others' => 0 );
	&save_module_acl_logged(\%acl, $_[0]->{'name'}, "syslog");
	}
}

# modify_all_resellers([&domain])
# Updates the Webmin users for all resellers (or just those who own some domain)
sub modify_all_resellers
{
local ($d) = @_;
local @resels = &list_resellers();
if ($d) {
	@resels = grep { $_->{'name'} eq $d->{'reseller'} } @resels;
	}
return if (!@resels);
&$first_print($text{'check_allresel'});
	{
	local ($first_print, $second_print, $indent_print, $outdent_print);
	&set_all_null_print();
	foreach my $r (@resels) {
		&modify_reseller($r, $r);
		}
	}
&$second_print($text{'setup_done'});
}

# send_reseller_email(&reseller, plainpass)
# Sends email to a new reseller. Returns a pair containing a
# number (0=failed, 1=success) and an optional message.
sub send_reseller_email
{
local ($resel, $plainpass) = @_;

# Get the email
&ensure_template("reseller-template");
return (1, undef) if ($config{'reseller_template'} eq 'none');
local $tmpl = $config{'reseller_template'} eq 'default' ?
	"$module_config_directory/reseller-template" :
	$config{'reseller_template'};

# Create reseller details hash
local %hash = %$resel;
$hash{'plainpass'} = $plainpass;
$hash{'email'} = $resel->{'acl'}->{'email'};
$hash{'desc'} = $resel->{'acl'}->{'desc'};

# Send it
local $subject = $config{'newreseller_subject'};
local $cc = $config{'newreseller_cc'};
local $cc = $config{'newreseller_bcc'};
return (1, undef) if (!$resel->{'acl'}->{'email'} && !$cc);
local @erv = &send_template_email(&cat_file($tmpl), $resel->{'acl'}->{'email'},
			    	  \%hash, $subject, $cc, $bcc);
}

# sync_parent_resellers([reseller])
# Update all sub-servers and set their resellers to match their parent domains
sub sync_parent_resellers
{
local ($resel) = @_;
local @alldoms = &list_domains();
local $count = 0;
foreach my $d (grep { !$_->{'parent'} } @alldoms) {
	next if (!$d->{'reseller'});
	next if ($resel && $d->{'reseller'} ne $resel);
	foreach my $sd (grep { $_->{'parent'} eq $d->{'id'} } @alldoms) {
		if ($sd->{'reseller'} ne $d->{'reseller'}) {
			$sd->{'reseller'} = $d->{'reseller'};
			&save_domain($sd);
			$count++;
			}
		}
	}
return $count;
}

1;

