Skip to content

Commit

Permalink
Item12041: Implementation of registration approval flow. Also some re…
Browse files Browse the repository at this point in the history
…-org of the messages to separate running system messages from registration messages. Plus full documentation of the =register= script.

git-svn-id: http://svn.foswiki.org/trunk@15296 0b4bb1d4-4e5a-0410-9cc4-b2b747904278
  • Loading branch information
CrawfordCurrie authored and CrawfordCurrie committed Aug 13, 2012
1 parent d6f5642 commit 829de4b
Show file tree
Hide file tree
Showing 13 changed files with 1,245 additions and 694 deletions.
5 changes: 2 additions & 3 deletions UnitTestContrib/test/unit/FoswikiFnTestCase.pm
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,8 @@ sub registerUser {
}
catch Foswiki::OopsException with {
my $e = shift;
$this->assert_str_equals( "attention", $e->{template},
$e->stringify() );
$this->assert_str_equals( "thanks", $e->{def}, $e->stringify() );
$this->assert_str_equals( "register", $e->{template}, $e->stringify() );
$this->assert_str_equals( "thanks", $e->{def}, $e->stringify() );
}
catch Foswiki::AccessControlException with {
my $e = shift;
Expand Down
402 changes: 307 additions & 95 deletions UnitTestContrib/test/unit/RegisterTests.pm

Large diffs are not rendered by default.

79 changes: 68 additions & 11 deletions core/data/System/CommandAndCGIScripts.txt
Original file line number Diff line number Diff line change
Expand Up @@ -257,21 +257,78 @@ context diffs.
---+++ =register=

| *Parameter* | *Description* | *Default* |
| =action= | =register= or =verify= or =approve= | _required_ |
| =action= | =register= or =verify= or =approve= or =disapprove= | _required_ |

<blockquote class="foswikiHelp"> *%X% Note:* The =register= script can only be called via the HTTP POST method except when the action is =verify=. Make sure you specify =method="post"= if you call the =register= script via a form action. It is not possible to call =register= from an =&lt;a href ...&gt;= link. The =verify= action is an exception as it is used to verify registration by clicking a href link from an email.</blockquote>

---++++ =action=register=

Starts the registration process for a new user.

User data is passed in 0 or more parameters of the format =FwkNname= where =Fwk= is a standard prefix, =N= is =0= for an optional parameter and =1= for a required parameter, and =name= is the parameter name. The following standard =Fwk= parameters are predefined:

| *Parameter* | *Description* | *Default* |
| =Fwk1Email= | New user's email address | _required_ |
| =Fwk1FirstName= | New user's first name | _required_ |
| =Fwk1LastName= | New user's surname | _required_ |
| =Fwk1WikiName= | Wikiname of user being registered | _required_ |
| =Fwk1LoginName= | New user's login name | _required_ |
| =Fwk1Password= | New user's password | |
| =Fwk0Confirm= | Password confirmation (if enabled) | |
| =Fwk0Name= | User's name. Defaults to =FirstName LastName= | |
| =Fwk0AddToGroups= | Accepts a comma-separated list of group names to add the new user to. | |

Any additional =Fwk= parameters will be written to the user topic (_except_
=Photo= and =Confirm=).

If registration verification (or registration approval) is enabled in
=configure=, a pending registration record will be created and the
registrant (or the approver) will be emailed with the verification code.

If all goes well, then:
* If verification is required, outputs the registration confirmation screen.
* If approval is required, outputs the pending approval screen.
* Otherwise outputs the welcome screen.

When called from CGI, this method requires a POST request.

---++++ =action=verify=

Sent to activate a user's pending registration. Only applicable if
registration verification is enabled.

| *Parameter* | *Description* | *Default* |
| =addtogroups= | Accepts a comma-separated list of group names to add the user to. | |
| =code= | (verify= only) Activation code, verifies a pending registration |
| =create= | If =on=, and a group being added to does not exist, create it. | |
| =email= | New user's email address | _required_ |
| =firstname= | New user's first name | _required_ |
| =lastname= | New user's surname | _required_ |
| =loginname= | New user's login name | _required_ |
| =password= | New user's password | |
| =wikiname= | Wikiname of user being registered | _required_ |
| &lt;any name&gt; | Any other parameter passed during registration will normally be passed on into the new user's home topic, or ignored. |
| =code= | Activation code, verifies a pending registration |

If the verification is successful:
* If approval is required, outputs the pending approval screen.
* Otherwise outputs the welcome screen.

---++++ =action=approve=
Sent to activate a pending registration. Only applicable if
registration approval is enabled.

| *Parameter* | *Description* | *Default* |
| =code= | Approval code for the pending registration |

Outputs the welcome screen and mails the successful registrant.

---++++ =action=disapprove=
Sent to deny a pending registration. Only applicable if
registration approval is enabled.

| *Parameter* | *Description* | *Default* |
| =code= | Approval code for the pending registration |

Presents a screen where the admin can optionally enter an email
message to be sent to the failed registrant. NOTE: the registration
fails even if this mail is _not_ sent.

If the =code= has the value =DENIED= then the request is interpreted as
the second stage of an approval denial. Registration parameters are
passed in the URL parameters =email=, =referee=, =wikiname= and =feedback.
These parameters are used to compose a feedback mail for the failed
registrant.

---+++ =rename=
Used for renaming webs, topics and attachments.
Expand Down
8 changes: 1 addition & 7 deletions core/data/System/VarUSERINFO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,8 @@
* With formatted output, using tokens:
<verbatim class="tml">%USERINFO{ format="$username is really $wikiname" }%</verbatim>
Expands to: =%USERINFO{ format="$username is really !$wikiname" }%=
* Retrieve information about another user:
* Retrieve information about another user. You can use either a wikiname or a login name to identify the user. You can only see information about another user if you are an admin, or the ={AntiSpam}{HideUserDetails}= configuration option is not enabled. %IF{"{AntiSpam}{HideUserDetails}" then=" _(User details are hidden on this site)_ "}%:
<verbatim class="tml">%USERINFO{ "WikiGuest" format="$username is really $wikiname" }%</verbatim>
Expands to: <code>%USERINFO{ "WikiGuest" format="$username is really !$wikiname" }%</code>
%IF{
"{AntiSpam}{HideUserDetails} AND NOT '%WIKIUSER%' ingroup 'AdminGroup'"
then="<blockquote class='foswikiHelp'>$percentT$percent You need to be a member of %USERSWEB%.AdminGroup for the =USERINFO= macro to display details about other users</blockquote>"
}%
* Notes
<blockquote class="foswikiHelp">%H% Use wikinames when specifying a =name=. You can also pass a login name. You can only see information about another user if you are an admin, or the ={AntiSpam}{HideUserDetails}= configuration option is not enabled. %IF{"{AntiSpam}{HideUserDetails}" then=" _(User details are hidden on this site)_ "}%</blockquote>
* Related: [[%IF{"'%INCLUDINGTOPIC%'='Macros'" then="#"}%VarUSERNAME][USERNAME]], [[%IF{"'%INCLUDINGTOPIC%'='Macros'" then="#"}%VarWIKINAME][WIKINAME]], [[%IF{"'%INCLUDINGTOPIC%'='Macros'" then="#"}%VarWIKIUSERNAME][WIKIUSERNAME]], [[%IF{"'%INCLUDINGTOPIC%'='Macros'" then="#"}%VarGROUPINFO][GROUPINFO]], UserAuthentication, ChangeEmailAddress
<!--%JQREQUIRE{"chili"}%-->
19 changes: 18 additions & 1 deletion core/lib/Foswiki.spec
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,23 @@ $Foswiki::cfg{Register}{EnableNewUserRegistration} = $TRUE;
# a link sent in an email to the user's registered email address
$Foswiki::cfg{Register}{NeedVerification} = $FALSE;
# **BOOLEAN**
# Whether registrations must be verified by a referee. The referees are
# listed in the {Register}{Approvers} setting, by wikiname. Note that
# the AntiWikiSpamPlugin supports automatic checking of registration
# sources against black- and white-lists, and may be a good alternative
# to an approval system.
$Foswiki::cfg{Register}{NeedApproval} = $FALSE;
# **STRING 40**
# Comma-separated list of WikiNames of users who are able to approve
# new registrations. These referees will be sent an email when a new
# user verifies their registration. The referee must click a link in
# the email to approve (or deny) the registration.
# If the approver list is empty, the email will be sent to the wiki
# administrator.
$Foswiki::cfg{Register}{Approvers} = '';
# **BOOLEAN EXPERT**
# Controls whether the user password has to be entered twice on the
# registration page or not. The default is to require confirmation, in which
Expand Down Expand Up @@ -692,7 +709,7 @@ $Foswiki::cfg{Password} = '';
# and %QUERY{}%. Extensions can push into this array to extend the set. This is done as
# a filter in because while the bulk of configuration items are quite innocent,
# it's better to be a bit paranoid.
$Foswiki::cfg{AccessibleCFG} = [ '{ScriptSuffix}', '{LoginManager}', '{AuthScripts}', '{LoginNameFilterIn}', '{AdminUserLogin}', '{AdminUserWikiName}', '{SuperAdminGroup}', '{UsersTopicName}', '{AuthRealm}', '{MinPasswordLength}', '{Register}{AllowLoginName}', '{Register}{EnableNewUserRegistration}', '{Register}{NeedVerification}', '{Register}{RegistrationAgentWikiName}', '{AllowInlineScript}', '{DenyDotDotInclude}', '{UploadFilter}', '{NameFilter}', '{AccessibleCFG}', '{AntiSpam}{EmailPadding}', '{AntiSpam}{EntityEncode}','{AntiSpam}{HideUserDetails}', '{AntiSpam}{RobotsAreWelcome}', '{Stats}{TopViews}', '{Stats}{TopContrib}', '{Stats}{TopicName}', '{UserInterfaceInternationalisation}', '{UseLocale}', '{Site}{Locale}', '{Site}{CharSet}', '{DisplayTimeValues}', '{DefaultDateFormat}', '{Site}{LocaleRegexes}', '{UpperNational}', '{LowerNational}', '{PluralToSingular}', '{EnableHierarchicalWebs}', '{WebMasterEmail}', '{WebMasterName}', '{NotifyTopicName}', '{SystemWebName}', '{TrashWebName}', '{SitePrefsTopicName}', '{LocalSitePreferences}', '{HomeTopicName}', '{WebPrefsTopicName}', '{UsersWebName}', '{TemplatePath}', '{LinkProtocolPattern}', '{NumberOfRevisions}', '{MaxRevisionsInADiff}', '{ReplaceIfEditedAgainWithin}', '{LeaseLength}', '{LeaseLengthLessForceful}', '{Plugins}{WebSearchPath}', '{PluginsOrder}', '{Cache}{Enabled}', '{Validation}{Method}', '{Register}{DisablePasswordConfirmation}' ];
$Foswiki::cfg{AccessibleCFG} = [ '{ScriptSuffix}', '{LoginManager}', '{AuthScripts}', '{LoginNameFilterIn}', '{AdminUserLogin}', '{AdminUserWikiName}', '{SuperAdminGroup}', '{UsersTopicName}', '{AuthRealm}', '{MinPasswordLength}', '{Register}{AllowLoginName}', '{Register}{EnableNewUserRegistration}', '{Register}{NeedVerification}', '{Register}{NeedApproval}', '{Register}{Approvers}', '{Register}{RegistrationAgentWikiName}', '{AllowInlineScript}', '{DenyDotDotInclude}', '{UploadFilter}', '{NameFilter}', '{AccessibleCFG}', '{AntiSpam}{EmailPadding}', '{AntiSpam}{EntityEncode}','{AntiSpam}{HideUserDetails}', '{AntiSpam}{RobotsAreWelcome}', '{Stats}{TopViews}', '{Stats}{TopContrib}', '{Stats}{TopicName}', '{UserInterfaceInternationalisation}', '{UseLocale}', '{Site}{Locale}', '{Site}{CharSet}', '{DisplayTimeValues}', '{DefaultDateFormat}', '{Site}{LocaleRegexes}', '{UpperNational}', '{LowerNational}', '{PluralToSingular}', '{EnableHierarchicalWebs}', '{WebMasterEmail}', '{WebMasterName}', '{NotifyTopicName}', '{SystemWebName}', '{TrashWebName}', '{SitePrefsTopicName}', '{LocalSitePreferences}', '{HomeTopicName}', '{WebPrefsTopicName}', '{UsersWebName}', '{TemplatePath}', '{LinkProtocolPattern}', '{NumberOfRevisions}', '{MaxRevisionsInADiff}', '{ReplaceIfEditedAgainWithin}', '{LeaseLength}', '{LeaseLengthLessForceful}', '{Plugins}{WebSearchPath}', '{PluginsOrder}', '{Cache}{Enabled}', '{Validation}{Method}', '{Register}{DisablePasswordConfirmation}' ];
# **BOOLEAN**
# Allow %INCLUDE of URLs. This is disabled by default, because it is possible
Expand Down
4 changes: 4 additions & 0 deletions core/lib/Foswiki/Contrib/core/MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -999,12 +999,16 @@ templates/oopsgeneric.tmpl 0444
templates/oopslanguagechanged.tmpl 0444
templates/oopsleaseconflict.tmpl 0444
templates/oopsredirectdenied.tmpl
templates/oopsregister.tmpl
templates/oopssaveerr.tmpl 0444
templates/preview.tmpl 0444
templates/rdiff.tmpl 0444
templates/registerapprove.tmpl 0444
templates/registerconfirm.tmpl 0444
templates/registerdenied.tmpl 0444
templates/registerfailednotremoved.tmpl 0444
templates/registerfailedremoved.tmpl 0444
templates/registermessages.tmpl 0444
templates/registernotify.tmpl 0444
templates/registernotifyadmin.tmpl 0444
templates/rename.tmpl 0444
Expand Down
63 changes: 39 additions & 24 deletions core/lib/Foswiki/UI/Passwords.pm
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
---+ package Foswiki::UI::Passwords
UI methods for password management.
Shares a message template with Register.pm (registermessages.tmpl)
=cut

Expand Down Expand Up @@ -38,7 +39,7 @@ sub resetPassword {
my $err = $session->i18n->maketext(
'Email has been disabled for this Foswiki installation');
throw Foswiki::OopsException(
'attention',
'register',
topic => $Foswiki::cfg{HomeTopicName},
def => 'reset_bad',
params => [$err]
Expand All @@ -47,7 +48,7 @@ sub resetPassword {

my @userNames = $query->param('LoginName');
unless (@userNames) {
throw Foswiki::OopsException( 'attention', def => 'no_users_to_reset' );
throw Foswiki::OopsException( 'register', def => 'no_users_to_reset' );
}
my $introduction = $query->param('Introduction') || '';

Expand Down Expand Up @@ -101,7 +102,7 @@ sub resetPassword {
}

throw Foswiki::OopsException(
'attention',
'register',
status => 200,
topic => $Foswiki::cfg{HomeTopicName},
def => 'reset_ok',
Expand All @@ -110,7 +111,7 @@ sub resetPassword {
}
else {
throw Foswiki::OopsException(
'attention',
'register',
topic => $Foswiki::cfg{HomeTopicName},
def => 'reset_bad',
params => [$message]
Expand Down Expand Up @@ -164,18 +165,15 @@ sub _resetUsersPassword {
my $wn = $users->getWikiName($user);
foreach my $email (@em) {
require Foswiki::UI::Register;
my $err = Foswiki::UI::Register::sendEmail(
my $err = _sendEmail(
$session,
'mailresetpassword',
{
webName => $Foswiki::cfg{UsersWebName},
LoginName => $ln,
Name => Foswiki::spaceOutWikiWord($wn),
WikiName => $wn,
Email => $email,
PasswordA => $password,
Introduction => $introduction,
}
webName => $Foswiki::cfg{UsersWebName},
LoginName => $ln,
FirstLastName => Foswiki::spaceOutWikiWord($wn),
WikiName => $wn,
EmailAddress => $email,
Password => $password,
Introduction => $introduction,
);

if ($err) {
Expand All @@ -201,6 +199,23 @@ sub _resetUsersPassword {
return $sent;
}

# sends $p->{template} with substitutions from $data
sub _sendEmail {
my ( $session, %data ) = @_;

my $text = $session->templates->readTemplate('mailresetpassword');
foreach my $field ( keys %data ) {
my $f = uc($field);
$text =~ s/\%$f\%/$data{$field}/g;
}

my $topicObject = Foswiki::Meta->new( $session, $Foswiki::cfg{UsersWebName},
$data{WikiName} );
$text = $topicObject->expandMacros($text);

return $session->net->sendEmail($text);
}

=begin TML
---++ StaticMethod changePasswordAndOrEmail( $session )
Expand Down Expand Up @@ -240,7 +255,7 @@ sub changePasswordAndOrEmail {

unless ($login) {
throw Foswiki::OopsException(
'attention',
'register',
web => $webName,
topic => $topic,
def => 'not_a_user',
Expand All @@ -263,7 +278,7 @@ sub changePasswordAndOrEmail {
# check if passwords are identical
if ( $passwordA ne $passwordB ) {
throw Foswiki::OopsException(
'attention',
'register',
web => $webName,
topic => $topic,
def => 'password_mismatch'
Expand All @@ -287,7 +302,7 @@ sub changePasswordAndOrEmail {
|| $users->checkPassword( $login, $oldpassword ) )
{
throw Foswiki::OopsException(
'attention',
'register',
web => $webName,
topic => $topic,
def => 'wrong_password'
Expand All @@ -299,7 +314,7 @@ sub changePasswordAndOrEmail {
# Determine that the cUID exists.
unless ( defined $cUID ) {
throw Foswiki::OopsException(
'attention',
'register',
web => $webName,
topic => $topic,
def => 'not_a_user',
Expand All @@ -312,7 +327,7 @@ sub changePasswordAndOrEmail {
&& $email !~ /($Foswiki::regex{emailAddrRegex}\s*)+/ )
{
throw Foswiki::OopsException(
'attention',
'register',
web => $webName,
topic => $topic,
def => 'bad_email',
Expand All @@ -324,7 +339,7 @@ sub changePasswordAndOrEmail {
&& length($passwordA) < $Foswiki::cfg{MinPasswordLength} )
{
throw Foswiki::OopsException(
'attention',
'register',
web => $webName,
topic => $topic,
def => 'bad_password',
Expand All @@ -351,7 +366,7 @@ sub changePasswordAndOrEmail {

unless ( $users->setPassword( $cUID, $passwordA, $oldpassword ) ) {
throw Foswiki::OopsException(
'attention',
'register',
web => $webName,
topic => $topic,
def => 'password_not_changed'
Expand All @@ -363,7 +378,7 @@ sub changePasswordAndOrEmail {

# OK - password changed
throw Foswiki::OopsException(
'attention',
'register',
status => 200,
web => $webName,
topic => $topic,
Expand All @@ -373,7 +388,7 @@ sub changePasswordAndOrEmail {

# must be just email
throw Foswiki::OopsException(
'attention',
'register',
status => 200,
web => $webName,
topic => $topic,
Expand Down
Loading

0 comments on commit 829de4b

Please sign in to comment.