diff --git a/root/etc/e-smith/web/functions/expireaccounts b/root/etc/e-smith/web/functions/expireaccounts index cba525e..08e241c 100755 --- a/root/etc/e-smith/web/functions/expireaccounts +++ b/root/etc/e-smith/web/functions/expireaccounts @@ -78,6 +78,13 @@ __DATA__ DESC_AUTO_REPLY + + DESC_DELETE_AFTER_LOCK + + diff --git a/root/sbin/e-smith/expire-accounts b/root/sbin/e-smith/expire-accounts index 840bf27..9df8393 100644 --- a/root/sbin/e-smith/expire-accounts +++ b/root/sbin/e-smith/expire-accounts @@ -5,6 +5,7 @@ use esmith::ConfigDB; use esmith::event; use Text::Template; use DateTime; +use User::pwent; use Getopt::Long; my $a = esmith::AccountsDB->open || die "Couldn't open the AccountsDB"; @@ -30,9 +31,32 @@ my $warn_delay = $service->prop('WarningDelay') || '30'; my $warn_users = $service->prop('WarnUsers') || 'no'; my $recipient = $service->prop('WarningRecipient') || 'root'; my $days_between_warn = $service->prop('DaysBetweenWarnings') || '5'; +my $archive_compress = $service->prop('ArchiveCompression') || '/usr/bin/pxz'; +my $archive_path = $service->prop('ArchivePath') || '/home/e-smith/files/archives/users'; +my $archive_ext = 'xz'; -my $rem = {}; -my @lock = (); +if ( !-x $archive_compress ){ + print "$archive_compress not found, switching back to the default /bin/gzip\n" if ($debug); + $archive_compress = '/bin/gzip'; +} + +if ( $archive_compress =~ m/xz$/ ){ + $archive_ext = 'xz'; +} +elsif ( $archive_compress =~ m/bz2$/ ){ + $archive_ext = 'bz2'; +} +elsif ( $archive_compress =~ m/gzip$/ ){ + $archive_ext = 'gz'; +} +else{ + print "$archive_compress creates unknown archive format, using a generic .z extension\n" if ($debug); + $archive_ext = 'z'; +} + +my $rem = {}; +my @lock = (); +my @delete = (); my $now = DateTime->now; @@ -40,15 +64,27 @@ foreach my $user ($a->users){ my $pass = $user->prop('PasswordSet') || 'no'; if ($pass ne 'yes'){ print $user->key . ": Account already locked\n" if $debug; + my $delete = $user->prop('ExpireDeleteAfterLock') || 'never'; + my $locked_date = $user->prop('ExpireLockedOn') || ''; + if ($delete =~ m/^\d+$/ && $locked_date =~ m/^(\d{4})\-(\d{1,2})\-(\d{1,2})$/){ + my $locked = DateTime->new( + year => $1, + month => $2, + day => $3, + ); + my $delete_date = $locked->add( days => $delete); + print $user->key . ": Account must be deleted\n" if $debug; + push @delete, $user->key; + } next; } - my $date = $user->prop('ExpireLockOn') || 'never'; - if ($date eq 'never'){ + my $lock_date = $user->prop('ExpireLockOn') || 'never'; + if ($lock_date eq 'never'){ print $user->key . ": No expiration date set\n" if $debug; next; } - elsif ($date !~ m/^(\d{4})\-(\d{1,2})\-(\d{1,2})/){ - print $user->key . ": Invalide expiration date ($date)\n" if $debug; + elsif ($lock_date !~ m/^(\d{4})\-(\d{1,2})\-(\d{1,2})$/){ + print $user->key . ": Invalide expiration date ($lock_date)\n" if $debug; next; } my $exp = DateTime->new( @@ -63,7 +99,7 @@ foreach my $user ($a->users){ } else{ my $remaining = ($exp - $now)->in_units('days'); - print $user->key . ": Account will expire on $date ($remaining days)\n" if $debug; + print $user->key . ": Account will expire on $lock_date ($remaining days)\n" if $debug; $rem->{$user->key} = $remaining if $remaining < $warn_delay; } } @@ -73,6 +109,36 @@ foreach my $u (@lock){ event_signal('user-expire-account', $u); } +foreach my $u (@delete){ + my $user = $a->get($u); + if (!$user || !$user->prop('type') || $user->prop('type') ne 'user'){ + print $u . ": This is not a user account\n"; + next; + } + unless( -d $archive_path ){ + print $u . ": $archive_path doesn't exist, can't continue\n" if ($debug); + next; + } + my $archive = $user->prop('ExpireArchiveBeforeDelete') || 'yes'; + if ($archive =~ m/^yes|enabled|1|on$/){ + my $tar = $archive_path . '/' . $u . '-' . $now->ymd . '.' . $archive_ext; + my $res = system( + 'tar', + 'cf', + $tar, + '--use-compress-program', + $archive_compress, + getpwnam($u)->dir + ); + if ($res == 0){ + print $u . ": Data archived as $tar, the user account will now be deleted\n" if ($debug); + $user->set_prop(type => 'user-deleted'); + event_signal('user-delete', $u); + $a = esmith::AccountsDB->open || die "Couldn't open AccountsDB\n"; + } + } +} + # Send a warning for accounts which will be locked soon my $send_warn_for = {}; foreach my $user (keys %$rem){ diff --git a/root/usr/share/perl5/vendor_perl/esmith/FormMagick/Panel/expireaccounts.pm b/root/usr/share/perl5/vendor_perl/esmith/FormMagick/Panel/expireaccounts.pm index ba34226..c8805c1 100644 --- a/root/usr/share/perl5/vendor_perl/esmith/FormMagick/Panel/expireaccounts.pm +++ b/root/usr/share/perl5/vendor_perl/esmith/FormMagick/Panel/expireaccounts.pm @@ -44,8 +44,9 @@ our $a = esmith::AccountsDB->open || die "Couldn't open AccountsDB"; our $c = esmith::ConfigDB->open || die "Couldn't open ConfigDB"; our %defaults = ( - ExpireAutoReply => 'enabled', - WarnUsers => 'enabled' + ExpireAutoReply => 'enabled', + ExpireDeleteAfterLock => 'never', + WarnUsers => 'enabled' ); sub new { @@ -122,7 +123,7 @@ sub print_custom_button{ sub get_user_prop{ my ($self, $field) = @_; - return $a->get($self->{cgi}->param('acctName'))->prop("$field") || ''; + return $a->get($self->{cgi}->param('acctName'))->prop("$field") || $defaults{$field} || ''; } sub get_user_bool{ @@ -173,7 +174,6 @@ sub modify_user { $self->localise('TAINTED_USER', { acctName => $acctName }) ); } - # Untaint the username before use in system() $acctName = $1; my $acct = $a->get($acctName); @@ -185,7 +185,7 @@ sub modify_user { ); } my %new_props = (); - foreach my $prop (qw(ExpireLockOn ExpireForwardAfterLock)){ + foreach my $prop (qw(ExpireLockOn ExpireForwardAfterLock ExpireDeleteAfterLock)){ if (!$self->{cgi}->param($prop) || $self->{cgi}->param($prop) eq ''){ $acct->delete_prop($prop); }