User account expiration control panel for SME Server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

152 lines
4.3 KiB

#!/usr/bin/perl -w
use esmith::AccountsDB;
use esmith::ConfigDB;
use esmith::event;
use Text::Template;
use DateTime;
use Getopt::Long;
my $a = esmith::AccountsDB->open || die "Couldn't open the AccountsDB";
my $c = esmith::ConfigDB->open || die "Couldn't open the ConfigDB";
my $domain = $c->get_value('DomainName');
my $debug = 0;
GetOptions(
debug => \$debug,
);
my $service = $c->get('ExpireAccounts') ||
$c->new_record('ExpireAccounts',
{
type => 'service',
status => 'enabled'
}
);
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 $rem = {};
my @lock = ();
my $now = DateTime->now;
foreach my $user ($a->users){
my $pass = $user->prop('PasswordSet') || 'no';
if ($pass ne 'yes'){
print $user->key . ": Account already locked\n" if $debug;
next;
}
my $date = $user->prop('ExpireLockOn') || 'never';
if ($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;
next;
}
my $exp = DateTime->new(
year => $1,
month => $2,
day => $3,
);
if ($exp < $now){
print $user->key . ": Expiration date is passed, account must be locked\n" if $debug;
push @lock, $user->key;
}
else{
my $remaining = ($exp - $now)->in_units('days');
print $user->key . ": Account will expire on $date ($remaining days)\n" if $debug;
$rem->{$user->key} = $remaining if $remaining < $warn_delay;
}
}
# Lock accounts which need to be locked now
foreach my $u (@lock){
event_signal('user-lock', $u);
$a = esmith::AccountsDB->open || die "Couldn't open the AccountsDB\n";
my $rec = $a->get($u);
my $fwd = $rec->prop('ExpireForwardAfterLock') || '';
if ($fwd ne ''){
$rec->set_prop('ForwardAddress', $fwd);
$rec->set_prop('EmailForward', 'forward');
}
$rec->delete_prop('ExpireLockOn');
$rec->delete_prop('ExpireLastNotifiedOn');
$rec->set_prop('ExpireLockedOn', $now->ymd);
}
# Send a warning for accounts which will be locked soon
my $send_warn_for = {};
foreach my $user (keys %$rem){
my $rec = $a->get($user) || next;
my $last_notif = $rec->prop('ExpireLastNotifiedOn') || 'never';
if ($last_notif =~ m/^(\d{4})\-(\d{1,2})\-(\d{1,2})/){
$last_notif = DateTime->new(
year => $1,
month => $2,
day => $3,
);
if (($last_notif - $now)->in_units('days') < $days_between_warn){
next;
}
}
my $templates = '/etc/e-smith/templates';
my $source = '/usr/lib/smeserver-expire-accounts/userNotifAccountExpiration.tmpl';
# Use templates-custom version by preference if it exists
-f "${templates}-custom${source}" and $templates .= "-custom";
if ($warn_users){
my $t = new Text::Template(TYPE => 'FILE',
SOURCE => "${templates}${source}");
open(QMAIL, "|/var/qmail/bin/qmail-inject -fdo-not-reply\@$domain $user")
|| die "Could not send mail via qmail-inject!\n";
print QMAIL $t->fill_in( HASH => {
conf => \$c,
user => $user,
days => $rem->{$user}
});
close QMAIL;
}
$rec->set_prop('ExpireLastNotifiedOn', $now->ymd);
# This one will be notified to the admin
$send_warn_for->{$user} = {
remaining => $rem->{$user},
name => $rec->prop('FirstName') . ' ' . $rec->prop('LastName')
};
}
if (keys %$send_warn_for > 0){
$templates = '/etc/e-smith/templates';
$source = '/usr/lib/smeserver-expire-accounts/adminNotifNextExpirations.tmpl';
# Use templates-custom version by preference if it exists
-f "${templates}-custom${source}" and $templates .= "-custom";
my $t = new Text::Template(TYPE => 'FILE',
SOURCE => "${templates}${source}");
open(QMAIL, "|/var/qmail/bin/qmail-inject -fdo-not-reply\@$domain $recipient")
|| die "Could not send mail via qmail-inject!\n";
print QMAIL $t->fill_in( HASH => {
conf => \$c,
users => \$send_warn_for
});
close QMAIL;
}
exit 0;