aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbrettp <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>2010-09-30 19:56:49 +0000
committerbrettp <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>2010-09-30 19:56:49 +0000
commitfad92747bec989fd6728eb7349c9ede4674764ff (patch)
tree6f1c6ca613dff0af2a769c6b13aa97d00cb432a9
parent9af90ffc9a20033ca9fdd9182122c01600a0867b (diff)
downloadelgg-fad92747bec989fd6728eb7349c9ede4674764ff.tar.gz
elgg-fad92747bec989fd6728eb7349c9ede4674764ff.tar.bz2
Fixes #617, #2271 User validation removed from core to UserValidationByEmail plugin. Without a validation plugin, users can login immediately.
Fixes #2243 Removed "You have validated your email" email. Users are logged in immediately after registration or validating email. Refs #2409 Added register, user plugin hook that is called only on self registration. Can be used to halt registration. git-svn-id: http://code.elgg.org/elgg/trunk@6983 36083f99-b078-4883-b0ff-0f9b5a30f544
-rw-r--r--actions/login.php74
-rw-r--r--actions/register.php58
-rw-r--r--actions/user/requestnewpassword.php27
-rw-r--r--engine/lib/sessions.php18
-rw-r--r--engine/lib/users.php111
-rw-r--r--languages/en.php6
-rw-r--r--mod/uservalidationbyemail/languages/en.php52
-rw-r--r--mod/uservalidationbyemail/lib/functions.php107
-rw-r--r--mod/uservalidationbyemail/start.php216
9 files changed, 367 insertions, 302 deletions
diff --git a/actions/login.php b/actions/login.php
index ef6b0b898..0063a1f08 100644
--- a/actions/login.php
+++ b/actions/login.php
@@ -2,37 +2,37 @@
/**
* Elgg login action
*
- * @package Elgg
- * @subpackage Core
- * @author Curverider Ltd
- * @link http://elgg.org/
+ * @package Elgg.Core
+ * @subpackage User.Authentication
*/
-// Get username and password
$username = get_input('username');
$password = get_input("password");
-$persistent = get_input("persistent", false);
+$persistent = get_input("persistent", FALSE);
+$result = FALSE;
-// If all is present and correct, try to log in
-$result = false;
-if (!empty($username) && !empty($password)) {
- // check first if this is an email address and do a login
- // email addies will be validated
- if (strpos($username, '@') !== FALSE && ($user=get_user_by_email($username))) {
- $username = $user[0]->username;
- }
+if (empty($username) || empty($password)) {
+ register_error(elgg_echo('loginerror'));
+ forward();
+}
- if ($user = authenticate($username, $password)) {
- $result = login($user, $persistent);
- }
+// check first if logging in with email address
+if (strpos($username, '@') !== FALSE && ($users = get_user_by_email($username))) {
+ $username = $users[0]->username;
}
-// Set the system_message as appropriate
+if ($user = authenticate($username, $password)) {
+ $result = login($user, $persistent);
+}
+
+// forward to correct page
if ($result) {
system_message(elgg_echo('loginok'));
+
if (isset($_SESSION['last_forward_from']) && $_SESSION['last_forward_from']) {
$forward_url = $_SESSION['last_forward_from'];
unset($_SESSION['last_forward_from']);
+
forward($forward_url);
} else {
if (get_input('returntoreferer')) {
@@ -44,25 +44,21 @@ if ($result) {
}
}
} else {
- $error_msg = elgg_echo('loginerror');
- // figure out why the login failed
- if (!empty($username) && !empty($password)) {
- // See if it exists and is disabled
- $access_status = access_get_show_hidden_status();
- access_show_hidden_entities(true);
- if (($user = get_user_by_username($username)) && !$user->validated) {
- // give plugins a chance to respond
- if (!trigger_plugin_hook('unvalidated_login_attempt','user',array('entity'=>$user))) {
- // if plugins have not registered an action, the default action is to
- // trigger the validation event again and assume that the validation
- // event will display an appropriate message
- trigger_elgg_event('validate', 'user', $user);
- }
- } else {
- register_error(elgg_echo('loginerror'));
- }
- access_show_hidden_entities($access_status);
- } else {
- register_error(elgg_echo('loginerror'));
- }
+ register_error(elgg_echo('loginerror'));
+// // let a plugin hook say why login failed or react to it.
+// $params = array(
+// 'username' => $username,
+// 'password' => $password,
+// 'persistent' => $persistent,
+// 'user' => $user
+// );
+//
+// // Returning FALSE to this function will generate a standard
+// // "Could not log you in" message.
+// // Plugins should use this hook to provide details, and then return TRUE.
+// if (!trigger_plugin_hook('failed_login', 'user', $params, FALSE)) {
+// register_error(elgg_echo('loginerror'));
+// }
}
+
+forward(REFERRER);
diff --git a/actions/register.php b/actions/register.php
index a5043fed9..9c4efa9f6 100644
--- a/actions/register.php
+++ b/actions/register.php
@@ -2,10 +2,8 @@
/**
* Elgg registration action
*
- * @package Elgg
- * @subpackage Core
- * @author Curverider Ltd
- * @link http://elgg.org/
+ * @package Elgg.Core
+ * @subpackage User.Account
*/
global $CONFIG;
@@ -19,11 +17,6 @@ $name = get_input('name');
$friend_guid = (int) get_input('friend_guid',0);
$invitecode = get_input('invitecode');
-$admin = get_input('admin');
-if (is_array($admin)) {
- $admin = $admin[0];
-}
-
if ($CONFIG->allow_registration) {
try {
if (trim($password) == "" || trim($password2) == "") {
@@ -35,37 +28,41 @@ if ($CONFIG->allow_registration) {
}
$guid = register_user($username, $password, $name, $email, false, $friend_guid, $invitecode);
+
if ($guid) {
$new_user = get_entity($guid);
- // @todo - consider removing registering admins since this is done
- // through the useradd action
- if (($guid) && ($admin)) {
- // Only admins can make someone an admin
- admin_gatekeeper();
- $new_user->makeAdmin();
- }
-
- // Send user validation request on register only
- global $registering_admin;
- if (!$registering_admin) {
- request_user_validation($guid);
- }
+ // allow plugins to respond to self registration
+ // note: To catch all new users, even those created by an admin,
+ // register for the create, user event instead.
+ // only passing vars that aren't in ElggUser.
+ $params = array(
+ 'user' => $new_user,
+ 'password' => $password,
+ 'friend_guid' => $friend_guid,
+ 'invitecode' => $invitecode
+ );
+ // if this user is admin, that means it was the first
+ // registered user. Don't trigger this hook.
+ // @todo This can be removed in the new installer
if (!$new_user->isAdmin()) {
- // Now disable if not an admin
- // Don't do a recursive disable. Any entities owned by the user at this point
- // are products of plugins that hook into create user and might need
- // access to the entities.
- $new_user->disable('new_user', false);
+ // @todo should registration be allowed no matter what the plugins return?
+ if (!trigger_plugin_hook('register', 'user', $params, TRUE)) {
+ $new_user->delete();
+ // @todo this is a generic messages. We could have plugins
+ // throw a RegistrationException, but that is very odd
+ // for the plugin hooks system.
+ throw new RegistrationException(elgg_echo('registerbad'));
+ }
}
- system_message(sprintf(elgg_echo("registerok"),$CONFIG->sitename));
+ system_message(sprintf(elgg_echo("registerok"), $CONFIG->sitename));
// Forward on success, assume everything else is an error...
// If just registered admin user, login the user in and forward to the
// plugins simple settings page.
- if (!datalist_get('first_admin_login')) {
+ if (!datalist_get('first_admin_login') && $new_user->isAdmin()) {
login($new_user);
// remove the "you've registered!" system_message();
$_SESSION['msg']['messages'] = array();
@@ -76,6 +73,7 @@ if ($CONFIG->allow_registration) {
datalist_set('first_admin_login', time());
forward('pg/admin/plugins/simple');
} else {
+ login($new_user);
forward();
}
} else {
@@ -88,4 +86,4 @@ if ($CONFIG->allow_registration) {
register_error(elgg_echo('registerdisabled'));
}
-forward(REFERER);
+forward(REFERER); \ No newline at end of file
diff --git a/actions/user/requestnewpassword.php b/actions/user/requestnewpassword.php
index 400ce86ae..22b4008e8 100644
--- a/actions/user/requestnewpassword.php
+++ b/actions/user/requestnewpassword.php
@@ -2,36 +2,21 @@
/**
* Action to request a new password.
*
- * @package Elgg
- * @subpackage Core
- * @author Curverider Ltd
- * @link http://elgg.org/
+ * @package Elgg.Core
+ * @subpackage User.Account
*/
-global $CONFIG;
-
$username = get_input('username');
-$access_status = access_get_show_hidden_status();
-access_show_hidden_entities(true);
$user = get_user_by_username($username);
if ($user) {
- if ($user->validated) {
- if (send_new_password_request($user->guid)) {
- system_message(elgg_echo('user:password:resetreq:success'));
- } else {
- register_error(elgg_echo('user:password:resetreq:fail'));
- }
- } else if (!trigger_plugin_hook('unvalidated_requestnewpassword','user',array('entity'=>$user))) {
- // if plugins have not registered an action, the default action is to
- // trigger the validation event again and assume that the validation
- // event will display an appropriate message
- trigger_elgg_event('validate', 'user', $user);
+ if (send_new_password_request($user->guid)) {
+ system_message(elgg_echo('user:password:resetreq:success'));
+ } else {
+ register_error(elgg_echo('user:password:resetreq:fail'));
}
} else {
register_error(sprintf(elgg_echo('user:username:notfound'), $username));
}
-access_show_hidden_entities($access_status);
forward();
-exit;
diff --git a/engine/lib/sessions.php b/engine/lib/sessions.php
index 3af571f5c..a61402577 100644
--- a/engine/lib/sessions.php
+++ b/engine/lib/sessions.php
@@ -160,19 +160,13 @@ function pam_auth_userpass($credentials = NULL) {
if (is_array($credentials) && ($credentials['username']) && ($credentials['password'])) {
if ($user = get_user_by_username($credentials['username'])) {
-
- // Let admins log in without validating their email, but normal users must have validated their email or been admin created
- if ((!$user->isAdmin()) && (!$user->validated) && (!$user->admin_created)) {
- return false;
- }
-
// User has been banned, so prevent from logging in
if ($user->isBanned()) {
- return false;
+ return FALSE;
}
if ($user->password == generate_user_password($user, $credentials['password'])) {
- return true;
+ return TRUE;
} else {
// Password failed, log.
log_login_failure($user->guid);
@@ -181,7 +175,7 @@ function pam_auth_userpass($credentials = NULL) {
}
}
- return false;
+ return FALSE;
}
/**
@@ -303,17 +297,17 @@ function login(ElggUser $user, $persistent = false) {
$code = (md5($user->name . $user->username . time() . rand()));
$_SESSION['code'] = $code;
$user->code = md5($code);
- setcookie("elggperm", $code, (time()+(86400 * 30)),"/");
+ setcookie("elggperm", $code, (time()+(86400 * 30)), "/");
}
- if (!$user->save() || !trigger_elgg_event('login','user',$user)) {
+ if (!$user->save() || !trigger_elgg_event('login', 'user', $user)) {
unset($_SESSION['username']);
unset($_SESSION['name']);
unset($_SESSION['code']);
unset($_SESSION['guid']);
unset($_SESSION['id']);
unset($_SESSION['user']);
- setcookie("elggperm", "", (time()-(86400 * 30)),"/");
+ setcookie("elggperm", "", (time()-(86400 * 30)), "/");
return false;
}
diff --git a/engine/lib/users.php b/engine/lib/users.php
index 281833625..c82db2046 100644
--- a/engine/lib/users.php
+++ b/engine/lib/users.php
@@ -875,60 +875,6 @@ function elgg_user_resetpassword_page_handler($page) {
}
/**
- * Set the validation status for a user.
- *
- * @param bool $status Validated (true) or false
- * @param string $method Optional method to say how a user was validated
- * @return bool
- */
-function set_user_validation_status($user_guid, $status, $method = '') {
- if (!$status) {
- $method = '';
- }
-
- if ($status) {
- if (
- (create_metadata($user_guid, 'validated', $status,'', 0, ACCESS_PUBLIC)) &&
- (create_metadata($user_guid, 'validated_method', $method,'', 0, ACCESS_PUBLIC))
- ) {
- return true;
- }
- } else {
- $validated = get_metadata_byname($user_guid, 'validated');
- $validated_method = get_metadata_byname($user_guid, 'validated_method');
-
- if (
- ($validated) &&
- ($validated_method) &&
- (delete_metadata($validated->id)) &&
- (delete_metadata($validated_method->id))
- )
- return true;
- }
-
- return false;
-}
-
-/**
- * Trigger an event requesting that a user guid be validated somehow - either by email address or some other way.
- *
- * This event invalidates any existing values and returns
- *
- * @param unknown_type $user_guid
- */
-function request_user_validation($user_guid) {
- $user = get_entity($user_guid);
-
- if (($user) && ($user instanceof ElggUser)) {
- // invalidate any existing validations
- set_user_validation_status($user_guid, false);
-
- // request validation
- trigger_elgg_event('validate', 'user', $user);
- }
-}
-
-/**
* Validates an email address.
*
* @param string $address Email address.
@@ -1067,9 +1013,8 @@ function register_user($username, $password, $name, $email, $allow_multiple_emai
// Load the configuration
global $CONFIG;
- $username = trim($username);
// no need to trim password.
- $password = $password;
+ $username = trim($username);
$name = trim(strip_tags($name));
$email = trim($email);
@@ -1081,39 +1026,33 @@ function register_user($username, $password, $name, $email, $allow_multiple_emai
return false;
}
- // See if it exists and is disabled
+ // Make sure a user with conflicting details hasn't registered and been disabled
$access_status = access_get_show_hidden_status();
access_show_hidden_entities(true);
- // Validate email address
if (!validate_email_address($email)) {
throw new RegistrationException(elgg_echo('registration:emailnotvalid'));
}
- // Validate password
if (!validate_password($password)) {
throw new RegistrationException(elgg_echo('registration:passwordnotvalid'));
}
- // Validate the username
if (!validate_username($username)) {
throw new RegistrationException(elgg_echo('registration:usernamenotvalid'));
}
- // Check to see if $username exists already
if ($user = get_user_by_username($username)) {
- //return false;
throw new RegistrationException(elgg_echo('registration:userexists'));
}
- // If we're not allowed multiple emails then see if this address has been used before
if ((!$allow_multiple_emails) && (get_user_by_email($email))) {
throw new RegistrationException(elgg_echo('registration:dupeemail'));
}
access_show_hidden_entities($access_status);
- // Otherwise ...
+ // Create user
$user = new ElggUser();
$user->username = $username;
$user->email = $email;
@@ -1142,15 +1081,17 @@ function register_user($username, $password, $name, $email, $allow_multiple_emai
// Check to see if we've registered the first admin yet.
// If not, this is the first admin user!
$have_admin = datalist_get('admin_registered');
- global $registering_admin;
if (!$have_admin) {
+ // makeAdmin() calls ElggUser::canEdit().
+ // right now no one is logged in and so canEdit() returns false.
+ // instead of making an override for this one instance that is called on every
+ // canEdit() call, just override the access system to set the first admin user.
+ // @todo remove this when Cash merges in the new installer
+ $ia = elgg_set_ignore_access(TRUE);
$user->makeAdmin();
- set_user_validation_status($user->getGUID(), TRUE, 'first_run');
datalist_set('admin_registered', 1);
- $registering_admin = true;
- } else {
- $registering_admin = false;
+ elgg_set_ignore_access($ia);
}
// Turn on email notifications by default
@@ -1289,34 +1230,6 @@ function set_last_login($user_guid) {
}
/**
- * A permissions plugin hook that grants access to users if they are newly created - allows
- * for email activation.
- *
- * @todo Do this in a better way!
- *
- * @param unknown_type $hook
- * @param unknown_type $entity_type
- * @param unknown_type $returnvalue
- * @param unknown_type $params
- */
-function new_user_enable_permissions_check($hook, $entity_type, $returnvalue, $params) {
- $entity = $params['entity'];
- $user = $params['user'];
- if (($entity) && ($entity instanceof ElggUser)) {
- if (
- (($entity->disable_reason == 'new_user') || (
- // if this isn't set at all they're a "new user"
- !$entity->validated
- ))
- && (!isloggedin())) {
- return true;
- }
- }
-
- return $returnvalue;
-}
-
-/**
* Creates a relationship between this site and the user.
*
* @param $event
@@ -1411,10 +1324,6 @@ function users_init() {
register_plugin_hook('usersettings:save','user','users_settings_save');
register_elgg_event_handler('create', 'user', 'user_create_hook_add_site_relationship');
-
- // Handle a special case for newly created users when the user is not logged in
- // @todo handle this better!
- register_plugin_hook('permissions_check','all','new_user_enable_permissions_check');
}
/**
diff --git a/languages/en.php b/languages/en.php
index 797cfee7a..95ec4ba38 100644
--- a/languages/en.php
+++ b/languages/en.php
@@ -22,7 +22,7 @@ $english = array(
'login' => "Log in",
'loginok' => "You have been logged in.",
- 'loginerror' => "We couldn't log you in. This may be because you haven't validated your account yet, the details you supplied were incorrect, or you have made too many incorrect login attempts. Make sure your details are correct and please try again.",
+ 'loginerror' => "We couldn't log you in. Please check your credentials and try again.",
'logout' => "Log out",
'logoutok' => "You have been logged out.",
@@ -379,7 +379,7 @@ To remove a widget drag it back to the <b>Widget gallery</b>.",
'register' => "Register",
'registerok' => "You have successfully registered for %s.",
- 'registerbad' => "Your registration was unsuccessful. The username may already exist, your passwords might not match, or your username or password may be too short.",
+ 'registerbad' => "Your registration was unsuccessful because of an unknown error.",
'registerdisabled' => "Registration has been disabled by the system administrator",
'firstadminlogininstructions' => "Enable and disable plugins to customize your new Elgg site! (Remember to hit 'Save' when you're done.)",
@@ -878,7 +878,7 @@ If you requested this click on the link below, otherwise ignore this email.
'likes:userslikedthis' => 'users like this',
'likes:river:annotate' => 'likes',
'likes:email:body' => '%s liked %s',
- 'likes:email:subject' => 'A user liked one of your objects',
+ 'likes:email:subject' => 'A user liked one of your objects',
/**
* Comments
diff --git a/mod/uservalidationbyemail/languages/en.php b/mod/uservalidationbyemail/languages/en.php
index 44eb5e45b..6b3a6f708 100644
--- a/mod/uservalidationbyemail/languages/en.php
+++ b/mod/uservalidationbyemail/languages/en.php
@@ -1,33 +1,31 @@
<?php
- /**
- * Email user validation plugin language pack.
- *
- * @package ElggUserValidationByEmail
- * @author Curverider Ltd
- * @link http://elgg.com/
- */
-
- $english = array(
-
- 'email:validate:subject' => "%s please confirm your email address!",
- 'email:validate:body' => "Hi %s,
+/**
+ * Email user validation plugin language pack.
+ *
+ * @package Elgg.Core.Plugin
+ * @subpackage ElggUserValidationByEmail
+ */
+
+$english = array(
+ 'email:validate:subject' => "%s please confirm your email address for %s!",
+ 'email:validate:body' => "%s,
+
+Before you can start you using %s, you must confirm your email address.
Please confirm your email address by clicking on the link below:
%s
+
+If you can't click on the link, copy and paste it to your browser manually.
+
+%s
+%s
",
- 'email:validate:success:subject' => "Email validated %s!",
- 'email:validate:success:body' => "Hi %s,
-
-Congratulations, you have successfully validated your email address.",
-
-
- 'email:confirm:success' => "You have confirmed your email address!",
- 'email:confirm:fail' => "Your email address could not be verified...",
-
- 'uservalidationbyemail:registerok' => "To activate your account, please confirm your email address by clicking on the link we just sent you."
-
- );
-
- add_translation("en",$english);
-?> \ No newline at end of file
+ 'email:confirm:success' => "You have confirmed your email address!",
+ 'email:confirm:fail' => "Your email address could not be verified...",
+
+ 'uservalidationbyemail:registerok' => "To activate your account, please confirm your email address by clicking on the link we just sent you."
+
+);
+
+add_translation("en", $english); \ No newline at end of file
diff --git a/mod/uservalidationbyemail/lib/functions.php b/mod/uservalidationbyemail/lib/functions.php
new file mode 100644
index 000000000..ed66b40d4
--- /dev/null
+++ b/mod/uservalidationbyemail/lib/functions.php
@@ -0,0 +1,107 @@
+<?php
+/**
+ * Helper functions
+ *
+ * @package Elgg.Core.Plugin
+ * @subpackage UserValidationByEmail
+ */
+
+/**
+ * Generate an email activation code.
+ *
+ * @param int $user_guid The guid of the user
+ * @param string $email_address Email address
+ * @return string
+ */
+function uservalidationbyemail_generate_code($user_guid, $email_address) {
+ global $CONFIG;
+
+ // Note I bind to site URL, this is important on multisite!
+ return md5($user_guid . $email_address . $CONFIG->site->url . get_site_secret());
+}
+
+/**
+ * Request user validation email.
+ * Send email out to the address and request a confirmation.
+ *
+ * @param int $user_guid The user
+ * @return mixed
+ */
+function uservalidationbyemail_request_validation($user_guid) {
+ global $CONFIG;
+
+ $user_guid = (int)$user_guid;
+ $user = get_entity($user_guid);
+
+ if (($user) && ($user instanceof ElggUser)) {
+ // Work out validate link
+ $code = uservalidationbyemail_generate_code($user_guid, $user->email);
+ $link = "{$CONFIG->site->url}pg/uservalidationbyemail/confirm?u=$user_guid&c=$code";
+ $site = $CONFIG->site;
+
+ // Send validation email
+ $subject = sprintf(elgg_echo('email:validate:subject'), $user->name, $site->name);
+ $body = sprintf(elgg_echo('email:validate:body'), $user->name, $site->name, $link, $site->name, $site->url);
+ $result = notify_user($user->guid, $CONFIG->site->guid, $subject, $body, NULL, 'email');
+
+ if ($result) {
+ system_message(elgg_echo('uservalidationbyemail:registerok'));
+ }
+
+ return $result;
+ }
+
+ return FALSE;
+}
+
+/**
+ * Validate a user
+ *
+ * @param unknown_type $user_guid
+ * @param unknown_type $code
+ * @return unknown
+ */
+function uservalidationbyemail_validate_email($user_guid, $code) {
+ $user = get_entity($user_guid);
+
+ if ($code == uservalidationbyemail_generate_code($user_guid, $user->email)) {
+ return uservalidationbyemail_set_user_validation_status($user_guid, true, 'email');
+ }
+
+ return false;
+}
+
+/**
+ * Set the validation status for a user.
+ *
+ * @param bool $status Validated (true) or false
+ * @param string $method Optional method to say how a user was validated
+ * @return bool
+ */
+function uservalidationbyemail_set_user_validation_status($user_guid, $status, $method = '') {
+ if (!$status) {
+ $method = '';
+ }
+
+ if ($status) {
+ if (
+ (create_metadata($user_guid, 'validated', $status,'', 0, ACCESS_PUBLIC)) &&
+ (create_metadata($user_guid, 'validated_method', $method,'', 0, ACCESS_PUBLIC))
+ ) {
+ return TRUE;
+ }
+ } else {
+ $validated = get_metadata_byname($user_guid, 'validated');
+ $validated_method = get_metadata_byname($user_guid, 'validated_method');
+
+ if (
+ ($validated) &&
+ ($validated_method) &&
+ (delete_metadata($validated->id)) &&
+ (delete_metadata($validated_method->id))
+ )
+ return TRUE;
+ }
+
+ return FALSE;
+} \ No newline at end of file
diff --git a/mod/uservalidationbyemail/start.php b/mod/uservalidationbyemail/start.php
index 3ce7542c2..677fea231 100644
--- a/mod/uservalidationbyemail/start.php
+++ b/mod/uservalidationbyemail/start.php
@@ -1,36 +1,120 @@
<?php
/**
* Email user validation plugin.
- * Non-admin or admin created accounts are invalid until their email address is confirmed.
+ * Non-admin accounts are invalid until their email address is confirmed.
*
- * @package ElggUserValidationByEmail
- * @author Curverider Ltd
- * @link http://elgg.com/
+ * @package Elgg.Core.Plugin
+ * @subpackage UserValidationByEmail
*/
function uservalidationbyemail_init() {
global $CONFIG;
+ require_once dirname(__FILE__) . '/lib/functions.php';
+
// Register page handler to validate users
- // This isn't an action because security is handled by the validation codes.
+ // This doesn't need to be an action because security is handled by the validation codes.
register_page_handler('uservalidationbyemail', 'uservalidationbyemail_page_handler');
- // Register hook listening to new users.
- register_elgg_event_handler('validate', 'user', 'uservalidationbyemail_email_validation');
-
+ // mark users as unvalidated when they register
+ register_plugin_hook('register', 'user', 'uservalidationbyemail_disable_new_user');
+
+ // prevent users from logging in if they aren't validated
+ register_plugin_hook('action', 'login', 'uservalidationbyemail_check_login_attempt');
+
+ // when requesting a new password
+ register_plugin_hook('action', 'user/requestnewpassword', 'uservalidationbyemail_check_request_password');
+
+ // prevent the engine from logging in users via login()
+ register_elgg_event_handler('login', 'user', 'uservalidationbyemail_check_manual_login');
+
+ // make admin users always validated
+ register_elgg_event_handler('make_admin', 'user', 'uservalidationbyemail_validate_new_admin_user');
+
// register Walled Garden public pages
register_plugin_hook('public_pages', 'walled_garden', 'uservalidationbyemail_public_pages');
}
/**
- * Get security token, forward to action.
+ * Disables a user upon registration.
+ *
+ * @param unknown_type $hook
+ * @param unknown_type $type
+ * @param unknown_type $value
+ * @param unknown_type $params
+ */
+function uservalidationbyemail_disable_new_user($hook, $type, $value, $params) {
+ $user = elgg_get_array_value('user', $params);
+
+ // no clue what's going on, so don't react.
+ if (!$user instanceof ElggUser) {
+ return NULL;
+ }
+
+ // disable user to prevent showing up on the site
+ // Don't do a recursive disable. Any entities owned by the user at this point
+ // are products of plugins that hook into create user and might need
+ // access to the entities.
+ // @todo That ^ sounds like a specific case...would be nice to track it down...
+ $user->disable('uservalidationbyemail_new_user', FALSE);
+
+ // set user as unvalidated and send out validation email
+ uservalidationbyemail_set_user_validation_status($user->guid, FALSE);
+ uservalidationbyemail_request_validation($user->guid);
+
+ return TRUE;
+}
+
+/**
+ * Checks if a login failed because the user hasn't validated his account.
+ *
+ * @param unknown_type $hook
+ * @param unknown_type $type
+ * @param unknown_type $value
+ * @param unknown_type $params
+ */
+function uservalidationbyemail_check_login_attempt($hook, $type, $value, $params) {
+ // everything is only stored in the input at this point
+ $username = get_input('username');
+ $password = get_input("password");
+
+ if (empty($username) || empty($password)) {
+ // return true to let the original login action deal with it.
+ return TRUE;
+ }
+
+ // see if we need to resolve an email address to a username
+ if (strpos($username, '@') !== FALSE && ($users = get_user_by_email($username))) {
+ $username = $users[0]->username;
+ }
+
+ // See the users exists and isn't validated
+ $access_status = access_get_show_hidden_status();
+ access_show_hidden_entities(TRUE);
+
+ $user = get_user_by_username($username);
+
+ // only resend validation if the password is correct
+ if ($user && authenticate($username, $password) && !$user->validated) {
+ // show an error and resend validation email
+ uservalidationbyemail_request_validation($user->guid);
+ // halt action
+ $value = FALSE;
+ }
+
+ access_show_hidden_entities($access_status);
+
+ return $value;
+}
+
+/**
+ * Checks sent passed validation code and user guids and validates the user.
*
- * @param unknown_type $page
- * @return unknown_type
+ * @param array $page
*/
function uservalidationbyemail_page_handler($page) {
global $CONFIG;
-
+
if (isset($page[0]) && $page[0] == 'confirm') {
$code = sanitise_string(get_input('c', FALSE));
$user_guid = get_input('u', FALSE);
@@ -47,9 +131,7 @@ function uservalidationbyemail_page_handler($page) {
$user = get_entity($user_guid);
$user->enable();
-
- notify_user($user_guid, $CONFIG->site->guid, sprintf(elgg_echo('email:validate:success:subject'), $user->username), sprintf(elgg_echo('email:validate:success:body'), $user->name), NULL, 'email');
-
+ login($user);
} else {
register_error(elgg_echo('email:confirm:fail'));
}
@@ -66,84 +148,80 @@ function uservalidationbyemail_page_handler($page) {
}
/**
- * Request email validation.
+ * Make sure any admin users are automatically validated
+ *
+ * @param unknown_type $event
+ * @param unknown_type $type
+ * @param unknown_type $object
*/
-function uservalidationbyemail_email_validation($event, $object_type, $object) {
- if (($object) && ($object instanceof ElggUser)) {
- uservalidationbyemail_request_validation($object->guid);
+function uservalidationbyemail_validate_new_admin_user($event, $type, $user) {
+ if ($user instanceof ElggUser && !$user->validated) {
+ uservalidationbyemail_set_user_validation_status($user->guid, TRUE, 'admin_user');
}
- return true;
+ return TRUE;
}
/**
- * Generate an email activation code.
- *
- * @param int $user_guid The guid of the user
- * @param string $email_address Email address
- * @return string
+ * Registers public pages to allow in the case Private Network has been enabled.
*/
-function uservalidationbyemail_generate_code($user_guid, $email_address) {
- global $CONFIG;
-
- // Note I bind to site URL, this is important on multisite!
- return md5($user_guid . $email_address . $CONFIG->site->url . get_site_secret());
+function uservalidationbyemail_public_pages($hook, $type, $return_value, $params) {
+ $return_value[] = 'pg/uservalidationbyemail/confirm';
+ return $return_value;
}
/**
- * Request user validation email.
- * Send email out to the address and request a confirmation.
+ * Prevent a manual code login with login().
*
- * @param int $user_guid The user
- * @return mixed
+ * @param unknown_type $event
+ * @param unknown_type $type
+ * @param unknown_type $user
*/
-function uservalidationbyemail_request_validation($user_guid) {
- global $CONFIG;
-
- $user_guid = (int)$user_guid;
- $user = get_entity($user_guid);
+function uservalidationbyemail_check_manual_login($event, $type, $user) {
+ $access_status = access_get_show_hidden_status();
+ access_show_hidden_entities(TRUE);
- if (($user) && ($user instanceof ElggUser)) {
- // Work out validate link
- $code = uservalidationbyemail_generate_code($user_guid, $user->email);
- $link = "{$CONFIG->site->url}pg/uservalidationbyemail/confirm?u=$user_guid&c=$code";
+ // @todo register_error()?
+ $return = ($user instanceof ElggUser && !$user->validated) ? FALSE : NULL;
- // Send validation email
- $result = notify_user($user->guid, $CONFIG->site->guid, sprintf(elgg_echo('email:validate:subject'), $user->username), sprintf(elgg_echo('email:validate:body'), $user->name, $link), NULL, 'email');
- if ($result) {
- system_message(elgg_echo('uservalidationbyemail:registerok'));
- }
+ access_show_hidden_entities($access_status);
- return $result;
- }
-
- return FALSE;
+ return $return;
}
/**
- * Validate a user
+ * Deny requests to change password if the account isn't validated.
*
- * @param unknown_type $user_guid
- * @param unknown_type $code
- * @return unknown
+ * @todo This is needed because changing the password requires the entity to be enabled.
+ *
+ * @param unknown_type $hook
+ * @param unknown_type $type
+ * @param unknown_type $value
+ * @param unknown_type $params
*/
-function uservalidationbyemail_validate_email($user_guid, $code) {
- $user = get_entity($user_guid);
+function uservalidationbyemail_check_request_password($hook, $type, $value, $params) {
+ $username = get_input('username');
- if ($code == uservalidationbyemail_generate_code($user_guid, $user->email)) {
- return set_user_validation_status($user_guid, true, 'email');
+ // see if we need to resolve an email address to a username
+ if (strpos($username, '@') !== FALSE && ($users = get_user_by_email($username))) {
+ $username = $users[0]->username;
}
- return false;
-}
+ // See the users exists and isn't validated
+ $access_status = access_get_show_hidden_status();
+ access_show_hidden_entities(TRUE);
-/**
- * Registers public pages to allow in the case Private Network has been enabled.
- */
-function uservalidationbyemail_public_pages($hook, $type, $return_value, $params) {
- $return_value[] = 'pg/uservalidationbyemail/confirm';
- return $return_value;
+ $user = get_user_by_username($username);
+
+ // resend validation instead of resetting password
+ if ($user && !$user->validated) {
+ uservalidationbyemail_request_validation($user->guid);
+ $value = FALSE;
+ }
+
+ access_show_hidden_entities($access_status);
+
+ return $value;
}
-// Initialise
register_elgg_event_handler('init', 'system', 'uservalidationbyemail_init'); \ No newline at end of file