forgotten_login.module 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <?php
  2. /**
  3. * Implements hook_menu().
  4. */
  5. function forgotten_login_menu() {
  6. $items = array();
  7. $items['admin/config/people/forgotten_login'] = array(
  8. 'title' => 'Forgotten Login',
  9. 'description' => 'Configure the settings for Forgotten Login module.',
  10. 'access arguments' => array('administer forgotten login'),
  11. 'page callback' => 'drupal_get_form',
  12. 'page arguments' => array('forgotten_login_admin_settings'),
  13. );
  14. return $items;
  15. }
  16. /**
  17. * Implements hook_permission().
  18. */
  19. function forgotten_login_permission() {
  20. return array(
  21. 'administer forgotten login' => array(
  22. 'title' => t('Administer Forgotten Login'),
  23. 'description' => t('Change the settings for Forgotten Login.'),
  24. ),
  25. );
  26. }
  27. /**
  28. * Implements hook_help().
  29. */
  30. function forgotten_login_help($path, $arg) {
  31. switch ($path) {
  32. case 'admin/config/people/forgotten_login':
  33. return '<p>' . t('Forgotten login will automatically send an e-mail to a user who fails to login more than the configured amount of times. The (default) value of 0 failed attempts will stop the module working and reset the failed attempts count for all users.') . '</p>';
  34. }
  35. }
  36. /**
  37. * Creates the form for setting the forgotten login email settings
  38. *
  39. * @ingroup forms
  40. */
  41. function forgotten_login_admin_settings() {
  42. $form = array();
  43. $form['forgotten_login_failed_attempts'] = array(
  44. '#type' => 'textfield',
  45. '#title' => t('Failed attempts'),
  46. '#description' => t('After how many attempts should the automatic e-mail be sent. Setting this to 0 will disable the email.'),
  47. '#default_value' => variable_get('forgotten_login_failed_attempts', 0),
  48. '#required' => TRUE,
  49. );
  50. $form['forgotten_login_email_from'] = array(
  51. '#type' => 'textfield',
  52. '#title' => t('Email From'),
  53. '#description' => t('Who the forgotten password e-mail should come from'),
  54. '#default_value' => variable_get('forgotten_login_email_from', variable_get('site_mail', '')),
  55. '#required' => TRUE,
  56. );
  57. $tokens = '!username, !site, !login_url, !mailto, !date';
  58. $form['forgotten_login_email_subject'] = array(
  59. '#type' => 'textfield',
  60. '#title' => t('Email Subject'),
  61. '#description' => t('The subject of the forgotten password e-mail. Available tokens are: @tokens', array('@tokens' => $tokens)),
  62. '#default_value' => variable_get('forgotten_login_email_subject', variable_get('site_name', '') . ': Forgotten password'),
  63. '#required' => TRUE,
  64. );
  65. $default_content = "Hi !username,\n\nYou appear to be having difficulty signing in to !site. To help, we have sent you a link which will give you access to your account:\n\n!login_url\n\nRegards,\n!site";
  66. $form['forgotten_login_email_content'] = array(
  67. '#type' => 'textarea',
  68. '#rows' => 10,
  69. '#title' => t('Email Content'),
  70. '#description' => t('The content of the forgotten password e-mail. Available tokens are: @tokens', array('@tokens' => $tokens)),
  71. '#default_value' => variable_get('forgotten_login_email_content', $default_content),
  72. '#required' => TRUE,
  73. );
  74. $form['#submit'] = array('forgotten_login_admin_settings_submit');
  75. return system_settings_form($form);
  76. }
  77. /**
  78. * Form validater for the forgotten login email settings.
  79. *
  80. * @see forgotten_login_admin_settings()
  81. * @see forgotten_login_admin_settings_submit()
  82. * @ingroup forms
  83. */
  84. function forgotten_login_admin_settings_validate($form, &$form_state) {
  85. $values = $form_state['values'];
  86. $failed_attempts = $values['forgotten_login_failed_attempts'];
  87. if (!preg_match('/^[0-9]+$/', $failed_attempts)) {
  88. form_set_error('forgotten_login_failed_attempts', t('The number of failed attempts must be numeric and positive'));
  89. }
  90. }
  91. /**
  92. * Form submit function for the forgotten login email settings. Simply sets
  93. * all users' login attempts to 0 if the module is "disabled".
  94. *
  95. * @see forgotten_login_admin_settings()
  96. * @see forgotten_login_admin_settings_validate()
  97. * @ingroup forms
  98. */
  99. function forgotten_login_admin_settings_submit($form, &$form_state) {
  100. if ($form_state['values']['forgotten_login_failed_attempts'] == 0) {
  101. db_query('UPDATE {users} SET forgotten_login_attempts = 0');
  102. }
  103. }
  104. /**
  105. * Implements hook_form_alter().
  106. *
  107. * Adds a validation handler to handle failed logins
  108. *
  109. * @see forgotten_login_check_login().
  110. */
  111. function forgotten_login_form_alter(&$form, $form_state, $form_id) {
  112. if ($form_id == 'user_login' || $form_id == 'user_login_block') {
  113. if (!is_array($form['#validate'])) {
  114. $form['#validate'] = array($form['#validate']);
  115. }
  116. $form['#validate'][] = 'forgotten_login_check_login';
  117. }
  118. }
  119. /**
  120. * Implements hook_user_login().
  121. */
  122. function forgotten_login_user_login(&$edit, &$account) {
  123. // On a valid login, simply reset the login attempts back to 0
  124. $args = array('uid' => $account->uid);
  125. db_query('UPDATE {users} SET forgotten_login_attempts = 0 WHERE uid = :uid', $args);
  126. }
  127. /**
  128. * Validate function for the user_login and user_login_block forms.
  129. *
  130. * This function is called after the user's details are validated, if they
  131. * don't have a UID now, they failed to login.
  132. */
  133. function forgotten_login_check_login($form, &$form_state) {
  134. global $user;
  135. if ($user->uid == 0) {
  136. // Check the trigger value here - if it's 0 we're disabled so no need to proceed
  137. $trigger_value = variable_get('forgotten_login_failed_attempts', 0);
  138. if ($trigger_value == 0) {
  139. return;
  140. }
  141. // Attempt to find the uid for the account they tried to log in to
  142. $uid = db_query('SELECT u.uid FROM {users} u WHERE u.status <> 0 AND u.name = :name', array(':name' => $form_state['values']['name']))->fetchField();
  143. if ($uid == FALSE) {
  144. // No user id found...
  145. return;
  146. }
  147. // Increment the login attempts value
  148. db_query('UPDATE {users} SET forgotten_login_attempts = forgotten_login_attempts + 1 WHERE uid = :uid', array(':uid' => $uid));
  149. // Check the value and send an email if needed
  150. $attempts = db_query('SELECT forgotten_login_attempts FROM {users} WHERE uid = :uid', array(':uid' => $uid))->fetchField();
  151. // We only check for an exact value so we send the email once until a valid login happens
  152. if ($attempts == $trigger_value) {
  153. global $language;
  154. $account = user_load($uid);
  155. $params = array('account' => $account);
  156. $language = $language ? $language : user_preferred_language($account);
  157. $message = drupal_mail('forgotten_login', 'forgotten_login_email', $account->mail, $language, $params);
  158. if ($message['result']) {
  159. if (module_exists('rules')) {
  160. rules_invoke_event('forgotten_login_email_sent', $account);
  161. }
  162. watchdog('forgotten_login', 'User %account was sent a login link after a total of %logins failed attempts.', array('%account' => $account->name, '%logins' => $attempts));
  163. }
  164. }
  165. }
  166. }
  167. /**
  168. * Implementation of hook_mail().
  169. */
  170. function forgotten_login_mail($key, &$message, $params) {
  171. $language = $message['language'];
  172. $variables = array();
  173. // Create the tokens from D6's user_mail_tokens() to help upgrades.
  174. $variables['!username'] = $params['account']->name;
  175. $variables['!site'] = variable_get('site_name', 'Drupal');
  176. $variables['!login_url'] = user_pass_reset_url($params['account']);
  177. $variables['!mailto'] = $params['account']->mail;
  178. $variables['!date'] = date(time());
  179. $default_content = "Hi !username,\n\nYou appear to be having difficulty signing in to !site. To help, we have sent you a link which will give you access to your account:\n\n!login_url\n\nRegards,\n!site";
  180. $message['subject'] = strtr(variable_get('forgotten_login_email_subject', variable_get('site_name', '') . ': Forgotten password'), $variables);
  181. $message['body'] = array(strtr(variable_get('forgotten_login_email_content', $default_content), $variables));
  182. }