source: trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/Aliases.pm @ 1821

Last change on this file since 1821 was 1821, checked in by nanardon, 8 years ago

Ensure forward update return true

File size: 9.6 KB
Line 
1package LATMOS::Accounts::Bases::Sql::Aliases;
2
3use 5.010000;
4use strict;
5use warnings;
6
7use base qw(LATMOS::Accounts::Bases::Sql::objects);
8use LATMOS::Accounts::Log;
9use LATMOS::Accounts::I18N;
10
11our $VERSION = (q$Rev: 341 $ =~ /^Rev: (\d+) /)[0];
12
13=head1 NAME
14
15LATMOS::Accounts::Bases::Sql::Aliases - Mail alias object
16
17=cut
18
19sub _object_table { 'aliases' }
20
21sub _key_field { 'name' }
22
23sub _has_extended_attributes { 1 }
24
25sub _get_attr_schema {
26    my ($class, $base) = @_;
27
28   
29    my $recurs = sub {
30        my ($attr) = @_;
31        my ($self) = $attr->object;
32        my $field = $attr->name; 
33
34        my $sth = $self->db->prepare_cached(q{
35            select name from aliases where array[lower($1)] <@
36            string_to_array(lower(array_to_string("forward", ',')), ',')
37            });
38        my @tocheck = ($field =~ /^sameforward$/
39            ? $self->get_attributes('forward')
40            : ($field =~ /^samedestination$/ 
41                ? $self->get_attributes('finalpoint')
42                : $self->id));
43        my @results;
44        my @already;
45        while (my $next = shift(@tocheck)) {
46            # endless loop detection
47            grep { $next eq $_ } @already and do {
48                push(@results, $next);
49                next;
50            };
51            push(@already, $next);
52            $sth->execute($next);
53            while (my $res = $sth->fetchrow_hashref) {
54                push(@tocheck, $res->{name});
55                $res->{name} eq $self->id and next;
56                push(@results, $res->{name});
57            }
58            $field =~ /^(parents|sameforward)$/ and last; # No recursive search
59        }
60        return scalar(@results) <= 1 ? $results[0] : \@results;
61    };
62
63    $class->SUPER::_get_attr_schema($base,
64        {
65            name            => {
66                ro => 1,
67            },
68            forward         => {
69                label => l('Forward'),
70                delayed => 1,
71                mandatory => 1,
72                multiple => 1,
73                monitored => 1,
74                set => sub {
75                    my ($self, $data) = @_;
76                    my $sql = $data
77                        ? '{' . join(',', map { $_ =~ s/\\/\\\\/g; '"' .$_.'"' } @$data) . '}'
78                        : undef;
79                    $base->db->do(
80                        q{UPDATE aliases SET forward = }
81                        . $base->db->quote($sql) . q{ where name = } .
82                        $base->db->quote($self->object->id)
83                    );
84                    return 1;
85                },
86                ro => sub {
87                    $_[0] && $_[0]->_get_c_field('autoMemberFilter') ? 1 : 0
88                },
89            },
90            rfc822MailMember => {
91                iname => 'forward',
92                hidden => 1,
93                ro => 1,
94                multiple => 1,
95            },
96            finalpoint      => {
97                ro => 1,
98                multiple => 1,
99                get => sub {
100                    my ($self) = @_;
101                    my $sth = $self->base->db->prepare_cached(q{
102                        select forward from aliases where lower(name) = lower(?)
103                        limit 1
104                        });
105                    my @res = ();
106                    my @next = @{ $self->object->get_field('forward') || [] };
107                    my %seen;
108                    while (my $next = shift(@next)) {
109                        # Avoiding loop:
110                        $seen{$next} and do {
111                            push(@res, $next);
112                            next;
113                        };
114                        $seen{$next} = 1;
115                        $sth->execute($next);
116                        if (my $res = $sth->fetchrow_hashref) {
117                            push(@next, @{ $res->{forward} });
118                        } else {
119                            push(@res, $next);
120                        }
121                    }
122                    $sth->finish;
123                    return @res ? \@res : undef;
124                },
125                label => l('Final recipient')
126            },
127            parents         => {
128                ro => 1,
129                get => $recurs,
130                label => l('Parents')
131            },
132            anyparents      => {
133                ro => 1,
134                get => $recurs,
135            },
136            sameforward     => {
137                ro => 1,
138                multiple => 1,
139                get => $recurs,
140            },
141            samedestination => {
142                ro => 1,
143                multiple => 1,
144                get => $recurs,
145            },
146            user            => {
147                ro => 1,
148                reference => 'user',
149                multiple => 1,
150                label => l('User'),
151            },
152            expire    => {
153                inline => 1,
154                formtype => 'DATE',
155                label => l('Expire'),
156            },
157            comment => {
158                label => l('Comment'),
159            },
160            autoMemberFilter => {
161                multiple => 1,
162                set => sub {
163                    my ($self, $data) = @_;
164                    $self->object->set_fields($self->name, $data) or return;
165                    $self->object->populate_dyn_aliases;
166                    return 1;
167                },
168                label => l('Automatics filters'),
169            },
170            autoFromSutype => {
171                multiple => 1,
172                set => sub {
173                    my ($self, $data) = @_;
174                    $self->object->set_fields($self->name, $data) or return;
175                    $self->object->populate_dyn_aliases;
176                    return 1;
177                },
178                label => l('From group type'),
179            },
180            autoExclude => {
181                multiple => 1,
182                reference => 'user',
183                label => l('User excluded'),
184            },
185        }
186    )
187}
188
189sub new {
190    my ($class, $base, $id) = @_;
191    my $sth = $base->db->prepare_cached(q{
192        select name from aliases where lower(name) = lower(?)
193    });
194    $sth->execute($id);
195    my $res = $sth->fetchrow_hashref;
196    $sth->finish;
197    if ($res) {
198        $class->SUPER::new($base, $res->{name});
199    } else {
200        return;
201    }
202}
203
204sub _create {
205    my ($class, $base, $id, %data) = @_;
206    $data{'forward'} = [ $data{'forward'} ] unless(ref $data{'forward'});
207    @{$data{'forward'}} = grep { $_ } @{$data{'forward'}};
208    my $sth = $base->db->prepare_cached(q{
209        select name from aliases where lower(name) = lower(?)
210        limit 1
211        });
212    $sth->execute($id);
213    my $res = $sth->fetchrow_hashref;
214    $sth->finish;
215    if ($res) {
216        $base->log(LA_ERR, "Aliases %s already exists as %s",
217            $id, $res->{name});
218        return;
219    } else {
220        return $class->SUPER::_create($base, $id, %data);
221    }
222}
223
224sub set_fields {
225    my ($self, %data) = @_;
226
227    if ($data{forward}) {
228        $data{forward} = ref $data{forward}
229            ? $data{forward}
230            : [ $data{forward} ];
231    }
232
233    $self->SUPER::set_fields(%data);
234}
235
236=head2 populate_dyn_aliases
237
238Synchronise aliase's forward according filter set into C<autoMemberFilter> attribute.
239
240=cut
241
242sub populate_dyn_aliases {
243    my ($self) = @_;
244
245
246    if (!$self->get_field('autoMemberFilter')
247     && !$self->get_field('autoFromSutype') ) {
248        return 0;
249    }
250
251    $self->base->log(LA_DEBUG,
252        "Populating aliases %s from autoMemberFilter attribute",
253        $self->id
254    );
255
256    my $listh = $self->base->db->prepare_cached(q{
257        SELECT forward FROM aliases WHERE ikey = ?
258    });
259
260    $listh->execute($self->Iid);
261    my $res = $listh->fetchrow_hashref;
262    $listh->finish;
263    my $currentForward = $res->{forward} || [];
264
265    my %email = $self->base->attributes_summary_by_object('user', 'mail');
266    my %users;
267
268    my $autoex = $self->get_field('autoExclude');
269    my %exclude = map { $_ => 1 } grep { $_  } (ref $autoex ? @$autoex : $autoex);
270
271    if (my $filter = $self->get_field('autoMemberFilter')) {
272        $users{$_} = 1 foreach( $self->base->search_objects('user', ref $filter ? @{ $filter } : $filter) );
273    }
274
275    if (my $filter = $self->get_field('autoFromSutype')) {
276        my @suTypeFilter = map { "sutype=$_" } (ref $filter ? @{ $filter } : $filter);
277        foreach my $group ($self->base->search_objects('group', @suTypeFilter)) {
278            foreach ($self->base->search_objects('user', "memberOf=$group")) {
279                $users{$_} = 1;
280            }
281        }
282    }
283
284    my %forward = ();
285
286    foreach my $user (keys %users) {
287        $exclude{$user} and next;
288        $email{$user} or next;
289        my $mail = $email{$user}->[0] or next;
290        $forward{$mail} = 1;
291    }
292
293    if (join(',', sort @$currentForward) eq join(',', sort keys %forward)) {
294        $self->base->log(
295            LA_DEBUG,
296            "No need to update alias %s for autoMemberFilter settings",
297            $self->id,
298        );
299        return 0;
300    }
301
302    my $sth = $self->base->db->prepare_cached(
303        'UPDATE aliases SET forward = ? WHERE ikey = ?'
304    );
305    if (!$sth->execute([ sort keys %forward ], $self->Iid)) {
306        $self->base->log(LA_ERR, "Cannot update forward for aliases %s: %s", $self->id, $sth->errstr());
307        return;
308    }
309
310    return 1;
311}
312
3131;
314
315__END__
316
317=head1 SEE ALSO
318
319L<LATMOS::Accounts::Bases::Sql>
320
321L<LATMOS::Accounts::Bases::Sql::Revaliases>
322
323=head1 AUTHOR
324
325Olivier Thauvin, E<lt>olivier.thauvin@latmos.ipsl.frE<gt>
326
327=head1 COPYRIGHT AND LICENSE
328
329Copyright (C) 2008, 2009 CNRS SA/CETP/LATMOS
330
331This library is free software; you can redistribute it and/or modify
332it under the same terms as Perl itself, either Perl version 5.10.0 or,
333at your option, any later version of Perl 5 you may have available.
334
335
336=cut
Note: See TracBrowser for help on using the repository browser.