From 095c0cc8d7561b23e5a6cbe5675c4c4380c9e6c7 Mon Sep 17 00:00:00 2001 From: Xavier Guimard Date: Sat, 14 Jan 2017 19:31:48 +0000 Subject: [PATCH] Register/Demo (#595) --- lemonldap-ng-portal/MANIFEST | 3 +- .../lib/Lemonldap/NG/Portal/Lib/SMTP.pm | 31 ++++--- .../Lemonldap/NG/Portal/Plugins/Register.pm | 68 +++++++++------- .../lib/Lemonldap/NG/Portal/Register/Demo.pm | 29 ++++--- .../lib/Lemonldap/NG/Portal/UserDB/Demo.pm | 32 ++++---- .../static => templates}/common/bullet_go.png | Bin .../site/templates/common/key.png | Bin 0 -> 612 bytes .../site/templates/common/mail_confirm.tpl | 2 +- .../common/mail_register_confirm.tpl | 2 +- .../templates/common/mail_register_done.tpl | 4 +- lemonldap-ng-portal/t/41-Register-Demo.t | 77 ++++++++++++++++-- 11 files changed, 162 insertions(+), 86 deletions(-) rename lemonldap-ng-portal/site/{htdocs/static => templates}/common/bullet_go.png (100%) create mode 100644 lemonldap-ng-portal/site/templates/common/key.png diff --git a/lemonldap-ng-portal/MANIFEST b/lemonldap-ng-portal/MANIFEST index d5ab6a299..033ba31e9 100644 --- a/lemonldap-ng-portal/MANIFEST +++ b/lemonldap-ng-portal/MANIFEST @@ -197,7 +197,6 @@ site/htdocs/static/common/backgrounds/1280px-Cedar_Breaks_National_Monument_part site/htdocs/static/common/backgrounds/1280px-Parry_Peak_from_Winter_Park.jpg site/htdocs/static/common/backgrounds/Aletschgletscher_mit_Pinus_cembra1.jpg site/htdocs/static/common/BrowserID.png -site/htdocs/static/common/bullet_go.png site/htdocs/static/common/calendar.png site/htdocs/static/common/cancel.png site/htdocs/static/common/CAS.png @@ -279,6 +278,8 @@ site/templates/bootstrap/register.tpl site/templates/bootstrap/standardform.tpl site/templates/bootstrap/yubikeyform.tpl site/templates/common/background.tpl +site/templates/common/bullet_go.png +site/templates/common/key.png site/templates/common/mail_confirm.tpl site/templates/common/mail_footer.tpl site/templates/common/mail_header.tpl diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SMTP.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SMTP.pm index e5dde9250..eefce1883 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SMTP.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/SMTP.pm @@ -42,19 +42,20 @@ sub gen_password { # @return boolean result sub send_mail { my ( $self, $mail, $subject, $body, $html ) = @_; + $self->lmLog( "send_mail called to send \"$subject\" to $mail", 'debug' ); # Encode the body with the given charset $body = encode( $self->charset, $body ); $subject = encode( $self->charset, $subject ); # Debug messages - $self->lmLog( "SMTP From " . $self->{mailFrom}, 'debug' ); - $self->lmLog( "SMTP To " . $mail, 'debug' ); - $self->lmLog( "SMTP Subject " . $subject, 'debug' ); - $self->lmLog( "SMTP Body " . $body, 'debug' ); + $self->lmLog( "SMTP From " . $self->conf->{mailFrom}, 'debug' ); + $self->lmLog( "SMTP To " . $mail, 'debug' ); + $self->lmLog( "SMTP Subject " . $subject, 'debug' ); + $self->lmLog( "SMTP Body " . $body, 'debug' ); $self->lmLog( "SMTP HTML flag " . ( $html ? "on" : "off" ), 'debug' ); - $self->lmLog( "SMTP Reply-To " . $self->{mailReplyTo}, 'debug' ) - if $self->{mailReplyTo}; + $self->lmLog( "SMTP Reply-To " . $self->conf->{mailReplyTo}, 'debug' ) + if $self->conf->{mailReplyTo}; # Encode the subject $subject = encode_base64( $subject, '' ); @@ -75,11 +76,15 @@ sub send_mail { # HTML case if ($html) { $message = MIME::Lite->new( - From => $self->{mailFrom}, - To => $mail, - "Reply-To" => $self->{mailReplyTo}, - Subject => $subject, - Type => 'multipart/related', + From => $self->conf->{mailFrom}, + To => $mail, + ( + $self->conf->{mailReplyTo} + ? ( "Reply-To" => $self->conf->{mailReplyTo} ) + : () + ), + Subject => $subject, + Type => 'multipart/related', ); # Attach HTML message @@ -101,9 +106,9 @@ sub send_mail { # Plain text case else { $message = MIME::Lite->new( - From => $self->{mailFrom}, + From => $self->conf->{mailFrom}, To => $mail, - "Reply-To" => $self->{mailReplyTo}, + "Reply-To" => $self->conf->{mailReplyTo}, Subject => $subject, Type => 'TEXT', Data => $body, diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/Register.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/Register.pm index f541a69a6..4ea7dc46d 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/Register.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/Register.pm @@ -1,7 +1,9 @@ package Lemonldap::NG::Portal::Plugins::Register; use strict; +use Encode; use Mouse; +use POSIX qw(strftime); use Lemonldap::NG::Portal::Main::Constants qw( PE_BADMAILTOKEN PE_CAPTCHAEMPTY @@ -83,13 +85,13 @@ sub _register { 'debug' ); # Get the corresponding session - my $registerSession = + my $registerSessionObj = $self->p->getApacheSession( $req->datas->{register_token} ); - if ( $registerSession && $registerSession->data ) { + if ( $registerSessionObj && $registerSessionObj->data ) { foreach (qw(mail firstname lastname ipAddr)) { $req->datas->{registerInfo}->{$_} = - $registerSession->data->{$_}; + $registerSessionObj->data->{$_}; } $self->lmLog( "User associated to token: " @@ -110,6 +112,7 @@ sub _register { # Captcha for register form # Only if register session does not already exist + # TODO captcha if ( $self->conf->{captcha_register_enabled} && $req->datas->{registerInfo}->{mail} && !$self->getRegisterSession( $req->datas->{registerInfo}->{mail} ) @@ -175,14 +178,16 @@ sub _register { ); return PE_REGISTERALREADYEXISTS; } + my $register_session = + $self->getRegisterSession( $req->datas->{registerInfo}->{mail} ); + $req->datas->{mail_already_sent} = + ( $register_session and !$req->id ) ? 1 : 0; # Skip this step if confirmation was already sent - unless ( $req->datas->{register_token} - or $self->getRegisterSession( $req->datas->{registerInfo}->{mail} ) ) - { + unless ( $req->datas->{register_token} or $register_session ) { # Create a new session - my $registerSession = $self->p->getApacheSession(); + my $registerSessionObj = $self->p->getApacheSession(); # Set _utime for session autoremove # Use default session timeout and register session timeout to compute it @@ -212,7 +217,8 @@ sub _register { $infos->{_type} = "register"; # Update session - $registerSession->update($infos); + $registerSessionObj->update($infos); + $register_session = $registerSessionObj->id; } # Send confirmation mail @@ -221,22 +227,25 @@ sub _register { unless ( $req->datas->{register_token} ) { # Check if confirmation mail has already been sent - my $register_session = - $self->getRegisterSession( $req->datas->{registerInfo}->{mail} ); - $req->datas->{mail_already_sent} = - ( $register_session and !$req->id ) ? 1 : 0; + $self->lmLog( 'No register_token', 'debug' ); + $self->lmLog( + 'mail ' + . ( $req->datas->{mail_already_sent} ? 'already' : 'not' ) + . ' sent', + 'debug' + ); # Read session to get creation and expiration dates $req->id($register_session) unless $req->id; $self->lmLog( "Register session found: $register_session", 'debug' ); - my $registerSession = + my $registerSessionObj = $self->p->getApacheSession( $register_session, 1 ); $req->datas->{registerInfo}->{registerSessionTimeoutTimestamp} = - $registerSession->data->{registerSessionTimeoutTimestamp}; + $registerSessionObj->data->{registerSessionTimeoutTimestamp}; $req->datas->{registerInfo}->{registerSessionStartTimestamp} = - $registerSession->data->{registerSessionStartTimestamp}; + $registerSessionObj->data->{registerSessionStartTimestamp}; # Mail session expiration date my $expTimestamp = @@ -262,14 +271,14 @@ sub _register { # Ask if user want another confirmation email if ( $req->datas->{mail_already_sent} - and !$self->param('resendconfirmation') ) + and !$req->param('resendconfirmation') ) { return PE_MAILCONFIRMATION_ALREADY_SENT; } # Build confirmation url my $url = $self->registerUrl . "?register_token=" . $req->{id}; - $url .= '&skin=' . $self->p->getSkin(); + $url .= '&skin=' . $self->p->getSkin($req); $url .= '&' . $self->conf->{authChoiceParam} . '=' . $req->datas->{_authChoice} @@ -302,6 +311,7 @@ sub _register { unless $self->send_mail( $req->datas->{registerInfo}->{mail}, $subject, $body, $html ); + $self->lmLog( 'Register message sent', 'debug' ); return PE_MAILCONFIRMOK; } @@ -325,7 +335,7 @@ sub _register { } # Create user - $self->lmLog( "Create new user $req->datas->{registerInfo}->{login}", + $self->lmLog( 'Create new user ' . $req->datas->{registerInfo}->{login}, 'debug' ); $result = $self->registerModule->createUser($req); unless ( $result == PE_OK ) { @@ -338,16 +348,16 @@ sub _register { # Register token can be used only one time, delete the session if all is ok # Get the corresponding session - my $registerSession = - $self->getApacheSession( $req->datas->{register_token} ); + my $registerSessionObj = + $self->p->getApacheSession( $req->datas->{register_token} ); - if ($registerSession) { + if ($registerSessionObj) { $self->lmLog( - "Delete register session " . $self->datas->{register_token}, + "Delete register session " . $req->datas->{register_token}, 'debug' ); - $registerSession->remove; + $registerSessionObj->remove; } else { $self->lmLog( "Register session not found", 'warn' ); @@ -368,12 +378,12 @@ sub _register { $body = $template->output(); # Replace variables in body - $body =~ s/\$(\w+)/decode("utf8",$self->{registerInfo}->{$1})/ge; + $body =~ s/\$(\w+)/decode("utf8",$req->datas->{registerInfo}->{$1})/ge; # Send mail return PE_MAILERROR - unless $self->send_mail( $self->{registerInfo}->{mail}, $subject, $body, - $html ); + unless $self->send_mail( $req->datas->{registerInfo}->{mail}, + $subject, $body, $html ); return PE_MAILOK; } @@ -381,7 +391,7 @@ sub _register { sub display { my ( $self, $req ) = @_; my %templateParams = ( - PORTAL_URL => $self->conf->param, + PORTAL_URL => $self->conf->{portal}, SKIN_PATH => '/static', SKIN => $self->conf->{portalSkin}, SKIN_BG => $self->conf->{portalSkinBackground}, @@ -400,10 +410,10 @@ sub display { FIRSTNAME => $self->p->checkXSSAttack( 'firstname', $req->datas->{registerInfo}->{firstname} ) ? "" : $req->datas->{registerInfo}->{firstname}, - LASTNAME => $req->datas->checkXSSAttack( 'lastname', + LASTNAME => $self->p->checkXSSAttack( 'lastname', $req->datas->{registerInfo}->{lastname} ) ? "" : $req->datas->{registerInfo}->{lastname}, - REGISTER_TOKEN => $req->datas->checkXSSAttack( 'register_token', + REGISTER_TOKEN => $self->p->checkXSSAttack( 'register_token', $req->datas->{register_token} ) ? "" : $req->datas->{register_token}, ); diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Register/Demo.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Register/Demo.pm index 5d64b7fda..bbbc82c1d 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Register/Demo.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Register/Demo.pm @@ -4,6 +4,8 @@ use strict; use Mouse; use Lemonldap::NG::Portal::Main::Constants qw(PE_OK); +extends 'Lemonldap::NG::Portal::Main::Plugin'; + our $VERSION = '2.0.0'; sub init { @@ -13,14 +15,14 @@ sub init { # Compute a login from register infos # @result Lemonldap::NG::Portal constant sub computeLogin { - my ($self) = @_; + my ( $self, $req ) = @_; # Get first letter of firstname and lastname my $login = - substr( lc $self->{registerInfo}->{firstname}, 0, 1 ) - . lc $self->{registerInfo}->{lastname}; + substr( lc $req->datas->{registerInfo}->{firstname}, 0, 1 ) + . lc $req->datas->{registerInfo}->{lastname}; - $self->{registerInfo}->{login} = $login; + $req->datas->{registerInfo}->{login} = $login; return PE_OK; } @@ -29,17 +31,14 @@ sub computeLogin { # Do nothing # @result Lemonldap::NG::Portal constant sub createUser { - my ($self) = @_; - - return PE_OK; -} - -## @method int registerDBFinish -# Do nothing -# @result Lemonldap::NG::Portal constant -sub registerDBFinish { - my ($self) = @_; - + my ( $self, $req ) = @_; + $self->p->_userDB->{demoAccounts}->{ $req->datas->{registerInfo}->{login} } + = { + uid => $req->datas->{registerInfo}->{login}, + cn => $req->datas->{registerInfo}->{firstname} . ' ' + . $req->datas->{registerInfo}->{lastname}, + mail => $req->datas->{registerInfo}->{login} . '@badwolf.org', + }; return PE_OK; } diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/Demo.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/Demo.pm index 3d26e6237..f068bae16 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/Demo.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/UserDB/Demo.pm @@ -13,18 +13,8 @@ extends 'Lemonldap::NG::Common::Module'; our $VERSION = '2.0.0'; -# INITIALIZATION - -# Check AuthDemo use -sub init { - my $self = shift; - - unless ( $self->p->getModule( undef, 'auth' ) =~ /Demo/ ) { - $self->p->error("Use UserDB::Demo only with Auth::Demo"); - } - # Sample accounts from Doctor Who characters - $self->{_demoAccounts} = { +has demoAccounts => (is=>'rw',default=>sub{{ 'rtyler' => { 'uid' => 'rtyler', 'cn' => 'Rose Tyler', @@ -40,7 +30,17 @@ sub init { 'cn' => 'Doctor Who', 'mail' => 'dwho@badwolf.org', }, - }; +}}); + +# INITIALIZATION + +# Check AuthDemo use +sub init { + my $self = shift; + + unless ( $self->p->getModule( undef, 'auth' ) =~ /Demo/ ) { + $self->p->error("Use UserDB::Demo only with Auth::Demo"); + } 1; } @@ -56,7 +56,7 @@ sub getUser { # Search by login if ( $req->user ) { return PE_OK - if ( defined $self->{_demoAccounts}->{ $req->user } ); + if ( defined $self->demoAccounts->{ $req->user } ); } # Search by mail @@ -64,8 +64,8 @@ sub getUser { return PE_OK if ( my $req->{user} = - grep { $self->{_demoAccounts}->{$_}->{mail} eq $req->{mail} } - keys %{ $self->{_demoAccounts} } + grep { $self->demoAccounts->{$_}->{mail} eq $req->{mail} } + keys %{ $self->demoAccounts } ); } @@ -82,7 +82,7 @@ sub setSessionInfo { %{ $self->conf->{demoExportedVars} } ); while ( my ( $k, $v ) = each %vars ) { $req->{sessionInfo}->{$k} = - $self->{_demoAccounts}->{ $req->{user} }->{$v} + $self->demoAccounts->{ $req->{user} }->{$v} || ""; } diff --git a/lemonldap-ng-portal/site/htdocs/static/common/bullet_go.png b/lemonldap-ng-portal/site/templates/common/bullet_go.png similarity index 100% rename from lemonldap-ng-portal/site/htdocs/static/common/bullet_go.png rename to lemonldap-ng-portal/site/templates/common/bullet_go.png diff --git a/lemonldap-ng-portal/site/templates/common/key.png b/lemonldap-ng-portal/site/templates/common/key.png new file mode 100644 index 0000000000000000000000000000000000000000..4ec1a928140311ff30a0a9120e958096c77f446e GIT binary patch literal 612 zcmV-q0-ODbP)nmX^MrbE*gmZ6|p*GkKoxa?X?hD9M+@sRvFH{EqYA??u6x z2pu{uGnrwz*>rh zfvUA@7b#acN?M*mBG3rQV?e^+0R5m3YXWyRZL5Bt@3vAw{9JaEW$}=f4bXO52yBH{ z;G~ZN|GLn>k~{On3Swd-Sy(gFkOdyw-RP%&exwl01RJRp))TI*SsngruhZksQ*NT%!X?K0000 Hello $cn,

- + Click here to reset your password diff --git a/lemonldap-ng-portal/site/templates/common/mail_register_confirm.tpl b/lemonldap-ng-portal/site/templates/common/mail_register_confirm.tpl index 0e684351a..eaa41d1b1 100644 --- a/lemonldap-ng-portal/site/templates/common/mail_register_confirm.tpl +++ b/lemonldap-ng-portal/site/templates/common/mail_register_confirm.tpl @@ -3,7 +3,7 @@

Hello $firstname $lastname,

- + Click here to confirm your account registration diff --git a/lemonldap-ng-portal/site/templates/common/mail_register_done.tpl b/lemonldap-ng-portal/site/templates/common/mail_register_done.tpl index 3508e9288..d8c642c12 100644 --- a/lemonldap-ng-portal/site/templates/common/mail_register_done.tpl +++ b/lemonldap-ng-portal/site/templates/common/mail_register_done.tpl @@ -7,11 +7,11 @@

Your login is - + $login
Your password is - + $password

diff --git a/lemonldap-ng-portal/t/41-Register-Demo.t b/lemonldap-ng-portal/t/41-Register-Demo.t index bd984684f..27c4924fb 100644 --- a/lemonldap-ng-portal/t/41-Register-Demo.t +++ b/lemonldap-ng-portal/t/41-Register-Demo.t @@ -2,27 +2,88 @@ use Test::More; use strict; use IO::String; -require 't/test-lib.pm'; +BEGIN { + require MIME::Lite; + require 't/test-lib.pm'; +} -my $res; +my ($res,$user,$pwd); +my $mailSend = 0; my $client = LLNG::Manager::Test->new( { ini => { - logLevel => 'debug', - useSafeJail => 1, - portalDisplayRegister => 1, - registerDB => 'Demo', + logLevel => 'error', + useSafeJail => 1, + portalDisplayRegister => 1, + registerDB => 'Demo', + captcha_register_enabled => 0, } } ); # Test normal first access # ------------------------ -ok( $res = $client->_get('/'), 'Unauth JSON request' ); +ok( + $res = $client->_get( '/register', accept => 'text/html' ), + 'Unauth JSON request', +); count(1); -expectReject($res); +my ( $host, $url, $query ) = + expectForm( $res, '#', undef, 'firstname', 'lastname', 'mail' ); + +ok( + $res = $client->_post( + '/register', + IO::String->new('firstname=foo&lastname=bar&mail=foobar%40badwolf.org'), + length => 52, + accept => 'text/html' + ), + 'Ask to create account' +); +count(1); +expectOK($res); + +# $query is set by MIME::Lite::send below +ok($query =~ /register_token=/, 'Found register_token'); +count(1); + +ok($res = $client->_get('/register',query=>$query,accept=>'text/html'),'Push register_token'); +expectOK($res); +count(1); + +# $user/$pwd are set by MIME::Lite::send below +ok($user eq 'fbar','Get good login'); +count(1); + +ok($res=$client->_post('/',IO::String->new('user=fbar&password=fbar'),length=>23,accept=>'text/html'),'Try to authenticate'); +count(1); +expectCookie($res); clean_sessions(); done_testing( count() ); + +no warnings 'redefine'; + +my $mail2 = 0; +sub MIME::Lite::send { + my ($mail) = @_; + pass('Mail sent'); + ok($mail->header_as_string =~ /foobar\@badwolf.org/s, 'Found dest') or explain($mail->header_as_string,'To: foobar@badwolf.org'); + count(2); + unless($mail2) { + $mailSend = 1; + ok($mail->body_as_string =~ m#a href="http://auth.example.com/register\?(.*?)"#, 'Found link'); + count(1); + $query = $1; + $mail2++; + } + else { + $mailSend = 2; + ok($mail->body_as_string =~ m#yourLoginIs.+?(\w+).*?pwdIs.+?(.*?)#s, 'Get login/pwd'); + ($user,$pwd) = ($1,$2); + count(1); + } +} +