#! /usr/bin/perl

=head1 NAME

quotas_others - quota settings for others than classes, projects or teachers

=head1 SYNOPSIS

 https://server/schulkonsole/quotas_others

=head1 DESCRIPTION

C<quotas_others> lets you edit the quotas of other users than classes,
projects or teachers, like students and system users.
The HTML template is quotas_others.tt.

=head2 Template variables

Additionally to the variables of Schulkonsole::Session C<quotas_others>
provides the following variables:

=over

=cut

use strict;
use utf8;
use lib '/usr/share/schulkonsole';
use Schulkonsole::Encode;
use Schulkonsole::Session;
use Schulkonsole::SophomorixConfig;
use Schulkonsole::SophomorixQuotas;
use Schulkonsole::Error::SophomorixError;

use Proc::ProcessTable;



my $this_file = 'quotas_others';




my $sk_session = new Schulkonsole::Session($this_file);
if (not $sk_session->get_password()) {
	my $q = new CGI;
	my $url = $q->url( -full => 1 );

	# we send cookies over secure connections only
	if ($url =~ s/^http:/https:/g) {
		$sk_session->redirect($url);
	} else {
		$sk_session->exit_with_login_page($this_file);
	}
}
if (not $Schulkonsole::SophomorixConfig::quotaactivated) {
	my $q = new CGI;
	my $url = $q->url( -full => 1 );

	$url =~ s/$this_file$/quotas/g;
	$sk_session->redirect($url);
}

my $q = $sk_session->query();

my $id = $sk_session->userdata('id');
my $password = $sk_session->get_password();



my @mountpoints = Schulkonsole::SophomorixQuotas::mountpoints();

my $process_table = new Proc::ProcessTable;
my $app_quota = $Schulkonsole::Config::_cmd_sophomorix_quota;
$app_quota =~ s:.*/::;
my %running;
foreach my $process (@{ $process_table->table }) {
	if ($process->fname =~ /^soph/ and $process->cmndline =~ /$app_quota/) {
			$running{quota} = $process->pid;
	}
}

