source: trunk/lib/Vote/Model/Vote.pm @ 42

Last change on this file since 42 was 42, checked in by nanardon, 15 years ago
  • html and perl fixes
File size: 18.2 KB
Line 
1package Vote::Model::Vote;
2
3use strict;
4use warnings;
5use base 'Catalyst::Model';
6use Vote;
7use DBI;
8use Mail::Mailer;
9
10=head1 NAME
11
12Vote::Model::Vote - Catalyst Model
13
14=head1 DESCRIPTION
15
16Catalyst Model.
17
18=cut
19
20sub new {
21    my ($class) = @_;
22    my $db = DBI->connect(
23        'dbi:Pg:' . Vote->config->{db},
24        undef, undef,
25        {
26            RaiseError => 0,
27            AutoCommit => 0,
28            PrintWarn => 0,
29            PrintError => 1,
30        }
31    ) or return;
32   
33    bless {
34        db => $db,
35    }, $class;
36}
37
38sub db { $_[0]->{db} }
39
40sub random_string {
41    my $lenght = $_[-1] || 8;
42
43    return join('', map { ('a'..'z', 'A'..'Z', 0..9)[rand 62] } (1..$lenght));
44}
45
46sub gen_enc_passwd {
47    my ($self, $passwd) = @_;
48
49    $passwd ||= random_string(8);
50    return(crypt($passwd, '$1$' . random_string(8) . '$'));
51}
52
53sub list_comming_vote {
54    my ($self) = @_;
55
56    my $sth = $self->db->prepare_cached(
57        q{
58        select id from poll where
59        (start > now() and "end" > now()) or
60        "end" is null or start is null
61        }
62    );
63
64    $sth->execute;
65    my @id;
66    while(my $res = $sth->fetchrow_hashref) {
67        push(@id, $res->{id});
68    }
69
70    @id
71}
72
73
74sub list_running_vote {
75    my ($self) = @_;
76
77    my $sth = $self->db->prepare_cached(
78        q{
79        select id from poll where start < now() and "end" > now()
80        }
81    );
82
83    $sth->execute;
84    my @id;
85    while(my $res = $sth->fetchrow_hashref) {
86        push(@id, $res->{id});
87    }
88
89    @id
90}
91
92sub list_closed_vote {
93    my ($self) = @_;
94
95    my $sth = $self->db->prepare_cached(
96        q{
97        select id from poll where
98        start < now() and "end" < now()
99        }
100    );
101
102    $sth->execute;
103    my @id;
104    while(my $res = $sth->fetchrow_hashref) {
105        push(@id, $res->{id});
106    }
107
108    @id
109}
110
111sub vote_param {
112    my ($self, $voteid, %attr) = @_;
113
114    keys %attr or return;
115    my @online_f = qw(label start end owner password);
116
117    if (grep { exists($attr{$_}) } @online_f) {
118        my $sth = $self->db->prepare_cached(
119            q{update poll set } .
120            join(',', map { qq("$_" = ?) } grep { exists $attr{$_} } @online_f) .
121            q{ where id = ?}
122        );
123        $sth->execute((map { $attr{$_} } grep { exists $attr{$_} } @online_f), $voteid)
124            or do {
125            $self->db->rollback;
126            return;
127        };
128    }
129
130    # vote settings in settings table
131    foreach my $var (keys %attr) {
132        grep { $var eq $_ } @online_f and next;
133        $self->vote_set_settings($voteid, $var, $attr{$var});
134    }
135    1
136}
137
138sub vote_status {
139    my ($self, $id) = @_;
140   
141    my $sth = $self->db->prepare_cached(
142        q{
143        select (start > now() or start is null) as before,
144               "end" < now() as after
145        from poll
146        where id = ?
147        }
148    );
149    $sth->execute($id);
150    my $res = $sth->fetchrow_hashref;
151    $sth->finish;
152    $res or return;
153    if ($res->{before}) {
154        return 'BEFORE';
155    } elsif ($res->{after}) {
156        return 'AFTER';
157    } else {
158        return 'RUNNING';
159    }
160}
161
162sub vote_info {
163    my ($self, $id) = @_;
164
165    my $sth = $self->db->prepare_cached(
166        q{
167        select * from poll where id = ?
168        }
169    );
170
171    $sth->execute($id);
172    my $res = $sth->fetchrow_hashref;
173    $sth->finish;
174    if ($res) {
175        my $get = $self->db->prepare_cached(
176            q{select var, val from settings where poll = ?}
177        );
178        $get->execute($id);
179        while (my $set = $get->fetchrow_hashref) {
180            $res->{$set->{var}} = $set->{val};
181        }
182    }
183    $res
184}
185
186sub vote_set_settings {
187    my ($self, $poll, $var, $val) = @_;
188
189    my $upd = $self->db->prepare_cached(
190        q{update settings set val = ? where poll = ? and var = ?}
191    );
192
193    if ($upd->execute($val, $poll, $var) == 0) {
194        my $add = $self->db->prepare_cached(
195            q{insert into settings (poll, var, val) values (?,?,?)}
196        );
197
198        $add->execute($poll, $var, $val);
199    }
200}
201
202sub vote_signing {
203    my ($self, $id) = @_;
204
205    my $sth = $self->db->prepare_cached(
206        q{
207        select *, voting.key as vkey from voting left join signing
208        on signing.key = voting.key
209        where poll = ? order by voting.mail
210        }
211    );
212    $sth->execute($id);
213    my @people;
214    while (my $res = $sth->fetchrow_hashref) {
215        push(@people, $res);
216    }
217    @people
218}
219
220sub vote_voting {
221    my ($self, $voteid) = @_;
222
223    my $sth = $self->db->prepare_cached(
224        q{
225        select key from voting
226        where poll = ? order by voting.mail
227        }
228    );
229    $sth->execute($voteid);
230    my @people;
231    while (my $res = $sth->fetchrow_hashref) {
232        push(@people, $res->{key});
233    }
234    @people
235}
236
237sub voting_info {
238    my ($self, $id) = @_;
239
240    my $sth = $self->db->prepare_cached(
241        q{
242        select *, voting.key as vkey from voting left join signing
243        on signing.key = voting.key
244        where voting.key = ?
245        }
246    );
247    $sth->execute($id);
248
249    my $res = $sth->fetchrow_hashref;
250    $sth->finish;
251    $res
252}
253
254sub vote_choices {
255    my ($self, $id) = @_;
256
257    my $sth = $self->db->prepare_cached(
258        q{
259        select key from choice where poll = ?
260        order by label
261        }
262    );
263    $sth->execute($id);
264    my @ch;
265    while (my $res = $sth->fetchrow_hashref) {
266        push(@ch, $res->{key});
267    }
268    @ch
269}
270
271sub choice_info {
272    my ($self, $chid) = @_;
273    my $sth = $self->db->prepare_cached(
274        q{select * from choice where key = ?}
275    );
276    $sth->execute($chid);
277    my $res = $sth->fetchrow_hashref;
278    $sth->finish;
279    $res
280}
281
282sub vote_add_choice {
283    my ($self, $voteid, $label) = @_;
284
285    my $sth = $self->db->prepare_cached(
286        q{insert into choice (poll, label) values (?,?)}
287    );
288
289    $sth->execute($voteid, $label) or do {
290        $self->db->rollback;
291        return;
292    };
293
294    1
295}
296
297sub modify_choice {
298    my ($self, $chid, $label) = @_;
299
300    my $sth = $self->db->prepare_cached(
301        q{update choice set label = ? where key = ?}
302    );
303    $sth->execute($label, $chid);
304}
305
306sub delete_choice {
307    my ($self, $chid) = @_;
308
309    my $sth = $self->db->prepare_cached(
310        q{delete from choice where key = ?}
311    );
312
313    $sth->execute($chid);
314}
315
316sub voting_info_id {
317    my ($self, $mail, $voteid) = @_;
318
319    my $sth = $self->db->prepare_cached(
320        q{
321        select * from voting where mail = ? and poll = ?
322        }
323    );
324    $sth->execute($mail, $voteid);
325    my $res = $sth->fetchrow_hashref();
326    $sth->finish;
327    $res
328}
329
330sub _register_signing {
331    my ($self, $mail, $voteid, $referal) = @_;
332
333    my $vinfo = $self->voting_info_id($mail, $voteid) or return;
334
335    my $sth = $self->db->prepare_cached(
336        q{
337        insert into signing (key, referal) values (?,?)
338        }
339    );
340    $sth->execute($vinfo->{key}, $referal) or do {
341        $self->db->rollback;
342        return;
343    };
344
345    1;
346}
347
348sub gen_uid {
349    unpack("H*", join("", map { chr(rand(256)) } (0..15)))
350}
351
352sub _register_ballot {
353    my ($self, $voteid, $choice, $fchoice) = @_;
354
355    my $addb = $self->db->prepare_cached(
356        q{
357        insert into ballot (id, poll, invalid) values (?,?,?)
358        }
359    );
360    my $uid = gen_uid;
361    $addb->execute($uid, $voteid, scalar(@{$fchoice || []}) ? undef : 'f') or do {
362        self->db->rollback;
363        return;
364    };
365
366    my $addbc = $self->db->prepare_cached(
367        q{
368        insert into ballot_item (id, value, fromlist) values (?,?,?)
369        }
370    );
371    foreach (@{ $choice || []}) {
372        $addbc->execute($uid, $_, 't') or do {
373            $self->db->rollback;
374            return;
375        };
376    }
377    foreach (@{ $fchoice || []}) {
378        $addbc->execute($uid, $_, 'f') or do {
379            $self->db->rollback;
380            return;
381        };
382    }
383
384    $uid;
385}
386
387sub register_ballot {
388    my ($self, $vid, $voteid, $choice, $fchoice, $referal) = @_;
389
390    # First we register voting has voted
391    $self->_register_signing($vid, $voteid, $referal) or return; # TODO error ?
392
393    # registring choices
394    my $uid = $self->_register_ballot($voteid, $choice, $fchoice) or return;
395
396    # everything went fine, saving!
397    $self->db->commit;
398
399    $uid
400}
401
402sub vote_voting_count {
403    my ($self, $id) = @_;
404
405    my $sth = $self->db->prepare_cached(
406        q{
407        select count(*) from voting
408        where poll = ?
409        }
410    );
411    $sth->execute($id);
412    my $res = $sth->fetchrow_hashref;
413    $sth->finish;
414    $res->{count}
415}
416
417sub signing_count { vote_signing_count(@_) }
418
419sub vote_signing_count {
420    my ($self, $voteid) = @_;
421
422    my $sth = $self->db->prepare_cached(
423        q{
424        select count(*) from signing join voting
425        on voting.key = signing.key where poll = ?
426        }
427    );
428
429    $sth->execute($voteid);
430    my $res = $sth->fetchrow_hashref;
431    $sth->finish;
432    $res->{count}
433}
434
435sub ballot_count { vote_ballot_count(@_) }
436
437sub vote_ballot_count {
438    my ($self, $voteid) = @_;
439
440    my $sth = $self->db->prepare_cached(
441        q{
442        select count(*) from ballot where poll = ?
443        }
444    );
445
446    $sth->execute($voteid);
447    my $res = $sth->fetchrow_hashref;
448    $sth->finish;
449    $res->{count}
450}
451
452sub ballot_count_nonull { vote_ballot_count_nonull(@_) }
453
454sub vote_ballot_count_nonull {
455    my ($self, $voteid) = @_;
456
457    my $sth = $self->db->prepare_cached(
458        q{
459        select count(*) from ballot where poll = ?
460        and id in (select id from ballot_item) and
461        (invalid = 'false' or invalid is null)
462        }
463    );
464
465    $sth->execute($voteid);
466    my $res = $sth->fetchrow_hashref;
467    $sth->finish;
468    $res->{count}
469}
470
471sub auth_voting {
472    my ($self, $poll, $mail, $password) = @_;
473    my $userinfo = $self->voting_info_id($mail, $poll) or return;
474
475    $userinfo->{passwd} or return;
476    if (crypt($password, $userinfo->{passwd} || '') eq $userinfo->{passwd}) {
477        return 1;
478    } else {
479        return 0;
480    }
481}
482
483sub auth_poll {
484    my ($self, $voteid, $passwd) = @_;
485
486    my $vinfo = $self->vote_info($voteid) or return;
487
488    $vinfo->{password} or return;
489    if (crypt($passwd, $vinfo->{password} || '') eq $vinfo->{password}) {
490        return 1;
491    } else {
492        return 0;
493    }
494}
495
496sub voting_has_sign {
497    my ($self, $poll, $user) = @_;
498
499    my $sth = $self->db->prepare_cached(
500        q{
501        select date from signing join voting
502        on voting.key = signing.key
503        where poll = ? and mail = ?
504        }
505    );
506
507    $sth->execute($poll, $user);
508    my $res = $sth->fetchrow_hashref;
509    $sth->finish;
510    return $res->{date}
511}
512
513# Requete de decompte des voix:
514
515sub vote_results_count {
516    my ($self, $voteid) = @_;
517
518    my $sth = $self->db->prepare(
519        q{
520        select count(ballot.id), value from ballot left join ballot_item
521        on ballot.id = ballot_item.id where ballot.poll = ? and invalid = 'false'
522        group by value
523        order by count
524        }
525    );
526    $sth->execute($voteid);
527    my @results;
528    while (my $res = $sth->fetchrow_hashref) {
529        push(@results, $res);
530    }
531    @results;
532}
533
534sub vote_results_nonull {
535    my ($self, $voteid) = @_;
536
537    my $sth = $self->db->prepare(
538        q{
539        select count(ballot.id), coalesce(corrected, value) as value
540        from ballot join ballot_item
541        on ballot.id = ballot_item.id where ballot.poll = ? and
542        (invalid = 'false' or invalid is null)
543        group by coalesce(corrected, value)
544        order by count desc
545        }
546    );
547    $sth->execute($voteid);
548    my @results;
549    while (my $res = $sth->fetchrow_hashref) {
550        push(@results, $res);
551    }
552    \@results;
553}
554
555sub list_vote_ballot {
556    my ($self, $voteid) = @_;
557
558    my $sth = $self->db->prepare_cached(
559        q{
560        select id from ballot where poll = ?
561        order by id
562        }
563    );
564    $sth->execute($voteid);
565    my @ids;
566    while (my $res = $sth->fetchrow_hashref) {
567        push(@ids, $res->{id});
568    }
569    @ids
570}
571
572sub list_vote_ballot_needvalid {
573    my ($self, $voteid) = @_;
574
575    my $sth = $self->db->prepare_cached(
576        q{
577        select id from ballot where poll = ?
578        and invalid is null order by id
579        }
580    );
581    $sth->execute($voteid);
582    my @ids;
583    while (my $res = $sth->fetchrow_hashref) {
584        push(@ids, $res->{id});
585    }
586    @ids
587}
588
589sub ballot_info {
590    my ($self, $ballotid) = @_;
591
592    my $sth = $self->db->prepare_cached(
593        q{ select * from ballot where id = ? }
594    );
595
596    $sth->execute($ballotid);
597    my $res = $sth->fetchrow_hashref;
598    $sth->finish;
599    $res
600}
601
602sub mark_ballot_invalid {
603    my ($self, $ballotid, $invalid) = @_;
604
605    my $sth = $self->db->prepare_cached(
606        q{update ballot set invalid = ? where id = ?}
607    );
608
609    $sth->execute($invalid ? 't' : 'f', $ballotid);
610}
611
612sub ballot_items {
613    my ($self, $ballotid) = @_;
614
615    my $sth = $self->db->prepare_cached(
616        q{select *, value as v from ballot_item where id = ?}
617    );
618    $sth->execute($ballotid);
619    my @ids;
620    while (my $res = $sth->fetchrow_hashref) {
621        push(@ids, $res);
622    }
623    \@ids
624}
625
626sub vote_ballot_untrusted_values {
627    my ($self, $voteid) = @_;
628
629    my $getval = $self->db->prepare_cached(
630        q{
631        select value from ballot join ballot_item
632        on ballot.id = ballot_item.id
633        where poll = ? and fromlist = false
634        group by value order by value
635        }
636    );
637    $getval->execute($voteid);
638    my @vals;
639    while (my $res = $getval->fetchrow_hashref) {
640        push(@vals, $res->{value});
641    }
642    @vals
643}
644
645sub vote_ballot_values {
646    my ($self, $voteid) = @_;
647
648    my $getval = $self->db->prepare_cached(
649        q{
650        select value from ballot join ballot_item
651        on ballot.id = ballot_item.id
652        where poll = ?
653        group by value order by value
654        }
655    );
656    $getval->execute($voteid);
657    my @vals;
658    while (my $res = $getval->fetchrow_hashref) {
659        push(@vals, $res->{value});
660    }
661    @vals
662}
663
664sub vote_map_value {
665    my ($self, $voteid, $from, $to) = @_;
666
667    my $sth = $self->db->prepare_cached(
668        q{
669        update ballot_item set corrected = ? where
670        id in (select id from ballot where poll = ?)
671        and value = ?
672        }
673    );
674
675    $sth->execute($to, $voteid, $from) or $self->db->rollback;
676    $self->db->commit;
677}
678
679sub addupd_voting {
680    my ($self, $voteid, $mail, $id) = @_;
681
682    my $upd = $self->db->prepare_cached(
683        q{
684        update voting set label = ? where mail = ? and poll = ?
685        }
686    );
687
688    if ($upd->execute($id, $mail, $voteid) == 0) {
689        my $add = $self->db->prepare_cached(q{
690            insert into voting (poll, label, mail) values (?,?,?)
691        });
692
693        $add->execute($voteid, $id, $mail);
694    }
695}
696
697sub delete_voting {
698    my ($self, $key) = @_;
699
700    my $sth = $self->db->prepare_cached(
701        q{delete from voting where key = ?}
702    );
703
704    $sth->execute($key);
705}
706
707sub voting_from_file {
708    my ($self, $voteid, $fh, $delete) = @_;
709
710    if ($delete) {
711        my $sth = $self->db->prepare(q{delete from voting where poll = ?});
712        $sth->execute($voteid);
713    }
714
715    while (my $line = <$fh>) {
716        chomp($line);
717        warn $line;
718        my ($id, $mail) = split(';', $line);
719        $id && $mail or do {
720            $self->db->rollback;
721            return;
722        };
723        $self->addupd_voting($voteid, $id, $mail);
724    }
725    1;
726}
727
728sub mail_passwd_ifnul {
729    my ($self, $voteid, $mailinfo) = @_;
730
731    my $list_voting = $self->db->prepare_cached(
732        q{select key from voting where poll = ? and passwd is null or passwd = ''}
733    );
734
735    $list_voting->execute($voteid);
736    while (my $res = $list_voting->fetchrow_hashref) {
737        $self->mail_voting_passwd($res->{key}, $mailinfo);
738    }
739}
740
741sub mail_voting_passwd {
742    my ($self, $id, $mailinfo) = @_;
743   
744    my $vinfo = $self->voting_info($id) or return;
745    my $voteinfo = $self->vote_info($vinfo->{poll});
746
747    my $passwd = random_string(8);
748    my $encpasswd = $self->gen_enc_passwd($passwd);
749
750    my $upd_voting = $self->db->prepare_cached(
751        q{update voting set passwd = ? where key = ?}
752    );
753
754    $upd_voting->execute($encpasswd, $id);
755
756    # TODO complete this properly:
757    my $mailer = new Mail::Mailer 'smtp', Server => 'mailhost';
758    $mailer->open({
759        From => 'Voting system <nomail@nomail.com>',
760        To => $vinfo->{mail},
761        Subject => 'Vote passwd',
762    });
763    print $mailer <<EOF;
764Vous êtes convié à voter:
765$voteinfo->{label}
766
767Votre identifiant est: $vinfo->{mail}
768Votre mot de passe est: $passwd
769
770Cordialement.
771EOF
772    $mailer->close;
773
774    $self->db->commit;
775}
776
777sub poll_request_info {
778    my ($self, $rid) = @_;
779
780    my $sth = $self->db->prepare_cached(
781        q{select * from poll_request where id = ?}
782    );
783
784    $sth->execute($rid);
785    my $res = $sth->fetchrow_hashref;
786    $sth->finish;
787    $res
788}
789
790sub poll_from_request {
791    my ($self, $rid, $passwd) = @_;
792    my $rinfo = $self->poll_request_info($rid) or return;
793
794    my $encpasswd = $self->gen_enc_passwd($passwd);
795
796    my $getpollid = $self->db->prepare_cached(
797        q{select nextval('poll_id_seq')}
798    );
799    $getpollid->execute();
800    my $newpollid = $getpollid->fetchrow_hashref->{nextval};
801   
802    my $newpoll = $self->db->prepare_cached(
803        q{insert into poll (id, label, owner, password) values (?,?,?,?)}
804    );
805
806    $newpoll->execute($newpollid, $rinfo->{label}, $rinfo->{mail}, $encpasswd);
807    # set some default
808    $self->vote_param($newpollid,
809        free_choice => 0,
810        choice_count => 1,
811    );     
812
813    my $delreq = $self->db->prepare_cached(
814        q{delete from poll_request where id = ?}
815    );
816
817    $delreq->execute($rid);
818    $self->db->commit;
819
820    $newpollid
821}
822
823sub create_poll_request {
824    my ($self, %info) = @_;
825
826    $info{mail} or return;
827    my $addreq = $self->db->prepare_cached(
828        q{insert into poll_request (id, label, mail) values (?,?,?)}
829    );
830
831    my $reqid = gen_uid;
832
833    $addreq->execute($reqid, $info{label}, $info{mail});
834    my $mailer = new Mail::Mailer 'smtp', Server => 'mailhost';
835    $mailer->open({
836        From => 'Voting system <nomail@nomail.com>',
837        To => $info{mail},
838        Subject => 'Votre nouveau vote',
839    });
840    print $mailer <<EOF;
841
842Vous avez demandez la création d'un nouveau vote:
843$info{label}
844
845Pour valider votre demande, veuiller allez visitez la page:
846$info{url}/$reqid
847
848A bientot
849EOF
850    $mailer->close;
851    $self->db->commit;
852    1;
853}
854
855=head1 AUTHOR
856
857Thauvin Olivier
858
859=head1 LICENSE
860
861This library is free software, you can redistribute it and/or modify
862it under the same terms as Perl itself.
863
864=cut
865
8661;
Note: See TracBrowser for help on using the repository browser.