start.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <?php
  2. /**
  3. * Email user validation plugin.
  4. * Non-admin accounts are invalid until their email address is confirmed.
  5. *
  6. * @package Elgg.Core.Plugin
  7. * @subpackage UserValidationByEmail
  8. */
  9. elgg_register_event_handler('init', 'system', 'uservalidationbyemail_init');
  10. function uservalidationbyemail_init() {
  11. require_once dirname(__FILE__) . '/lib/functions.php';
  12. // Register page handler to validate users
  13. // This doesn't need to be an action because security is handled by the validation codes.
  14. elgg_register_page_handler('uservalidationbyemail', 'uservalidationbyemail_page_handler');
  15. // mark users as unvalidated and disable when they register
  16. elgg_register_plugin_hook_handler('register', 'user', 'uservalidationbyemail_disable_new_user');
  17. // forward to uservalidationbyemail/emailsent page after register
  18. elgg_register_plugin_hook_handler('forward', 'system', 'uservalidationbyemail_after_registration_url');
  19. // canEdit override to allow not logged in code to disable a user
  20. elgg_register_plugin_hook_handler('permissions_check', 'user', 'uservalidationbyemail_allow_new_user_can_edit');
  21. // prevent users from logging in if they aren't validated
  22. register_pam_handler('uservalidationbyemail_check_auth_attempt', "required");
  23. // when requesting a new password
  24. elgg_register_plugin_hook_handler('action', 'user/requestnewpassword', 'uservalidationbyemail_check_request_password');
  25. // prevent the engine from logging in users via login()
  26. elgg_register_event_handler('login:before', 'user', 'uservalidationbyemail_check_manual_login');
  27. // make admin users always validated
  28. elgg_register_event_handler('make_admin', 'user', 'uservalidationbyemail_validate_new_admin_user');
  29. // register Walled Garden public pages
  30. elgg_register_plugin_hook_handler('public_pages', 'walled_garden', 'uservalidationbyemail_public_pages');
  31. // admin interface to manually validate users
  32. elgg_register_admin_menu_item('administer', 'unvalidated', 'users');
  33. elgg_extend_view('css/admin', 'uservalidationbyemail/css');
  34. elgg_extend_view('js/elgg', 'uservalidationbyemail/js');
  35. $action_path = dirname(__FILE__) . '/actions';
  36. elgg_register_action('uservalidationbyemail/validate', "$action_path/validate.php", 'admin');
  37. elgg_register_action('uservalidationbyemail/resend_validation', "$action_path/resend_validation.php", 'admin');
  38. elgg_register_action('uservalidationbyemail/delete', "$action_path/delete.php", 'admin');
  39. elgg_register_action('uservalidationbyemail/bulk_action', "$action_path/bulk_action.php", 'admin');
  40. }
  41. /**
  42. * Disables a user upon registration.
  43. *
  44. * @param string $hook
  45. * @param string $type
  46. * @param bool $value
  47. * @param array $params
  48. * @return bool
  49. */
  50. function uservalidationbyemail_disable_new_user($hook, $type, $value, $params) {
  51. $user = elgg_extract('user', $params);
  52. // no clue what's going on, so don't react.
  53. if (!$user instanceof ElggUser) {
  54. return;
  55. }
  56. // another plugin is requesting that registration be terminated
  57. // no need for uservalidationbyemail
  58. if (!$value) {
  59. return $value;
  60. }
  61. // has the user already been validated?
  62. if (elgg_get_user_validation_status($user->guid) == true) {
  63. return $value;
  64. }
  65. // disable user to prevent showing up on the site
  66. // set context so our canEdit() override works
  67. elgg_push_context('uservalidationbyemail_new_user');
  68. $hidden_entities = access_get_show_hidden_status();
  69. access_show_hidden_entities(TRUE);
  70. // Don't do a recursive disable. Any entities owned by the user at this point
  71. // are products of plugins that hook into create user and might need
  72. // access to the entities.
  73. // @todo That ^ sounds like a specific case...would be nice to track it down...
  74. $user->disable('uservalidationbyemail_new_user', FALSE);
  75. // set user as unvalidated and send out validation email
  76. elgg_set_user_validation_status($user->guid, FALSE);
  77. uservalidationbyemail_request_validation($user->guid);
  78. elgg_pop_context();
  79. access_show_hidden_entities($hidden_entities);
  80. return $value;
  81. }
  82. /**
  83. * Override the URL to be forwarded after registration
  84. *
  85. * @param string $hook
  86. * @param string $type
  87. * @param bool $value
  88. * @param array $params
  89. * @return string
  90. */
  91. function uservalidationbyemail_after_registration_url($hook, $type, $value, $params) {
  92. $url = elgg_extract('current_url', $params);
  93. if ($url == elgg_get_site_url() . 'action/register') {
  94. $session = elgg_get_session();
  95. $email = $session->get('emailsent', '');
  96. if ($email) {
  97. return elgg_get_site_url() . 'uservalidationbyemail/emailsent';
  98. }
  99. }
  100. }
  101. /**
  102. * Override the canEdit() call for if we're in the context of registering a new user.
  103. *
  104. * @param string $hook
  105. * @param string $type
  106. * @param bool $value
  107. * @param array $params
  108. * @return bool|null
  109. */
  110. function uservalidationbyemail_allow_new_user_can_edit($hook, $type, $value, $params) {
  111. // $params['user'] is the user to check permissions for.
  112. // we want the entity to check, which is a user.
  113. $user = elgg_extract('entity', $params);
  114. if (!($user instanceof ElggUser)) {
  115. return;
  116. }
  117. $context = elgg_get_context();
  118. if ($context == 'uservalidationbyemail_new_user' || $context == 'uservalidationbyemail_validate_user') {
  119. return TRUE;
  120. }
  121. return;
  122. }
  123. /**
  124. * Checks if an account is validated
  125. *
  126. * @params array $credentials The username and password
  127. * @return bool
  128. */
  129. function uservalidationbyemail_check_auth_attempt($credentials) {
  130. if (!isset($credentials['username'])) {
  131. return;
  132. }
  133. $username = $credentials['username'];
  134. // See if the user exists and isn't validated
  135. $access_status = access_get_show_hidden_status();
  136. access_show_hidden_entities(TRUE);
  137. // check if logging in with email address
  138. if (strpos($username, '@') !== false) {
  139. $users = get_user_by_email($username);
  140. if ($users) {
  141. $username = $users[0]->username;
  142. }
  143. }
  144. $user = get_user_by_username($username);
  145. if ($user && isset($user->validated) && !$user->validated) {
  146. // show an error and resend validation email
  147. uservalidationbyemail_request_validation($user->guid);
  148. access_show_hidden_entities($access_status);
  149. throw new LoginException(elgg_echo('uservalidationbyemail:login:fail'));
  150. }
  151. access_show_hidden_entities($access_status);
  152. }
  153. /**
  154. * Checks sent passed validation code and user guids and validates the user.
  155. *
  156. * @param array $page
  157. * @return bool
  158. */
  159. function uservalidationbyemail_page_handler($page) {
  160. $valid_pages = array('emailsent', 'confirm');
  161. if (empty($page[0]) || !in_array($page[0], $valid_pages)) {
  162. forward('', '404');
  163. }
  164. // note, safe to include based on input because we validated above.
  165. require dirname(__FILE__) . "/pages/{$page[0]}.php";
  166. return true;
  167. }
  168. /**
  169. * Make sure any admin users are automatically validated
  170. *
  171. * @param string $event
  172. * @param string $type
  173. * @param ElggUser $user
  174. */
  175. function uservalidationbyemail_validate_new_admin_user($event, $type, $user) {
  176. if ($user instanceof ElggUser && !$user->validated) {
  177. elgg_set_user_validation_status($user->guid, TRUE, 'admin_user');
  178. }
  179. }
  180. /**
  181. * Registers public pages to allow in the case walled garden has been enabled.
  182. */
  183. function uservalidationbyemail_public_pages($hook, $type, $return_value, $params) {
  184. $return_value[] = 'uservalidationbyemail/confirm';
  185. $return_value[] = 'uservalidationbyemail/emailsent';
  186. return $return_value;
  187. }
  188. /**
  189. * Prevent a manual code login with login().
  190. *
  191. * @param string $event
  192. * @param string $type
  193. * @param ElggUser $user
  194. * @return bool
  195. *
  196. * @throws LoginException
  197. */
  198. function uservalidationbyemail_check_manual_login($event, $type, $user) {
  199. $access_status = access_get_show_hidden_status();
  200. access_show_hidden_entities(TRUE);
  201. if (($user instanceof ElggUser) && !$user->isEnabled() && !$user->validated) {
  202. // send new validation email
  203. uservalidationbyemail_request_validation($user->getGUID());
  204. // restore hidden entities settings
  205. access_show_hidden_entities($access_status);
  206. // throw error so we get a nice error message
  207. throw new LoginException(elgg_echo('uservalidationbyemail:login:fail'));
  208. }
  209. access_show_hidden_entities($access_status);
  210. }