# Tests for bin/installpassword # usage: # cd $BASEDIR/test # perl -mError bin/TestRunner.pl $pathTo/InstallPasswordTests.pm # ====================================================================== # Test summary: # # 1 Successful installation without verification # 2 Successful installation with verification # 3 Declined installation without verification and bogus approval # 4 Declined installation with bogus verification # 5 Declined installation with verification and bogus approval # # For each successful testcase verify login with the installed password # For each declined testcase verify login with the original password # ====================================================================== use strict; package InstallPasswordTests; use base qw( TWikiTestCase ); # the test object use TWiki::UI::InstallPassword; # test support use TWiki; use TWiki::UI::Register; use TWiki::Plugins::TestFixturePlugin::HTMLDiffer; # CPAN basics use CGI; use Error qw( :try ); use File::Path; sub new { my $self = shift()->SUPER::new(@_); return $self; } # variables exchanged between set_up and the tests my $twiki = TWiki->new("TestRunner"); my $testWikiName = 'RinceWind'; my $testLoginName = 'riw'; my $testEmail = 'riw@oook.m.uunet.de'; my $testPasswordR = 'pointy hat'; # for registration my $testPassword = 'wizzard'; # for installation my $testComment = 'I lost my password in the Mended Drum'; # just a string my $systemWeb = 'TemporaryRegisterTestsSystemWeb'; # avoid %PREFS% my $peopleWeb = 'TemporaryRegisterTestsPeopleWeb'; # don't clutter Main my @mails = (); local $TWiki::cfg{PasswordManager} = 'TWiki::Users::HtPasswdUser'; my $testEncrypted = $twiki->{users}->{passwords}->encrypt($testLoginName,$testPassword,'fresh'); # setting up the structure for all tests sub set_up { my $this = shift; $this->SUPER::set_up(); $twiki = TWiki->new("TestRunner"); try { $twiki->{store}->createWeb($twiki->{user}, $peopleWeb, $TWiki::cfg{UsersWebName}); # copy the system web to get rid of any preference variables $twiki->{store}->createWeb($twiki->{user}, $systemWeb, $TWiki::cfg{UsersWebName}); $twiki->{store}->saveTopic($twiki->{user}, $peopleWeb, 'TWikiAdminGroup', " * Set GROUP = TestAdmin\n"); # copy Main.TWikiUsers $twiki->{store}->copyTopic( undef, $TWiki::cfg{UsersWebName}, $TWiki::cfg{UsersTopicName}, $peopleWeb , $TWiki::cfg{UsersTopicName}, ); my $user = $twiki->{users}->findUser("TestAdmin", "TestAdmin"); } catch TWiki::AccessControlException with { $this->assert(0,shift->stringify()); } catch Error::Simple with { $this->assert(0,shift->stringify()); }; $TWiki::cfg{UsersWebName} = $peopleWeb; $TWiki::cfg{SystemWebName} = $systemWeb; $TWiki::cfg{PasswordManager} = 'TWiki::Users::HtPasswdUser'; $TWiki::cfg{HtpasswdFileName} = '/tmp/htpasswd'; $TWiki::cfg{RegistrationApprovals} = '/tmp/RegistrationApprovals'; $TWiki::cfg{Register}{NeedVerification} = 0; $Error::Debug = 1; @mails = (); } sub tear_down { my $this = shift; $twiki->{store}->removeWeb($twiki->{user},$peopleWeb); $twiki->{store}->removeWeb($twiki->{user},$systemWeb); File::Path::rmtree($TWiki::cfg{RegistrationApprovals}); unlink($TWiki::cfg{HtpasswdFileName}); @mails = (); $this->SUPER::tear_down(); } # ====================================================================== # test_okWithoutVerification($twiki) # # Purpose # perform a complete installation without verification sub test_okWithoutVerification { my $this = shift; local $TWiki::cfg{Register}{NeedVerification} = 0; _startComplete($this); _actionApproveOK($this); } # ====================================================================== # test_okWithVerification($twiki) # # Purpose # perform a complete installation with verification sub test_okWithVerification { my $this = shift; local $TWiki::cfg{Register}{NeedVerification} = 1; _startComplete($this); my $code = _assertMailUserPleaseVerify($this); _actionVerifyOK($this,$code); _actionApproveOK($this); } # ====================================================================== # test_NokBadVerification($twiki) # # Purpose # attempt an installation with wrong verification code sub test_NokBadVerification { my $this = shift; local $TWiki::cfg{Register}{NeedVerification} = 1; _startComplete($this); my $code = _assertMailUserPleaseVerify($this); # fire off the verification step, this time with a bogus code $code++; $twiki->{cgiQuery} = CGI->new({ action => 'verify', code => $code, }); try { TWiki::UI::InstallPassword::installPassword($twiki); } catch TWiki::OopsException with { my $e = shift; $this->assert_str_equals("attention", $e->{template},$e->stringify()); $this->assert_str_equals("bad_ver_code", $e->{def}); } otherwise { $this->assert(0, "expected an oops redirect"); }; # end of test here - no mail should have been sent $this->assert_equals(0, scalar(@mails)); _assertLogonWithRegistered($this); } # ====================================================================== # test_NokWithoutVerificationBadApproval($twiki) # # Purpose # attempt an installation without verification and wrong approval code sub test_NokWithoutVerificationBadApproval { my $this = shift; local $TWiki::cfg{Register}{NeedVerification} = 0; _startComplete($this); _actionApproveNOK($this); } # ====================================================================== # test_NokWithVerificationBadApproval($twiki) # # Purpose # attempt an installation with verification and wrong approval code sub test_NokWithVerificationBadApproval { my $this = shift; local $TWiki::cfg{Register}{NeedVerification} = 1; _startComplete($this); my $code = _assertMailUserPleaseVerify($this); _actionVerifyOK($this,$code); # wrong code this time _actionApproveNOK($this); } # ###################################################################### # Utility routines, as usual, in alphabetical order # ###################################################################### # ====================================================================== # _actionApproveNOK($twiki) # # Purpose # final step: perform a bogus approval without password installation sub _actionApproveNOK { my $this = shift; my $code = _assertMailAdminPleaseApprove($this); $code++; $twiki->{cgiQuery} = CGI->new({ action => 'approve', code => $code, }); try { TWiki::UI::InstallPassword::installPassword($twiki); } catch TWiki::OopsException with { my $e = shift; $this->assert_str_equals("attention", $e->{template},$e->stringify()); $this->assert_str_equals("bad_ver_code", $e->{def}); } otherwise { $this->assert(0, "expected an oops redirect"); }; # no mail should have been sent $this->assert_equals(0, scalar(@mails)); @mails = (); _assertLogonWithRegistered($this); } # ====================================================================== # _actionApproveOK($this) # # Purpose # final step: perform a succesfull approval and password installation sub _actionApproveOK { my $this = shift; # process the mail to the admin my $code = _assertMailAdminPleaseApprove($this); $twiki->{cgiQuery} = CGI->new({ action => 'approve', code => $code, }); try { TWiki::UI::InstallPassword::installPassword($twiki); } catch TWiki::OopsException with { my $e = shift; $this->assert_str_equals("installpassworddone", $e->{template},$e->stringify()); $this->assert_matches(qr/$testEmail/, $e->stringify()); } otherwise { $this->assert(0, "expected an oops redirect"); }; # process the mail $this->assert_equals(1, scalar(@mails)); foreach my $mail ( @mails ) { $this->assert_matches(qr/To: {users}->{passwords}; $this->assert($passwordHandler->checkPassword($testLoginName,"$testPassword")); $this->assert(!$passwordHandler->checkPassword($testLoginName,"$testPasswordR")); } # ====================================================================== # _assertLogonWithRegistered($this) # # Purpose # we should be able to login with the registrationpassword sub _assertLogonWithRegistered { my $this = shift; my $passwordHandler = $twiki->{users}->{passwords}; $this->assert($passwordHandler->checkPassword($testLoginName,"$testPasswordR")); $this->assert(!$passwordHandler->checkPassword($testLoginName,"$testPassword")); } # ====================================================================== # _actionVerifyOK($this,$code) # # Purpose # perform a succesful verification, always leading to approval sub _actionVerifyOK { my $this = shift; my ($code) = @_; $twiki->{cgiQuery} = CGI->new({ action => 'verify', code => $code, }); try { TWiki::UI::InstallPassword::installPassword($twiki); } catch TWiki::OopsException with { my $e = shift; $this->assert_str_equals("installpasswordapprove", $e->{template},$e->stringify()); $this->assert_matches(qr/$testEmail/, $e->stringify()); } otherwise { $this->assert(0, "expected an oops redirect"); }; } # ====================================================================== # _assertMailAdminPleaseApprove($twiki) # # Purpose # check the mail to the admin asking for approval # # Returns # a valid approval code sub _assertMailAdminPleaseApprove { my $this = shift; my $code = ''; $this->assert_equals(1, scalar(@mails)); foreach my $mail ( @mails ) { $this->assert_matches(qr/To: %WIKIWEBMASTERNAME/, $mail); $this->assert_matches(qr/$testWikiName/,$mail); $this->assert_matches(qr/$testLoginName/,$mail); $this->assert_matches(qr/$testComment/,$mail); # and don't lose the code, would you? ($code) = $mail =~ /;code=($testWikiName\.\d+)/; } @mails = (); return $code; } # ====================================================================== # _assertMailUserPleaseVerify($twiki) # # Purpose # check the mail to the user asking for email verification # # Returns # a valid approval code sub _assertMailUserPleaseVerify { my $this = shift; my $code = ''; $this->assert_equals(1, scalar(@mails)); foreach my $mail ( @mails ) { $this->assert_matches(qr/To: assert_matches(qr/$testWikiName/,$mail); $this->assert_matches(qr/$testLoginName/,$mail); $this->assert_matches(qr/\baction=verify;/,$mail); $this->assert_matches(qr/code=$testWikiName\.\d+/,$mail); # and don't lose the code, would you? ($code) = $mail =~ /;code=($testWikiName\.\d+)/; } @mails = (); return $code; } # ====================================================================== # _registerUser($twiki) # # Purpose # register the test user, check with assertions: from RegisterTests.pm. # use a password which is not equal to that of the installations. sub _registerUser { my $this = shift; local $TWiki::cfg{Register}{NeedVerification} = 0; my $query = new CGI ({'Twk1WikiName' => [$testWikiName], 'Twk1LoginName' => [$testLoginName], 'Twk1Email' => [$testEmail], 'Twk1Password' => [$testPasswordR], 'Twk1Confirm' => [$testPasswordR], 'action' => ['register'], }); $query->path_info( "/$peopleWeb/TWikiRegistration" ); $twiki = new TWiki($TWiki::cfg{DefaultUserName},$query); $twiki->{net}->setMailHandler(\&_sendMailToVar); try { TWiki::UI::Register::register_cgi($twiki); } catch TWiki::OopsException with { my $e = shift; $this->assert_str_equals("attention", $e->{template}); $this->assert_str_equals("thanks", $e->{def}); $this->assert_equals(2, scalar(@mails)); my $done = ''; foreach my $mail ( @mails ) { if( $mail =~ /^Subject:.*Registration for/m ) { if( $mail =~ /^To: .*\b$testEmail\b/m ) { $this->assert(!$done, $done."\n---------\n".$mail); $done = $mail; } else { $this->assert_matches(qr/To: %WIKIWEBMASTERNAME/, $mail); } } else { $this->assert(0, $mail); } } $this->assert($done); @mails = (); } catch TWiki::AccessControlException with { my $e = shift; $this->assert(0, $e->stringify); } catch Error::Simple with { my $e = shift; $this->assert(0, $e->stringify); } otherwise { $this->assert(0, "expected an oops redirect"); }; } # callback used by Net.pm sub _sendMailToVar { my($net, $mess ) = @_; push( @mails, $mess ); return undef; } # ====================================================================== # _startComplete($twiki) # # Purpose # register the test user and initialize a complete form for our entry sub _startComplete { my $this = shift; # create a user _registerUser($this); $twiki->{cgiQuery} = CGI->new({ loginname => $testLoginName, email => $testEmail, password => $testPassword, confirm => $testPassword, comment => $testComment, }); # ################################################################## # fire off the first step: action=start # should result in approve or verify oops my $next = $TWiki::cfg{Register}{NeedVerification} ? 'verify' : 'approve'; try { TWiki::UI::InstallPassword::installPassword($twiki); } catch TWiki::OopsException with { my $e = shift; $this->assert_str_equals("installpassword$next", $e->{template},$e->stringify()); $this->assert_matches(qr/$testEmail/, $e->stringify()); } otherwise { $this->assert(0, "expected an oops redirect"); }; } 1;