source: LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Objects.pm @ 178

Last change on this file since 178 was 178, checked in by nanardon, 15 years ago
  • fix cryptmd5 salt
  • w/o options sync_access use defaults values
  • Property svn:keywords set to Id Rev
File size: 6.8 KB
Line 
1package LATMOS::Accounts::Bases::Objects;
2
3use 5.010000;
4use strict;
5use warnings;
6
7our $VERSION = (q$Rev$ =~ /^Rev: (\d+) /)[0];
8
9=head1 NAME
10
11LATMOS::Accounts::Bases::Objects - Base class for account objects
12
13=head1 SYNOPSIS
14
15  use LATMOS::Accounts::Bases::Objects;
16  LATMOS::Accounts::Bases::Objects->new($base, $type, $id);
17
18=head1 DESCRIPTION
19
20=head1 FUNCTIONS
21
22=cut
23
24=head2 list($base)
25
26List object supported by this module existing in base $base
27
28Must be provide by object class
29
30    sub list {
31        my ($class, $base) = @_;
32    }
33
34=cut
35
36=head2 new($base, $id)
37
38Create a new object having $id as uid.
39
40=cut
41
42sub new {
43    my ($class, $base, $id, @args) = @_;
44    # So can be call as $class->SUPER::new()
45    bless {
46        _base => $base,
47        _type => ($class =~ m/[^:]*$/)[0],
48    }, $class;
49}
50
51# _new($base, $type, $id, ...)
52
53# Return a new object of type $type having unique identifier
54# $id, all remaining arguments are passed to the subclass.
55
56sub _new {
57    my ($class, $base, $otype, $id, @args) = @_;
58
59    # finding perl class:
60    my $pclass = $base->_load_obj_class($otype) or return;
61    my $newobj = "$pclass"->new($base, $id, @args) or return;
62    $newobj->{_base} = $base;
63    $newobj->{_type} = lc($otype);
64    $newobj->{_id} ||= $id;
65    return $newobj;
66}
67
68=head2 _create($class, $base, $id, %data)
69
70Must create a new object in database.
71
72Is called if underling base does not override create_object
73
74    sub _create(
75        my ($class, $base, $id, %data)
76    }
77
78=cut
79
80=head2 type
81
82Return the type of the object
83
84=cut
85
86sub type {
87    my ($self) = @_;
88    if (ref $self) {
89        return $self->{_type}
90    } else {
91        return lc(($self =~ /::([^:]+)$/)[0]);
92    }
93}
94
95=head2 base
96
97Return the base handle for this object.
98
99=cut
100
101sub base {
102    return $_[0]->{_base}
103}
104
105=head2 id
106
107Must return the unique identifier for this object
108
109=cut
110
111sub id {
112    my ($self) = @_;
113    $self->{_id}
114}
115
116=head2 list_canonical_fields($for)
117
118Object shortcut to get the list of field supported by the object.
119
120=cut
121
122sub list_canonical_fields {
123    my ($self, $for) = @_;
124    $self->base->list_canonical_fields($self->type, $for);
125}
126
127=head2 get_field_name($field, $for)
128
129Object shortcut to get the field name supported by the object.
130
131=cut
132
133sub get_field_name {
134    my ($self, $field, $for) = @_;
135    $self->base->get_field_name($self->type, $field, $for);
136}
137
138=head2 _canonical_fields
139
140Must return the list of field supported by the object.
141
142Notice this query will always come from the upstream data base,
143this function is just a facility to store data in the module, but the
144underling database can reply themself.
145
146Is call if underling base doesn't override list_canonical_fields()
147
148See list_canonical_fields().
149
150    sub _canonical_fields {
151        my ($self) = @_;
152    }
153
154=cut
155
156sub _delayed_fields {
157    my ($self)= @_;
158    return ();
159}
160
161=head2 _get_fields_name($field, $for)
162
163Return the fields name for canonical field $field.
164$for, if set, is a string containing 'r' for read, 'w' for write,
165depending usage context.
166
167    sub _get_field_name {
168        my ($self, $field, $for) = @_;
169    }
170
171=cut
172
173=head2 get_field($field)
174
175Return the value for $field, must be provide by data base.
176
177    sub get_field {
178        my ($self, $field)
179    }
180
181=cut
182
183=head2 get_c_fields($cfield)
184
185Return the value for canonical field $cfield.
186
187Call driver specific get_field_name() and get_field()
188
189=cut
190
191sub get_c_field {
192    my ($self, $cfield) = @_;
193    my $field = $self->base->get_field_name($self->type, $cfield, 'r') or return;
194    $self->get_field($field);
195}
196
197=head2 set_fields(%data)
198
199Set values for this object. %data is a list or peer field => values.
200
201    sub set_fields {
202        my ($self, %data) = @_;
203    }
204
205=cut
206
207=head2 set_c_fields(%data)
208
209Set values for this object. %data is a list or peer
210canonical field => values. Fields names are translated.
211
212=cut
213
214sub set_c_fields {
215    my ($self, %cdata) = @_;
216    my %data;
217    foreach my $cfield (keys %cdata) {
218        my $field = $self->base->get_field_name($self->type, $cfield) or next;
219        $data{$field} = $cdata{$cfield};
220    }
221    keys %data or return 1; # TODO: return an error ?
222    $self->set_fields(%data);
223}
224
225=head2 set_password($password)
226
227Set the password into the database, $password is the clear version
228of the password.
229
230This function store it into userPassword canonical field if supported
231using crypt unix and md5 algorythm (crypt md5), the salt is 8 random
232caracters.
233
234The base driver should override it if another encryption is need.
235
236=cut
237
238sub set_password {
239    my ($self, $clear_pass) = @_;
240    if (my $field = $self->base->get_field_name($self->type, 'userPassword')) {
241        my @salt_char = (('a' .. 'z'), ('A' .. 'Z'), (0 .. 9), '/', '.');
242        my $salt = join('', map { $salt_char[rand(scalar(@salt_char))] } (1 .. 8));
243        $self->set_fields($field, crypt($clear_pass, '$1$' . $salt));
244    }
245}
246
247sub search {
248    my ($class, $base, %filter) = @_;
249    my @results;
250    foreach my $id ($base->list_objects($class->type)) {
251        my $obj = $base->get_object($class->type, $id);
252        my $match = 1;
253        foreach my $field (keys %filter) {
254            my $value = $filter{$field};
255            $base->get_field_name($class->type, $field, 'r') or next;
256            my $fval = $obj->get_c_field($field) || '';
257            if ($value eq '*') {
258                if ($fval eq '') {
259                    $match = 0;
260                    last;
261                }
262            } elsif ($fval !~ m/\Q$value\E/i) {
263                $match = 0;
264                last;
265            }
266        }
267        push(@results, $id) if($match);
268    }
269    @results;
270}
271
272sub find_next_numeric_id {
273    my ($class, $base, $field, $min, $max) = @_;
274    $base->get_field_name($class->type, $field) or return;
275    $min ||= 
276        $field eq 'uidNumber' ? 500 :
277        $field eq 'gidNumber' ? 500 :
278        1;
279    $max ||= 65635;
280    my %existsid;
281    foreach ($base->list_objects($class->type)) {
282        my $obj = $base->get_object($class->type, $_) or next;
283        my $id = $obj->get_c_field($field) or next;
284        $existsid{$id} = 1;
285    }
286    for(my $i = $min; $i <= $max; $i++) {
287        $existsid{$i} or return $i;
288    }
289    return;
290}
291
2921;
293
294__END__
295
296=head1 CANICALS FIELDS
297
298=head2 User class
299
300=head2 Group class
301
302=head1 SEE ALSO
303
304Mention other useful documentation such as the documentation of
305related modules or operating system documentation (such as man pages
306in UNIX), or any relevant external documentation such as RFCs or
307standards.
308
309If you have a mailing list set up for your module, mention it here.
310
311If you have a web site set up for your module, mention it here.
312
313=head1 AUTHOR
314
315Thauvin Olivier, E<lt>olivier.thauvin.ipsl.fr@localdomainE<gt>
316
317=head1 COPYRIGHT AND LICENSE
318
319Copyright (C) 2009 by Thauvin Olivier
320
321This library is free software; you can redistribute it and/or modify
322it under the same terms as Perl itself, either Perl version 5.10.0 or,
323at your option, any later version of Perl 5 you may have available.
324
325=cut
Note: See TracBrowser for help on using the repository browser.