source: LATMOS-Accounts/lib/LATMOS/Accounts/Maintenance.pm @ 850

Last change on this file since 850 was 850, checked in by nanardon, 14 years ago
  • add functions to find already expired account
  • Property svn:keywords set to Id Rev
File size: 7.2 KB
Line 
1package LATMOS::Accounts::Maintenance;
2
3use strict;
4use warnings;
5use base qw(LATMOS::Accounts);
6use LATMOS::Accounts::Log;
7use FindBin qw($Bin);
8use Crypt::RSA;
9use Crypt::RSA::Key::Public::SSH;
10use Crypt::RSA::Key::Private::SSH;
11use MIME::Base64;
12
13sub _base {
14    my ($self) = @_;
15    my $base = $self->SUPER::default_base;
16    $base->type eq 'sql' or die "This module work only with SQL base type\n";
17    $base
18}
19
20sub find_next_expire_users {
21    # Do not replace this code by $base->find_next_expire_users
22    # it does not exctly the same thing
23    my ($self, $expire) = @_;
24    my $base = $self->_base;
25
26    my $sth= $base->db->prepare(q{
27        select name, justify_hours(expire - now()) as delay from "user" where
28            expire < now() + ?::interval
29            and expire > now()
30            and expire is not null
31            and exported = True
32            order by expire
33        }
34    );
35    $sth->execute($expire || '1 month');
36    my @users;
37    while (my $res = $sth->fetchrow_hashref) {
38        $res->{delay} =~ s/ day.? .*//;
39        $res->{obj} = $base->get_object('user', $res->{name});
40        $res->{obj}->get_attributes('locked') and next;
41        push(@users, $res);
42    }
43    @users
44}
45
46=head2 warn_next_expire_users(%options)
47
48Send a mail to user having account expiring soon
49
50C<%options are>
51
52=over 4
53
54=item users => []
55
56Warn only this users (if need)
57
58=item to
59
60Send the only to this person.
61
62=back
63
64=cut
65
66sub warn_next_expire_users {
67    my ($self, %options) = @_;
68
69    require Mail::Sendmail;
70    require Template;
71    my $template = Template->new(
72        INCLUDE_PATH => [
73            ($self->val('_default_', 'templatespath')
74               ? $self->val('_default_', 'templatespath') . '/mail'
75               : ()),
76            "$FindBin::Bin/../templates" . '/mail',
77            '/usr/share/latmos-accounts/templates/mail',
78        ],
79        POST_CHOMP   => 1,
80        EXTENSION    => '.mail',
81    );
82    my @summary;
83    foreach my $user ($self->find_next_expire_users($options{delay})) {
84        if ($options{users} && ! grep { $_ eq $user->{name} } @{$options{users}}) {
85            next;
86        }
87        my %mail = (
88            From => $self->val('_default_', 'mailFrom', 'nomail@localhost'),
89            Subject => 'LATMOS Expire in ' . $user->{delay} . 'days',
90            smtp => $self->val('_default_', 'smtp'),
91            'Content-Type' => 'text/plain; charset=utf-8',
92            'X-LATMOS-Accounts' => '$Rev$',
93            'X-LATMOS-Reason' => 'Account expiration',
94        );
95        my ($manager, $mail) = ($user->{obj}->get_c_field('managerContact'),
96            $user->{obj}->get_c_field('mail'));
97        my $managermail = $manager ? $user->{obj}->base->
98            get_object('user', $manager)->get_c_field('mail') : undef;
99 
100        # if user have no mail, mail only to manager, avoiding empty To
101        # NB: at time, for testing purpose, mail is not really sent
102        my ($to, @cc) = grep { $_ } ($mail, $managermail,
103            $self->val('_default_', 'allwayscc'));
104        if ($options{to}) {
105            $mail{to} = $options{to};
106        } else {
107            $mail{to} = $to;
108            $mail{cc} = join(', ', @cc);
109        }
110        $mail{to} or do {
111            la_log(LA_ERR, 
112                "Cannot send expiration for `%s', no mail to send to",
113                $user->{obj}->id,
114            );
115            next;
116        };
117        my $mailcc = join(', ', @cc) || '';
118        push(@summary, sprintf("%s : %s : %s\n",
119                $user->{obj}->queryformat('%{sn} %{givenName} : %{name} : %{department} : %{managerContact} : %{expireText}'),
120                $to || 'Not sent, no destination',
121                ($mailcc ? $mailcc : ''),
122            )
123        );
124        my $message;
125        $template->process('account_expire.mail', $user, \$message)
126            or do {
127                la_log(LA_ERR, "Cannot send expiration mail: %s, exiting",
128                    $template->error());
129                exit(1);
130            };
131
132        if (!$options{test}) {
133            if (Mail::Sendmail::sendmail(
134                    %mail,
135                    Message => $message,
136                )) {
137                la_log(LA_NOTICE, "Expiration mail for %s (%s) sent to %s; cc %s",
138                    $user->{obj}->id,
139                    $user->{delay},
140                    $mail{to}, ($mail{cc} || ''));
141                if ($options{to}) {
142                    la_log(LA_NOTICE,"\tbut sent to %s", $mail{to});
143                }
144            } else {
145                la_log(LA_ERR, "Cannot send mail: %s", $Mail::Sendmail::error);
146            }
147        }
148    }
149
150    if (@summary) {
151        if ($options{test}) {
152            print join('', @summary);
153        } else {
154            if ($self->val('_default_', 'expire_summary_to')) {
155                my %mail = (
156                    From => $self->val('_default_', 'mailFrom', 'nomail@localhost'),
157                    Subject => 'LATMOS account expiration summary',
158                    smtp => $self->val('_default_', 'smtp'),
159                    'Content-Type' => 'text/plain; charset=utf-8',
160                    'X-LATMOS-Accounts' => '$Rev$',
161                    'X-LATMOS-Reason' => 'Account expiration',
162                    To => $self->val('_default_', 'expire_summary_to'),
163                );
164                if (Mail::Sendmail::sendmail(
165                        %mail,
166                        Message => join('', @summary),
167                    )) {
168                    la_log(LA_NOTICE, "Expiration summary mail sent to %s",
169                        $self->val('_default_', 'expire_summary_to'),
170                    );
171                } else {
172                    la_log(LA_ERR, "Cannot send mail: %s", $Mail::Sendmail::error);
173                }
174            }
175        }
176    }
177
178    1;
179}
180
181sub find_expired_users {
182    my ($self, $expire) = @_;
183    $self->_base->find_expired_users($expire);
184}
185
186sub generate_rsa_key {
187    my ($self, $password) = @_;
188   
189    my $rsa = new Crypt::RSA ES => 'PKCS1v15';
190    my ($public, $private) = $rsa->keygen (
191        Identity  => 'LATMOS-Accounts',
192        Size      => 768,
193        Password  => $password,
194        Verbosity => 0,
195        KF=>'SSH',
196    ) or die
197    $self->rsa->errstr(); # TODO avoid die
198    return ($public, $private);
199}
200
201sub store_rsa_key {
202    my ($self, $public, $private) = @_;
203    my $base = $self->_base;
204    $base->set_global_value('rsa_private_key',
205        encode_base64($private->serialize));
206    $base->set_global_value('rsa_public_key',
207        $public->serialize);
208    return;
209}
210
211sub private_key {
212    my ($self, $password) = @_;
213    my $base = $self->_base;
214    my $serialize = $base->get_global_value('rsa_private_key') or return;
215    my $privkey = Crypt::RSA::Key::Private::SSH->new;
216    $privkey->deserialize(String => [ decode_base64($serialize) ],
217        Passphrase => $password);
218    $privkey
219}
220
221sub get_rsa_password {
222    my ($self) = @_;
223    my $base = $self->_base;
224    my $sth = $base->db->prepare(q{
225        select "name", value from "user" join user_attributes_base
226        on "user".ikey = user_attributes_base.okey
227        where user_attributes_base.attr = 'encryptedPassword'
228    });
229    $sth->execute;
230    my %users;
231    while (my $res = $sth->fetchrow_hashref) {
232        $users{$res->{name}} = $res->{value};
233    }
234    %users
235}
236
2371;
Note: See TracBrowser for help on using the repository browser.