eval {
COMMANDS: {
$q->param('acceptusers') and do {
	my $users = Schulkonsole::SophomorixQuotas::read_quota_conf();
	my %new_users;

	my $is_changed = 0;
	my @errors;
	my @processed_params;

	if (my $login = $q->param('newlogin')) {
		my $userdata = Schulkonsole::DB::get_userdata($login);
		if ($userdata) {
			if ($$userdata{gid} eq 'teachers') {
				$sk_session->set_status(sprintf($sk_session->d()->get(
					'%s ist ein Lehrer'), $login), 1);
				last COMMANDS;
			}
		} elsif (   not Schulkonsole::SophomorixQuotas::is_passwd_user($login)
		         or $login eq 'root') {
			$sk_session->set_status(sprintf($sk_session->d()->get(
				'Benutzer %s unbekannt'), $login), 1);
			last COMMANDS;
		} elsif ($$users{$login}) {
			$sk_session->set_status(sprintf($sk_session->d()->get(
					'Für Benutzer %s gibt es bereits einen Eintrag'),
					$login),
				1);
			last COMMANDS;
		}


		my %new_user;
		my $is_undefined = 0;
		foreach my $mountpoint (@mountpoints) {
			my $value = $q->param("$mountpoint-newdiskquota");
			if (length $value) {
				$new_user{diskquotas}{$mountpoint} = $value;
			} else {
				$is_undefined++;
			}
			push @processed_params, "$mountpoint-newdiskquota";
		}
		if (    $is_undefined
		    and $is_undefined != @mountpoints) {
			die new Schulkonsole::SophomorixError(Schulkonsole::Error::SophomorixError::QUOTA_NOT_ALL_MOUNTPOINTS)
		}
		my $mailquota = $q->param('newmailquota');
		push @processed_params, 'newmailquota';
		if (length $mailquota) {
			$new_user{mailquota} = $mailquota;
		} elsif ($is_undefined == @mountpoints) {
			$sk_session->set_status($sk_session->d()->get(
				'Tragen Sie mindestens Disk- oder Mailquota ein'), 1);
			last COMMANDS;
		}

		$is_changed++;
		$new_users{$login} = \%new_user;
		push @processed_params, 'newlogin';
	}



	foreach my $param ($q->param) {
		if (my ($login, $action) = $param =~ /^(.+)_user(.+-diskquota|mailquota)$/) {
			if ($$users{$login}) {
				my ($value) = $q->param($param) =~ /^\s*(.+?)\s*$/;
				if ($value !~ /^\d*$/) {
					push @errors, sprintf($sk_session->d()->get(
							'%s: Quota muss eine Zahl sein'), $login);
				} else {
					push @processed_params, $param;

					if ($action =~ /^m/) {	# mailquota
						if (   (    not defined $$users{$login}{mailquota}
						        and length($value))
						    or (    defined $$users{$login}{mailquota}
						        and (   not length($value)
						             or $$users{$login}{mailquota} != $value))) {

							$new_users{$login}{mailquota} =
								(length($value) ?
								   $value
								 : $Schulkonsole::SophomorixQuotas::mailquota_undefined);
							$is_changed++;
						}
					} else {	# diskquota
						my ($mountpoint) = $action =~ /^(.+?)-diskquota$/;
						if (   (    length($value)
						        and not $$users{$login}{diskquotas}{$mountpoint})
						    or $$users{$login}{diskquotas}{$mountpoint} ne $value) {
							$new_users{$login}{diskquotas} = $$users{$login}{diskquotas} unless $new_users{$login}{diskquotas};
							$new_users{$login}{diskquotas}{$mountpoint} = $value;
							$is_changed++;
						}
					}
				}
			} else {
				push @errors, sprintf($sk_session->d()->get(
					'Benutzer %s hat keine Sonderquota'), $login);
			}
		}
	}

	if (@errors) {
		$sk_session->set_status(join(', ', @errors), 1);
	} elsif ($is_changed) {
		my $quota_lines = Schulkonsole::SophomorixQuotas::new_quota_lines(\%new_users);
		my $mailquota_lines =Schulkonsole::SophomorixQuotas::new_mailquota_lines(\%new_users);

		Schulkonsole::SophomorixQuotas::write_quota_conf($id, $password, $quota_lines);
		Schulkonsole::SophomorixQuotas::write_mailquota_conf($id, $password, $mailquota_lines);


		Schulkonsole::SophomorixQuotas::process_quota($id, $password, 8);
		
		$running{quota} = 1;

		$sk_session->set_status($sk_session->d()->get(
			'Änderungen übernommen.'), 0);
		$q->delete(@processed_params);
	} else {
		$sk_session->set_status($sk_session->d()->get(
			'Keine Änderungen.'), 1);
	}


	last COMMANDS;
};	# end acceptusers

($q->param('logquota') or $running{quota}) and do {
	eval {
		my $logquota =
			Schulkonsole::SophomorixQuotas::read_quota_log_file($id, $password);

=item C<logquota>

Output of C<sophomorix-quota --set>

=cut

		splice @$logquota, 0, -30;
		$sk_session->set_var('logquota', join("", @$logquota));
	};
	if ($@) {
		$sk_session->set_status(
			$sk_session->d()->get('Kann Logdatei nicht öffnen'), 1);
	}
	last COMMANDS;
};


} # end COMMANDS
};
if ($@) {
	$sk_session->standard_error_handling($this_file, $@);
}






my $userquotas = Schulkonsole::SophomorixQuotas::read_quota_conf();
my $hosts = Schulkonsole::Config::hosts();
my @userquotas_array;
my @workstationquotas_array;
my @adminquotas_array;
my @systemquotas_array;
my $wwwquota;
foreach my $user (sort keys %$userquotas) {
	my @diskquotas;
	foreach my $mountpoint (@mountpoints) {
		push @diskquotas, {
				mountpoint => $mountpoint,
				quota => $$userquotas{$user}{diskquotas}{$mountpoint},
			};
	}
	my $userquota = {
		login => $user,
		diskquotas => \@diskquotas,
		mailquota => $$userquotas{$user}{mailquota},
	};
	if ($user eq 'www-data') {
		$wwwquota = $userquota;
	} elsif ($$hosts{$user}) {
		push @workstationquotas_array, $userquota;
	} else {
		my $userdata = Schulkonsole::DB::get_userdata($user);

		if ($userdata) {
			$$userquota{firstname} = $$userdata{firstname};
			$$userquota{surname} = $$userdata{surname};

			if ($$userdata{gidnumber} < 10000) {
				push @adminquotas_array, $userquota;
			} else {
				push @userquotas_array, $userquota;
			}
		} else {
			push @systemquotas_array, $userquota;
		}
	}
}

