#!/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 ""; } my $scriptname = basename($0); my $now = DateTime->now; print " "; print $q->start_table ({-CLASS => "sme-border"}); if (_count_active_users() > 0){ 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") ); 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 = "" . $self->localise('MODIFY') . ""; 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 = "" . $self->localise('MODIFY') . ""; 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(\n); return ""; } sub print_save_button { my ($self) = @_; $self->print_button("SAVE"); } sub print_section_bar{ my $self = shift; print " \n \n"; print "
\n"; return undef; } sub print_custom_button{ my ($self, $desc, $page) = @_; my $url = basename($0) . "?page=0&page_stack=&Next=Next&wherenext=" . $page; print ""; print $self->{cgi}->p( $self->{cgi}->a({href => $url, -class => "button-like"}, $self->localise($desc)) ); print qq(); 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 get_delete_options{ my ($self) = @_; my $options = [ qw(never 7 30 180 365) ]; my $acctName = $self->{cgi}->param('acctName'); if ($acctName =~ /^(\w[\-\w_\.]*)$/){ $acctName = $1; my $acct = $a->get($acctName); my $pass = $acct->prop('PasswordSet') || 'no'; my $locked = $acct->prop('ExpireLockedOn') || ''; if ($pass eq 'no' && $locked !~ m/^\d{4}\-\d{1,2}\-\d{1,2}$/){ $options = [ qw(never) ]; } } return $options; } 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 ExpireAutoReply 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'; }