#!/usr/bin/perl -w use warnings; use strict; use Getopt::Long; use DBI; use esmith::ConfigDB; use esmith::AccountsDB; use Text::Unaccent::PurePerl qw(unac_string); use utf8; my $c = esmith::ConfigDB->open_ro or die "Can't open the configuration DB\n"; my $a = esmith::AccountsDB->open or die "Can't open the accounts DB\n"; my $domain = $c->get('DomainName')->value; my $limesurvey = $c->get('limesurvey') or die "No limesurvey entry found in the config DB\n"; my $host = 'localhost'; my $dbname = $limesurvey->prop('DbName') || 'limesurvey'; my $dbpass = $limesurvey->prop('DbPassword') || ''; my $dbuser = $limesurvey->prop('DbUser') || 'limesurvey'; my $survey = '889944'; my @notify = (); my $dry = 0; my $ok_cnt = 0; my $ko_cnt = 0; GetOptions( 'dbname=s' => \$dbname, 'dbuser=s' => \$dbuser, 'dbpassword=s' => \$dbpass, 'survey=s' => \$survey, 'notify=s' => \@notify, 'dry-run' => \$dry ); # Allow comma separated multi-argument @notify = split(/,/, join(',', @notify)); if ($survey !~ m/^\d+$/){ die "$survey isn't a valid survey ID\n"; } my $survey_table = 'survey_' . $survey; my $new_date = undef; my $col2field = { submitdate => 'submitdate', first_name => '889944X91X1181SQ001', last_name => '889944X91X1181SQ002', email => '889944X91X1181SQ003', phone => '889944X91X1181SQ004', end_contract => '889944X91X1189', unit => '889944X90X1191', unit_other => '889944X90X1191other', supervisor_name => '889944X90X1190', supervisor_name_other => '889944X90X1190other', supervisor_email => '889944X90X1203' }; my $dsn = "DBI:mysql:database=$dbname;host=localhost"; my $dbh = DBI->connect($dsn, $dbuser, $dbpass, { mysql_enable_utf8 => 1 }); my $last_run; # Identify last time the script ran my $sth = $dbh->prepare( 'SELECT submitdate FROM ' . $survey_table . ' WHERE token = \'last_run\'') or die "prepare statement failed: $dbh->errstr()"; $sth->execute() or die "execution failed: $dbh->errstr()"; if ($sth->rows gt 1){ die "More than one last_run entry found\n"; } elsif ($sth->rows lt 1){ die "Last run not found\n"; } while (my $ref = $sth->fetchrow_hashref) { $last_run = $ref->{submitdate}; } # Query all the submission done after last run $sth = $dbh->prepare( 'SELECT ' . join(',', map { $col2field->{$_} . ' AS ' . $_ } keys %{$col2field}) . ' FROM ' . $survey_table . ' WHERE submitdate > ?' ) or die "prepare statement failed: $dbh->errstr()"; $sth->execute($last_run); if ($sth->rows > 0){ print "Last run was $last_run\n"; print "Found " . $sth->rows . " responses to process\n"; } my $report = ''; while (my $ref = $sth->fetchrow_hashref) { # Build info for this new user my $info = { login => unac_string(lc substr($ref->{first_name}, 0, 1) . lc substr($ref->{last_name},0,12)), first_name => $ref->{first_name} || '', last_name => $ref->{last_name} || '', supervisor_name => $ref->{supervisor_name} || '', unit => $ref->{unit} || '', email => $ref->{email} || '', phone => $ref->{phone} || '', end_contract => $ref->{end_contract} || '', }; $info->{login} =~ s/[^\da-z]//g; foreach (qw(first_name last_name)){ utf8::encode($info->{$_}); } # Extract email, as it can be in the form "Foo Bar" $info->{email} = $1 if ($info->{email} =~ m/\<(.+\@.+)\>/); # Blank out the email if not valid $info->{email} = '' if not ($info->{email} =~ m/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/); # Keep only the day for the end of contract $info->{end_contract} = $1 if ($info->{end_contract} =~ m/^(\d{4}\-\d{1,2}\-\d{1,2})/); # unit and supervisor can be selected from a dropdown, or entered after selecting "other" # So we have to do the lookup my $ansh = $dbh->prepare('SELECT answer FROM answers WHERE code = ? AND qid = ?') or die "prepare statement failed: $dbh->errstr()"; foreach my $field (qw(unit supervisor_name)){ # We have to extract question ID to query the answers table if ($info->{$field} eq '-oth-'){ $info->{$field} = $ref->{$field . '_other'}; } else { my $qid = $col2field->{$field}; $qid =~ s/.*(\d{4})$/$1/; $ansh->execute($ref->{$field},$qid); if ($ansh->rows == 1){ while (my $ansref = $ansh->fetchrow_hashref){ $info->{$field} = $ansref->{answer}; } } } utf8::encode($info->{$field}); } # Validate data my $msg = ''; foreach my $field (qw(login first_name last_name email end_contract unit supervisor_name)){ $msg .= "\n$field $info->{$field} contains invalid data\n" if ($info->{$field} !~ m/[\w\-]*/ or length($info->{$field}) > 60); } unless (esmith::AccountsDB::validate_account_name($info->{login})){ $msg .= "Created login $info->{login} is invalid\n"; } if ($a->get($info->{login})){ $msg .= "A user with login $info->{login} already exists\n"; } $report .= "-----------------------------------------------------------------------\n"; if ($msg ne ''){ $ko_cnt++; $report .= "An error occured while processing account for $info->{last_name} $info->{first_name}. " . "The error is : $msg\n"; } else { print "Creating user account $info->{login} ($info->{first_name} $info->{last_name})\n"; if (not $dry){ $a->new_record($info->{login}, { type => 'user', FirstName => $info->{first_name}, LastName => $info->{last_name}, Phone => $info->{phone}, Dept => $info->{supervisor_name}, PasswordSet => 'no', Company => $info->{unit}, PreferredMail => $info->{email} }); unless ( system("/sbin/e-smith/signal-event", "user-create", $info->{login}) == 0 ){ $report .= "Error occured while creating account $info->{login}, please contact your administrator\n"; $ko_cnt++; } } $ok_cnt++; $report .= <<_EOF; New account created (please, review group membership and set a password) * Login : $info->{login} * Last name : $info->{last_name} * First name : $info->{first_name} * Email : $info->{email} * Unit : $info->{unit} * Supervisor : $info->{supervisor_name} _EOF # Set expiration if ($info->{end_contract} ne ''){ $a->set_prop($info->{login}, 'ExpireLockOn', $info->{end_contract}); $a->set_prop($info->{login}, 'ExpireAutoReply', 'enabled'); $a->set_prop($info->{login}, 'ExpireDeleteAfterLock', '365'); $report .= " * Expiration date : $info->{end_contract}\n" } $report .= "\n\n\n"; } $new_date = $ref->{submitdate}; } # Update the last run entry if (defined $new_date and not $dry){ $sth = $dbh->prepare( "UPDATE `$survey_table` SET `submitdate` = ? WHERE `token` = 'last_run'") or die "prepare statement failed: $dbh->errstr()"; $sth->execute($new_date) or die "execution failed: $dbh->errstr()"; } $sth->finish; print $report; if ($ok_cnt > 0 or $ko_cnt > 1){ foreach my $email (@notify){ print "Sending notification to $email\n"; open(QMAIL, "|/var/qmail/bin/qmail-inject -fdo-not-reply\@$domain $email") || die "Could not send mail via qmail-inject!\n"; print QMAIL <