=item C<users>, C<workstations>, C<admins>, C<systems>

Quotas for students, workstation accounts, administrators and system
users respectively as an array of hashes with the keys

=over

=item C<login>

Login name of the user

=item C<diskquotas>

Disk quotas of the user as an array of hashes with the keys

=over

=item C<mountpoint>

A mountpoint

=item C<quota>

Quota for this mountpoint in MB

=back

=item C<mailquota>

Mail quota in MB

=back

Additionally for all but the workstation accounts these keys exist:

=over

=item C<firstname>

The user's first name

=item C<surname>

The user's surname

=back

=cut

$sk_session->set_var('users', \@userquotas_array);
$sk_session->set_var('workstations', \@workstationquotas_array);
$sk_session->set_var('admins', \@adminquotas_array);
$sk_session->set_var('systems', \@systemquotas_array);

=item C<www>

Quotas for WWW user as a hash with the keys

=over

=item C<login>

Login name of the WWW user

=item C<diskquotas>

Disk quotas of the user as an array of hashes with the keys

=over

=item C<mountpoint>

A mountpoint

=item C<quota>

Quota for this mountpoint in MB

=back

=item C<mailquota>

Mail quota in MB

=back

=cut

$sk_session->set_var('www', $wwwquota);


eval {
my $standard_quota = Schulkonsole::SophomorixQuotas::standard_quota('schueler');
my @standardquota_array;
foreach my $mountpoint (@mountpoints) {
	push @standardquota_array, {
			mountpoint => $mountpoint,
			diskquota => $$standard_quota{$mountpoint},
		};
}

=item C<standarddiskquotas>

standard disk quotas as an array of hashes with the keys

=over

=item C<mountpoint>

A mountpoint

=item C<quota>

Quota for this mountpoint in MB

=back

=cut

$sk_session->set_var("standarddiskquotas", \@standardquota_array);

=item C<standardmailquota>

standard mail quota in MB

=cut

$sk_session->set_var('standardmailquota',
	Schulkonsole::SophomorixQuotas::standard_mailquota('schueler'));
};
if ($@) {
	$sk_session->standard_error_handling($this_file, $@);
}


=item C<mountpoints>

An array with the mountpoints

=cut

$sk_session->set_var('mountpoints', \@mountpoints);

=item C<mountpoints_cnt>

The number of mountpoints

=cut

$sk_session->set_var('mountpoints_cnt', scalar(@mountpoints));

=item C<isbusy>

True if C<sophomorix-quota> is running

=cut

$sk_session->set_var('isbusy', ($running{quota}? 1 : 0));

$sk_session->print_page("$this_file.tt", $this_file);




=back

=head2 Form fields

=over

=item C<acceptusers>

Accept changes to form

=item C<newlogin>

Account name for new non-standard quota

=item C<${standarddiskquotas{mountpoint}}-newdiskquota>

Disk quota for mountpoint C<$standarddiskquotas{mountpoint}> for the new
account.
Created in loop over template variable C<standarddiskquotas>

=item C<newmailquota>

Mail quota for the new account.

=item C<${login}_user${diskquotas{mountpoint}}-diskquota>

Disk quota for an existing account C<$login> on the mountpoint
C<$diskquotas{mountpoint}>.
C<$login> and C<$diskquotas{mountpoint}> are from the template
variable C<www> or created in a loop over the template variables
C<admins>, C<users>, C<workstations>, or C<systems>

=item C<${login}_usermailquota>

Mail quota for an existing account C<$login>.
C<$login> and is the template variable C<www{login}> or created in a loop
over the template variables C<admins>, C<users>, C<workstations>,
or C<systems>

=back

