From 2544f6ea8a6a748416e33014fec7ee66060a600d Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Sat, 23 Feb 2013 21:23:02 +0100 Subject: Fripost::Schema::Pending --- lib/Fripost/Schema/Pending.pm | 166 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 lib/Fripost/Schema/Pending.pm diff --git a/lib/Fripost/Schema/Pending.pm b/lib/Fripost/Schema/Pending.pm new file mode 100644 index 0000000..868f591 --- /dev/null +++ b/lib/Fripost/Schema/Pending.pm @@ -0,0 +1,166 @@ +package Fripost::Schema::Pending; + +=head1 NAME + +Pending.pm - Manage pending entries + +=head1 DESCRIPTION + +This module abstracts the LDAP schema definition and provides methods to +unlock, list or delete pending entries. + +=cut + +use 5.010_000; +use strict; +use warnings; +use utf8; + +use parent 'Fripost::Schema::Auth'; +use Fripost::Schema::Util qw/ldap_error dn2mail ldap_and_filter/; +use POSIX 'strftime'; + + +=head1 METHODS + +=over 4 + +=item B (I, I, I) + +Unlock the pending I, locked with I. I may be left +undefined if I is marked as pending, but is not locked. + +=over 4 + +=item B<-dry-run> => 0|1 + +Merely simulate the unlock. I is still checked to be a valid code +when defined. + +=back + +Errors can be caught with options B<-die> and B<-error>; See +B for details. + +=cut + + +sub unlock { + my $self = shift; + my $name = shift; + my $token = shift; + my %options = @_; + + # Nothing to do after an error. + return if $options{'-error'} && ${$options{'-error'}}; + + my $dn = $self->mail2dn( $name ); + my %delete = (objectClass => 'FripostPendingEntry'); + if ($token) { + my $mesg = $self->ldap->compare( $dn + , attr => 'fripostPendingToken' + , value => $token ); + my $catch = { Net::LDAP::Constant::LDAP_COMPARE_TRUE => 0 + , Net::LDAP::Constant::LDAP_COMPARE_FALSE => + "Wrong unlock code for ‘".$name."’" + }; + ldap_error($mesg, %options, -die => $catch) // return; + return 1 if $options{'-dry-run'}; + $delete{fripostPendingToken} = []; + } + + my $mesg = $self->ldap->modify( $dn, delete => \%delete ); + ldap_error($mesg, %options); +} + + +=item B (I) + +List all pending entries. + +=over 4 + +=item B<-delete> => 0|1 + +When set, delete all found entries. + +=item B<-quiet> => 0|1 + +When set, do not print the list of found entries. + +=item B<-max-age> + +When set, limit found entries to those that were created before the +given date, in second since epoch. + +=back + +Errors can be caught with options B<-die> and B<-error>; See +B for details. + +=cut + + +sub find { + my $self = shift; + my %options = @_; + + # Nothing to do after an error. + return if $options{'-error'} && ${$options{'-error'}}; + + my @filter = 'objectClass=FripostPendingEntry'; + if ($options{'-max-age'}) { + my $now = int(strftime "%s", gmtime); + my $maxdate = Net::LDAP::Util::escape_filter_value( + strftime ("%Y%m%d%H%M%SZ", + localtime($now - $options{'-max-age'})) + ); + push @filter, "createTimestamp<=$maxdate" + } + + my $base = Fripost::Schema::Util::canonical_dn(@{$self->suffix}); + my $found = $self->ldap->search ( + base => $base, + scope => 'subtree', + deref => 'never', + filter => ldap_and_filter (@filter), + attrs => [ '1.1' ], + (!$options{'-delete'} && $options{'-quiet'} ? () : + callback => + sub { + my ($mesg, $obj) = @_; + if (defined $obj and $obj->isa('Net::LDAP::Entry')) { + print STDERR "Deleting DN ".$obj->dn."\n" + unless $options{'-quiet'}; + if ($options{'-delete'}) { + $obj->delete; + my $mesg = $obj->update($self->ldap); + ldap_error($mesg, %options) // return; + } + $mesg->pop_entry; + } + }) + ); + ldap_error($found, %options); +} + +=back + +=head1 AUTHOR + +Guilhem Moulin C<< >> + +=head1 COPYRIGHT + +Copyright 2012,2013 Guilhem Moulin. + +=head1 LICENSE + +This program is free software; you can redistribute it and/or modify it +under the same terms as perl itself. + +=cut + +1; + +__END__ -- cgit v1.2.3