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.
316 lines
11 KiB
316 lines
11 KiB
#!/usr/bin/perl -w
|
|
|
|
#---------------------------------------------------------------------
|
|
# Copyright (C) 2016 Firewall-Services
|
|
# daniel@firewall-services.com
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#----------------------------------------------------------------------
|
|
package esmith::FormMagick::Panel::expireaccounts;
|
|
|
|
use strict;
|
|
|
|
use esmith::FormMagick;
|
|
use esmith::AccountsDB;
|
|
use esmith::ConfigDB;
|
|
use esmith::cgi;
|
|
use DateTime;
|
|
use File::Basename;
|
|
use Exporter;
|
|
use Carp qw(verbose);
|
|
|
|
our @ISA = qw(esmith::FormMagick Exporter);
|
|
|
|
our @EXPORT = qw(
|
|
print_user_table
|
|
print_save_button
|
|
print_custom_button
|
|
print_section_bar
|
|
);
|
|
|
|
our $a = esmith::AccountsDB->open || die "Couldn't open AccountsDB";
|
|
our $c = esmith::ConfigDB->open || die "Couldn't open ConfigDB";
|
|
|
|
our %defaults = (
|
|
ExpireAutoReply => 'enabled',
|
|
ExpireDeleteAfterLock => 'never',
|
|
WarnUsers => 'enabled'
|
|
);
|
|
|
|
sub new {
|
|
shift;
|
|
my $self = esmith::FormMagick->new();
|
|
$self->{calling_package} = (caller)[0];
|
|
bless $self;
|
|
return $self;
|
|
}
|
|
|
|
sub print_user_table {
|
|
my $self = shift;
|
|
my $q = $self->{cgi};
|
|
|
|
my @users = $a->users;
|
|
|
|
if ( scalar @users < 1) {
|
|
print $q->Tr($q->td($self->localise('NO_USER_ACCOUNTS')));
|
|
return "";
|
|
}
|
|
|
|
if (_count_active_users() > 0){
|
|
print " <tr><td colspan=\"2\">";
|
|
print $q->start_table ({-CLASS => "sme-border"});
|
|
print $q->Tr(
|
|
esmith::cgi::genSmallCell($q, $self->localise('ACTIVE_ACCOUNT'), "header"),
|
|
esmith::cgi::genSmallCell($q, $self->localise('USER_NAME'), "header"),
|
|
esmith::cgi::genSmallCell($q, $self->localise('FORWARD'), "header"),
|
|
esmith::cgi::genSmallCell($q, $self->localise('DAYS_BEFORE_LOCK'), "header"),
|
|
esmith::cgi::genSmallCell($q, $self->localise('ACTION'), "header")
|
|
);
|
|
|
|
my $scriptname = basename($0);
|
|
|
|
my $now = DateTime->now;
|
|
foreach my $u (@users) {
|
|
my $username = $u->key();
|
|
next unless (($u->prop('PasswordSet') || 'no') eq 'yes');
|
|
my $first = $u->prop('FirstName') || '';
|
|
my $last = $u->prop('LastName') || '';
|
|
my $lock_date = $u->prop('ExpireLockOn') || '';
|
|
my $delivery = $u->prop('EmailForward') || 'local';
|
|
my $fwd = $u->prop('ForwardAddress') || '';
|
|
my $action = "<a href=\"$scriptname?page=0&page_stack=&acctName=$username&wherenext=ModifyActive\">" .
|
|
$self->localise('MODIFY') . "</a>";
|
|
my $days_left = '';
|
|
if ($lock_date =~ m/^(\d{4})\-(\d{1,2})\-(\d{1,2})$/){
|
|
my $lock_on = eval {
|
|
DateTime->new(
|
|
year => $1,
|
|
month => $2,
|
|
day => $3
|
|
);
|
|
};
|
|
$days_left = ($lock_on - $now)->in_units('days') if ($lock_on);
|
|
}
|
|
my $addr = ($delivery eq 'local') ? '' : $fwd;
|
|
print $q->Tr(
|
|
esmith::cgi::genSmallCell($q, $username, "normal"),
|
|
esmith::cgi::genSmallCell($q, "$first $last", "normal"),
|
|
esmith::cgi::genSmallCell($q, $addr, "normal"),
|
|
esmith::cgi::genSmallCell($q, $days_left, "normal"),
|
|
esmith::cgi::genSmallCell($q, $action, "normal")
|
|
);
|
|
}
|
|
}
|
|
if (_count_inactive_users() > 0){
|
|
# Now, same for locked accounts
|
|
print $q->Tr(
|
|
esmith::cgi::genSmallCell($q, $self->localise('INACTIVE_ACCOUNT'), "header"),
|
|
esmith::cgi::genSmallCell($q, $self->localise('USER_NAME'), "header"),
|
|
esmith::cgi::genSmallCell($q, $self->localise('FORWARD'), "header"),
|
|
esmith::cgi::genSmallCell($q, $self->localise('DAYS_BEFORE_DELETE'), "header"),
|
|
esmith::cgi::genSmallCell($q, $self->localise('ACTION'), "header")
|
|
);
|
|
foreach my $u (@users) {
|
|
my $username = $u->key();
|
|
next unless (($u->prop('PasswordSet') || 'no') ne 'yes');
|
|
my $first = $u->prop('FirstName') || '';
|
|
my $last = $u->prop('LastName') || '';
|
|
my $delete_in = $u->prop('ExpireDeleteAfterLock') || '';
|
|
my $locked_on = $u->prop('ExpireLockedOn') || '';
|
|
my $delivery = $u->prop('EmailForward') || '';
|
|
my $fwd = $u->prop('ForwardAddress') || '';
|
|
my $action = "<a href=\"$scriptname?page=0&page_stack=&acctName=$username&wherenext=ModifyLocked\">" .
|
|
$self->localise('MODIFY') . "</a>";
|
|
my $days_left = '';
|
|
if ($delete_in =~ m/^\d+$/ && $locked_on =~ m/^(\d{4})\-(\d{1,2})\-(\d{1,2})$/){
|
|
my $locked_date = eval {
|
|
DateTime->new(
|
|
year => $1,
|
|
month => $2,
|
|
day => $3
|
|
);
|
|
};
|
|
if ($locked_date){
|
|
my $delete_on = $locked_date->add(days => $delete_in);
|
|
$days_left = ($delete_on - $now)->in_units('days');
|
|
}
|
|
}
|
|
my $addr = ($delivery eq 'local') ? '' : $fwd;
|
|
print $q->Tr(
|
|
esmith::cgi::genSmallCell($q, $username, "normal"),
|
|
esmith::cgi::genSmallCell($q, "$first $last", "normal"),
|
|
esmith::cgi::genSmallCell($q, $addr, "normal"),
|
|
esmith::cgi::genSmallCell($q, $days_left, "normal"),
|
|
esmith::cgi::genSmallCell($q, $action, "normal")
|
|
);
|
|
}
|
|
}
|
|
print qq(</table></td></tr>\n);
|
|
return "";
|
|
}
|
|
|
|
sub print_save_button {
|
|
my ($self) = @_;
|
|
$self->print_button("SAVE");
|
|
}
|
|
|
|
sub print_section_bar{
|
|
my $self = shift;
|
|
print " <tr>\n <td colspan='2'>\n";
|
|
print "<hr class=\"sectionbar\"/>\n";
|
|
return undef;
|
|
}
|
|
|
|
sub print_custom_button{
|
|
my ($self, $desc, $page) = @_;
|
|
my $url = basename($0) . "?page=0&page_stack=&Next=Next&wherenext=" . $page;
|
|
|
|
print "<tr><td colspan='2'>";
|
|
print $self->{cgi}->p(
|
|
$self->{cgi}->a({href => $url, -class => "button-like"}, $self->localise($desc))
|
|
);
|
|
print qq(</tr>);
|
|
return undef;
|
|
}
|
|
|
|
sub get_user_prop{
|
|
my ($self, $field) = @_;
|
|
return $a->get($self->{cgi}->param('acctName'))->prop("$field") || $defaults{$field} || '';
|
|
}
|
|
|
|
sub get_user_bool{
|
|
my ($self, $field) = @_;
|
|
my $val = $self->get_user_prop($self, $field);
|
|
$val = $defaults{$field} if ($val eq '');
|
|
return ($val =~ m/^yes|enabled|1|on$/) ? 'enabled' : 'disabled';
|
|
}
|
|
|
|
sub get_conf_prop{
|
|
my ($self, $field) = @_;
|
|
return $c->get('ExpireAccounts')->prop($field) || '';
|
|
}
|
|
|
|
sub get_conf_bool{
|
|
my ($self, $field) = @_;
|
|
my $val = $self->get_conf_prop($self, $field);
|
|
$val = $defaults{$field} if ($val eq '');
|
|
return ($val =~ m/^yes|enabled|1|on$/) ? 'enabled' : 'disabled';
|
|
}
|
|
|
|
sub modify_config{
|
|
my ($self) = @_;
|
|
my $rec = $c->get('ExpireAccounts') || $c->new_record('ExpireAccounts', { type => 'service' });
|
|
my %new_props = ();
|
|
foreach my $prop (qw(WarningDelay DaysBetweenWarnings WarningRecipient)){
|
|
if (!$self->{cgi}->param($prop) || $self->{cgi}->param($prop) eq ''){
|
|
$rec->delete_prop($prop);
|
|
}
|
|
else{
|
|
$new_props{$prop} = $self->{cgi}->param($prop);
|
|
}
|
|
}
|
|
# Bool props
|
|
foreach my $prop (qw(WarnUsers)){
|
|
$new_props{$prop} = ($self->{cgi}->param($prop)) ? 'enabled' : 'disabled';
|
|
}
|
|
$rec->merge_props(%new_props);
|
|
$self->success('CONFIG_MODIFIED');
|
|
}
|
|
|
|
sub modify_user {
|
|
my ($self) = @_;
|
|
my $acctName = $self->{cgi}->param('acctName');
|
|
|
|
unless (($acctName) = ($acctName =~ /^(\w[\-\w_\.]*)$/)) {
|
|
return $self->error(
|
|
$self->localise('TAINTED_USER', { acctName => $acctName })
|
|
);
|
|
}
|
|
$acctName = $1;
|
|
|
|
my $acct = $a->get($acctName);
|
|
my $type = $acct->prop('type');
|
|
|
|
unless ($type eq 'user'){
|
|
return $self->error(
|
|
$self->localise('NOT_A_USER_ACCOUNT', { acctName => $acctName })
|
|
);
|
|
}
|
|
my %new_props = ();
|
|
foreach my $prop (qw(ExpireLockOn ExpireForwardAfterLock ExpireDeleteAfterLock)){
|
|
if (!$self->{cgi}->param($prop) || $self->{cgi}->param($prop) eq ''){
|
|
$acct->delete_prop($prop);
|
|
}
|
|
else{
|
|
$new_props{$prop} = $self->{cgi}->param($prop);
|
|
}
|
|
}
|
|
$acct->merge_props(%new_props);
|
|
unless(system('/sbin/e-smith/signal-event', 'user-update-expire-settings', $acctName) == 0){
|
|
return $self->error('ERROR_OCCURRED');
|
|
}
|
|
$self->success('USER_MODIFIED');
|
|
}
|
|
|
|
sub _count_active_users{
|
|
my $users = 0;
|
|
foreach my $user ($a->users){
|
|
$users++ if ($user->prop('PasswordSet') || 'no') eq 'yes';
|
|
}
|
|
return $users;
|
|
}
|
|
|
|
sub _count_inactive_users{
|
|
my $users = 0;
|
|
foreach my $user ($a->users){
|
|
$users++ unless ($user->prop('PasswordSet') || 'no') eq 'yes';
|
|
}
|
|
return $users;
|
|
}
|
|
|
|
# Validation routines
|
|
|
|
# Number must be int and positive
|
|
sub is_positive_int{
|
|
my ($self, $num) = @_;
|
|
return $self->localise('MUST_BE_POSITIVE_NUMBER') unless ($num =~ m/^\d+$/ && $num > 0);
|
|
return 'OK';
|
|
}
|
|
|
|
# Take a string representing a date, must be YYY-MM-DD format, and in the future, or an empty string
|
|
sub is_future_date_or_empty {
|
|
my ($self, $date_string) = @_;
|
|
return 'OK' if ($date_string eq '');
|
|
return $self->localise('DATE_FORMAT_INVALID') unless ($date_string =~ /^(\d{4})\-(\d{1,2})\-(\d{1,2})$/);
|
|
my $date = eval {
|
|
DateTime->new(
|
|
year => $1,
|
|
month => $2,
|
|
day => $3
|
|
);
|
|
};
|
|
return $self->localise('DATE_FORMAT_INVALID') unless ($date);
|
|
my $now = DateTime->now;
|
|
return $self->localise('DATE_IS_PASSED') unless ($date > $now);
|
|
return 'OK';
|
|
}
|
|
|
|
# Take a string, must be a valid email or an empty string
|
|
sub is_email_or_empty {
|
|
my ($self, $field) = @_;
|
|
return $self->localise('BAD_SYNTAX') unless (($field =~ m/^[a-zA-Z][a-zA-Z0-9\._\-]*\@?([a-zA-Z0-9\._\-]*)?$/) || ($field eq ''));
|
|
return 'OK';
|
|
}
|
|
|
|
|