diff options
Diffstat (limited to 'mod/uservalidationbyemail/start.php')
| -rw-r--r-- | mod/uservalidationbyemail/start.php | 280 |
1 files changed, 193 insertions, 87 deletions
diff --git a/mod/uservalidationbyemail/start.php b/mod/uservalidationbyemail/start.php index 3ce7542c2..f44d2ab50 100644 --- a/mod/uservalidationbyemail/start.php +++ b/mod/uservalidationbyemail/start.php @@ -1,149 +1,255 @@ <?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 */ +elgg_register_event_handler('init', 'system', 'uservalidationbyemail_init'); + 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. - register_page_handler('uservalidationbyemail', 'uservalidationbyemail_page_handler'); + // This doesn't need to be an action because security is handled by the validation codes. + elgg_register_page_handler('uservalidationbyemail', 'uservalidationbyemail_page_handler'); + + // mark users as unvalidated and disable when they register + elgg_register_plugin_hook_handler('register', 'user', 'uservalidationbyemail_disable_new_user'); + + // canEdit override to allow not logged in code to disable a user + elgg_register_plugin_hook_handler('permissions_check', 'user', 'uservalidationbyemail_allow_new_user_can_edit'); + + // prevent users from logging in if they aren't validated + register_pam_handler('uservalidationbyemail_check_auth_attempt', "required"); + + // when requesting a new password + elgg_register_plugin_hook_handler('action', 'user/requestnewpassword', 'uservalidationbyemail_check_request_password'); + + // prevent the engine from logging in users via login() + elgg_register_event_handler('login', 'user', 'uservalidationbyemail_check_manual_login'); + + // make admin users always validated + elgg_register_event_handler('make_admin', 'user', 'uservalidationbyemail_validate_new_admin_user'); - // Register hook listening to new users. - register_elgg_event_handler('validate', 'user', 'uservalidationbyemail_email_validation'); - // register Walled Garden public pages - register_plugin_hook('public_pages', 'walled_garden', 'uservalidationbyemail_public_pages'); + elgg_register_plugin_hook_handler('public_pages', 'walled_garden', 'uservalidationbyemail_public_pages'); + + // admin interface to manually validate users + elgg_register_admin_menu_item('administer', 'unvalidated', 'users'); + + elgg_extend_view('css/admin', 'uservalidationbyemail/css'); + elgg_extend_view('js/elgg', 'uservalidationbyemail/js'); + + $action_path = dirname(__FILE__) . '/actions'; + + elgg_register_action('uservalidationbyemail/validate', "$action_path/validate.php", 'admin'); + elgg_register_action('uservalidationbyemail/resend_validation', "$action_path/resend_validation.php", 'admin'); + elgg_register_action('uservalidationbyemail/delete', "$action_path/delete.php", 'admin'); + elgg_register_action('uservalidationbyemail/bulk_action', "$action_path/bulk_action.php", 'admin'); } /** - * Get security token, forward to action. + * Disables a user upon registration. * - * @param unknown_type $page - * @return unknown_type + * @param string $hook + * @param string $type + * @param bool $value + * @param array $params + * @return bool */ -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); +function uservalidationbyemail_disable_new_user($hook, $type, $value, $params) { + $user = elgg_extract('user', $params); - // new users are not enabled by default. - $access_status = access_get_show_hidden_status(); - access_show_hidden_entities(true); + // no clue what's going on, so don't react. + if (!$user instanceof ElggUser) { + return; + } - $user = get_entity($user_guid); + // another plugin is requesting that registration be terminated + // no need for uservalidationbyemail + if (!$value) { + return $value; + } - if (($code) && ($user)) { - if (uservalidationbyemail_validate_email($user_guid, $code)) { - system_message(elgg_echo('email:confirm:success')); + // has the user already been validated? + if (elgg_get_user_validation_status($user->guid) == true) { + return $value; + } - $user = get_entity($user_guid); - $user->enable(); + // disable user to prevent showing up on the site + // set context so our canEdit() override works + elgg_push_context('uservalidationbyemail_new_user'); + $hidden_entities = access_get_show_hidden_status(); + access_show_hidden_entities(TRUE); - 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'); + // 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); - } else { - register_error(elgg_echo('email:confirm:fail')); - } - } else { - register_error(elgg_echo('email:confirm:fail')); - } + // set user as unvalidated and send out validation email + elgg_set_user_validation_status($user->guid, FALSE); + uservalidationbyemail_request_validation($user->guid); - access_show_hidden_entities($access_status); - } else { - register_error(elgg_echo('email:confirm:fail')); - } + elgg_pop_context(); + access_show_hidden_entities($hidden_entities); - forward(); + return $value; } /** - * Request email validation. + * Override the canEdit() call for if we're in the context of registering a new user. + * + * @param string $hook + * @param string $type + * @param bool $value + * @param array $params + * @return bool|null */ -function uservalidationbyemail_email_validation($event, $object_type, $object) { - if (($object) && ($object instanceof ElggUser)) { - uservalidationbyemail_request_validation($object->guid); +function uservalidationbyemail_allow_new_user_can_edit($hook, $type, $value, $params) { + // $params['user'] is the user to check permissions for. + // we want the entity to check, which is a user. + $user = elgg_extract('entity', $params); + + if (!($user instanceof ElggUser)) { + return; + } + + $context = elgg_get_context(); + if ($context == 'uservalidationbyemail_new_user' || $context == 'uservalidationbyemail_validate_user') { + return TRUE; } - return true; + return; } /** - * Generate an email activation code. + * Checks if an account is validated * - * @param int $user_guid The guid of the user - * @param string $email_address Email address - * @return string + * @params array $credentials The username and password + * @return bool */ -function uservalidationbyemail_generate_code($user_guid, $email_address) { - global $CONFIG; +function uservalidationbyemail_check_auth_attempt($credentials) { - // Note I bind to site URL, this is important on multisite! - return md5($user_guid . $email_address . $CONFIG->site->url . get_site_secret()); + if (!isset($credentials['username'])) { + return; + } + + $username = $credentials['username']; + + // See if the user exists and isn't validated + $access_status = access_get_show_hidden_status(); + access_show_hidden_entities(TRUE); + + $user = get_user_by_username($username); + if ($user && isset($user->validated) && !$user->validated) { + // show an error and resend validation email + uservalidationbyemail_request_validation($user->guid); + access_show_hidden_entities($access_status); + throw new LoginException(elgg_echo('uservalidationbyemail:login:fail')); + } + + access_show_hidden_entities($access_status); } /** - * Request user validation email. - * Send email out to the address and request a confirmation. + * Checks sent passed validation code and user guids and validates the user. * - * @param int $user_guid The user - * @return mixed + * @param array $page + * @return bool */ -function uservalidationbyemail_request_validation($user_guid) { - global $CONFIG; +function uservalidationbyemail_page_handler($page) { + + if (isset($page[0]) && $page[0] == 'confirm') { + $code = sanitise_string(get_input('c', FALSE)); + $user_guid = get_input('u', FALSE); + + // new users are not enabled by default. + $access_status = access_get_show_hidden_status(); + access_show_hidden_entities(true); - $user_guid = (int)$user_guid; - $user = get_entity($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"; + if ($code && $user) { + if (uservalidationbyemail_validate_email($user_guid, $code)) { + + elgg_push_context('uservalidationbyemail_validate_user'); + system_message(elgg_echo('email:confirm:success')); + $user = get_entity($user_guid); + $user->enable(); + elgg_pop_context(); - // 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')); + try { + login($user); + } catch(LoginException $e){ + register_error($e->getMessage()); + } + } else { + register_error(elgg_echo('email:confirm:fail')); + } + } else { + register_error(elgg_echo('email:confirm:fail')); } - return $result; + access_show_hidden_entities($access_status); + } else { + register_error(elgg_echo('email:confirm:fail')); } - return FALSE; + // forward to front page + forward(''); } /** - * Validate a user + * Make sure any admin users are automatically validated * - * @param unknown_type $user_guid - * @param unknown_type $code - * @return unknown + * @param string $event + * @param string $type + * @param ElggUser $user */ -function uservalidationbyemail_validate_email($user_guid, $code) { - $user = get_entity($user_guid); - - if ($code == uservalidationbyemail_generate_code($user_guid, $user->email)) { - return set_user_validation_status($user_guid, true, 'email'); +function uservalidationbyemail_validate_new_admin_user($event, $type, $user) { + if ($user instanceof ElggUser && !$user->validated) { + elgg_set_user_validation_status($user->guid, TRUE, 'admin_user'); } - - return false; } /** - * Registers public pages to allow in the case Private Network has been enabled. + * Registers public pages to allow in the case walled garden has been enabled. */ function uservalidationbyemail_public_pages($hook, $type, $return_value, $params) { - $return_value[] = 'pg/uservalidationbyemail/confirm'; + $return_value[] = 'uservalidationbyemail/confirm'; return $return_value; } -// Initialise -register_elgg_event_handler('init', 'system', 'uservalidationbyemail_init');
\ No newline at end of file +/** + * Prevent a manual code login with login(). + * + * @param string $event + * @param string $type + * @param ElggUser $user + * @return bool + * + * @throws LoginException + */ +function uservalidationbyemail_check_manual_login($event, $type, $user) { + $access_status = access_get_show_hidden_status(); + access_show_hidden_entities(TRUE); + + if (($user instanceof ElggUser) && !$user->isEnabled() && !$user->validated) { + // send new validation email + uservalidationbyemail_request_validation($user->getGUID()); + + // restore hidden entities settings + access_show_hidden_entities($access_status); + + // throw error so we get a nice error message + throw new LoginException(elgg_echo('uservalidationbyemail:login:fail')); + } + + access_show_hidden_entities($access_status); +} |
