From 033af5c7de65c2ba38c45ba649ad29823bfb7141 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Sun, 15 Apr 2012 22:04:31 +0200 Subject: fripost-adduser: LDAP ready --- fripost-adduser | 205 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 166 insertions(+), 39 deletions(-) (limited to 'fripost-adduser') diff --git a/fripost-adduser b/fripost-adduser index 5c21ef1..f13868d 100755 --- a/fripost-adduser +++ b/fripost-adduser @@ -9,60 +9,174 @@ use utf8; fripost-adduser - Add a new mailbox to the system +=head1 SYNOPSIS + +B [B<--verbose>] [B<--debug>] [B<--pretend>] [I] +[B<--password=>I] + +=head1 DESCRIPTION + +B adds a new mailbox to the system, unless B<--pretend> +is set. +If no I or I are given, the user is prompted for them. +If I is not fully qualified, C is appended. + +=head1 OPTIONS + +=over 8 + +=item B<--prentend> + +Only simulates the insertion. (But still query the LDAP server to check +if I is already in the database.) + +=item B<--password=>I + +By default, the user is prompted for his/her new password, which is +hashed, salted and then inserted added to the LDAP entry. +By using B<--password>, I is inserted RAW in the database. +This can be useful if the user does not want to give the clear copy but +only a hash, for example. +Using this option disables the sending of credentials. + +=item B<--server_host=>I + +The LDAP URI to connect to. +The default value is read from the configuration file, see B. + +=item B<--bind_dn=>I + +The Distinguished Name (DN) to bind to the LDAP directory. +(If not set, B binds anonymously.) +The default value is read from the configuration file, see B. + +=item B<--bind_pw=>I + +The password to to bind with. +The default value is read from the configuration file, see B. + +=item B<--base_dn=>I + +The root DN for everything done by B. +The default value is read from the configuration file, see B. + +=item B<-v>, B<--verbose> + +Verbose mode. + +=item B<--debug> + +Debug mode. + +=back + +=head1 CONFIGURATION + +The configuration is read from the file C<$HOME/.fripost.yml>. +Valid keys include: + +=over 4 + +=item I + +The LDAP URI to connect to. It has to be set, either in the +configuration file, or using the command line option B<--server_host>. + +=item I + +The I e-mail address to use. Defaults to C. + +=item I + +The Distinguished Name (DN) to bind to the LDAP directory. +(If not set, B binds anonymously.) + +=item I + +The password to to bind with. + +=item I + +The root DN for everything done by B. + +=back + =cut use FindBin qw($Bin); use lib "$Bin/lib"; +use Env qw /HOME/; +use File::Spec::Functions; + use Data::Dumper; use Encode qw(encode); use File::Slurp qw(slurp); use Fripost::Password; use Fripost::Prompt; use Fripost::Schema; -use Getopt::Long; +use Getopt::Long qw /:config noauto_abbrev no_ignore_case + gnu_compat bundling permute nogetopt_compat + auto_version auto_help/; +use Pod::Usage; use IO::Prompt; -use MIME::Base64; use MIME::Lite; use MIME::QuotedPrint; use Template; use YAML::Syck; + ## Get command line options -our $conf = LoadFile('default.yml'); +our $conf = LoadFile( catfile ($HOME, '.fripost.yml') ); GetOptions( - 'dbi_dsn' => \$conf->{dbi_dsn}, - 'admuser=s' => \$conf->{admuser}, - 'admpass=s' => \$conf->{admpass}, - 'debug' => \$conf->{debug}, - 'pretend' => \$conf->{pretend}, - 'verbose' => \$conf->{verbose}, -) or die "Unable to get command line options."; - -sub dsay { say @_ if $conf->{debug}; } -sub vsay { say @_ if $conf->{verbose} || $conf->{debug}; } - -# Connect to the database -my $schema = Fripost::Schema->connect( - $conf->{dbi_dsn}, $conf->{admuser}, $conf->{admpass}, {} #\%dbi_params -); - + 'server_host' => \$conf->{server_host}, + 'base_dn=s' => \$conf->{base_dn}, + 'bind_dn=s' => \$conf->{bind_dn}, + 'bind_pw=s' => \$conf->{bind_pw}, + 'debug' => \$conf->{debug}, + 'pretend' => \$conf->{pretend}, + 'v|verbose' => \$conf->{verbose}, + 'password=s' => \$conf->{password}, + 'man' => sub { pod2usage(-exitstatus => 0, + -verbose => 2) } +) or pod2usage(2); + +sub dsay { say STDERR @_ if $conf->{debug}; } +sub vsay { say STDERR @_ if $conf->{verbose} || $conf->{debug}; } + +# Connect to the LDAP server +my $ldap = Fripost::Schema->new( $conf ); + + +# Define the new user my $user; { - my $username = prompt_email("New username: ", 'is_user'); - my $domain = (split /\@/, $username)[1]; - my $maildir = "$domain/". (split /\@/, $username)[0] . "/Maildir/"; # trailing slash important - my $active = 1; - my $password = prompt_password(); + my $username = $ARGV[0]; + $username //= prompt_email("New username: ", 'is_user'); + + # Default domain + $username .= '@fripost.org' unless $username =~ /\@.+$/; + + my ($domain, $login) = split /\@/, $username, 2; + my $maildir = "$domain/$login/Maildir/"; # Trailing slash important + my $isActive = 'TRUE'; + my ($userPassword, $clearPassword); + if ( defined $conf->{password} ) { + $userPassword = $conf->{password}; + } + else { + $clearPassword = 'hop'; #prompt_password(); + $userPassword = hash( undef, undef, $clearPassword ); + } $user = { - username => $username, - domain => $domain, - maildir => $maildir, - active => $active, - password => $password, + username => $username, + maildir => $maildir, + isActive => $isActive, + userPassword => $userPassword, }; + $user->{clearPassword} = $clearPassword unless defined $conf->{password}; say "User name: $user->{username}"; say "Password: (hidden)"; @@ -70,19 +184,25 @@ my $user; confirm_or_abort(); } -die "User already exists" - if ($schema->resultset('Mailbox')->search({ - username => $user->{username} })->count); +die "Error: User already exists.\n" + if $ldap->searchUser($user->{username})->count; + -## Insert user into database +## Insert the new user if ($conf->{pretend}) { - vsay "Did not create user since we are pretending." + vsay "Did not create user since we are pretending."; } else { - $schema->resultset('Mailbox')->new($user)->insert; - say "New account $user->{username} added."; + my %user = %$user; + delete $user{clearPassword}; + $ldap->addUser(\%user); + say "New account $user{username} added."; } +$ldap->unbind(); + + + ### Prepare sending emails my $tt = Template->new({ @@ -90,8 +210,11 @@ my $tt = Template->new({ INTERPOLATE => 1, }) || die "$Template::ERROR\n"; +my $admin_email = 'admin@fripost.org'; +$admin_email = $conf->{admin_email} if defined $conf->{admin_email}; my $msg = MIME::Lite->new( - From => encode('MIME-Q', 'Friposts administratörer') . ' ', + + From => encode('MIME-Q', 'Friposts administratörer') . ' <' .$admin_email. '>', Subject => encode('MIME-Q', 'Välkommen till Fripost!'), Encoding => 'quoted-printable', ); @@ -130,11 +253,11 @@ if (confirm("Subscribe user to announce mailing list? ")) { } ### Send login credentials to new user -{ +if (exists $user->{clearPassword}) { my ($vars, $data); $vars = { user => $user->{username}, - pass => $user->{password}, + pass => $user->{clearPassword}, }; $tt->process('user_info.tt', $vars, \$data) @@ -164,10 +287,14 @@ if (confirm("Subscribe user to announce mailing list? ")) { Stefan Kangas C<< >> +Guilhem Moulin C<< >> + =head1 COPYRIGHT Copyright 2010,2011 Stefan Kangas. +Copyright 2012 Guilhem Moulin. + =head1 LICENSE This program is free software; you can redistribute it and/or modify it -- cgit v1.2.3